diff options
47 files changed, 182 insertions, 22 deletions
diff --git a/pkg/commands/git_commands/stash.go b/pkg/commands/git_commands/stash.go index eddf676ff..572a87a73 100644 --- a/pkg/commands/git_commands/stash.go +++ b/pkg/commands/git_commands/stash.go @@ -123,6 +123,10 @@ func (self *StashCommands) SaveStagedChanges(message string) error { return nil } +func (self *StashCommands) StashIncludeUntrackedChanges(message string) error { + return self.cmd.New(fmt.Sprintf("git stash save %s --include-untracked", self.cmd.Quote(message))).Run() +} + func (self *StashCommands) Rename(index int, message string) error { sha, err := self.Sha(index) if err != nil { diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 8f0b8333f..2a4434264 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -758,37 +758,53 @@ func (self *FilesController) createStashMenu() error { { Label: self.c.Tr.LcStashAllChanges, OnPress: func() error { - return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashAllChanges, self.c.Tr.NoFilesToStash) + if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) + } + return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashAllChanges) }, Key: 'a', }, { Label: self.c.Tr.LcStashAllChangesKeepIndex, OnPress: func() error { + if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) + } // if there are no staged files it behaves the same as Stash.Save - return self.handleStashSave(self.git.Stash.StashAndKeepIndex, self.c.Tr.Actions.StashAllChangesKeepIndex, self.c.Tr.NoFilesToStash) + return self.handleStashSave(self.git.Stash.StashAndKeepIndex, self.c.Tr.Actions.StashAllChangesKeepIndex) }, Key: 'i', }, { + Label: self.c.Tr.LcStashIncludeUntrackedChanges, + OnPress: func() error { + return self.handleStashSave(self.git.Stash.StashIncludeUntrackedChanges, self.c.Tr.Actions.StashIncludeUntrackedChanges) + }, + Key: 'U', + }, + { Label: self.c.Tr.LcStashStagedChanges, OnPress: func() error { // there must be something in staging otherwise the current implementation mucks the stash up if !self.helpers.WorkingTree.AnyStagedFiles() { return self.c.ErrorMsg(self.c.Tr.NoTrackedStagedFilesStash) } - return self.handleStashSave(self.git.Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges, self.c.Tr.NoTrackedStagedFilesStash) + return self.handleStashSave(self.git.Stash.SaveStagedChanges, self.c.Tr.Actions.StashStagedChanges) }, Key: 's', }, { Label: self.c.Tr.LcStashUnstagedChanges, OnPress: func() error { + if !self.helpers.WorkingTree.IsWorkingTreeDirty() { + return self.c.ErrorMsg(self.c.Tr.NoFilesToStash) + } if self.helpers.WorkingTree.AnyStagedFiles() { - return self.handleStashSave(self.git.Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges, self.c.Tr.NoFilesToStash) + return self.handleStashSave(self.git.Stash.StashUnstagedChanges, self.c.Tr.Actions.StashUnstagedChanges) } // ordinary stash - return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashUnstagedChanges, self.c.Tr.NoFilesToStash) + return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashUnstagedChanges) }, Key: 'u', }, @@ -797,7 +813,7 @@ func (self *FilesController) createStashMenu() error { } func (self *FilesController) stash() error { - return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashAllChanges, self.c.Tr.NoTrackedStagedFilesStash) + return self.handleStashSave(self.git.Stash.Save, self.c.Tr.Actions.StashAllChanges) } func (self *FilesController) createResetToUpstreamMenu() error { @@ -825,11 +841,7 @@ func (self *FilesController) toggleTreeView() error { return self.c.PostRefreshUpdate(self.context()) } -func (self *FilesController) handleStashSave(stashFunc func(message string) error, action string, errorMsg string) error { - if !self.helpers.WorkingTree.IsWorkingTreeDirty() { - return self.c.ErrorMsg(errorMsg) - } - +func (self *FilesController) handleStashSave(stashFunc func(message string) error, action string) error { return self.c.Prompt(types.PromptOpts{ Title: self.c.Tr.StashChanges, HandleConfirm: func(stashComment string) error { diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index 75e121545..e152b62a4 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -295,6 +295,7 @@ type TranslationSet struct { LcStashStagedChanges string LcStashAllChangesKeepIndex string LcStashUnstagedChanges string + LcStashIncludeUntrackedChanges string LcStashOptions string NotARepository string LcJump string @@ -588,6 +589,7 @@ type Actions struct { StashAllChangesKeepIndex string StashStagedChanges string StashUnstagedChanges string + StashIncludeUntrackedChanges string GitFlowFinish string GitFlowStart string CopyToClipboard string @@ -940,6 +942,7 @@ func EnglishTranslationSet() TranslationSet { LcStashStagedChanges: "stash staged changes", LcStashAllChangesKeepIndex: "stash all changes and keep index", LcStashUnstagedChanges: "stash unstaged changes", + LcStashIncludeUntrackedChanges: "stash all changes including untracked files", LcStashOptions: "Stash options", NotARepository: "Error: must be run inside a git repository", LcJump: "jump to panel", @@ -1216,6 +1219,7 @@ func EnglishTranslationSet() TranslationSet { StashAllChangesKeepIndex: "Stash all changes and keep index", StashStagedChanges: "Stash staged changes", StashUnstagedChanges: "Stash unstaged changes", + StashIncludeUntrackedChanges: "Stash all changes including untracked files", GitFlowFinish: "Git flow finish", GitFlowStart: "Git Flow start", CopyToClipboard: "Copy to clipboard", diff --git a/pkg/integration/components/assert.go b/pkg/integration/components/assert.go index daa376c66..c911dbefa 100644 --- a/pkg/integration/components/assert.go +++ b/pkg/integration/components/assert.go @@ -84,6 +84,17 @@ func (self *Assert) CommitCount(expectedCount int) { }) } +func (self *Assert) StashCount(expectedCount int) { + self.assertWithRetries(func() (bool, string) { + actualCount := len(self.gui.Model().StashEntries) + + return actualCount == expectedCount, fmt.Sprintf( + "Expected %d stash entries, but got %d", + expectedCount, actualCount, + ) + }) +} + func (self *Assert) AtLeastOneCommit() { self.assertWithRetries(func() (bool, string) { actualCount := len(self.gui.Model().Commits) diff --git a/pkg/integration/tests/stash/stash.go b/pkg/integration/tests/stash/stash.go new file mode 100644 index 000000000..00d666168 --- /dev/null +++ b/pkg/integration/tests/stash/stash.go @@ -0,0 +1,34 @@ +package stash + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var Stash = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Stashing files", + ExtraCmdArgs: "", + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.CreateFile("file", "content") + shell.GitAddAll() + }, + Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { + assert.StashCount(0) + assert.WorkingTreeFileCount(1) + + input.PressKeys(keys.Files.ViewStashOptions) + assert.InMenu() + + input.PressKeys("a") + assert.InPrompt() + assert.MatchCurrentViewTitle(Equals("Stash changes")) + + input.Type("my stashed file") + input.Confirm() + assert.StashCount(1) + assert.WorkingTreeFileCount(0) + }, +}) diff --git a/pkg/integration/tests/stash/stash_including_untracked_files.go b/pkg/integration/tests/stash/stash_including_untracked_files.go new file mode 100644 index 000000000..2f37f943c --- /dev/null +++ b/pkg/integration/tests/stash/stash_including_untracked_files.go @@ -0,0 +1,35 @@ +package stash + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var StashIncludingUntrackedFiles = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Stashing all files including untracked ones", + ExtraCmdArgs: "", + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.CreateFile("file_1", "content") + shell.CreateFile("file_2", "content") + shell.GitAdd("file_1") + }, + Run: func(shell *Shell, input *Input, assert *Assert, keys config.KeybindingConfig) { + assert.StashCount(0) + assert.WorkingTreeFileCount(2) + + input.PressKeys(keys.Files.ViewStashOptions) + assert.InMenu() + + input.PressKeys("U") + assert.InPrompt() + assert.MatchCurrentViewTitle(Equals("Stash changes")) + + input.Type("my stashed file") + input.Confirm() + assert.StashCount(1) + assert.WorkingTreeFileCount(0) + }, +}) diff --git a/pkg/integration/tests/tests.go b/pkg/integration/tests/tests.go index 5c891a4e3..8d5f6adde 100644 --- a/pkg/integration/tests/tests.go +++ b/pkg/integration/tests/tests.go @@ -24,24 +24,26 @@ import ( // be sure to add it to this list. var tests = []*components.IntegrationTest{ - commit.Commit, - commit.NewBranch, - branch.Suggestions, + bisect.Basic, + bisect.FromOtherBranch, branch.Delete, branch.Rebase, branch.RebaseAndDrop, - interactive_rebase.One, - interactive_rebase.AmendMerge, - custom_commands.Basic, - custom_commands.MultiplePrompts, - custom_commands.MenuFromCommand, - bisect.Basic, - bisect.FromOtherBranch, + branch.Suggestions, cherry_pick.CherryPick, cherry_pick.CherryPickConflicts, + commit.Commit, + commit.NewBranch, + custom_commands.Basic, custom_commands.FormPrompts, - stash.Rename, + custom_commands.MenuFromCommand, + custom_commands.MultiplePrompts, file.DirWithUntrackedFile, + interactive_rebase.AmendMerge, + interactive_rebase.One, + stash.Rename, + stash.Stash, + stash.StashIncludingUntrackedFiles, } func GetTests() []*components.IntegrationTest { diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/COMMIT_EDITMSG b/test/integration_new/stash/stash/expected/repo/.git_keep/COMMIT_EDITMSG new file mode 100644 index 000000000..802607664 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/COMMIT_EDITMSG @@ -0,0 +1 @@ +initial commit diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/FETCH_HEAD b/test/integration_new/stash/stash/expected/repo/.git_keep/FETCH_HEAD new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/FETCH_HEAD diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/HEAD b/test/integration_new/stash/stash/expected/repo/.git_keep/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/ORIG_HEAD b/test/integration_new/stash/stash/expected/repo/.git_keep/ORIG_HEAD new file mode 100644 index 000000000..9130d91a2 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/ORIG_HEAD @@ -0,0 +1 @@ +e6ed7d5c2198fa4791de9c66e8000da607eaf9a3 diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/config b/test/integration_new/stash/stash/expected/repo/.git_keep/config new file mode 100644 index 000000000..8a748ce32 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/config @@ -0,0 +1,12 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true +[user] + email = CI@example.com + name = CI +[commit] + gpgSign = false diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/description b/test/integration_new/stash/stash/expected/repo/.git_keep/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/index b/test/integration_new/stash/stash/expected/repo/.git_keep/index Binary files differnew file mode 100644 index 000000000..65d675154 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/index diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/info/exclude b/test/integration_new/stash/stash/expected/repo/.git_keep/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/info/exclude @@ -0,0 +1,6 @@ +# 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] +# *~ diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/logs/HEAD b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/HEAD new file mode 100644 index 000000000..e89e8b09a --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 e6ed7d5c2198fa4791de9c66e8000da607eaf9a3 CI <CI@example.com> 1668288675 -0330 commit (initial): initial commit +e6ed7d5c2198fa4791de9c66e8000da607eaf9a3 e6ed7d5c2198fa4791de9c66e8000da607eaf9a3 CI <CI@example.com> 1668288676 -0330 reset: moving to HEAD diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/heads/master b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/heads/master new file mode 100644 index 000000000..79820d14f --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/heads/master @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 e6ed7d5c2198fa4791de9c66e8000da607eaf9a3 CI <CI@example.com> 1668288675 -0330 commit (initial): initial commit diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/stash b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/stash new file mode 100644 index 000000000..6933fca6b --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/logs/refs/stash @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 c86eeda485a49ca608cb2617bb027be66cd92bc3 CI <CI@example.com> 1668288676 -0330 On master: my stashed file diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 Binary files differnew file mode 100644 index 000000000..adf64119a --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/6b/584e8ece562ebffc15d38808cd6b98fc3d97ea b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/6b/584e8ece562ebffc15d38808cd6b98fc3d97ea Binary files differnew file mode 100644 index 000000000..ec9764eae --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/6b/584e8ece562ebffc15d38808cd6b98fc3d97ea diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/b4/ba8c398d35c204cc9ae06e120c6f0801fd3f32 b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/b4/ba8c398d35c204cc9ae06e120c6f0801fd3f32 new file mode 100644 index 000000000..e75cf01e2 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/b4/ba8c398d35c204cc9ae06e120c6f0801fd3f32 @@ -0,0 +1 @@ +xAj0E) cI@V>X3"9~l?=^ZSUA HdrN/)ra,sX̃w];()ÁkDQ0(߷n|ߦ=@mc=~x7u}B߃^y?yNFY
\ No newline at end of file diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/c8/6eeda485a49ca608cb2617bb027be66cd92bc3 b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/c8/6eeda485a49ca608cb2617bb027be66cd92bc3 Binary files differnew file mode 100644 index 000000000..330924b9f --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/c8/6eeda485a49ca608cb2617bb027be66cd92bc3 diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/d9/1d06157bdc633d25f970b9cc54d0eb74fb850f b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/d9/1d06157bdc633d25f970b9cc54d0eb74fb850f Binary files differnew file mode 100644 index 000000000..00c028c95 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/d9/1d06157bdc633d25f970b9cc54d0eb74fb850f diff --git a/test/integration_new/stash/stash/expected/repo/.git_keep/objects/e6/ed7d5c2198fa4791de9c66e8000da607eaf9a3 b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/e6/ed7d5c2198fa4791de9c66e8000da607eaf9a3 Binary files differnew file mode 100644 index 000000000..e53b1e068 --- /dev/null +++ b/test/integration_new/stash/stash/expected/repo/.git_keep/objects/e6/ed7d5c2198fa4791de9c66e8000da607eaf9a3 |