diff --git a/pkg/commands/git_commands/stash_loader.go b/pkg/commands/git_commands/stash_loader.go index d0a290507..67c3fb317 100644 --- a/pkg/commands/git_commands/stash_loader.go +++ b/pkg/commands/git_commands/stash_loader.go @@ -32,31 +32,31 @@ func (self *StashLoader) GetStashEntries(filterPath string) []*models.StashEntry return self.getUnfilteredStashEntries() } - cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--name-only", "--pretty=%ct|%gs").ToArgv() + cmdArgs := NewGitCmd("stash").Arg("list", "--name-only", "--pretty=%gd:%ct|%gs").ToArgv() rawString, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput() if err != nil { return self.getUnfilteredStashEntries() } stashEntries := []*models.StashEntry{} var currentStashEntry *models.StashEntry - lines := utils.SplitNul(rawString) + lines := utils.SplitLines(rawString) isAStash := func(line string) bool { return strings.HasPrefix(line, "stash@{") } - re := regexp.MustCompile(`stash@\{(\d+)\}`) + re := regexp.MustCompile(`^stash@\{(\d+)\}:(.*)$`) outer: for i := 0; i < len(lines); i++ { - if !isAStash(lines[i]) { + match := re.FindStringSubmatch(lines[i]) + if match == nil { continue } - match := re.FindStringSubmatch(lines[i]) idx, err := strconv.Atoi(match[1]) if err != nil { return self.getUnfilteredStashEntries() } - currentStashEntry = stashEntryFromLine(lines[i], idx) + currentStashEntry = stashEntryFromLine(match[2], idx) for i+1 < len(lines) && !isAStash(lines[i+1]) { i++ - if lines[i] == filterPath { + if strings.HasPrefix(lines[i], filterPath) { stashEntries = append(stashEntries, currentStashEntry) continue outer } diff --git a/pkg/gui/controllers/filtering_menu_action.go b/pkg/gui/controllers/filtering_menu_action.go index 3a109a887..2ed072676 100644 --- a/pkg/gui/controllers/filtering_menu_action.go +++ b/pkg/gui/controllers/filtering_menu_action.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -122,7 +123,7 @@ func (self *FilteringMenuAction) setFiltering() error { self.c.Context().Push(self.c.Contexts().LocalCommits, types.OnFocusOpts{}) - self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}, Then: func() { + self.c.Refresh(types.RefreshOptions{Scope: helpers.ScopesToRefreshWhenFilteringModeChanges(), Then: func() { self.c.Contexts().LocalCommits.SetSelection(0) self.c.Contexts().LocalCommits.HandleFocus(types.OnFocusOpts{}) }}) diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go index f90519e4d..702825c58 100644 --- a/pkg/gui/controllers/helpers/mode_helper.go +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -168,7 +168,7 @@ func (self *ModeHelper) ClearFiltering() error { } self.c.Refresh(types.RefreshOptions{ - Scope: []types.RefreshableView{types.COMMITS}, + Scope: ScopesToRefreshWhenFilteringModeChanges(), Then: func() { // Find the commit that was last selected in filtering mode, and select it again after refreshing if !self.c.Contexts().LocalCommits.SelectCommitByHash(selectedCommitHash) { @@ -178,12 +178,24 @@ func (self *ModeHelper) ClearFiltering() error { // before we entered filtering self.c.Contexts().LocalCommits.SelectCommitByHash(self.c.Modes().Filtering.GetSelectedCommitHash()) } - self.c.Contexts().LocalCommits.HandleFocus(types.OnFocusOpts{}) + + self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits) }, }) return nil } +// Stashes really only need to be refreshed when filtering by path, not by author, but it's too much +// work to distinguish this, and refreshing stashes is fast, so we don't bother +func ScopesToRefreshWhenFilteringModeChanges() []types.RefreshableView { + return []types.RefreshableView{ + types.COMMITS, + types.SUB_COMMITS, + types.REFLOG, + types.STASH, + } +} + func (self *ModeHelper) SetSuppressRebasingMode(value bool) { self.suppressRebasingMode = value } diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index 2682d8296..dc396be3f 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -345,6 +345,10 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error { } func (self *RefreshHelper) refreshSubCommitsWithLimit() error { + if self.c.Contexts().SubCommits.GetRef() == nil { + return nil + } + self.c.Mutexes().SubCommitsMutex.Lock() defer self.c.Mutexes().SubCommitsMutex.Unlock() diff --git a/pkg/integration/tests/stash/filter_by_path.go b/pkg/integration/tests/stash/filter_by_path.go new file mode 100644 index 000000000..ea397d70e --- /dev/null +++ b/pkg/integration/tests/stash/filter_by_path.go @@ -0,0 +1,60 @@ +package stash + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var FilterByPath = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Filter the stash list by path", + ExtraCmdArgs: []string{}, + Skip: false, + SetupConfig: func(config *config.AppConfig) {}, + SetupRepo: func(shell *Shell) { + shell.EmptyCommit("initial commit") + shell.CreateFileAndAdd("file1", "content") + shell.Stash("file1") + shell.CreateDir("subdir") + shell.CreateFileAndAdd("subdir/file2", "content") + shell.Stash("subdir/file2") + shell.CreateFileAndAdd("file1", "other content") + shell.Stash("file1 again") + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + filterBy := func(path string) { + t.GlobalPress(keys.Universal.FilteringMenu) + t.ExpectPopup().Menu(). + Title(Equals("Filtering")). + Select(Contains("Enter path to filter by")). + Confirm() + + t.ExpectPopup().Prompt(). + Title(Equals("Enter path:")). + Type(path). + Confirm() + } + + t.Views().Stash(). + Lines( + Contains("file1 again"), + Contains("subdir/file2"), + Contains("file1"), + ) + + filterBy("file1") + + t.Views().Stash(). + Lines( + Contains("file1 again"), + Contains("file1"), + ) + + t.GlobalPress(keys.Universal.Return) + filterBy("subdir") + + t.Views().Stash(). + Lines( + Contains("subdir/file2"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index d5f4f5c21..4a8754284 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -352,6 +352,7 @@ var tests = []*components.IntegrationTest{ stash.CreateBranch, stash.Drop, stash.DropMultiple, + stash.FilterByPath, stash.Pop, stash.PreventDiscardingFileChanges, stash.Rename,