mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-10 20:05:50 +02:00
We need to pass %P instead of %p in the format string of the git log command, so that the parent hashes have the full length and can be shared with the real hashes.
93 lines
2.9 KiB
Go
93 lines
2.9 KiB
Go
package git_commands
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
"github.com/jesseduffield/lazygit/pkg/common"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
)
|
|
|
|
type ReflogCommitLoader struct {
|
|
*common.Common
|
|
cmd oscommands.ICmdObjBuilder
|
|
}
|
|
|
|
func NewReflogCommitLoader(common *common.Common, cmd oscommands.ICmdObjBuilder) *ReflogCommitLoader {
|
|
return &ReflogCommitLoader{
|
|
Common: common,
|
|
cmd: cmd,
|
|
}
|
|
}
|
|
|
|
// 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(hashPool *utils.StringPool, lastReflogCommit *models.Commit, filterPath string, filterAuthor string) ([]*models.Commit, bool, error) {
|
|
commits := make([]*models.Commit, 0)
|
|
|
|
cmdArgs := NewGitCmd("log").
|
|
Config("log.showSignature=false").
|
|
Arg("-g").
|
|
Arg("--abbrev=40").
|
|
Arg("--format=%h%x00%ct%x00%gs%x00%P").
|
|
ArgIf(filterAuthor != "", "--author="+filterAuthor).
|
|
ArgIf(filterPath != "", "--follow", "--", filterPath).
|
|
ToArgv()
|
|
|
|
cmdObj := self.cmd.New(cmdArgs).DontLog()
|
|
|
|
onlyObtainedNewReflogCommits := false
|
|
err := cmdObj.RunAndProcessLines(func(line string) (bool, error) {
|
|
commit, ok := self.parseLine(hashPool, line)
|
|
if !ok {
|
|
return false, nil
|
|
}
|
|
|
|
// note that the unix timestamp here is the timestamp of the COMMIT, not the reflog entry itself,
|
|
// so two consecutive reflog entries may have both the same hash and therefore same timestamp.
|
|
// We use the reflog message to disambiguate, and fingers crossed that we never see the same of those
|
|
// twice in a row. Reason being that it would mean we'd be erroneously exiting early.
|
|
if lastReflogCommit != nil && self.sameReflogCommit(commit, lastReflogCommit) {
|
|
onlyObtainedNewReflogCommits = true
|
|
// after this point we already have these reflogs loaded so we'll simply return the new ones
|
|
return true, nil
|
|
}
|
|
|
|
commits = append(commits, commit)
|
|
return false, nil
|
|
})
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
return commits, onlyObtainedNewReflogCommits, nil
|
|
}
|
|
|
|
func (self *ReflogCommitLoader) sameReflogCommit(a *models.Commit, b *models.Commit) bool {
|
|
return a.Hash() == b.Hash() && a.UnixTimestamp == b.UnixTimestamp && a.Name == b.Name
|
|
}
|
|
|
|
func (self *ReflogCommitLoader) parseLine(hashPool *utils.StringPool, line string) (*models.Commit, bool) {
|
|
fields := strings.SplitN(line, "\x00", 4)
|
|
if len(fields) <= 3 {
|
|
return nil, false
|
|
}
|
|
|
|
unixTimestamp, _ := strconv.Atoi(fields[1])
|
|
|
|
parentHashes := fields[3]
|
|
parents := []string{}
|
|
if len(parentHashes) > 0 {
|
|
parents = strings.Split(parentHashes, " ")
|
|
}
|
|
|
|
return models.NewCommit(hashPool, models.NewCommitOpts{
|
|
Hash: fields[0],
|
|
Name: fields[2],
|
|
UnixTimestamp: int64(unixTimestamp),
|
|
Status: models.StatusReflog,
|
|
Parents: parents,
|
|
}), true
|
|
}
|