diff options
author | Stefan Haller <stefan@haller-berlin.de> | 2023-06-10 10:49:18 +0200 |
---|---|---|
committer | Stefan Haller <stefan@haller-berlin.de> | 2023-06-26 09:02:46 +0200 |
commit | ff8bc91a8e5ad22be798c512ad4c3bc8e80d306b (patch) | |
tree | 09d2136188840317702e4a4ba956b110cdc29b6e | |
parent | 4e573e4bb12ff1fb603366522ca48317f3a4f778 (diff) |
Use remote upstreams of main branches to determine merged status of commits
This solves three problems:
1. When the local main branch is behind its upstream, the merged status of
commits of a feature branch sitting on origin/main was not correct. This can
easily happen when you rebase a branch onto origin/main instead of main, and
don't bother keeping local main up to date.
2. It works when you don't have the main branch locally at all. This could
happen when you check out a colleague's feature branch that goes off of
"develop", but you don't have "develop" locally yourself because you normally
only work on "main".
3. It also works when you work on a main branch itself, e.g. by committing to it
directly, or by merging a branch locally. These local commits on a main
branch would previously be shown in green instead of red; this broke with
910a61dc46.
-rw-r--r-- | pkg/commands/git_commands/commit_loader.go | 28 | ||||
-rw-r--r-- | pkg/commands/git_commands/commit_loader_test.go | 28 |
2 files changed, 43 insertions, 13 deletions
diff --git a/pkg/commands/git_commands/commit_loader.go b/pkg/commands/git_commands/commit_loader.go index e5b9ab0f4..99119f6aa 100644 --- a/pkg/commands/git_commands/commit_loader.go +++ b/pkg/commands/git_commands/commit_loader.go @@ -490,13 +490,33 @@ func (self *CommitLoader) getMergeBase(refName string) string { func (self *CommitLoader) getExistingMainBranches() []string { return lo.FilterMap(self.UserConfig.Git.MainBranches, func(branchName string, _ int) (string, bool) { - ref := "refs/heads/" + branchName + // Try to determine upstream of local main branch + if ref, err := self.cmd.New( + NewGitCmd("rev-parse").Arg("--symbolic-full-name", branchName+"@{u}").ToArgv(), + ).DontLog().RunWithOutput(); err == nil { + return strings.TrimSpace(ref), true + } + + // If this failed, a local branch for this main branch doesn't exist or it + // has no upstream configured. Try looking for one in the "origin" remote. + ref := "refs/remotes/origin/" + branchName if err := self.cmd.New( NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(), - ).DontLog().Run(); err != nil { - return "", false + ).DontLog().Run(); err == nil { + return ref, true } - return ref, true + + // If this failed as well, try if we have the main branch as a local + // branch. This covers the case where somebody is using git locally + // for something, but never pushing anywhere. + ref = "refs/heads/" + branchName + if err := self.cmd.New( + NewGitCmd("rev-parse").Arg("--verify", "--quiet", ref).ToArgv(), + ).DontLog().Run(); err == nil { + return ref, true + } + + return "", false }) } diff --git a/pkg/commands/git_commands/commit_loader_test.go b/pkg/commands/git_commands/commit_loader_test.go index 5c0102964..9f7f60bc5 100644 --- a/pkg/commands/git_commands/commit_loader_test.go +++ b/pkg/commands/git_commands/commit_loader_test.go @@ -67,17 +67,21 @@ func TestGetCommits(t *testing.T) { logOrder: "topo-order", rebaseMode: enums.REBASE_MODE_NONE, opts: GetCommitsOptions{RefName: "HEAD", IncludeRebaseCommits: false}, - mainBranches: []string{"master", "main"}, + mainBranches: []string{"master", "main", "develop"}, runner: oscommands.NewFakeRunner(t). // here it's seeing which commits are yet to be pushed ExpectGitArgs([]string{"merge-base", "HEAD", "HEAD@{u}"}, "b21997d6b4cbdf84b149d8e6a2c4d06a8e9ec164", nil). // here it's actually getting all the commits in a formatted form, one per line ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, commitsOutput, nil). - // here it's testing which of the configured main branches exist - ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/master"}, "", nil). // this one does - ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/main"}, "", errors.New("error")). // this one doesn't + // here it's testing which of the configured main branches have an upstream + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). // this one does + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/main"}, "", nil). // yep, origin/main exists + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "", errors.New("error")). // this one doesn't, so it checks origin instead + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/develop"}, "", errors.New("error")). // doesn't exist there, either, so it checks for a local branch + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/develop"}, "", errors.New("error")). // no local branch either // here it's seeing where our branch diverged from the master branch so that we can mark that commit and parent commits as 'merged' - ExpectGitArgs([]string{"merge-base", "HEAD", "refs/heads/master"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil), + ExpectGitArgs([]string{"merge-base", "HEAD", "refs/remotes/origin/master", "refs/remotes/origin/main"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil), expectedCommits: []*models.Commit{ { @@ -207,7 +211,11 @@ func TestGetCommits(t *testing.T) { // here it's actually getting all the commits in a formatted form, one per line ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil). // here it's testing which of the configured main branches exist; neither does + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "", errors.New("error")). + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/master"}, "", errors.New("error")). ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/master"}, "", errors.New("error")). + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/main"}, "", errors.New("error")). ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/main"}, "", errors.New("error")), expectedCommits: []*models.Commit{ @@ -240,12 +248,14 @@ func TestGetCommits(t *testing.T) { // here it's actually getting all the commits in a formatted form, one per line ExpectGitArgs([]string{"log", "HEAD", "--topo-order", "--oneline", "--pretty=format:%H%x00%at%x00%aN%x00%ae%x00%d%x00%p%x00%s", "--abbrev=40", "--no-show-signature", "--"}, singleCommitOutput, nil). // here it's testing which of the configured main branches exist - ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/master"}, "", nil). + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "master@{u}"}, "refs/remotes/origin/master", nil). + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "main@{u}"}, "", errors.New("error")). + ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/remotes/origin/main"}, "", errors.New("error")). ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/main"}, "", errors.New("error")). - ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/develop"}, "", nil). - ExpectGitArgs([]string{"rev-parse", "--verify", "--quiet", "refs/heads/1.0-hotfixes"}, "", nil). + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "develop@{u}"}, "refs/remotes/origin/develop", nil). + ExpectGitArgs([]string{"rev-parse", "--symbolic-full-name", "1.0-hotfixes@{u}"}, "refs/remotes/origin/1.0-hotfixes", nil). // here it's seeing where our branch diverged from the master branch so that we can mark that commit and parent commits as 'merged' - ExpectGitArgs([]string{"merge-base", "HEAD", "refs/heads/master", "refs/heads/develop", "refs/heads/1.0-hotfixes"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil), + ExpectGitArgs([]string{"merge-base", "HEAD", "refs/remotes/origin/master", "refs/remotes/origin/develop", "refs/remotes/origin/1.0-hotfixes"}, "26c07b1ab33860a1a7591a0638f9925ccf497ffa", nil), expectedCommits: []*models.Commit{ { |