-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option to filter by changes (-S flag) #4383
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ func NewReflogCommitLoader(common *common.Common, cmd oscommands.ICmdObjBuilder) | |
|
||
// GetReflogCommits only returns the new reflog commits since the given lastReflogCommit | ||
// if none is passed (i.e. it's value is nil) then we get all the reflog commits | ||
func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string, filterAuthor string) ([]*models.Commit, bool, error) { | ||
func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit, filterPath string, filterAuthor string, filterChanges string) ([]*models.Commit, bool, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This now has too many positional parameters: let's introduce a CommitFilters struct which contains Path, Author, and PickaxeString fields. Seems Pickaxe is the official term (https://git-scm.com/book/en/v2/Git-Tools-Searching):
|
||
commits := make([]*models.Commit, 0) | ||
|
||
cmdArgs := NewGitCmd("log"). | ||
|
@@ -33,6 +33,7 @@ func (self *ReflogCommitLoader) GetReflogCommits(lastReflogCommit *models.Commit | |
Arg("--format=%h%x00%ct%x00%gs%x00%p"). | ||
ArgIf(filterAuthor != "", "--author="+filterAuthor). | ||
ArgIf(filterPath != "", "--follow", "--", filterPath). | ||
ArgIf(filterChanges != "", "-S", "filterChanges"). | ||
ToArgv() | ||
|
||
cmdObj := self.cmd.New(cmdArgs).DontLog() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,21 @@ func (self *FilteringMenuAction) Call() error { | |
Tooltip: tooltip, | ||
}) | ||
|
||
menuItems = append(menuItems, &types.MenuItem{ | ||
Label: self.c.Tr.FilterChangesOption, | ||
OnPress: func() error { | ||
self.c.Prompt(types.PromptOpts{ | ||
Title: self.c.Tr.EnterChanges, | ||
HandleConfirm: func(response string) error { | ||
return self.setFilteringChanges(strings.TrimSpace(response)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we shouldn't trim space now that we support filtering by patch content. Often you actually do care about trailing/leading space when doing that. |
||
}, | ||
}) | ||
|
||
return nil | ||
}, | ||
Tooltip: tooltip, | ||
}) | ||
|
||
if self.c.Modes().Filtering.Active() { | ||
menuItems = append(menuItems, &types.MenuItem{ | ||
Label: self.c.Tr.ExitFilterMode, | ||
|
@@ -112,6 +127,12 @@ func (self *FilteringMenuAction) setFilteringAuthor(author string) error { | |
return self.setFiltering() | ||
} | ||
|
||
func (self *FilteringMenuAction) setFilteringChanges(changes string) error { | ||
self.c.Modes().Filtering.Reset() | ||
self.c.Modes().Filtering.SetChanges(changes) | ||
return self.setFiltering() | ||
} | ||
|
||
func (self *FilteringMenuAction) setFiltering() error { | ||
self.c.Modes().Filtering.SetSelectedCommitHash(self.c.Contexts().LocalCommits.GetSelectedCommitHash()) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,24 @@ type ModeStatus struct { | |
Reset func() error | ||
} | ||
|
||
func (self *ModeHelper) getFilter() string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should return two strings: one for the type of thing we're filtering by, and one for the value. That removes the ambiguity |
||
filtering := self.c.Modes().Filtering | ||
|
||
if path := filtering.GetPath(); path != "" { | ||
return path | ||
} | ||
|
||
if author := filtering.GetAuthor(); author != "" { | ||
return author | ||
} | ||
|
||
if changes := filtering.GetChanges(); changes != "" { | ||
return changes | ||
} | ||
|
||
return "" | ||
} | ||
|
||
func (self *ModeHelper) Statuses() []ModeStatus { | ||
return []ModeStatus{ | ||
{ | ||
|
@@ -72,12 +90,11 @@ func (self *ModeHelper) Statuses() []ModeStatus { | |
{ | ||
IsActive: self.c.Modes().Filtering.Active, | ||
Description: func() string { | ||
filterContent := lo.Ternary(self.c.Modes().Filtering.GetPath() != "", self.c.Modes().Filtering.GetPath(), self.c.Modes().Filtering.GetAuthor()) | ||
return self.withResetButton( | ||
fmt.Sprintf( | ||
"%s '%s'", | ||
self.c.Tr.FilteringBy, | ||
filterContent, | ||
self.getFilter(), | ||
), | ||
style.FgRed, | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -328,6 +328,7 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error { | |
Limit: self.c.Contexts().LocalCommits.GetLimitCommits(), | ||
FilterPath: self.c.Modes().Filtering.GetPath(), | ||
FilterAuthor: self.c.Modes().Filtering.GetAuthor(), | ||
FilterChanges: self.c.Modes().Filtering.GetChanges(), | ||
IncludeRebaseCommits: true, | ||
RefName: self.refForLog(), | ||
RefForPushedStatus: checkedOutBranchName, | ||
|
@@ -356,6 +357,7 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error { | |
Limit: self.c.Contexts().SubCommits.GetLimitCommits(), | ||
FilterPath: self.c.Modes().Filtering.GetPath(), | ||
FilterAuthor: self.c.Modes().Filtering.GetAuthor(), | ||
FilterChanges: self.c.Modes().Filtering.GetChanges(), | ||
IncludeRebaseCommits: false, | ||
RefName: self.c.Contexts().SubCommits.GetRef().FullRefName(), | ||
RefToShowDivergenceFrom: self.c.Contexts().SubCommits.GetRefToShowDivergenceFrom(), | ||
|
@@ -456,7 +458,7 @@ func (self *RefreshHelper) refreshBranches(refreshWorktrees bool, keepBranchSele | |
// which allows us to order them correctly. So if we're filtering we'll just | ||
// manually load all the reflog commits here | ||
var err error | ||
reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "", "") | ||
reflogCommits, _, err = self.c.Git().Loaders.ReflogCommitLoader.GetReflogCommits(nil, "", "", "") | ||
if err != nil { | ||
self.c.Log.Error(err) | ||
} | ||
|
@@ -623,9 +625,9 @@ func (self *RefreshHelper) refreshReflogCommits() error { | |
lastReflogCommit = model.ReflogCommits[0] | ||
} | ||
|
||
refresh := func(stateCommits *[]*models.Commit, filterPath string, filterAuthor string) error { | ||
refresh := func(stateCommits *[]*models.Commit, filterPath string, filterAuthor string, filterChanges string) error { | ||
commits, onlyObtainedNewReflogCommits, err := self.c.Git().Loaders.ReflogCommitLoader. | ||
GetReflogCommits(lastReflogCommit, filterPath, filterAuthor) | ||
GetReflogCommits(lastReflogCommit, filterPath, filterAuthor, filterChanges) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -638,12 +640,12 @@ func (self *RefreshHelper) refreshReflogCommits() error { | |
return nil | ||
} | ||
|
||
if err := refresh(&model.ReflogCommits, "", ""); err != nil { | ||
if err := refresh(&model.ReflogCommits, "", "", ""); err != nil { | ||
return err | ||
} | ||
|
||
if self.c.Modes().Filtering.Active() { | ||
if err := refresh(&model.FilteredReflogCommits, self.c.Modes().Filtering.GetPath(), self.c.Modes().Filtering.GetAuthor()); err != nil { | ||
if err := refresh(&model.FilteredReflogCommits, self.c.Modes().Filtering.GetPath(), self.c.Modes().Filtering.GetAuthor(), self.c.Modes().Filtering.GetChanges()); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even here I'd just go |
||
return err | ||
} | ||
} else { | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -596,8 +596,10 @@ type TranslationSet struct { | |||||
ExitFilterMode string | ||||||
FilterPathOption string | ||||||
FilterAuthorOption string | ||||||
FilterChangesOption string | ||||||
EnterFileName string | ||||||
EnterAuthor string | ||||||
EnterChanges string | ||||||
FilteringMenuTitle string | ||||||
WillCancelExistingFilterTooltip string | ||||||
MustExitFilterModeTitle string | ||||||
|
@@ -1637,8 +1639,10 @@ func EnglishTranslationSet() *TranslationSet { | |||||
ExitFilterMode: "Stop filtering", | ||||||
FilterPathOption: "Enter path to filter by", | ||||||
FilterAuthorOption: "Enter author to filter by", | ||||||
FilterChangesOption: "Enter changes to filter by", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
EnterFileName: "Enter path:", | ||||||
EnterAuthor: "Enter author:", | ||||||
EnterChanges: "Enter changes:", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
FilteringMenuTitle: "Filtering", | ||||||
WillCancelExistingFilterTooltip: "Note: this will cancel the existing filter", | ||||||
MustExitFilterModeTitle: "Command not available", | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package filter_by_changes | ||
|
||
import ( | ||
"github.com/jesseduffield/lazygit/pkg/config" | ||
. "github.com/jesseduffield/lazygit/pkg/integration/components" | ||
) | ||
|
||
var TypeChanges = NewIntegrationTest(NewIntegrationTestArgs{ | ||
Description: "Filter commits by author using the typed in author", | ||
ExtraCmdArgs: []string{}, | ||
Skip: false, | ||
SetupConfig: func(config *config.AppConfig) { | ||
}, | ||
SetupRepo: func(shell *Shell) { | ||
shell.CreateNCommits(4) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to explicitly add files and associated commits, just to make this more readable. At the moment the reader has to look up the definition of CreateNCommits to see the relationship between the commit messages and their corresponding file changes. The |
||
}, | ||
Run: func(t *TestDriver, keys config.KeybindingConfig) { | ||
t.Views().Status(). | ||
Focus(). | ||
Press(keys.Universal.FilteringMenu) | ||
|
||
t.ExpectPopup().Menu(). | ||
Title(Equals("Filtering")). | ||
Select(Contains("Enter changes to filter by")). | ||
Confirm() | ||
|
||
t.ExpectPopup().Prompt(). | ||
Title(Equals("Enter changes:")). | ||
Type("file01"). | ||
Confirm() | ||
|
||
t.Views().Commits(). | ||
IsFocused(). | ||
Lines( | ||
Contains("commit 01"), | ||
) | ||
|
||
t.Views().Information().Content(Contains("Filtering by 'file01'")) | ||
|
||
t.Views().Status(). | ||
Focus(). | ||
Press(keys.Universal.FilteringMenu) | ||
|
||
t.ExpectPopup().Menu(). | ||
Title(Equals("Filtering")). | ||
Select(Contains("Enter changes to filter by")). | ||
Confirm() | ||
|
||
t.ExpectPopup().Prompt(). | ||
Title(Equals("Enter changes:")). | ||
Type("file02"). | ||
Confirm() | ||
|
||
t.Views().Commits(). | ||
IsFocused(). | ||
Lines( | ||
Contains("commit 02"), | ||
) | ||
|
||
t.Views().Information().Content(Contains("Filtering by 'file02'")) | ||
}, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.