mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-04 10:34:55 +02:00
Merge pull request #2114 from jesseduffield/more-test-examples
This commit is contained in:
commit
a95d3e26b3
@ -13,7 +13,7 @@ Usage:
|
||||
See https://github.com/jesseduffield/lazygit/tree/master/pkg/integration/README.md
|
||||
|
||||
CLI mode:
|
||||
> go run cmd/integration_test/main.go cli <test1> <test2> ...
|
||||
> go run cmd/integration_test/main.go cli [--slow] <test1> <test2> ...
|
||||
If you pass no test names, it runs all tests
|
||||
Accepted environment variables:
|
||||
KEY_PRESS_DELAY (e.g. 200): the number of milliseconds to wait between keypresses
|
||||
@ -40,7 +40,14 @@ func main() {
|
||||
case "help":
|
||||
fmt.Println(usage)
|
||||
case "cli":
|
||||
clients.RunCLI(os.Args[2:])
|
||||
testNames := os.Args[2:]
|
||||
slow := false
|
||||
// get the next arg if it's --slow
|
||||
if len(os.Args) > 2 && (os.Args[2] == "--slow" || os.Args[2] == "-slow") {
|
||||
testNames = os.Args[3:]
|
||||
slow = true
|
||||
}
|
||||
clients.RunCLI(testNames, slow)
|
||||
case "tui":
|
||||
clients.RunTUI()
|
||||
default:
|
||||
|
@ -314,7 +314,9 @@ type CustomCommand struct {
|
||||
}
|
||||
|
||||
type CustomCommandPrompt struct {
|
||||
Type string `yaml:"type"` // one of 'input', 'menu', or 'confirm'
|
||||
// one of 'input', 'menu', 'confirm', or 'menuFromCommand'
|
||||
Type string `yaml:"type"`
|
||||
|
||||
Title string `yaml:"title"`
|
||||
|
||||
// this only apply to input prompts
|
||||
|
@ -71,3 +71,11 @@ func (self *GuiDriver) LogUI(message string) {
|
||||
func (self *GuiDriver) CheckedOutRef() *models.Branch {
|
||||
return self.gui.helpers.Refs.GetCheckedOutRef()
|
||||
}
|
||||
|
||||
func (self *GuiDriver) MainView() *gocui.View {
|
||||
return self.gui.mainView()
|
||||
}
|
||||
|
||||
func (self *GuiDriver) SecondaryView() *gocui.View {
|
||||
return self.gui.secondaryView()
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ If you find yourself doing something frequently in a test, consider making it a
|
||||
|
||||
There are three ways to invoke a test:
|
||||
|
||||
1. go run cmd/integration_test/main.go cli [<testname>...]
|
||||
1. go run cmd/integration_test/main.go cli [--slow] [<testname or testpath>...]
|
||||
2. go run cmd/integration_test/main.go tui
|
||||
3. go test pkg/integration/clients/go_test.go
|
||||
|
||||
@ -47,7 +47,7 @@ The third, the go-test command, intended only for use in CI, to be run along wit
|
||||
|
||||
The name of a test is based on its path, so the name of the test at `pkg/integration/tests/commit/new_branch.go` is commit/new_branch. So to run it with our test runner you would run `go run cmd/integration_test/main.go cli commit/new_branch`.
|
||||
|
||||
You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses, which helps for watching a test at a realistic speed to understand what it's doing. Or in the tui you can press 't' to run the test with a pre-set delay.
|
||||
You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a delay in milliseconds between keypresses, which helps for watching a test at a realistic speed to understand what it's doing. Or you can pass the '--slow' flag which sets a pre-set 'slow' key delay. In the tui you can press 't' to run the test in slow mode.
|
||||
|
||||
### Snapshots
|
||||
|
||||
|
@ -4,8 +4,11 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests"
|
||||
)
|
||||
@ -20,14 +23,19 @@ import (
|
||||
|
||||
// If invoked directly, you can specify tests to run by passing their names as positional arguments
|
||||
|
||||
func RunCLI(testNames []string) {
|
||||
func RunCLI(testNames []string, slow bool) {
|
||||
keyPressDelay := tryConvert(os.Getenv("KEY_PRESS_DELAY"), 0)
|
||||
if slow {
|
||||
keyPressDelay = SLOW_KEY_PRESS_DELAY
|
||||
}
|
||||
|
||||
err := components.RunTests(
|
||||
getTestsToRun(testNames),
|
||||
log.Printf,
|
||||
runCmdInTerminal,
|
||||
runAndPrintError,
|
||||
getModeFromEnv(),
|
||||
tryConvert(os.Getenv("KEY_PRESS_DELAY"), 0),
|
||||
keyPressDelay,
|
||||
)
|
||||
if err != nil {
|
||||
log.Print(err.Error())
|
||||
@ -36,21 +44,30 @@ func RunCLI(testNames []string) {
|
||||
|
||||
func runAndPrintError(test *components.IntegrationTest, f func() error) {
|
||||
if err := f(); err != nil {
|
||||
log.Print(err.Error())
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func getTestsToRun(testNames []string) []*components.IntegrationTest {
|
||||
allIntegrationTests := tests.GetTests()
|
||||
var testsToRun []*components.IntegrationTest
|
||||
|
||||
if len(testNames) == 0 {
|
||||
return tests.Tests
|
||||
return allIntegrationTests
|
||||
}
|
||||
|
||||
testNames = slices.Map(testNames, func(name string) string {
|
||||
// allowing full test paths to be passed for convenience
|
||||
return strings.TrimSuffix(
|
||||
regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(name, ""),
|
||||
".go",
|
||||
)
|
||||
})
|
||||
|
||||
outer:
|
||||
for _, testName := range testNames {
|
||||
// check if our given test name actually exists
|
||||
for _, test := range tests.Tests {
|
||||
for _, test := range allIntegrationTests {
|
||||
if test.Name() == testName {
|
||||
testsToRun = append(testsToRun, test)
|
||||
continue outer
|
||||
|
@ -29,7 +29,7 @@ func TestIntegration(t *testing.T) {
|
||||
testNumber := 0
|
||||
|
||||
err := components.RunTests(
|
||||
tests.Tests,
|
||||
tests.GetTests(),
|
||||
t.Logf,
|
||||
runCmdHeadless,
|
||||
func(test *components.IntegrationTest, f func() error) {
|
||||
|
@ -52,7 +52,8 @@ func getIntegrationTest() integrationTypes.IntegrationTest {
|
||||
))
|
||||
}
|
||||
|
||||
for _, candidateTest := range tests.Tests {
|
||||
allTests := tests.GetTests()
|
||||
for _, candidateTest := range allTests {
|
||||
if candidateTest.Name() == integrationTestName {
|
||||
return candidateTest
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ import (
|
||||
|
||||
// This program lets you run integration tests from a TUI. See pkg/integration/README.md for more info.
|
||||
|
||||
var SLOW_KEY_PRESS_DELAY = 300
|
||||
|
||||
func RunTUI() {
|
||||
rootDir := utils.GetLazygitRootDirectory()
|
||||
testDir := filepath.Join(rootDir, "test", "integration")
|
||||
@ -106,7 +108,7 @@ func RunTUI() {
|
||||
return nil
|
||||
}
|
||||
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, 200)
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, SLOW_KEY_PRESS_DELAY)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
@ -168,7 +170,7 @@ func RunTUI() {
|
||||
return err
|
||||
}
|
||||
|
||||
app.filteredTests = tests.Tests
|
||||
app.filteredTests = app.allTests
|
||||
app.renderTests()
|
||||
app.editorView.TextArea.Clear()
|
||||
app.editorView.Clear()
|
||||
@ -204,6 +206,7 @@ func RunTUI() {
|
||||
}
|
||||
|
||||
type app struct {
|
||||
allTests []*components.IntegrationTest
|
||||
filteredTests []*components.IntegrationTest
|
||||
itemIdx int
|
||||
testDir string
|
||||
@ -214,7 +217,7 @@ type app struct {
|
||||
}
|
||||
|
||||
func newApp(testDir string) *app {
|
||||
return &app{testDir: testDir}
|
||||
return &app{testDir: testDir, allTests: tests.GetTests()}
|
||||
}
|
||||
|
||||
func (self *app) getCurrentTest() *components.IntegrationTest {
|
||||
@ -226,7 +229,7 @@ func (self *app) getCurrentTest() *components.IntegrationTest {
|
||||
}
|
||||
|
||||
func (self *app) loadTests() {
|
||||
self.filteredTests = tests.Tests
|
||||
self.filteredTests = self.allTests
|
||||
|
||||
self.adjustCursor()
|
||||
}
|
||||
@ -237,9 +240,9 @@ func (self *app) adjustCursor() {
|
||||
|
||||
func (self *app) filterWithString(needle string) {
|
||||
if needle == "" {
|
||||
self.filteredTests = tests.Tests
|
||||
self.filteredTests = self.allTests
|
||||
} else {
|
||||
self.filteredTests = slices.Filter(tests.Tests, func(test *components.IntegrationTest) bool {
|
||||
self.filteredTests = slices.Filter(self.allTests, func(test *components.IntegrationTest) bool {
|
||||
return strings.Contains(test.Name(), needle)
|
||||
})
|
||||
}
|
||||
|
@ -19,6 +19,43 @@ func NewAssert(gui integrationTypes.GuiDriver) *Assert {
|
||||
return &Assert{gui: gui}
|
||||
}
|
||||
|
||||
// for making assertions on string values
|
||||
type matcher struct {
|
||||
testFn func(string) (bool, string)
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (self *matcher) test(value string) (bool, string) {
|
||||
ok, message := self.testFn(value)
|
||||
if ok {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
if self.prefix != "" {
|
||||
return false, self.prefix + " " + message
|
||||
}
|
||||
|
||||
return false, message
|
||||
}
|
||||
|
||||
func (self *matcher) context(prefix string) *matcher {
|
||||
self.prefix = prefix
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func Contains(target string) *matcher {
|
||||
return &matcher{testFn: func(value string) (bool, string) {
|
||||
return strings.Contains(value, target), fmt.Sprintf("Expected '%s' to contain '%s'", value, target)
|
||||
}}
|
||||
}
|
||||
|
||||
func Equals(target string) *matcher {
|
||||
return &matcher{testFn: func(value string) (bool, string) {
|
||||
return target == value, fmt.Sprintf("Expected '%s' to equal '%s'", value, target)
|
||||
}}
|
||||
}
|
||||
|
||||
func (self *Assert) WorkingTreeFileCount(expectedCount int) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
actualCount := len(self.gui.Model().Files)
|
||||
@ -41,22 +78,16 @@ func (self *Assert) CommitCount(expectedCount int) {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) HeadCommitMessage(expectedMessage string) {
|
||||
func (self *Assert) MatchHeadCommitMessage(matcher *matcher) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
if len(self.gui.Model().Commits) == 0 {
|
||||
return false, "Expected at least one commit to be present"
|
||||
}
|
||||
|
||||
headCommit := self.gui.Model().Commits[0]
|
||||
if headCommit.Name != expectedMessage {
|
||||
return false, fmt.Sprintf(
|
||||
"Expected commit message to be '%s', but got '%s'",
|
||||
expectedMessage, headCommit.Name,
|
||||
)
|
||||
}
|
||||
|
||||
return true, ""
|
||||
return len(self.gui.Model().Commits) > 0, "Expected at least one commit to be present"
|
||||
})
|
||||
|
||||
self.matchString(matcher, "Unexpected commit message.",
|
||||
func() string {
|
||||
return self.gui.Model().Commits[0].Name
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) CurrentViewName(expectedViewName string) {
|
||||
@ -81,10 +112,70 @@ func (self *Assert) InListContext() {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) SelectedLineContains(text string) {
|
||||
func (self *Assert) MatchSelectedLine(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected selected line.",
|
||||
func() string {
|
||||
return self.gui.CurrentContext().GetView().SelectedLine()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) InPrompt() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
line := self.gui.CurrentContext().GetView().SelectedLine()
|
||||
return strings.Contains(line, text), fmt.Sprintf("Expected selected line to contain '%s', but got '%s'", text, line)
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && currentView.Editable, "Expected prompt popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InConfirm() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && !currentView.Editable, "Expected confirmation popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InAlert() {
|
||||
// basically the same thing as a confirmation popup with the current implementation
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
currentView := self.gui.CurrentContext().GetView()
|
||||
return currentView.Name() == "confirmation" && !currentView.Editable, "Expected alert popup to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) InMenu() {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
return self.gui.CurrentContext().GetView().Name() == "menu", "Expected popup menu to be focused"
|
||||
})
|
||||
}
|
||||
|
||||
func (self *Assert) MatchCurrentViewTitle(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected current view title.",
|
||||
func() string {
|
||||
return self.gui.CurrentContext().GetView().Title
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) MatchMainViewContent(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected main view content.",
|
||||
func() string {
|
||||
return self.gui.MainView().Buffer()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) MatchSecondaryViewContent(matcher *matcher) {
|
||||
self.matchString(matcher, "Unexpected secondary view title.",
|
||||
func() string {
|
||||
return self.gui.SecondaryView().Buffer()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (self *Assert) matchString(matcher *matcher, context string, getValue func() string) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
value := getValue()
|
||||
return matcher.context(context).test(value)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ func (self *Input) Cancel() {
|
||||
}
|
||||
|
||||
// i.e. pressing space
|
||||
func (self *Input) Select() {
|
||||
func (self *Input) PrimaryAction() {
|
||||
self.pressKey(self.keys.Universal.Select)
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ func (self *Input) PreviousItem() {
|
||||
|
||||
func (self *Input) ContinueMerge() {
|
||||
self.PressKeys(self.keys.Universal.CreateRebaseOptionsMenu)
|
||||
self.assert.SelectedLineContains("continue")
|
||||
self.assert.MatchSelectedLine(Contains("continue"))
|
||||
self.Confirm()
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ func NewIntegrationTest(args NewIntegrationTestArgs) *IntegrationTest {
|
||||
if args.Description != unitTestDescription {
|
||||
// this panics if we're in a unit test for our integration tests,
|
||||
// so we're using "test test" as a sentinel value
|
||||
name = testNameFromFilePath()
|
||||
name = testNameFromCurrentFilePath()
|
||||
}
|
||||
|
||||
return &IntegrationTest{
|
||||
@ -106,8 +106,12 @@ func (self *IntegrationTest) Run(gui integrationTypes.GuiDriver) {
|
||||
}
|
||||
}
|
||||
|
||||
func testNameFromFilePath() string {
|
||||
func testNameFromCurrentFilePath() string {
|
||||
path := utils.FilePath(3)
|
||||
return TestNameFromFilePath(path)
|
||||
}
|
||||
|
||||
func TestNameFromFilePath(path string) string {
|
||||
name := strings.Split(path, "integration/tests/")[1]
|
||||
|
||||
return name[:len(name)-len(".go")]
|
||||
|
@ -3,6 +3,7 @@ package components
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@ -47,6 +48,14 @@ func (self *fakeGuiDriver) CheckedOutRef() *models.Branch {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) MainView() *gocui.View {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *fakeGuiDriver) SecondaryView() *gocui.View {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAssertionFailure(t *testing.T) {
|
||||
test := NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: unitTestDescription,
|
||||
|
@ -2,24 +2,24 @@ package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var Commit = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var Commit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Staging a couple files and committing",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("myfile", "myfile content")
|
||||
shell.CreateFile("myfile2", "myfile2 content")
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(0)
|
||||
|
||||
input.Select()
|
||||
input.PrimaryAction()
|
||||
input.NextItem()
|
||||
input.Select()
|
||||
input.PrimaryAction()
|
||||
input.PressKeys(keys.Files.CommitChanges)
|
||||
|
||||
commitMessage := "my commit message"
|
||||
@ -27,6 +27,6 @@ var Commit = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
input.Confirm()
|
||||
|
||||
assert.CommitCount(1)
|
||||
assert.HeadCommitMessage(commitMessage)
|
||||
assert.MatchHeadCommitMessage(Equals(commitMessage))
|
||||
},
|
||||
})
|
||||
|
@ -2,21 +2,21 @@ package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var NewBranch = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var NewBranch = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Creating a new branch from a commit",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("commit 1").
|
||||
EmptyCommit("commit 2").
|
||||
EmptyCommit("commit 3")
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(3)
|
||||
|
||||
input.SwitchToCommitsWindow()
|
||||
@ -32,7 +32,7 @@ var NewBranch = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
input.Confirm()
|
||||
|
||||
assert.CommitCount(2)
|
||||
assert.HeadCommitMessage("commit 2")
|
||||
assert.MatchHeadCommitMessage(Contains("commit 2"))
|
||||
assert.CurrentBranchName(branchName)
|
||||
},
|
||||
})
|
||||
|
36
pkg/integration/tests/custom_commands/basic.go
Normal file
36
pkg/integration/tests/custom_commands/basic.go
Normal file
@ -0,0 +1,36 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var Basic = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using a custom command to create a new file",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "files",
|
||||
Command: "touch myfile",
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
|
||||
input.PressKeys("a")
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("myfile"))
|
||||
},
|
||||
})
|
74
pkg/integration/tests/custom_commands/menu_from_command.go
Normal file
74
pkg/integration/tests/custom_commands/menu_from_command.go
Normal file
@ -0,0 +1,74 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
// NOTE: we're getting a weird offset in the popup prompt for some reason. Not sure what's behind that.
|
||||
|
||||
var MenuFromCommand = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using menuFromCommand prompt type",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
EmptyCommit("foo").
|
||||
EmptyCommit("bar").
|
||||
EmptyCommit("baz").
|
||||
NewBranch("feature/foo")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "localBranches",
|
||||
Command: `echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{ .SelectedLocalBranch.Name }}" > output.txt`,
|
||||
Prompts: []config.CustomCommandPrompt{
|
||||
{
|
||||
Type: "menuFromCommand",
|
||||
Title: "Choose commit message",
|
||||
Command: `git log --oneline --pretty=%B`,
|
||||
Filter: `(?P<commit_message>.*)`,
|
||||
ValueFormat: `{{ .commit_message }}`,
|
||||
LabelFormat: `{{ .commit_message | yellow }}`,
|
||||
},
|
||||
{
|
||||
Type: "input",
|
||||
Title: "Description",
|
||||
InitialValue: `{{ if .SelectedLocalBranch.Name }}Branch: #{{ .SelectedLocalBranch.Name }}{{end}}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
input.SwitchToBranchesWindow()
|
||||
|
||||
input.PressKeys("a")
|
||||
|
||||
assert.InMenu()
|
||||
assert.MatchCurrentViewTitle(Equals("Choose commit message"))
|
||||
assert.MatchSelectedLine(Equals("baz"))
|
||||
input.NextItem()
|
||||
assert.MatchSelectedLine(Equals("bar"))
|
||||
input.Confirm()
|
||||
|
||||
assert.InPrompt()
|
||||
assert.MatchCurrentViewTitle(Equals("Description"))
|
||||
input.Type(" my branch")
|
||||
input.Confirm()
|
||||
|
||||
input.SwitchToFilesWindow()
|
||||
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("output.txt"))
|
||||
assert.MatchMainViewContent(Contains("bar Branch: #feature/foo my branch feature/foo"))
|
||||
},
|
||||
})
|
86
pkg/integration/tests/custom_commands/multiple_prompts.go
Normal file
86
pkg/integration/tests/custom_commands/multiple_prompts.go
Normal file
@ -0,0 +1,86 @@
|
||||
package custom_commands
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var MultiplePrompts = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Using a custom command with multiple prompts",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.EmptyCommit("blah")
|
||||
},
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.UserConfig.CustomCommands = []config.CustomCommand{
|
||||
{
|
||||
Key: "a",
|
||||
Context: "files",
|
||||
Command: `echo "{{index .PromptResponses 1}}" > {{index .PromptResponses 0}}`,
|
||||
Prompts: []config.CustomCommandPrompt{
|
||||
{
|
||||
Type: "input",
|
||||
Title: "Enter a file name",
|
||||
},
|
||||
{
|
||||
Type: "menu",
|
||||
Title: "Choose file content",
|
||||
Options: []config.CustomCommandMenuOption{
|
||||
{
|
||||
Name: "foo",
|
||||
Description: "Foo",
|
||||
Value: "FOO",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Description: "Bar",
|
||||
Value: "BAR",
|
||||
},
|
||||
{
|
||||
Name: "baz",
|
||||
Description: "Baz",
|
||||
Value: "BAZ",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: "confirm",
|
||||
Title: "Are you sure?",
|
||||
Body: "Are you REALLY sure you want to make this file? Up to you buddy.",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
Run: func(
|
||||
shell *Shell,
|
||||
input *Input,
|
||||
assert *Assert,
|
||||
keys config.KeybindingConfig,
|
||||
) {
|
||||
assert.WorkingTreeFileCount(0)
|
||||
|
||||
input.PressKeys("a")
|
||||
|
||||
assert.InPrompt()
|
||||
assert.MatchCurrentViewTitle(Equals("Enter a file name"))
|
||||
input.Type("myfile")
|
||||
input.Confirm()
|
||||
|
||||
assert.InMenu()
|
||||
assert.MatchCurrentViewTitle(Equals("Choose file content"))
|
||||
assert.MatchSelectedLine(Contains("foo"))
|
||||
input.NextItem()
|
||||
assert.MatchSelectedLine(Contains("bar"))
|
||||
input.Confirm()
|
||||
|
||||
assert.InConfirm()
|
||||
assert.MatchCurrentViewTitle(Equals("Are you sure?"))
|
||||
input.Confirm()
|
||||
|
||||
assert.WorkingTreeFileCount(1)
|
||||
assert.MatchSelectedLine(Contains("myfile"))
|
||||
assert.MatchMainViewContent(Contains("BAR"))
|
||||
},
|
||||
})
|
@ -2,37 +2,37 @@ package interactive_rebase
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var One = components.NewIntegrationTest(components.NewIntegrationTestArgs{
|
||||
var One = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Begins an interactive rebase, then fixups, drops, and squashes some commits",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *components.Shell) {
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.
|
||||
CreateNCommits(5) // these will appears at commit 05, 04, 04, down to 01
|
||||
},
|
||||
Run: func(shell *components.Shell, input *components.Input, assert *components.Assert, keys config.KeybindingConfig) {
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
input.SwitchToCommitsWindow()
|
||||
assert.CurrentViewName("commits")
|
||||
|
||||
input.NavigateToListItemContainingText("commit 02")
|
||||
input.PressKeys(keys.Universal.Edit)
|
||||
assert.SelectedLineContains("YOU ARE HERE")
|
||||
assert.MatchSelectedLine(Contains("YOU ARE HERE"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Commits.MarkCommitAsFixup)
|
||||
assert.SelectedLineContains("fixup")
|
||||
assert.MatchSelectedLine(Contains("fixup"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Universal.Remove)
|
||||
assert.SelectedLineContains("drop")
|
||||
assert.MatchSelectedLine(Contains("drop"))
|
||||
|
||||
input.PreviousItem()
|
||||
input.PressKeys(keys.Commits.SquashDown)
|
||||
assert.SelectedLineContains("squash")
|
||||
assert.MatchSelectedLine(Contains("squash"))
|
||||
|
||||
input.ContinueRebase()
|
||||
|
||||
|
@ -1,18 +1,74 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/set"
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/branch"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/commit"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/custom_commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests/interactive_rebase"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
// Here is where we lists the actual tests that will run. When you create a new test,
|
||||
// be sure to add it to this list.
|
||||
|
||||
var Tests = []*components.IntegrationTest{
|
||||
var tests = []*components.IntegrationTest{
|
||||
commit.Commit,
|
||||
commit.NewBranch,
|
||||
branch.Suggestions,
|
||||
interactive_rebase.One,
|
||||
custom_commands.Basic,
|
||||
custom_commands.MultiplePrompts,
|
||||
custom_commands.MenuFromCommand,
|
||||
}
|
||||
|
||||
func GetTests() []*components.IntegrationTest {
|
||||
// first we ensure that each test in this directory has actually been added to the above list.
|
||||
testCount := 0
|
||||
|
||||
testNamesSet := set.NewFromSlice(slices.Map(
|
||||
tests,
|
||||
func(test *components.IntegrationTest) string {
|
||||
return test.Name()
|
||||
},
|
||||
))
|
||||
|
||||
missingTestNames := []string{}
|
||||
|
||||
if err := filepath.Walk(filepath.Join(utils.GetLazygitRootDirectory(), "pkg/integration/tests"), func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".go") {
|
||||
// ignoring this current file
|
||||
if filepath.Base(path) == "tests.go" {
|
||||
return nil
|
||||
}
|
||||
|
||||
nameFromPath := components.TestNameFromFilePath(path)
|
||||
if !testNamesSet.Includes(nameFromPath) {
|
||||
missingTestNames = append(missingTestNames, nameFromPath)
|
||||
}
|
||||
testCount++
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(fmt.Sprintf("failed to walk tests: %v", err))
|
||||
}
|
||||
|
||||
if len(missingTestNames) > 0 {
|
||||
panic(fmt.Sprintf("The following tests are missing from the list of tests: %s. You need to add them to `pkg/integration/tests/tests.go`.", strings.Join(missingTestNames, ", ")))
|
||||
}
|
||||
|
||||
if testCount > len(tests) {
|
||||
panic("you have not added all of the tests to the tests list in `pkg/integration/tests/tests.go`")
|
||||
} else if testCount < len(tests) {
|
||||
panic("There are more tests in `pkg/integration/tests/tests.go` than there are test files in the tests directory. Ensure that you only have one test per file and you haven't included the same test twice in the tests list.")
|
||||
}
|
||||
|
||||
return tests
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
@ -28,4 +29,9 @@ type GuiDriver interface {
|
||||
// logs in the actual UI (in the commands panel)
|
||||
LogUI(message string)
|
||||
CheckedOutRef() *models.Branch
|
||||
// the view that appears to the right of the side panel
|
||||
MainView() *gocui.View
|
||||
// the other view that sometimes appears to the right of the side panel
|
||||
// e.g. when we're showing both staged and unstaged changes
|
||||
SecondaryView() *gocui.View
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
disableStartupPopups: true
|
||||
customCommands:
|
||||
- key : 'N'
|
||||
description: 'Add file'
|
||||
command: "echo {{index .PromptResponses 0}} > {{index .PromptResponses 1}}"
|
||||
context: 'files'
|
||||
prompts:
|
||||
- type: 'input'
|
||||
title: 'File name:'
|
||||
- type: 'input'
|
||||
title: 'File content:'
|
||||
gui:
|
||||
theme:
|
||||
activeBorderColor:
|
||||
- green
|
||||
- bold
|
||||
SelectedRangeBgcolor:
|
||||
- reverse
|
@ -1 +0,0 @@
|
||||
test
|
Binary file not shown.
@ -1 +0,0 @@
|
||||
0000000000000000000000000000000000000000 15bdb2c31c825116ad5af06ee25517d90b24f13b CI <CI@example.com> 1617684452 +1000 commit (initial): test
|
@ -1 +0,0 @@
|
||||
0000000000000000000000000000000000000000 15bdb2c31c825116ad5af06ee25517d90b24f13b CI <CI@example.com> 1617684452 +1000 commit (initial): test
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
15bdb2c31c825116ad5af06ee25517d90b24f13b
|
@ -1 +0,0 @@
|
||||
myfile
|
@ -1 +0,0 @@
|
||||
{"KeyEvents":[{"Timestamp":837,"Mod":0,"Key":256,"Ch":78},{"Timestamp":1622,"Mod":0,"Key":256,"Ch":109},{"Timestamp":1798,"Mod":0,"Key":256,"Ch":121},{"Timestamp":1918,"Mod":0,"Key":256,"Ch":102},{"Timestamp":2006,"Mod":0,"Key":256,"Ch":105},{"Timestamp":2078,"Mod":0,"Key":256,"Ch":108},{"Timestamp":2174,"Mod":0,"Key":256,"Ch":101},{"Timestamp":2431,"Mod":0,"Key":13,"Ch":13},{"Timestamp":3246,"Mod":0,"Key":256,"Ch":98},{"Timestamp":3294,"Mod":0,"Key":256,"Ch":108},{"Timestamp":3398,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3462,"Mod":0,"Key":256,"Ch":104},{"Timestamp":3735,"Mod":0,"Key":13,"Ch":13},{"Timestamp":4206,"Mod":0,"Key":256,"Ch":32},{"Timestamp":4421,"Mod":0,"Key":256,"Ch":99},{"Timestamp":4646,"Mod":0,"Key":256,"Ch":116},{"Timestamp":4726,"Mod":0,"Key":256,"Ch":101},{"Timestamp":4886,"Mod":0,"Key":256,"Ch":115},{"Timestamp":4918,"Mod":0,"Key":256,"Ch":116},{"Timestamp":5190,"Mod":0,"Key":13,"Ch":13},{"Timestamp":5550,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":74}]}
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd $1
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
@ -1 +0,0 @@
|
||||
{ "description": "Invoke a custom command that creates a file, and then stage and commit that file", "speed": 5 }
|
@ -1,31 +0,0 @@
|
||||
disableStartupPopups: true
|
||||
customCommands:
|
||||
- key: 'N'
|
||||
description: 'Add file'
|
||||
context: 'localBranches'
|
||||
command: 'echo "{{index .PromptResponses 0}} {{index .PromptResponses 1}} {{index .PromptResponses 2}} {{ .SelectedLocalBranch.Name }}" > output.txt'
|
||||
loadingText: 'Running custom command...'
|
||||
prompts:
|
||||
- type: 'menuFromCommand'
|
||||
title: 'Title'
|
||||
command: 'git log --oneline --pretty=%B'
|
||||
filter: '(?P<commit_message>.*)'
|
||||
valueFormat: '{{ .commit_message }}'
|
||||
labelFormat: '{{ .commit_message | yellow }}'
|
||||
- type: 'input'
|
||||
title: 'Description'
|
||||
initialValue: "{{ if .SelectedLocalBranch.Name }}Branch: #{{ .SelectedLocalBranch.Name }}{{end}}"
|
||||
- type: 'menu'
|
||||
title: 'yes or no'
|
||||
options:
|
||||
- name: 'no'
|
||||
value: 'false'
|
||||
- name: 'yes'
|
||||
value: 'true'
|
||||
gui:
|
||||
theme:
|
||||
activeBorderColor:
|
||||
- green
|
||||
- bold
|
||||
SelectedRangeBgcolor:
|
||||
- reverse
|
@ -1 +0,0 @@
|
||||
test
|
Binary file not shown.
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 ab38b1ca116f77648925d952e731f419db360cdb CI <CI@example.com> 1642201096 +1100 commit (initial): myfile1
|
||||
ab38b1ca116f77648925d952e731f419db360cdb 4fdfedfd9d406506be8b02f5b863dbc08d43cc9f CI <CI@example.com> 1642201096 +1100 commit: myfile2
|
||||
4fdfedfd9d406506be8b02f5b863dbc08d43cc9f 7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 CI <CI@example.com> 1642201096 +1100 commit: myfile3
|
||||
7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 f708d3e3819470a69f6c8562ff1e68eef02f8cac CI <CI@example.com> 1642201096 +1100 commit: myfile4
|
||||
f708d3e3819470a69f6c8562ff1e68eef02f8cac 5428838691c97ac192c8b8e1c3f573d8541a94b6 CI <CI@example.com> 1642201104 +1100 commit: test
|
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 ab38b1ca116f77648925d952e731f419db360cdb CI <CI@example.com> 1642201096 +1100 commit (initial): myfile1
|
||||
ab38b1ca116f77648925d952e731f419db360cdb 4fdfedfd9d406506be8b02f5b863dbc08d43cc9f CI <CI@example.com> 1642201096 +1100 commit: myfile2
|
||||
4fdfedfd9d406506be8b02f5b863dbc08d43cc9f 7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 CI <CI@example.com> 1642201096 +1100 commit: myfile3
|
||||
7dd93a4be3d27d40fbe791d6d77e0d2fedc4d785 f708d3e3819470a69f6c8562ff1e68eef02f8cac CI <CI@example.com> 1642201096 +1100 commit: myfile4
|
||||
f708d3e3819470a69f6c8562ff1e68eef02f8cac 5428838691c97ac192c8b8e1c3f573d8541a94b6 CI <CI@example.com> 1642201104 +1100 commit: test
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x�ÍA
|
||||
ƒ0@Ñ®sŠÙÊL:#)¸ò1™PÁ!")ØÛ×#tûyðS5[Ë¥íª€*©`”¹ë5df¥ 9��T:žùž…KLï⧽ëãÏqzém[õ–ª
@ÂÞ#a/p%Btg='MÿäξeY•Ü.,,·
|
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x�ЮA
|
||||
Т0@Qз9Eі�Ь$�I"BW=F��`СиR"шээм~от�ЕЕЅ[LtъЛЊu�1№�*в�ЬaШ>АFvфCЩ!ЁйђЎЏnЃHђ�fѕтЂдYcBa�QA\U)$q&Пћcнэ8йы8нѕ�лідKYлЭ"�s��и�ЬQ�ЉЎrгОuy*�3н9�
|
@ -1 +0,0 @@
|
||||
5428838691c97ac192c8b8e1c3f573d8541a94b6
|
@ -1 +0,0 @@
|
||||
test1
|
@ -1 +0,0 @@
|
||||
test2
|
@ -1 +0,0 @@
|
||||
test3
|
@ -1 +0,0 @@
|
||||
test4
|
@ -1 +0,0 @@
|
||||
myfile2 Branch: #master haha true master
|
@ -1 +0,0 @@
|
||||
{"KeyEvents":[{"Timestamp":623,"Mod":0,"Key":259,"Ch":0},{"Timestamp":1369,"Mod":0,"Key":256,"Ch":78},{"Timestamp":1904,"Mod":0,"Key":258,"Ch":0},{"Timestamp":2033,"Mod":0,"Key":258,"Ch":0},{"Timestamp":2328,"Mod":0,"Key":13,"Ch":13},{"Timestamp":2848,"Mod":0,"Key":256,"Ch":32},{"Timestamp":3296,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3616,"Mod":0,"Key":127,"Ch":127},{"Timestamp":3824,"Mod":0,"Key":256,"Ch":104},{"Timestamp":3879,"Mod":0,"Key":256,"Ch":97},{"Timestamp":3927,"Mod":0,"Key":256,"Ch":104},{"Timestamp":4000,"Mod":0,"Key":256,"Ch":97},{"Timestamp":4239,"Mod":0,"Key":13,"Ch":13},{"Timestamp":4809,"Mod":0,"Key":258,"Ch":0},{"Timestamp":5024,"Mod":0,"Key":13,"Ch":13},{"Timestamp":5824,"Mod":0,"Key":260,"Ch":0},{"Timestamp":6079,"Mod":0,"Key":256,"Ch":32},{"Timestamp":6376,"Mod":0,"Key":256,"Ch":99},{"Timestamp":6591,"Mod":0,"Key":256,"Ch":116},{"Timestamp":6640,"Mod":0,"Key":256,"Ch":101},{"Timestamp":6816,"Mod":0,"Key":256,"Ch":115},{"Timestamp":6856,"Mod":0,"Key":256,"Ch":116},{"Timestamp":7136,"Mod":0,"Key":13,"Ch":13},{"Timestamp":7487,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":36}]}
|
@ -1,23 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd $1
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test1 > myfile1
|
||||
git add .
|
||||
git commit -am "myfile1"
|
||||
echo test2 > myfile2
|
||||
git add .
|
||||
git commit -am "myfile2"
|
||||
echo test3 > myfile3
|
||||
git add .
|
||||
git commit -am "myfile3"
|
||||
echo test4 > myfile4
|
||||
git add .
|
||||
git commit -am "myfile4"
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"description": "Invoke a custom command that creates a file, and then stage and commit that file. In this case we're using a more customised flow",
|
||||
"speed": 5
|
||||
}
|
@ -0,0 +1 @@
|
||||
blah
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 fe47c0cf0521f8864cd0531ddf35d2f741c14abf CI <CI@example.com> 1660476851 +1000 commit (initial): blah
|
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 fe47c0cf0521f8864cd0531ddf35d2f741c14abf CI <CI@example.com> 1660476851 +1000 commit (initial): blah
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
fe47c0cf0521f8864cd0531ddf35d2f741c14abf
|
@ -0,0 +1 @@
|
||||
baz
|
@ -0,0 +1 @@
|
||||
ref: refs/heads/feature/foo
|
Binary file not shown.
@ -0,0 +1,4 @@
|
||||
0000000000000000000000000000000000000000 d50975554a574b9c66e109927fdb4edfb6bbadb3 CI <CI@example.com> 1660476303 +1000 commit (initial): foo
|
||||
d50975554a574b9c66e109927fdb4edfb6bbadb3 af550d3777f20bf024ad55c9c796e7e85ef32ccb CI <CI@example.com> 1660476303 +1000 commit: bar
|
||||
af550d3777f20bf024ad55c9c796e7e85ef32ccb 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 commit: baz
|
||||
16919871d6b442beac07e1573c557ca433cff356 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 checkout: moving from master to feature/foo
|
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 branch: Created from HEAD
|
@ -0,0 +1,3 @@
|
||||
0000000000000000000000000000000000000000 d50975554a574b9c66e109927fdb4edfb6bbadb3 CI <CI@example.com> 1660476303 +1000 commit (initial): foo
|
||||
d50975554a574b9c66e109927fdb4edfb6bbadb3 af550d3777f20bf024ad55c9c796e7e85ef32ccb CI <CI@example.com> 1660476303 +1000 commit: bar
|
||||
af550d3777f20bf024ad55c9c796e7e85ef32ccb 16919871d6b442beac07e1573c557ca433cff356 CI <CI@example.com> 1660476303 +1000 commit: baz
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
x�ֽA
|
||||
ֲ0@Q׳9ֵל™₪׃1)BW=F&� `˜R"פרצn?~±ײ�<…K�U�$†q-L¡«₪��:’װ¸r
|
||||
1VQ¥„הע·¿l‡y�ַ¼<ץָm�טX›ְ3#�yְ®�YֿI׳?¹«fמ~�+T
|
@ -0,0 +1 @@
|
||||
16919871d6b442beac07e1573c557ca433cff356
|
@ -0,0 +1 @@
|
||||
16919871d6b442beac07e1573c557ca433cff356
|
@ -0,0 +1 @@
|
||||
bar Branch: #feature/foo my branch feature/foo
|
@ -0,0 +1 @@
|
||||
blah
|
@ -0,0 +1,10 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[user]
|
||||
email = CI@example.com
|
||||
name = CI
|
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
||||
.DS_Store
|
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 b97a1d7c0e8dceef724220008962f8512a974ff0 CI <CI@example.com> 1660476863 +1000 commit (initial): blah
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user