mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-02-09 13:47:11 +02:00
Merge pull request #2323 from jesseduffield/migrate-more-tests
This commit is contained in:
commit
6ec88ce8ba
10
go.mod
10
go.mod
@ -18,7 +18,7 @@ require (
|
||||
github.com/integrii/flaggy v1.4.0
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221112081529-154bebde5bb5
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221203233251-eeb9b3fb2494
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
|
||||
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
|
||||
@ -62,14 +62,14 @@ require (
|
||||
github.com/onsi/ginkgo v1.10.3 // indirect
|
||||
github.com/onsi/gomega v1.7.1 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/rivo/uniseg v0.4.2 // indirect
|
||||
github.com/rivo/uniseg v0.4.3 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/xanzy/ssh-agent v0.2.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
|
||||
golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 // indirect
|
||||
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect
|
||||
golang.org/x/sys v0.2.0 // indirect
|
||||
golang.org/x/term v0.2.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/term v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
20
go.sum
20
go.sum
@ -72,8 +72,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
|
||||
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
|
||||
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221112081529-154bebde5bb5 h1:gjk12IHGGASij7/kaKEbOJ6jP3lWZzGvDrE9wxiDMoY=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221112081529-154bebde5bb5/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221203233251-eeb9b3fb2494 h1:SH16ZF/+7S8ZyzDq+sXpOLULBs6lRo6bnYvuRAbhYbk=
|
||||
github.com/jesseduffield/gocui v0.3.1-0.20221203233251-eeb9b3fb2494/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
|
||||
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
|
||||
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=
|
||||
@ -137,8 +137,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
|
||||
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
|
||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||
github.com/samber/lo v1.31.0 h1:Sfa+/064Tdo4SvlohQUQzBhgSer9v/coGvKQI/XLWAM=
|
||||
@ -200,16 +200,16 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -63,26 +63,22 @@ You can pass the KEY_PRESS_DELAY env var to the test runner in order to set a de
|
||||
|
||||
### Running tests in VSCode
|
||||
|
||||
If you've opened an integration test file in your editor you can run that file by bringing up the command panel with `cmd+shift+p` and typing 'run task', then selecting the test task you want to run
|
||||
If you've opened an integration test file in your editor you can run that file by bringing up the command panel with `cmd+shift+p` and typing 'run task', then selecting the test task you want to run
|
||||
|
||||
![image](https://user-images.githubusercontent.com/8456633/201500427-b86e129f-5f35-4d55-b7bd-fff5d8e4a04e.png)
|
||||
![image](https://user-images.githubusercontent.com/8456633/201500431-903deb8c-c210-4054-8514-ab7088c7a839.png)
|
||||
The test will run in a VSCode terminal:
|
||||
![image](https://user-images.githubusercontent.com/8456633/201500446-b87abf11-9653-438f-8a9a-e0bf8abdb7ee.png)
|
||||
|
||||
### Snapshots
|
||||
|
||||
At the moment (this is subject to change) each test has a snapshot repo created after running for the first time. These snapshots live in `test/integration_new`, in folders named 'expected' (alongside the 'actual' folders which contain the resulting repo from the last test run). Whenever you run a test, the resultant repo will be compared against the snapshot repo and if they're different, you'll be asked whether you want to update the snapshot. If you want to update a snapshot without being prompted you can pass MODE=update to the test runner.
|
||||
|
||||
### Sandbox mode
|
||||
|
||||
Say you want to do a manual test of how lazygit handles merge-conflicts, but you can't be bothered actually finding a way to create merge conflicts in a repo. To make your life easier, you can simply run a merge-conflicts test in sandbox mode, meaning the setup step is run for you, and then instead of the test driving the lazygit session, you're allowed to drive it yourself.
|
||||
|
||||
To run a test in sandbox mode you can press 's' on a test in the test TUI or in the test runner pass MODE=sandbox or the --sandbox argument.
|
||||
To run a test in sandbox mode you can press 's' on a test in the test TUI or in the test runner pass the --sandbox argument.
|
||||
|
||||
## Migration process
|
||||
|
||||
At the time of writing, most tests are created under an old approach, where you would record yourself in a lazygit session and then the test would replay the keybindings with the same timestamps. This old approach is great for writing tests quickly, but is much harder to maintain. It has to rely entirely on snapshots to determining if a test passes or fails, and can't do assertions along the way. It's also harder to grok what's the intention behind certain actions that take place within the test (e.g. was the recorder intentionally switching to another panel or was that just a misclick?).
|
||||
At the time of writing, most tests are created under an old approach, where you would record yourself in a lazygit session and then the test would replay the keybindings with the same timestamps. This old approach is great for writing tests quickly, but is much harder to maintain. It has to rely on snapshots to determining if a test passes or fails, and can't do assertions along the way. It's also harder to grok what's the intention behind certain actions that take place within the test (e.g. was the recorder intentionally switching to another panel or was that just a misclick?).
|
||||
|
||||
At the moment, all the deprecated test code lives in pkg/integration/deprecated. Hopefully in the very near future we migrate everything across so that we don't need to maintain two systems.
|
||||
|
||||
@ -92,6 +88,6 @@ We should never write any new tests under the old method, and if a given test br
|
||||
go run pkg/integration/deprecated/cmd/tui/main.go
|
||||
```
|
||||
|
||||
The tests in the old format live in test/integration. In the old format, test definitions are co-located with the snapshots. The setup step is done in a `setup.sh` shell script and the `recording.json` file contains the recorded keypresses to be replayed during the test.
|
||||
The tests in the old format live in test/integration. In the old format, test definitions are co-located with snapshots. The setup step is done in a `setup.sh` shell script and the `recording.json` file contains the recorded keypresses to be replayed during the test.
|
||||
|
||||
If you have rewritten an integration test under the new pattern, be sure to delete the old integration test directory.
|
||||
|
@ -29,19 +29,12 @@ func RunCLI(testNames []string, slow bool, sandbox bool) {
|
||||
keyPressDelay = SLOW_KEY_PRESS_DELAY
|
||||
}
|
||||
|
||||
var mode components.Mode
|
||||
if sandbox {
|
||||
mode = components.SANDBOX
|
||||
} else {
|
||||
mode = getModeFromEnv()
|
||||
}
|
||||
|
||||
err := components.RunTests(
|
||||
getTestsToRun(testNames),
|
||||
log.Printf,
|
||||
runCmdInTerminal,
|
||||
runAndPrintFatalError,
|
||||
mode,
|
||||
sandbox,
|
||||
keyPressDelay,
|
||||
1,
|
||||
)
|
||||
@ -95,22 +88,6 @@ func runCmdInTerminal(cmd *exec.Cmd) error {
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func getModeFromEnv() components.Mode {
|
||||
switch os.Getenv("MODE") {
|
||||
case "", "ask":
|
||||
return components.ASK_TO_UPDATE_SNAPSHOT
|
||||
case "check":
|
||||
return components.CHECK_SNAPSHOT
|
||||
case "update":
|
||||
return components.UPDATE_SNAPSHOT
|
||||
case "sandbox":
|
||||
return components.SANDBOX
|
||||
default:
|
||||
log.Fatalf("unknown test mode: %s, must be one of [ask, check, update, sandbox]", os.Getenv("MODE"))
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func tryConvert(numStr string, defaultVal int) int {
|
||||
num, err := strconv.Atoi(numStr)
|
||||
if err != nil {
|
||||
|
@ -46,7 +46,7 @@ func TestIntegration(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
},
|
||||
components.CHECK_SNAPSHOT,
|
||||
false,
|
||||
0,
|
||||
// allowing two attempts at the test. If a test fails intermittently,
|
||||
// there may be a concurrency issue that we need to resolve.
|
||||
|
@ -82,7 +82,7 @@ func RunTUI() {
|
||||
return nil
|
||||
}
|
||||
|
||||
suspendAndRunTest(currentTest, components.SANDBOX, 0)
|
||||
suspendAndRunTest(currentTest, true, 0)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
@ -95,7 +95,7 @@ func RunTUI() {
|
||||
return nil
|
||||
}
|
||||
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, 0)
|
||||
suspendAndRunTest(currentTest, false, 0)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
@ -108,7 +108,7 @@ func RunTUI() {
|
||||
return nil
|
||||
}
|
||||
|
||||
suspendAndRunTest(currentTest, components.ASK_TO_UPDATE_SNAPSHOT, SLOW_KEY_PRESS_DELAY)
|
||||
suspendAndRunTest(currentTest, false, SLOW_KEY_PRESS_DELAY)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
@ -268,12 +268,12 @@ func (self *app) wrapEditor(f func(v *gocui.View, key gocui.Key, ch rune, mod go
|
||||
}
|
||||
}
|
||||
|
||||
func suspendAndRunTest(test *components.IntegrationTest, mode components.Mode, keyPressDelay int) {
|
||||
func suspendAndRunTest(test *components.IntegrationTest, sandbox bool, keyPressDelay int) {
|
||||
if err := gocui.Screen.Suspend(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
runTuiTest(test, mode, keyPressDelay)
|
||||
runTuiTest(test, sandbox, keyPressDelay)
|
||||
|
||||
fmt.Fprintf(os.Stdout, "\n%s", style.FgGreen.Sprint("press enter to return"))
|
||||
fmt.Scanln() // wait for enter press
|
||||
@ -367,13 +367,13 @@ func quit(g *gocui.Gui, v *gocui.View) error {
|
||||
return gocui.ErrQuit
|
||||
}
|
||||
|
||||
func runTuiTest(test *components.IntegrationTest, mode components.Mode, keyPressDelay int) {
|
||||
func runTuiTest(test *components.IntegrationTest, sandbox bool, keyPressDelay int) {
|
||||
err := components.RunTests(
|
||||
[]*components.IntegrationTest{test},
|
||||
log.Printf,
|
||||
runCmdInTerminal,
|
||||
runAndPrintError,
|
||||
mode,
|
||||
sandbox,
|
||||
keyPressDelay,
|
||||
1,
|
||||
)
|
||||
|
@ -2,6 +2,8 @@ package components
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -56,6 +58,16 @@ func NotContains(target string) *matcher {
|
||||
}}
|
||||
}
|
||||
|
||||
func MatchesRegexp(regexStr string) *matcher {
|
||||
return &matcher{testFn: func(value string) (bool, string) {
|
||||
matched, err := regexp.MatchString(regexStr, value)
|
||||
if err != nil {
|
||||
return false, fmt.Sprintf("Unexpected error parsing regular expression '%s': %s", regexStr, err.Error())
|
||||
}
|
||||
return matched, fmt.Sprintf("Expected '%s' to match regular expression '%s'", value, regexStr)
|
||||
}}
|
||||
}
|
||||
|
||||
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)
|
||||
@ -248,3 +260,19 @@ func (self *Assert) assertWithRetries(test func() (bool, string)) {
|
||||
func (self *Assert) Fail(message string) {
|
||||
self.gui.Fail(message)
|
||||
}
|
||||
|
||||
// This does _not_ check the files panel, it actually checks the filesystem
|
||||
func (self *Assert) FileSystemPathPresent(path string) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil, fmt.Sprintf("Expected path '%s' to exist, but it does not", path)
|
||||
})
|
||||
}
|
||||
|
||||
// This does _not_ check the files panel, it actually checks the filesystem
|
||||
func (self *Assert) FileSystemPathNotPresent(path string) {
|
||||
self.assertWithRetries(func() (bool, string) {
|
||||
_, err := os.Stat(path)
|
||||
return os.IsNotExist(err), fmt.Sprintf("Expected path '%s' to not exist, but it does", path)
|
||||
})
|
||||
}
|
||||
|
@ -18,29 +18,12 @@ const (
|
||||
SANDBOX_ENV_VAR = "SANDBOX"
|
||||
)
|
||||
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
// Default: if a snapshot test fails, the we'll be asked whether we want to update it
|
||||
ASK_TO_UPDATE_SNAPSHOT Mode = iota
|
||||
// fails the test if the snapshots don't match
|
||||
CHECK_SNAPSHOT
|
||||
// runs the test and updates the snapshot
|
||||
UPDATE_SNAPSHOT
|
||||
// This just makes use of the setup step of the test to get you into
|
||||
// a lazygit session. Then you'll be able to do whatever you want. Useful
|
||||
// when you want to test certain things without needing to manually set
|
||||
// up the situation yourself.
|
||||
// fails the test if the snapshots don't match
|
||||
SANDBOX
|
||||
)
|
||||
|
||||
func RunTests(
|
||||
tests []*IntegrationTest,
|
||||
logf func(format string, formatArgs ...interface{}),
|
||||
runCmd func(cmd *exec.Cmd) error,
|
||||
testWrapper func(test *IntegrationTest, f func() error),
|
||||
mode Mode,
|
||||
sandbox bool,
|
||||
keyPressDelay int,
|
||||
maxAttempts int,
|
||||
) error {
|
||||
@ -65,7 +48,7 @@ func RunTests(
|
||||
)
|
||||
|
||||
for i := 0; i < maxAttempts; i++ {
|
||||
err := runTest(test, paths, projectRootDir, logf, runCmd, mode, keyPressDelay)
|
||||
err := runTest(test, paths, projectRootDir, logf, runCmd, sandbox, keyPressDelay)
|
||||
if err != nil {
|
||||
if i == maxAttempts-1 {
|
||||
return err
|
||||
@ -89,7 +72,7 @@ func runTest(
|
||||
projectRootDir string,
|
||||
logf func(format string, formatArgs ...interface{}),
|
||||
runCmd func(cmd *exec.Cmd) error,
|
||||
mode Mode,
|
||||
sandbox bool,
|
||||
keyPressDelay int,
|
||||
) error {
|
||||
if test.Skip() {
|
||||
@ -103,7 +86,7 @@ func runTest(
|
||||
return err
|
||||
}
|
||||
|
||||
cmd, err := getLazygitCommand(test, paths, projectRootDir, mode, keyPressDelay)
|
||||
cmd, err := getLazygitCommand(test, paths, projectRootDir, sandbox, keyPressDelay)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -113,7 +96,7 @@ func runTest(
|
||||
return err
|
||||
}
|
||||
|
||||
return HandleSnapshots(paths, logf, test, mode)
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareTestDir(
|
||||
@ -151,7 +134,7 @@ func createFixture(test *IntegrationTest, paths Paths) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, mode Mode, keyPressDelay int) (*exec.Cmd, error) {
|
||||
func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, sandbox bool, keyPressDelay int) (*exec.Cmd, error) {
|
||||
osCommand := oscommands.NewDummyOSCommand()
|
||||
|
||||
templateConfigDir := filepath.Join(rootDir, "test", "default_test_config")
|
||||
@ -170,7 +153,7 @@ func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, mode
|
||||
cmdObj := osCommand.Cmd.New(cmdStr)
|
||||
|
||||
cmdObj.AddEnvVars(fmt.Sprintf("%s=%s", TEST_NAME_ENV_VAR, test.Name()))
|
||||
if mode == SANDBOX {
|
||||
if sandbox {
|
||||
cmdObj.AddEnvVars(fmt.Sprintf("%s=%s", "SANDBOX", "true"))
|
||||
}
|
||||
|
||||
|
@ -1,372 +0,0 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// This creates and compares integration test snapshots.
|
||||
|
||||
type (
|
||||
logf func(format string, formatArgs ...interface{})
|
||||
)
|
||||
|
||||
func HandleSnapshots(paths Paths, logf logf, test *IntegrationTest, mode Mode) error {
|
||||
return NewSnapshotter(paths, logf, test, mode).
|
||||
handleSnapshots()
|
||||
}
|
||||
|
||||
type Snapshotter struct {
|
||||
paths Paths
|
||||
logf logf
|
||||
test *IntegrationTest
|
||||
mode Mode
|
||||
}
|
||||
|
||||
func NewSnapshotter(
|
||||
paths Paths,
|
||||
logf logf,
|
||||
test *IntegrationTest,
|
||||
mode Mode,
|
||||
) *Snapshotter {
|
||||
return &Snapshotter{
|
||||
paths: paths,
|
||||
logf: logf,
|
||||
test: test,
|
||||
mode: mode,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Snapshotter) handleSnapshots() error {
|
||||
switch self.mode {
|
||||
case UPDATE_SNAPSHOT:
|
||||
return self.handleUpdate()
|
||||
case CHECK_SNAPSHOT:
|
||||
return self.handleCheck()
|
||||
case ASK_TO_UPDATE_SNAPSHOT:
|
||||
return self.handleAskToUpdate()
|
||||
case SANDBOX:
|
||||
self.logf("Sandbox session exited")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Snapshotter) handleUpdate() error {
|
||||
if err := self.updateSnapshot(); err != nil {
|
||||
return err
|
||||
}
|
||||
self.logf("Test passed: %s", self.test.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Snapshotter) handleCheck() error {
|
||||
self.logf("Comparing snapshots")
|
||||
if err := self.compareSnapshots(); err != nil {
|
||||
return err
|
||||
}
|
||||
self.logf("Test passed: %s", self.test.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Snapshotter) handleAskToUpdate() error {
|
||||
if _, err := os.Stat(self.paths.Expected()); os.IsNotExist(err) {
|
||||
if err := self.updateSnapshot(); err != nil {
|
||||
return err
|
||||
}
|
||||
self.logf("No existing snapshot found for %s. Created snapshot.", self.test.Name())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
self.logf("Comparing snapshots...")
|
||||
if err := self.compareSnapshots(); err != nil {
|
||||
self.logf("%s", err)
|
||||
|
||||
// prompt user whether to update the snapshot (Y/N)
|
||||
if promptUserToUpdateSnapshot() {
|
||||
if err := self.updateSnapshot(); err != nil {
|
||||
return err
|
||||
}
|
||||
self.logf("Snapshot updated: %s", self.test.Name())
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
self.logf("Test passed: %s", self.test.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Snapshotter) updateSnapshot() error {
|
||||
// create/update snapshot
|
||||
err := oscommands.CopyDir(self.paths.Actual(), self.paths.Expected())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := renameSpecialPaths(self.paths.Expected()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *Snapshotter) compareSnapshots() error {
|
||||
// there are a couple of reasons we're not generating the snapshot in expectedDir directly:
|
||||
// Firstly we don't want to have to revert our .git file back to .git_keep.
|
||||
// Secondly, the act of calling git commands like 'git status' actually changes the index
|
||||
// for some reason, and we don't want to leave your lazygit working tree dirty as a result.
|
||||
expectedDirCopy := filepath.Join(os.TempDir(), "expected_dir_test", self.test.Name())
|
||||
err := oscommands.CopyDir(self.paths.Expected(), expectedDirCopy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := os.RemoveAll(expectedDirCopy)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := restoreSpecialPaths(expectedDirCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = validateSameRepos(expectedDirCopy, self.paths.Actual())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// iterate through each repo in the expected dir and comparet to the corresponding repo in the actual dir
|
||||
expectedFiles, err := ioutil.ReadDir(expectedDirCopy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range expectedFiles {
|
||||
if !f.IsDir() {
|
||||
return errors.New("unexpected file (as opposed to directory) in integration test 'expected' directory")
|
||||
}
|
||||
|
||||
// get corresponding file name from actual dir
|
||||
actualRepoPath := filepath.Join(self.paths.Actual(), f.Name())
|
||||
expectedRepoPath := filepath.Join(expectedDirCopy, f.Name())
|
||||
|
||||
actualRepo, expectedRepo, err := generateSnapshots(actualRepoPath, expectedRepoPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if expectedRepo != actualRepo {
|
||||
// get the log file and print it
|
||||
bytes, err := os.ReadFile(filepath.Join(self.paths.Config(), "development.log"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.logf("%s", string(bytes))
|
||||
|
||||
return errors.New(getDiff(f.Name(), expectedRepo, actualRepo))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func promptUserToUpdateSnapshot() bool {
|
||||
fmt.Println("Test failed. Update snapshot? (y/n)")
|
||||
var input string
|
||||
fmt.Scanln(&input)
|
||||
return input == "y"
|
||||
}
|
||||
|
||||
func generateSnapshots(actualDir string, expectedDir string) (string, string, error) {
|
||||
actual, err := generateSnapshot(actualDir)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
expected, err := generateSnapshot(expectedDir)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return actual, expected, nil
|
||||
}
|
||||
|
||||
// note that we don't actually store this snapshot in the lazygit repo.
|
||||
// Instead we store the whole expected git repo of our test, so that
|
||||
// we can easily change what we want to compare without needing to regenerate
|
||||
// snapshots for each test.
|
||||
func generateSnapshot(dir string) (string, error) {
|
||||
osCommand := oscommands.NewDummyOSCommand()
|
||||
|
||||
_, err := os.Stat(filepath.Join(dir, ".git"))
|
||||
if err != nil {
|
||||
return "git directory not found", nil
|
||||
}
|
||||
|
||||
snapshot := ""
|
||||
|
||||
cmdStrs := []string{
|
||||
`remote show -n origin`, // remote branches
|
||||
// TODO: find a way to bring this back without breaking tests
|
||||
// `ls-remote origin`,
|
||||
`status`, // file tree
|
||||
`log --pretty=%B|%an|%ae -p -1`, // log
|
||||
`tag -n`, // tags
|
||||
`stash list`, // stash
|
||||
`submodule foreach 'git status'`, // submodule status
|
||||
`submodule foreach 'git log --pretty=%B -p -1'`, // submodule log
|
||||
`submodule foreach 'git tag -n'`, // submodule tags
|
||||
`submodule foreach 'git stash list'`, // submodule stash
|
||||
}
|
||||
|
||||
for _, cmdStr := range cmdStrs {
|
||||
// ignoring error for now. If there's an error it could be that there are no results
|
||||
output, _ := osCommand.Cmd.New(fmt.Sprintf("git -C %s %s", dir, cmdStr)).RunWithOutput()
|
||||
|
||||
snapshot += fmt.Sprintf("git %s:\n%s\n", cmdStr, output)
|
||||
}
|
||||
|
||||
snapshot += "files in repo:\n"
|
||||
err = filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.IsDir() {
|
||||
if f.Name() == ".git" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
bytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relativePath, err := filepath.Rel(dir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshot += fmt.Sprintf("path: %s\ncontent:\n%s\n", relativePath, string(bytes))
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return snapshot, nil
|
||||
}
|
||||
|
||||
func getPathsToRename(dir string, needle string, contains string) []string {
|
||||
pathsToRename := []string{}
|
||||
|
||||
err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.Name() == needle && (contains == "" || strings.Contains(path, contains)) {
|
||||
pathsToRename = append(pathsToRename, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return pathsToRename
|
||||
}
|
||||
|
||||
var specialPathMappings = []struct{ original, new, contains string }{
|
||||
// git refuses to track .git or .gitmodules in subdirectories so we need to rename them
|
||||
{".git", ".git_keep", ""},
|
||||
{".gitmodules", ".gitmodules_keep", ""},
|
||||
// we also need git to ignore the contents of our test gitignore files so that
|
||||
// we actually commit files that are ignored within the test.
|
||||
{".gitignore", "lg_ignore_file", ""},
|
||||
// this is the .git/info/exclude file. We're being a little more specific here
|
||||
// so that we don't accidentally mess with some other file named 'exclude' in the test.
|
||||
{"exclude", "lg_exclude_file", ".git/info/exclude"},
|
||||
}
|
||||
|
||||
func renameSpecialPaths(dir string) error {
|
||||
for _, specialPath := range specialPathMappings {
|
||||
for _, path := range getPathsToRename(dir, specialPath.original, specialPath.contains) {
|
||||
err := os.Rename(path, filepath.Join(filepath.Dir(path), specialPath.new))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func restoreSpecialPaths(dir string) error {
|
||||
for _, specialPath := range specialPathMappings {
|
||||
for _, path := range getPathsToRename(dir, specialPath.new, specialPath.contains) {
|
||||
err := os.Rename(path, filepath.Join(filepath.Dir(path), specialPath.original))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validates that the actual and expected dirs have the same repo names (doesn't actually check the contents of the repos)
|
||||
func validateSameRepos(expectedDir string, actualDir string) error {
|
||||
// iterate through each repo in the expected dir and compare to the corresponding repo in the actual dir
|
||||
expectedFiles, err := ioutil.ReadDir(expectedDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var actualFiles []os.FileInfo
|
||||
actualFiles, err = ioutil.ReadDir(actualDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
expectedFileNames := slices.Map(expectedFiles, getFileName)
|
||||
actualFileNames := slices.Map(actualFiles, getFileName)
|
||||
if !slices.Equal(expectedFileNames, actualFileNames) {
|
||||
return fmt.Errorf("expected and actual repo dirs do not match: expected: %s, actual: %s", expectedFileNames, actualFileNames)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFileName(f os.FileInfo) string {
|
||||
return f.Name()
|
||||
}
|
||||
|
||||
func getDiff(prefix string, expected string, actual string) string {
|
||||
mockT := &MockTestingT{}
|
||||
assert.Equal(mockT, expected, actual, fmt.Sprintf("Unexpected %s. Expected:\n%s\nActual:\n%s\n", prefix, expected, actual))
|
||||
return mockT.err
|
||||
}
|
||||
|
||||
type MockTestingT struct {
|
||||
err string
|
||||
}
|
||||
|
||||
func (self *MockTestingT) Errorf(format string, args ...interface{}) {
|
||||
self.err += fmt.Sprintf(format, args...)
|
||||
}
|
34
pkg/integration/tests/commit/commit_multiline.go
Normal file
34
pkg/integration/tests/commit/commit_multiline.go
Normal file
@ -0,0 +1,34 @@
|
||||
package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var CommitMultiline = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Commit with a multi-line commit message",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("myfile", "myfile content")
|
||||
},
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(0)
|
||||
|
||||
input.PrimaryAction()
|
||||
input.PressKeys(keys.Files.CommitChanges)
|
||||
|
||||
input.Type("first line")
|
||||
input.PressKeys(keys.Universal.AppendNewline)
|
||||
input.PressKeys(keys.Universal.AppendNewline)
|
||||
input.Type("third line")
|
||||
input.Confirm()
|
||||
|
||||
assert.CommitCount(1)
|
||||
assert.MatchHeadCommitMessage(Equals("first line"))
|
||||
|
||||
input.SwitchToCommitsWindow()
|
||||
assert.MatchMainViewContent(MatchesRegexp("first line\n\\s*\n\\s*third line"))
|
||||
},
|
||||
})
|
37
pkg/integration/tests/commit/revert.go
Normal file
37
pkg/integration/tests/commit/revert.go
Normal file
@ -0,0 +1,37 @@
|
||||
package commit
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var Revert = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Reverts a commit",
|
||||
ExtraCmdArgs: "",
|
||||
Skip: false,
|
||||
SetupConfig: func(config *config.AppConfig) {},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
shell.CreateFile("myfile", "myfile content")
|
||||
shell.GitAddAll()
|
||||
shell.Commit("first commit")
|
||||
},
|
||||
Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) {
|
||||
assert.CommitCount(1)
|
||||
|
||||
input.SwitchToCommitsWindow()
|
||||
|
||||
input.PressKeys(keys.Commits.RevertCommit)
|
||||
assert.InConfirm()
|
||||
assert.MatchCurrentViewTitle(Equals("Revert commit"))
|
||||
assert.MatchCurrentViewContent(MatchesRegexp("Are you sure you want to revert \\w+?"))
|
||||
input.Confirm()
|
||||
|
||||
assert.CommitCount(2)
|
||||
assert.MatchHeadCommitMessage(Contains("Revert \"first commit\""))
|
||||
input.PreviousItem()
|
||||
assert.MatchMainViewContent(Contains("-myfile content"))
|
||||
assert.FileSystemPathNotPresent("myfile")
|
||||
|
||||
input.Wait(10)
|
||||
},
|
||||
})
|
@ -36,6 +36,8 @@ var tests = []*components.IntegrationTest{
|
||||
cherry_pick.CherryPick,
|
||||
cherry_pick.CherryPickConflicts,
|
||||
commit.Commit,
|
||||
commit.CommitMultiline,
|
||||
commit.Revert,
|
||||
commit.NewBranch,
|
||||
commit.Staged,
|
||||
commit.Unstaged,
|
||||
|
@ -1,3 +0,0 @@
|
||||
first line
|
||||
|
||||
third line
|
@ -1 +0,0 @@
|
||||
ref: refs/heads/master
|
@ -1,10 +0,0 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[user]
|
||||
email = CI@example.com
|
||||
name = CI
|
@ -1 +0,0 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
# 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
|
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 176069f0ded1db43eecb3b629a6077dba6c68295 CI <CI@example.com> 1645602422 +1100 commit (initial): myfile1
|
||||
176069f0ded1db43eecb3b629a6077dba6c68295 9f1b5440546da24daad7014ccf3e1f4d81f9414b CI <CI@example.com> 1645602422 +1100 commit: myfile2
|
||||
9f1b5440546da24daad7014ccf3e1f4d81f9414b 3933a268c502712421b7bfa04888319d6f108574 CI <CI@example.com> 1645602422 +1100 commit: myfile3
|
||||
3933a268c502712421b7bfa04888319d6f108574 37128a3020849daa0847462d14c384cc74c42ae0 CI <CI@example.com> 1645602422 +1100 commit: myfile4
|
||||
37128a3020849daa0847462d14c384cc74c42ae0 574013716a7f007a27b647b90cdbc78d006d792b CI <CI@example.com> 1645602427 +1100 commit: first line
|
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 176069f0ded1db43eecb3b629a6077dba6c68295 CI <CI@example.com> 1645602422 +1100 commit (initial): myfile1
|
||||
176069f0ded1db43eecb3b629a6077dba6c68295 9f1b5440546da24daad7014ccf3e1f4d81f9414b CI <CI@example.com> 1645602422 +1100 commit: myfile2
|
||||
9f1b5440546da24daad7014ccf3e1f4d81f9414b 3933a268c502712421b7bfa04888319d6f108574 CI <CI@example.com> 1645602422 +1100 commit: myfile3
|
||||
3933a268c502712421b7bfa04888319d6f108574 37128a3020849daa0847462d14c384cc74c42ae0 CI <CI@example.com> 1645602422 +1100 commit: myfile4
|
||||
37128a3020849daa0847462d14c384cc74c42ae0 574013716a7f007a27b647b90cdbc78d006d792b CI <CI@example.com> 1645602427 +1100 commit: first line
|
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x�ÍA
|
||||
ƒ0@Ñ®sŠÙÊL:Ž))¸ò1™PÁ!")ØÛ×#tûyðS5[Ë¥íª€*©`”¹hÈÌJAr ©ô<ó=—˜:ï⧽ëãÏqzém[õ–ª
@Â� gïáJ„èÎzNšþÉ�}˲*¹.Ñ,¹
|
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�ŽK
|
||||
Ã0D»ö)¼/YVbJ)d•c(²BùáºÐã7Ðt5ÃcŒìëš«Eè.µ¨Zì„=E7%�ÔŒ€¬,Ó0¥I‘ÉûQÍÁE·j}pÙB¤.1Ÿ¨ÅäH|$‘@B§†ßuÞ‹í{~x=½É¾>¬k©i ƒ½:`NzžªúçÜL¹¼ª]ò¦ÆÔ9—ôë_�!?’
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
574013716a7f007a27b647b90cdbc78d006d792b
|
@ -1 +0,0 @@
|
||||
test1
|
@ -1 +0,0 @@
|
||||
test2
|
@ -1 +0,0 @@
|
||||
test3
|
@ -1 +0,0 @@
|
||||
test4
|
@ -1 +0,0 @@
|
||||
test5
|
@ -1 +0,0 @@
|
||||
{"KeyEvents":[{"Timestamp":931,"Mod":0,"Key":256,"Ch":32},{"Timestamp":1467,"Mod":0,"Key":256,"Ch":99},{"Timestamp":2035,"Mod":0,"Key":256,"Ch":102},{"Timestamp":2090,"Mod":0,"Key":256,"Ch":105},{"Timestamp":2162,"Mod":0,"Key":256,"Ch":114},{"Timestamp":2259,"Mod":0,"Key":256,"Ch":115},{"Timestamp":2314,"Mod":0,"Key":256,"Ch":116},{"Timestamp":2411,"Mod":0,"Key":256,"Ch":32},{"Timestamp":2546,"Mod":0,"Key":256,"Ch":108},{"Timestamp":2578,"Mod":0,"Key":256,"Ch":105},{"Timestamp":2627,"Mod":0,"Key":256,"Ch":110},{"Timestamp":2691,"Mod":0,"Key":256,"Ch":101},{"Timestamp":3358,"Mod":4,"Key":13,"Ch":13},{"Timestamp":3577,"Mod":4,"Key":13,"Ch":13},{"Timestamp":3810,"Mod":0,"Key":256,"Ch":116},{"Timestamp":3874,"Mod":0,"Key":256,"Ch":104},{"Timestamp":3914,"Mod":0,"Key":256,"Ch":105},{"Timestamp":3986,"Mod":0,"Key":256,"Ch":114},{"Timestamp":4107,"Mod":0,"Key":256,"Ch":100},{"Timestamp":4195,"Mod":0,"Key":256,"Ch":32},{"Timestamp":4291,"Mod":0,"Key":256,"Ch":108},{"Timestamp":4322,"Mod":0,"Key":256,"Ch":105},{"Timestamp":4370,"Mod":0,"Key":256,"Ch":110},{"Timestamp":4426,"Mod":0,"Key":256,"Ch":101},{"Timestamp":4603,"Mod":0,"Key":13,"Ch":13},{"Timestamp":5267,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":74}]}
|
@ -1,24 +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"
|
||||
echo test5 > myfile5
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"description": "stage a file and commit the change with a multiline commit message",
|
||||
"speed": 15
|
||||
}
|
@ -1 +0,0 @@
|
||||
revert commit
|
@ -1 +0,0 @@
|
||||
ref: refs/heads/master
|
@ -1,10 +0,0 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[user]
|
||||
email = CI@example.com
|
||||
name = CI
|
@ -1 +0,0 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
# 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
|
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 9eaae8f342ca71c060b760870a715a6303905935 CI <CI@example.com> 1643148217 +1100 commit (initial): file0
|
||||
9eaae8f342ca71c060b760870a715a6303905935 1727eeb6864e52a8967a1a494099359dbdfcc235 CI <CI@example.com> 1643148217 +1100 commit: file1
|
||||
1727eeb6864e52a8967a1a494099359dbdfcc235 b781ffd3aa940dde39f73c9149b67e2b128de085 CI <CI@example.com> 1643148217 +1100 commit: file2
|
||||
b781ffd3aa940dde39f73c9149b67e2b128de085 ab15072795e72a2061bc40060494c3ca2138b297 CI <CI@example.com> 1643148219 +1100 revert: Revert "file1"
|
||||
ab15072795e72a2061bc40060494c3ca2138b297 7e03c9a9538a907c936de5c9a2154707b9ee541c CI <CI@example.com> 1643148227 +1100 commit (amend): revert commit
|
@ -1,5 +0,0 @@
|
||||
0000000000000000000000000000000000000000 9eaae8f342ca71c060b760870a715a6303905935 CI <CI@example.com> 1643148217 +1100 commit (initial): file0
|
||||
9eaae8f342ca71c060b760870a715a6303905935 1727eeb6864e52a8967a1a494099359dbdfcc235 CI <CI@example.com> 1643148217 +1100 commit: file1
|
||||
1727eeb6864e52a8967a1a494099359dbdfcc235 b781ffd3aa940dde39f73c9149b67e2b128de085 CI <CI@example.com> 1643148217 +1100 commit: file2
|
||||
b781ffd3aa940dde39f73c9149b67e2b128de085 ab15072795e72a2061bc40060494c3ca2138b297 CI <CI@example.com> 1643148219 +1100 revert: Revert "file1"
|
||||
ab15072795e72a2061bc40060494c3ca2138b297 7e03c9a9538a907c936de5c9a2154707b9ee541c CI <CI@example.com> 1643148227 +1100 commit (amend): revert commit
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x+)JMU03c040031QHËÌI5`°±º²àŸÖ¶wÁ‡Þw.½ùhïTÓ[H
|
||||
Œ$x~5(í;÷rÕ¢ðªþ–WÚó-Ôö9
|
@ -1,4 +0,0 @@
|
||||
x}ŽK
|
||||
1]ç½$�O'�A„YÍ1òé `œ!DñøèÚmQõxymí6@Iy�tDfëÙ:MÒ„Xl
|
||||
ŠÈ¡-šŒ"4)c[ìü�œÇZ‹Ž1Y
|
||||
ëP�ÎMHäX%T¾°ôVÄ縮æ¦y¹ð;¶íΧ¼¶3 ½ï*pD”Rìt?5ø¿®ÜO�_Ü|3ñÂ<
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x��K
|
||||
Т0@]чй��ќ& "tеcL� [J�o�ріёМВѕО
/убI�8�ZЈж�мrЋо@в" ЁЭ�кљ�їF�"9Ppт�)�ШР.9��ѕЉцкJAыЦk;є4ыћ4?хЫ}_хVЖўа�GQ_�Q'=Ї�ќЉЋЖЌ�ъЁ\9Ј
|
@ -1,2 +0,0 @@
|
||||
x+)JMU03c040031QHヒフI5`ーアコイ燹ヨカwチ�w.ス��モ[H
|
||||
矢y�5�来ミ(桍ァ^-ンW(x9
|
@ -1 +0,0 @@
|
||||
7e03c9a9538a907c936de5c9a2154707b9ee541c
|
@ -1 +0,0 @@
|
||||
test0
|
@ -1 +0,0 @@
|
||||
test2
|
@ -1 +0,0 @@
|
||||
{"KeyEvents":[{"Timestamp":614,"Mod":0,"Key":259,"Ch":0},{"Timestamp":749,"Mod":0,"Key":259,"Ch":0},{"Timestamp":980,"Mod":0,"Key":258,"Ch":0},{"Timestamp":1219,"Mod":0,"Key":256,"Ch":116},{"Timestamp":1854,"Mod":0,"Key":13,"Ch":13},{"Timestamp":2469,"Mod":0,"Key":257,"Ch":0},{"Timestamp":2725,"Mod":0,"Key":257,"Ch":0},{"Timestamp":3892,"Mod":0,"Key":256,"Ch":114},{"Timestamp":5421,"Mod":2,"Key":21,"Ch":21},{"Timestamp":5854,"Mod":2,"Key":21,"Ch":21},{"Timestamp":6197,"Mod":2,"Key":21,"Ch":21},{"Timestamp":6469,"Mod":2,"Key":21,"Ch":21},{"Timestamp":6781,"Mod":2,"Key":21,"Ch":21},{"Timestamp":7078,"Mod":2,"Key":21,"Ch":21},{"Timestamp":7907,"Mod":0,"Key":256,"Ch":114},{"Timestamp":7989,"Mod":0,"Key":256,"Ch":101},{"Timestamp":8148,"Mod":0,"Key":256,"Ch":118},{"Timestamp":8285,"Mod":0,"Key":256,"Ch":101},{"Timestamp":8356,"Mod":0,"Key":256,"Ch":114},{"Timestamp":8493,"Mod":0,"Key":256,"Ch":116},{"Timestamp":8604,"Mod":0,"Key":256,"Ch":32},{"Timestamp":8700,"Mod":0,"Key":256,"Ch":102},{"Timestamp":9125,"Mod":0,"Key":127,"Ch":127},{"Timestamp":9189,"Mod":0,"Key":256,"Ch":99},{"Timestamp":9317,"Mod":0,"Key":256,"Ch":111},{"Timestamp":9509,"Mod":0,"Key":256,"Ch":109},{"Timestamp":9637,"Mod":0,"Key":256,"Ch":109},{"Timestamp":9685,"Mod":0,"Key":256,"Ch":105},{"Timestamp":9781,"Mod":0,"Key":256,"Ch":116},{"Timestamp":9918,"Mod":0,"Key":13,"Ch":13},{"Timestamp":11110,"Mod":0,"Key":256,"Ch":113}],"ResizeEvents":[{"Timestamp":0,"Width":272,"Height":74}]}
|
@ -1,22 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
cd $1
|
||||
|
||||
git init
|
||||
|
||||
git config user.email "CI@example.com"
|
||||
git config user.name "CI"
|
||||
|
||||
echo test0 > file0
|
||||
git add .
|
||||
git commit -am file0
|
||||
|
||||
echo test1 > file1
|
||||
git add .
|
||||
git commit -am file1
|
||||
|
||||
echo test2 > file2
|
||||
git add .
|
||||
git commit -am file2
|
@ -1 +0,0 @@
|
||||
{ "description": "Reverting a commit. Note here that our snapshot test fails if the commit SHA is included in the message hence the renaming of the revert commit after creating it", "speed": 20 }
|
@ -1 +0,0 @@
|
||||
commit 10
|
@ -1 +0,0 @@
|
||||
ref: refs/heads/master
|
@ -1,12 +0,0 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[user]
|
||||
email = CI@example.com
|
||||
name = CI
|
||||
[commit]
|
||||
gpgSign = false
|
@ -1 +0,0 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
# 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
|
@ -1,13 +0,0 @@
|
||||
0000000000000000000000000000000000000000 18197bb6052becf371aca9ab58d8352cebd3bc29 CI <CI@example.com> 1661160645 +1000 commit (initial): commit 01
|
||||
18197bb6052becf371aca9ab58d8352cebd3bc29 0ce746de5bee98147a370a19b4568b448fdedfcc CI <CI@example.com> 1661160645 +1000 commit: commit 02
|
||||
0ce746de5bee98147a370a19b4568b448fdedfcc d4308139592744ccc7fa9ab0931812da9fdfcc1d CI <CI@example.com> 1661160645 +1000 commit: commit 03
|
||||
d4308139592744ccc7fa9ab0931812da9fdfcc1d 0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 CI <CI@example.com> 1661160645 +1000 commit: commit 04
|
||||
0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 685d0baa299ec29ff2c7a1ca9268abdd374adef2 CI <CI@example.com> 1661160645 +1000 commit: commit 05
|
||||
685d0baa299ec29ff2c7a1ca9268abdd374adef2 483fcff024ff52df164dddea9ab5032370d14228 CI <CI@example.com> 1661160645 +1000 commit: commit 06
|
||||
483fcff024ff52df164dddea9ab5032370d14228 f3f9cf9d8f02f35f955b868d277913fc45d724db CI <CI@example.com> 1661160645 +1000 commit: commit 07
|
||||
f3f9cf9d8f02f35f955b868d277913fc45d724db a83ada2a0a285982aaa96baeddb70135532ed004 CI <CI@example.com> 1661160645 +1000 commit: commit 08
|
||||
a83ada2a0a285982aaa96baeddb70135532ed004 a89b19d40efb59f1f77b5a6b59ed1a9898545d0d CI <CI@example.com> 1661160645 +1000 commit: commit 09
|
||||
a89b19d40efb59f1f77b5a6b59ed1a9898545d0d 670ea6605e6780007c543b3d034bcf49c898290d CI <CI@example.com> 1661160645 +1000 commit: commit 10
|
||||
670ea6605e6780007c543b3d034bcf49c898290d 685d0baa299ec29ff2c7a1ca9268abdd374adef2 CI <CI@example.com> 1661160646 +1000 checkout: moving from master to 685d0baa299ec29ff2c7a1ca9268abdd374adef2
|
||||
685d0baa299ec29ff2c7a1ca9268abdd374adef2 0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 CI <CI@example.com> 1661160646 +1000 checkout: moving from 685d0baa299ec29ff2c7a1ca9268abdd374adef2 to 0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7
|
||||
0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 670ea6605e6780007c543b3d034bcf49c898290d CI <CI@example.com> 1661160647 +1000 checkout: moving from 0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 to master
|
@ -1,10 +0,0 @@
|
||||
0000000000000000000000000000000000000000 18197bb6052becf371aca9ab58d8352cebd3bc29 CI <CI@example.com> 1661160645 +1000 commit (initial): commit 01
|
||||
18197bb6052becf371aca9ab58d8352cebd3bc29 0ce746de5bee98147a370a19b4568b448fdedfcc CI <CI@example.com> 1661160645 +1000 commit: commit 02
|
||||
0ce746de5bee98147a370a19b4568b448fdedfcc d4308139592744ccc7fa9ab0931812da9fdfcc1d CI <CI@example.com> 1661160645 +1000 commit: commit 03
|
||||
d4308139592744ccc7fa9ab0931812da9fdfcc1d 0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 CI <CI@example.com> 1661160645 +1000 commit: commit 04
|
||||
0f77bf7bd7dd91550c927549af82d5b7c6f8a0d7 685d0baa299ec29ff2c7a1ca9268abdd374adef2 CI <CI@example.com> 1661160645 +1000 commit: commit 05
|
||||
685d0baa299ec29ff2c7a1ca9268abdd374adef2 483fcff024ff52df164dddea9ab5032370d14228 CI <CI@example.com> 1661160645 +1000 commit: commit 06
|
||||
483fcff024ff52df164dddea9ab5032370d14228 f3f9cf9d8f02f35f955b868d277913fc45d724db CI <CI@example.com> 1661160645 +1000 commit: commit 07
|
||||
f3f9cf9d8f02f35f955b868d277913fc45d724db a83ada2a0a285982aaa96baeddb70135532ed004 CI <CI@example.com> 1661160645 +1000 commit: commit 08
|
||||
a83ada2a0a285982aaa96baeddb70135532ed004 a89b19d40efb59f1f77b5a6b59ed1a9898545d0d CI <CI@example.com> 1661160645 +1000 commit: commit 09
|
||||
a89b19d40efb59f1f77b5a6b59ed1a9898545d0d 670ea6605e6780007c543b3d034bcf49c898290d CI <CI@example.com> 1661160645 +1000 commit: commit 10
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +0,0 @@
|
||||
x�ЮA
|
||||
1@Qз=Eі�$M[[f5ЧHгыC�я,<�лЯ[|]z cЋи Ой�Г�"saAЋЫк{п
|
||||
�UЖњPc$N>йГsЊzn�$cb�d�ЄV�*#яq_6�fИLѓ~ЄЏЯzвЅ_�B
|
||||
��#!Ђйы>5ъ�ќч�љЈы;@
|
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
xŤÍM
|
||||
Â@@a×sŠěI&?6P¤ĐUŹQKŠ‚ĂHÁăŰEŕöńÁ[j)Ď$Ý©m ĘäWröŚ(ĽŢQVöč˛:™;şjFIó§=ęăý8
ńťËű—Ą–�‘ˇ‰Â™1íuź´ř“�Ň�”+
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,2 +0,0 @@
|
||||
x+)JMU0¶0`040031QHËÌI50Ô+©(ap¿Þu}QýñÆ��zûëû„ŠìAVeVÅæþÏ»˜éýþM¦;>dHG궘k†¬Ê¬ÊúGÆâÎìv…q-ý|�mÙ\-O!«2«út@ªC,Ñ#_¤Îý뾦‰>±<ȪLÁª…ž÷ûþ7,qåµîÂ"ç•O´Y× «2«ï,=vèêŠËù“Íßß[¥Á�´ñ}
²*s°*ƒµ5>f‹G<ÈܸiƒÖŽpdU`Uûµ™»j"¯Ü6\2©Ò í׿Loô‘UY‚U\MTç?öäúñ‰f?Í�j®9µ
|
||||
I•¡XU¯§ÐÍS§·eú3Mج8oâ²Ï)gŽI”Ð
|
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.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user