Skip to content

Commit 9815ff7

Browse files
committed
feat: git change detection works on any commit
1 parent f23d4c0 commit 9815ff7

File tree

7 files changed

+926
-26
lines changed

7 files changed

+926
-26
lines changed

cmd/terramate/cli/cli.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -754,11 +754,11 @@ func (c *cli) setupGit() {
754754
}
755755

756756
if c.parsedArgs.GitChangeBase != "" {
757-
c.prj.baseRef = c.parsedArgs.GitChangeBase
757+
c.prj.baseRev = c.parsedArgs.GitChangeBase
758758
} else if remoteCheckFailed {
759-
c.prj.baseRef = c.prj.defaultLocalBaseRef()
759+
c.prj.baseRev = c.prj.defaultLocalBaseRef()
760760
} else {
761-
c.prj.baseRef = c.prj.defaultBaseRef()
761+
c.prj.baseRev = c.prj.selectChangeBase()
762762
}
763763
}
764764

@@ -2175,7 +2175,7 @@ func (c *cli) gitSafeguardRemoteEnabled() bool {
21752175
func (c *cli) wd() string { return c.prj.wd }
21762176
func (c *cli) rootdir() string { return c.prj.rootdir }
21772177
func (c *cli) cfg() *config.Root { return &c.prj.root }
2178-
func (c *cli) baseRef() string { return c.prj.baseRef }
2178+
func (c *cli) baseRef() string { return c.prj.baseRev }
21792179
func (c *cli) stackManager() *stack.Manager { return c.prj.stackManager }
21802180
func (c *cli) rootNode() hcl.Config { return c.prj.root.Tree().Node }
21812181
func (c *cli) cred() credential { return c.cloud.client.Credential.(credential) }

cmd/terramate/cli/project.go

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type project struct {
2020
wd string
2121
isRepo bool
2222
root config.Root
23-
baseRef string
23+
baseRev string
2424
normalizedRepo string
2525
stackManager *stack.Manager
2626

@@ -139,18 +139,6 @@ func (p *project) isDefaultBranch() bool {
139139
return branch == git.DefaultBranch
140140
}
141141

142-
// defaultBaseRef returns the baseRef for the current git environment.
143-
func (p *project) defaultBaseRef() string {
144-
if p.isDefaultBranch() &&
145-
p.remoteDefaultCommit() == p.headCommit() {
146-
_, err := p.git.wrapper.RevParse(defaultBranchBaseRef)
147-
if err == nil {
148-
return defaultBranchBaseRef
149-
}
150-
}
151-
return p.defaultBranchRef()
152-
}
153-
154142
// defaultLocalBaseRef returns the baseRef in case there's no remote setup.
155143
func (p *project) defaultLocalBaseRef() string {
156144
git := p.gitcfg()
@@ -163,9 +151,58 @@ func (p *project) defaultLocalBaseRef() string {
163151
return git.DefaultBranch
164152
}
165153

166-
func (p project) defaultBranchRef() string {
167-
git := p.gitcfg()
168-
return git.DefaultRemote + "/" + git.DefaultBranch
154+
// selectChangeBase returns the revision used for change comparison based on the current Git state.
155+
func (p *project) selectChangeBase() string {
156+
gitcfg := p.gitcfg()
157+
gw := p.git.wrapper
158+
159+
// Try using remote default branch first
160+
defaultBranchRev, _ := gw.RevParse(gitcfg.DefaultRemote + "/" + gitcfg.DefaultBranch)
161+
if defaultBranchRev == "" {
162+
// Fall back to local default branch
163+
defaultBranchRev, _ = gw.RevParse(gitcfg.DefaultBranch)
164+
165+
if defaultBranchRev == "" {
166+
// There's no default branch available, so we can't look for a common parent with it.
167+
return defaultBranchBaseRef
168+
}
169+
}
170+
171+
branch, _ := gw.CurrentBranch()
172+
173+
// Either we are on a branch or at a detached HEAD.
174+
if branch != "" {
175+
if branch == gitcfg.DefaultBranch {
176+
// We are at the tip of the default branch -> latest default commit.
177+
return defaultBranchBaseRef
178+
}
179+
180+
// Fallthrough to common parent if not on default branch
181+
} else {
182+
headRev, _ := gw.RevParse("HEAD")
183+
isDetachedDefaultBranchTip := headRev == defaultBranchRev
184+
if isDetachedDefaultBranchTip {
185+
// We are at the latest commit of the default branch.
186+
return defaultBranchBaseRef
187+
}
188+
189+
isDefaultBranchAncestor, _ := gw.IsFirstParentAncestor("HEAD", defaultBranchRev)
190+
if isDefaultBranchAncestor {
191+
// We are at an older commit of the default branch.
192+
return defaultBranchBaseRef
193+
}
194+
195+
// Fallthrough to common parent if not at commit of default branch
196+
}
197+
198+
commonParentWithDefaultBranch, _ := gw.FindNearestCommonParent(defaultBranchRev, "HEAD")
199+
if commonParentWithDefaultBranch != "" {
200+
// We have a nearest common parent with the default branch. Similar to the historic merge base.
201+
return commonParentWithDefaultBranch
202+
}
203+
204+
// Fall back to default. Should never happen unless running on an isolated commit.
205+
return defaultBranchBaseRef
169206
}
170207

171208
func (p *project) setDefaults() error {

0 commit comments

Comments
 (0)