mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-21 22:43:27 +02:00
Keep track of authors across local commits and branch commits for suggestions
Previously, we would only show the authors based on local commits, but sometimes you want to set a commit author to that of a commit on another branch. Now, so long as you've viewed the branch's commits, the author will appear as a suggestion.
This commit is contained in:
parent
a7969aef2c
commit
3cee37388c
13
pkg/commands/models/author.go
Normal file
13
pkg/commands/models/author.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// A commit author
|
||||||
|
type Author struct {
|
||||||
|
Name string
|
||||||
|
Email string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Author) Combined() string {
|
||||||
|
return fmt.Sprintf("%s <%s>", self.Name, self.Email)
|
||||||
|
}
|
@ -266,6 +266,7 @@ func (self *RefreshHelper) refreshCommitsWithLimit() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.c.Model().Commits = commits
|
self.c.Model().Commits = commits
|
||||||
|
self.RefreshAuthors(commits)
|
||||||
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
self.c.Model().WorkingTreeStateAtLastCommitRefresh = self.c.Git().Status.WorkingTreeState()
|
||||||
|
|
||||||
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
return self.c.PostRefreshUpdate(self.c.Contexts().LocalCommits)
|
||||||
@ -287,10 +288,26 @@ func (self *RefreshHelper) refreshSubCommitsWithLimit() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.c.Model().SubCommits = commits
|
self.c.Model().SubCommits = commits
|
||||||
|
self.RefreshAuthors(commits)
|
||||||
|
|
||||||
return self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
return self.c.PostRefreshUpdate(self.c.Contexts().SubCommits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RefreshHelper) RefreshAuthors(commits []*models.Commit) {
|
||||||
|
self.c.Mutexes().AuthorsMutex.Lock()
|
||||||
|
defer self.c.Mutexes().AuthorsMutex.Unlock()
|
||||||
|
|
||||||
|
authors := self.c.Model().Authors
|
||||||
|
for _, commit := range commits {
|
||||||
|
if _, ok := authors[commit.AuthorEmail]; !ok {
|
||||||
|
authors[commit.AuthorEmail] = &models.Author{
|
||||||
|
Email: commit.AuthorEmail,
|
||||||
|
Name: commit.AuthorName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *RefreshHelper) refreshCommitFilesContext() error {
|
func (self *RefreshHelper) refreshCommitFilesContext() error {
|
||||||
ref := self.c.Contexts().CommitFiles.GetRef()
|
ref := self.c.Contexts().CommitFiles.GetRef()
|
||||||
to := ref.RefName()
|
to := ref.RefName()
|
||||||
|
@ -176,9 +176,11 @@ func (self *SuggestionsHelper) GetRefsSuggestionsFunc() func(string) []*types.Su
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsHelper) GetAuthorsSuggestionsFunc() func(string) []*types.Suggestion {
|
func (self *SuggestionsHelper) GetAuthorsSuggestionsFunc() func(string) []*types.Suggestion {
|
||||||
authors := lo.Uniq(slices.Map(self.c.Model().Commits, func(commit *models.Commit) string {
|
authors := lo.Map(lo.Values(self.c.Model().Authors), func(author *models.Author, _ int) string {
|
||||||
return fmt.Sprintf("%s <%s>", commit.AuthorName, commit.AuthorEmail)
|
return author.Combined()
|
||||||
}))
|
})
|
||||||
|
|
||||||
|
slices.Sort(authors)
|
||||||
|
|
||||||
return FuzzySearchFunc(authors)
|
return FuzzySearchFunc(authors)
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ func (self *SwitchToSubCommitsController) viewCommits() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.setSubCommits(commits)
|
self.setSubCommits(commits)
|
||||||
|
self.c.Helpers().Refresh.RefreshAuthors(commits)
|
||||||
|
|
||||||
subCommitsContext := self.c.Contexts().SubCommits
|
subCommitsContext := self.c.Contexts().SubCommits
|
||||||
subCommitsContext.SetSelectedLineIdx(0)
|
subCommitsContext.SetSelectedLineIdx(0)
|
||||||
|
@ -349,6 +349,7 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs, reuseState bool) types.
|
|||||||
ReflogCommits: make([]*models.Commit, 0),
|
ReflogCommits: make([]*models.Commit, 0),
|
||||||
BisectInfo: git_commands.NewNullBisectInfo(),
|
BisectInfo: git_commands.NewNullBisectInfo(),
|
||||||
FilesTrie: patricia.NewTrie(),
|
FilesTrie: patricia.NewTrie(),
|
||||||
|
Authors: map[string]*models.Author{},
|
||||||
},
|
},
|
||||||
Modes: &types.Modes{
|
Modes: &types.Modes{
|
||||||
Filtering: filtering.New(startArgs.FilterPath),
|
Filtering: filtering.New(startArgs.FilterPath),
|
||||||
@ -456,6 +457,7 @@ func NewGui(
|
|||||||
SyncMutex: &deadlock.Mutex{},
|
SyncMutex: &deadlock.Mutex{},
|
||||||
LocalCommitsMutex: &deadlock.Mutex{},
|
LocalCommitsMutex: &deadlock.Mutex{},
|
||||||
SubCommitsMutex: &deadlock.Mutex{},
|
SubCommitsMutex: &deadlock.Mutex{},
|
||||||
|
AuthorsMutex: &deadlock.Mutex{},
|
||||||
SubprocessMutex: &deadlock.Mutex{},
|
SubprocessMutex: &deadlock.Mutex{},
|
||||||
PopupMutex: &deadlock.Mutex{},
|
PopupMutex: &deadlock.Mutex{},
|
||||||
PtyMutex: &deadlock.Mutex{},
|
PtyMutex: &deadlock.Mutex{},
|
||||||
|
@ -217,6 +217,8 @@ type Model struct {
|
|||||||
|
|
||||||
// for displaying suggestions while typing in a file name
|
// for displaying suggestions while typing in a file name
|
||||||
FilesTrie *patricia.Trie
|
FilesTrie *patricia.Trie
|
||||||
|
|
||||||
|
Authors map[string]*models.Author
|
||||||
}
|
}
|
||||||
|
|
||||||
// if you add a new mutex here be sure to instantiate it. We're using pointers to
|
// if you add a new mutex here be sure to instantiate it. We're using pointers to
|
||||||
@ -228,6 +230,7 @@ type Mutexes struct {
|
|||||||
SyncMutex *deadlock.Mutex
|
SyncMutex *deadlock.Mutex
|
||||||
LocalCommitsMutex *deadlock.Mutex
|
LocalCommitsMutex *deadlock.Mutex
|
||||||
SubCommitsMutex *deadlock.Mutex
|
SubCommitsMutex *deadlock.Mutex
|
||||||
|
AuthorsMutex *deadlock.Mutex
|
||||||
SubprocessMutex *deadlock.Mutex
|
SubprocessMutex *deadlock.Mutex
|
||||||
PopupMutex *deadlock.Mutex
|
PopupMutex *deadlock.Mutex
|
||||||
PtyMutex *deadlock.Mutex
|
PtyMutex *deadlock.Mutex
|
||||||
|
@ -5,29 +5,58 @@ import (
|
|||||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Originally we only suggested authors present in the current branch, but now
|
||||||
|
// we include authors from other branches whose commits you've looked at in the
|
||||||
|
// lazygit session.
|
||||||
|
|
||||||
var SetAuthor = NewIntegrationTest(NewIntegrationTestArgs{
|
var SetAuthor = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Description: "Set author on a commit",
|
Description: "Set author on a commit",
|
||||||
ExtraCmdArgs: []string{},
|
ExtraCmdArgs: []string{},
|
||||||
Skip: false,
|
Skip: false,
|
||||||
SetupConfig: func(config *config.AppConfig) {},
|
SetupConfig: func(config *config.AppConfig) {},
|
||||||
SetupRepo: func(shell *Shell) {
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.NewBranch("original")
|
||||||
|
|
||||||
shell.SetConfig("user.email", "Bill@example.com")
|
shell.SetConfig("user.email", "Bill@example.com")
|
||||||
shell.SetConfig("user.name", "Bill Smith")
|
shell.SetConfig("user.name", "Bill Smith")
|
||||||
|
|
||||||
shell.EmptyCommit("one")
|
shell.EmptyCommit("one")
|
||||||
|
|
||||||
|
shell.NewBranch("other")
|
||||||
|
|
||||||
shell.SetConfig("user.email", "John@example.com")
|
shell.SetConfig("user.email", "John@example.com")
|
||||||
shell.SetConfig("user.name", "John Smith")
|
shell.SetConfig("user.name", "John Smith")
|
||||||
|
|
||||||
shell.EmptyCommit("two")
|
shell.EmptyCommit("two")
|
||||||
|
|
||||||
|
shell.Checkout("original")
|
||||||
},
|
},
|
||||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
t.Views().Commits().
|
t.Views().Commits().
|
||||||
Focus().
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("BS").Contains("one").IsSelected(),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
Lines(
|
||||||
|
Contains("original").IsSelected(),
|
||||||
|
Contains("other"),
|
||||||
|
).
|
||||||
|
NavigateToLine(Contains("other")).
|
||||||
|
PressEnter()
|
||||||
|
|
||||||
|
// ensuring we get these commit authors as suggestions
|
||||||
|
t.Views().SubCommits().
|
||||||
|
IsFocused().
|
||||||
Lines(
|
Lines(
|
||||||
Contains("JS").Contains("two").IsSelected(),
|
Contains("JS").Contains("two").IsSelected(),
|
||||||
Contains("BS").Contains("one"),
|
Contains("BS").Contains("one"),
|
||||||
).
|
)
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
Press(keys.Commits.ResetCommitAuthor).
|
Press(keys.Commits.ResetCommitAuthor).
|
||||||
Tap(func() {
|
Tap(func() {
|
||||||
t.ExpectPopup().Menu().
|
t.ExpectPopup().Menu().
|
||||||
@ -38,14 +67,13 @@ var SetAuthor = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
t.ExpectPopup().Prompt().
|
t.ExpectPopup().Prompt().
|
||||||
Title(Contains("Set author")).
|
Title(Contains("Set author")).
|
||||||
SuggestionLines(
|
SuggestionLines(
|
||||||
Contains("John Smith"),
|
|
||||||
Contains("Bill Smith"),
|
Contains("Bill Smith"),
|
||||||
|
Contains("John Smith"),
|
||||||
).
|
).
|
||||||
ConfirmSuggestion(Contains("John Smith"))
|
ConfirmSuggestion(Contains("John Smith"))
|
||||||
}).
|
}).
|
||||||
Lines(
|
Lines(
|
||||||
Contains("JS").Contains("two").IsSelected(),
|
Contains("JS").Contains("one").IsSelected(),
|
||||||
Contains("BS").Contains("one"),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user