Skip to content

Commit 06ca857

Browse files
authored
create gitutil (#37)
1 parent 5b14b0e commit 06ca857

42 files changed

Lines changed: 668 additions & 609 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,20 @@ Commands follow this structure:
5858
- Helper functions: `getTargetCommits()`
5959
- Shell completions are provided by cobra's built-in `completion` command
6060

61-
**util/** - Shared utilities
61+
**util/** - Core infrastructure
6262
- `AppConfig`: Dependency injection struct for testing (holds IO, Exit function, paths)
6363
- `execute.go`: Command execution with `ExecuteOrDie()` and `ExecuteOptions`
64-
- `git_util.go`: Git operations (branch detection, stashing, etc.)
65-
- `gh_util.go`: GitHub CLI interactions
64+
- `git_util.go`: Low-level git helpers (`GetCurrentBranchName`, `GetRepoName`) needed by infrastructure
6665
- `TestExecutor`: Mock executor for unit tests (allows faking git/gh responses)
6766

67+
**gitutil/** - Git and GitHub operations
68+
- `git_util.go`: Branch detection (local/remote main, worktrees), stashing, cherry-pick, rebase
69+
- `gh_util.go`: GitHub CLI interactions (PR status, checks, reviews)
70+
- `gh_pr_info.go`: PR info queries (merged/unmerged PR lookup)
71+
- `gh_repo.go`: Repository metadata (name with owner, hostname)
72+
- `gh_checks.go`: CI check status with historical min-checks caching
73+
- `git_rollback.go`: Rollback manager for safe git operations
74+
6875
**templates/** - PR template system and git log parsing
6976
- `GitLog` struct: Represents a commit with its branch and metadata
7077
- `GetNewCommits()`: Parses commits between local main and origin/main
@@ -113,7 +120,7 @@ To add a new command:
113120

114121
## Important Conventions
115122

116-
- **Main branch**: Tool supports either `main` or `master` via `util.GetMainBranchOrDie()`
123+
- **Main branch**: Tool supports either `main` or `master` via `gitutil.GetLocalMainBranchOrDie()` (respects worktrees) and `gitutil.GetRemoteMainBranchOrDie()`
117124
- **Branch naming**: Auto-generated from commit subject (sanitized, max 120 chars)
118125
- **Error handling**: Use `panic()` for user-facing errors (caught by defer/recover in `ExecuteCommand` and `testParseArgumentsWithOut`). This is an intentional design choice, not a code smell. The panic/recover pattern keeps command implementations clean — commands just `panic("message")` on errors and the top-level recover catches them, prints the message, and exits gracefully. Do NOT refactor this to use returned errors; that would add boilerplate to every command for no benefit
119126
- **Logging**: Use `slog` (Debug, Info, Warn, Error levels). Always pass a single `fmt.Sprint(...)` message string — do NOT use slog's key-value args (e.g. `slog.Debug(fmt.Sprint("msg: ", val))` not `slog.Debug("msg", "key", val)`), as the key-value format produces undesirable output with the project's custom logger

commands/command_add_description.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"strings"
1111

1212
"github.com/slackhq/gh-stacked-diff/v2/ai"
13+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1314
"github.com/slackhq/gh-stacked-diff/v2/interactive"
1415
"github.com/slackhq/gh-stacked-diff/v2/templates"
1516
"github.com/slackhq/gh-stacked-diff/v2/util"
@@ -52,7 +53,7 @@ func executeAddDescription(targetCommits []templates.GitLog) {
5253
func addDescriptionForBranch(branch string) {
5354
appConfig := util.GetAppConfig()
5455
slog.Info("Getting PR info for branch " + branch)
55-
pr := util.GetUnmergedPR(branch)
56+
pr := gitutil.GetUnmergedPR(branch)
5657
if pr == nil {
5758
panic("No open PR found for branch " + branch)
5859
}
@@ -63,7 +64,7 @@ func addDescriptionForBranch(branch string) {
6364
util.ExecuteOrDie(util.ExecuteOptions{Io: appConfig.Io}, "gh", "pr", "edit", pr.Number, "--body", newBody)
6465
}
6566

66-
func createAiDescription(pr util.PrInfo) string {
67+
func createAiDescription(pr gitutil.PrInfo) string {
6768
appConfig := util.GetAppConfig()
6869
prompt := ai.GetPromptPrDescription(pr.Number)
6970
outWriter := util.NewWriteRecorder(appConfig.Io.Out)
@@ -104,7 +105,7 @@ func parseDescription(aiOutput string) string {
104105
return string(aiOutput[start+len(begins[beginIndex]) : start+end])
105106
}
106107

107-
func getNewPrBody(pr util.PrInfo, description string) string {
108+
func getNewPrBody(pr gitutil.PrInfo, description string) string {
108109
bodyComment := GENERATED_CLAUDE_SUMMARY_BEGIN + description + GENERATED_CLAUDE_SUMMARY_END
109110

110111
bodyWithoutComment := pr.Body

commands/command_add_description_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
tea "github.com/charmbracelet/bubbletea"
1010

11+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1112
"github.com/slackhq/gh-stacked-diff/v2/interactive"
1213
"github.com/slackhq/gh-stacked-diff/v2/testutil"
1314
"github.com/slackhq/gh-stacked-diff/v2/util"
@@ -25,7 +26,7 @@ func TestSdAddDescription_WhenHasPr_UpdatesPrBody(t *testing.T) {
2526

2627
testParseArguments("new", "1")
2728

28-
testExecutor.SetResponse("101"+util.GhDelim+"first"+util.GhDelim+"open"+util.GhDelim+prBodyBegin+prBodyEnd, nil, "gh", "pr", "list", util.MatchAnyRemainingArgs)
29+
testExecutor.SetResponse("101"+gitutil.GhDelim+"first"+gitutil.GhDelim+"open"+gitutil.GhDelim+prBodyBegin+prBodyEnd, nil, "gh", "pr", "list", util.MatchAnyRemainingArgs)
2930

3031
generatedDescription := "Ai\ngenerated\ndescription\n"
3132
aiOut := "Based on the PR changes, here's my recommended description:\n```markdown\n" + generatedDescription + "\n```\n"
@@ -68,7 +69,7 @@ func TestSdAddDescription_WhenHasPrHasExistingComment_ReplacesComment(t *testing
6869
originalBody := prBodyBegin + addition + prBodyEnd
6970
testParseArguments("new", "1")
7071

71-
testExecutor.SetResponse("101"+util.GhDelim+"first"+util.GhDelim+"open"+util.GhDelim+originalBody, nil, "gh", "pr", "list", util.MatchAnyRemainingArgs)
72+
testExecutor.SetResponse("101"+gitutil.GhDelim+"first"+gitutil.GhDelim+"open"+gitutil.GhDelim+originalBody, nil, "gh", "pr", "list", util.MatchAnyRemainingArgs)
7273

7374
updatedDescription := "this is an\nupdated description\n"
7475
aiOut := "Based on the PR changes, here's my recommended description:\n```markdown\n" + updatedDescription + "\n```\n"

commands/command_add_reviewers.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"sync"
99
"time"
1010

11+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1112
"github.com/slackhq/gh-stacked-diff/v2/interactive"
1213
"github.com/slackhq/gh-stacked-diff/v2/templates"
1314
"github.com/slackhq/gh-stacked-diff/v2/util"
@@ -101,7 +102,7 @@ func checkBranch(targetCommit templates.GitLog, opts AddReviewersOptions, progre
101102
addReviewers(targetCommit, opts.Reviewers, progressIndicator, index)
102103
}
103104
if opts.AutoMerge {
104-
util.ExecuteOrDie(util.ExecuteOptions{Retries: util.GhRetries}, "gh", "pr", "merge", targetCommit.Branch, "--auto", "--squash")
105+
util.ExecuteOrDie(util.ExecuteOptions{Retries: gitutil.GhRetries}, "gh", "pr", "merge", targetCommit.Branch, "--auto", "--squash")
105106
progressIndicator.SetLogLine(index, "Auto-merge enabled")
106107
}
107108
}
@@ -123,7 +124,7 @@ func waitForChecks(targetCommit templates.GitLog, opts AddReviewersOptions, prog
123124
countdown(progressIndicator, index, int(opts.WaitBeforePolling.Seconds()), "for Github to add checks to pushed changes")
124125
}
125126
for {
126-
summary := util.GetChecksStatus(targetCommit.Branch, opts.MinChecks)
127+
summary := gitutil.GetChecksStatus(targetCommit.Branch, opts.MinChecks)
127128
progressIndicator.SetProgress(index, float64(summary.PercentageComplete()))
128129
if summary.IsFailing() {
129130
if !opts.Silent {
@@ -150,7 +151,7 @@ func waitForChecks(targetCommit templates.GitLog, opts AddReviewersOptions, prog
150151

151152
func markPrReady(targetCommit templates.GitLog, progressIndicator *interactive.ProgressIndicator, index int) {
152153
progressIndicator.SetLogLine(index, "Marking PR as ready for review")
153-
util.ExecuteOrDie(util.ExecuteOptions{Retries: util.GhRetries}, "gh", "pr", "ready", targetCommit.Branch)
154+
util.ExecuteOrDie(util.ExecuteOptions{Retries: gitutil.GhRetries}, "gh", "pr", "ready", targetCommit.Branch)
154155
progressIndicator.SetLogLine(index, "PR marked as ready for review")
155156
}
156157

@@ -177,7 +178,7 @@ func addReviewers(targetCommit templates.GitLog, reviewers string, progressIndic
177178
}
178179

179180
func getNonApprovingUsers(commit templates.GitLog, reviewers string) (string, string) {
180-
allApprovingUsers := util.GetAllApprovingUsers(commit.Branch)
181+
allApprovingUsers := gitutil.GetAllApprovingUsers(commit.Branch)
181182
approvingUsers := make([]string, 0)
182183
nonApprovingUsers := make([]string, 0)
183184
for _, reviewer := range strings.Split(reviewers, ",") {

commands/command_add_reviewers_test.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"errors"
1515

16+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1617
"github.com/slackhq/gh-stacked-diff/v2/interactive"
1718
"github.com/slackhq/gh-stacked-diff/v2/templates"
1819
"github.com/slackhq/gh-stacked-diff/v2/testutil"
@@ -31,10 +32,10 @@ func TestSdAddReviewers_AddReviewers(t *testing.T) {
3132
allCommits := templates.GetAllCommits()
3233
testExecutor.SetResponse(
3334
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
34-
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks),
35+
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks),
3536
nil, "gh", "pr", "view", util.MatchAnyRemainingArgs)
3637

37-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--reviewers=mybestie", allCommits[0].Commit)
38+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--reviewers=mybestie", allCommits[0].Commit)
3839

3940
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
4041
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "mybestie"}
@@ -57,10 +58,10 @@ func TestSdAddReviewers_WhenUsingListIndicator_AddReviewers(t *testing.T) {
5758
allCommits := templates.GetAllCommits()
5859
testExecutor.SetResponse(
5960
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
60-
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks),
61+
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks),
6162
nil, "gh", "pr", "view", util.MatchAnyRemainingArgs)
6263

63-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--indicator=list", "--reviewers=mybestie", "1")
64+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--indicator=list", "--reviewers=mybestie", "1")
6465

6566
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
6667
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "mybestie"}
@@ -83,11 +84,11 @@ func TestSdAddReviewers_WhenOmittingCommitIndicator_AsksForSelection(t *testing.
8384
allCommits := templates.GetAllCommits()
8485
testExecutor.SetResponse(
8586
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
86-
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks),
87+
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks),
8788
nil, "gh", "pr", "view", util.MatchAnyRemainingArgs)
8889

8990
interactive.SendToProgram(0, interactive.NewMessageKey(tea.KeyEnter))
90-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--indicator=list", "--reviewers=mybestie")
91+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--indicator=list", "--reviewers=mybestie")
9192

9293
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
9394
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "mybestie"}
@@ -109,7 +110,7 @@ func TestSdAddReviewers_WhenUserAlreadyApproved_DoesNotRequestReview(t *testing.
109110

110111
allCommits := templates.GetAllCommits()
111112
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
112-
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks)
113+
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks)
113114
testExecutor.SetResponseFunc(checksSuccess, nil, func(programName string, args ...string) bool {
114115
return programName == "gh" &&
115116
args[0] == "pr" &&
@@ -125,7 +126,7 @@ func TestSdAddReviewers_WhenUserAlreadyApproved_DoesNotRequestReview(t *testing.
125126
slices.Contains(args, "reviews")
126127
})
127128

128-
out := testParseArguments("--log-level=info", "add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--reviewers=alreadyapproved2,mybestie,alreadyapproved1", "1")
129+
out := testParseArguments("--log-level=info", "add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--reviewers=alreadyapproved2,mybestie,alreadyapproved1", "1")
129130

130131
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
131132
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "mybestie"}
@@ -149,15 +150,15 @@ func TestSdAddReviewers_UserChoosesHistory_ChoosesSameReviewers(t *testing.T) {
149150

150151
allCommits := templates.GetAllCommits()
151152
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
152-
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks)
153+
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks)
153154
testExecutor.SetResponseFunc(checksSuccess, nil, func(programName string, args ...string) bool {
154155
return programName == "gh" &&
155156
args[0] == "pr" &&
156157
args[1] == "view" &&
157158
slices.Contains(args, "statusCheckRollup")
158159
})
159160

160-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--reviewers=mybestie", "1")
161+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--reviewers=mybestie", "1")
161162

162163
// Clear responses.
163164
testExecutor.Responses = []util.ExecutedResponse{}
@@ -167,7 +168,7 @@ func TestSdAddReviewers_UserChoosesHistory_ChoosesSameReviewers(t *testing.T) {
167168
interactive.NewMessageKey(tea.KeyUp),
168169
interactive.NewMessageKey(tea.KeyEnter),
169170
)
170-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "1")
171+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "1")
171172

172173
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
173174
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "mybestie"}
@@ -189,7 +190,7 @@ func TestSdAddReviewers_UserChoosesHistoryFromTyped_ChoosesSameReviewers(t *test
189190

190191
allCommits := templates.GetAllCommits()
191192
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
192-
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks)
193+
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks)
193194
testExecutor.SetResponseFunc(checksSuccess, nil, func(programName string, args ...string) bool {
194195
return programName == "gh" &&
195196
args[0] == "pr" &&
@@ -203,7 +204,7 @@ func TestSdAddReviewers_UserChoosesHistoryFromTyped_ChoosesSameReviewers(t *test
203204
interactive.NewMessageRune('y'),
204205
interactive.NewMessageKey(tea.KeyEnter),
205206
)
206-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "1")
207+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "1")
207208

208209
// Clear responses.
209210
testExecutor.Responses = []util.ExecutedResponse{}
@@ -213,7 +214,7 @@ func TestSdAddReviewers_UserChoosesHistoryFromTyped_ChoosesSameReviewers(t *test
213214
interactive.NewMessageKey(tea.KeyUp),
214215
interactive.NewMessageKey(tea.KeyEnter),
215216
)
216-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "1")
217+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "1")
217218

218219
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
219220
ghExpectedArgs := []string{"pr", "edit", allCommits[0].Branch, "--add-reviewer", "my"}
@@ -232,12 +233,12 @@ func TestSdAddReviewers_WhenNoReviewersSelected_DoesNotAddReviewers(t *testing.T
232233
testParseArguments("new", "1")
233234

234235
testExecutor.SetResponse(
235-
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks),
236+
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks),
236237
nil, "gh", "pr", "view", util.MatchAnyRemainingArgs)
237238

238239
// Select PR, then enter empty reviewers.
239240
interactive.SendToProgram(0, interactive.NewMessageKey(tea.KeyEnter))
240-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "1")
241+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "1")
241242

242243
assertGhSubcommandCalled(t, testExecutor.Responses, false, "pr", "edit")
243244
assertGhSubcommandCalled(t, testExecutor.Responses, true, "pr", "ready")
@@ -255,10 +256,10 @@ func TestSdAddReviewers_WhenMergeFlag_EnablesAutoMerge(t *testing.T) {
255256
allCommits := templates.GetAllCommits()
256257
testExecutor.SetResponse(
257258
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
258-
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks),
259+
strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks),
259260
nil, "gh", "pr", "view", util.MatchAnyRemainingArgs)
260261

261-
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(util.DefaultMinChecks), "--merge", "--reviewers=mybestie", allCommits[0].Commit)
262+
testParseArguments("add-reviewers", "--min-checks", fmt.Sprint(gitutil.DefaultMinChecks), "--merge", "--reviewers=mybestie", allCommits[0].Commit)
262263

263264
contains := slices.ContainsFunc(testExecutor.Responses, func(next util.ExecutedResponse) bool {
264265
ghExpectedArgs := []string{"pr", "merge", allCommits[0].Branch, "--auto", "--squash"}
@@ -280,7 +281,7 @@ func TestSdAddReviewers_WhenMinChecksFails_UsesDefault(t *testing.T) {
280281

281282
allCommits := templates.GetAllCommits()
282283
// Each check has 3 values: status, conclusion, and state. Copied DefaultMinChecks times.
283-
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", util.DefaultMinChecks)
284+
checksSuccess := strings.Repeat("SUCCESS\nSUCCESS\nSUCCESS\n", gitutil.DefaultMinChecks)
284285
testExecutor.SetResponseFunc(checksSuccess, nil, func(programName string, args ...string) bool {
285286
return programName == "gh" &&
286287
args[0] == "pr" &&

commands/command_checkout.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package commands
22

33
import (
4+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
45
"github.com/slackhq/gh-stacked-diff/v2/interactive"
56
"github.com/slackhq/gh-stacked-diff/v2/util"
67
"github.com/spf13/cobra"
@@ -12,11 +13,11 @@ func createCheckoutCommand() *cobra.Command {
1213
Short: "Checks out branch associated with commit indicator",
1314
Long: "Checks out the branch associated with commit indicator.\n" +
1415
"\n" +
15-
"For when you want to merge only the branch with with origin/" + util.GetMainBranchForHelp() + ",\n" +
16-
"rather than your entire local " + util.GetMainBranchForHelp() + " branch, verify why \n" +
16+
"For when you want to merge only the branch with with origin/" + gitutil.GetMainBranchForHelp() + ",\n" +
17+
"rather than your entire local " + gitutil.GetMainBranchForHelp() + " branch, verify why \n" +
1718
"CI is failing on that particular branch, or for any other reason.\n" +
1819
"\n" +
19-
"After modifying the branch you can use \"sd replace-commit\" to sync local " + util.GetMainBranchForHelp() + ".",
20+
"After modifying the branch you can use \"sd replace-commit\" to sync local " + gitutil.GetMainBranchForHelp() + ".",
2021
Args: cobra.MaximumNArgs(1),
2122
}
2223
indicatorTypeString := addIndicatorFlag(cmd)

commands/command_code_owners.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"slices"
88
"strings"
99

10+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1011
"github.com/slackhq/gh-stacked-diff/v2/util"
1112
"github.com/spf13/cobra"
1213

@@ -84,7 +85,7 @@ func changedFilesOwners(changedFiles []string) map[string][]string {
8485
Returns changed files against main.
8586
*/
8687
func getChangedFiles() []string {
87-
firstOriginCommit := util.FirstOriginMainCommit(util.GetCurrentBranchName())
88+
firstOriginCommit := gitutil.FirstOriginMainCommit(util.GetCurrentBranchName())
8889
filenamesRaw := util.ExecuteOrDie(util.ExecuteOptions{}, "git", "--no-pager",
8990
"log", "--pretty=format:\"\"", "--name-only", firstOriginCommit+"..HEAD")
9091
return strings.Split(strings.TrimSpace(filenamesRaw), "\n")

commands/command_code_owners_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/stretchr/testify/assert"
99

10+
"github.com/slackhq/gh-stacked-diff/v2/gitutil"
1011
"github.com/slackhq/gh-stacked-diff/v2/testutil"
1112
"github.com/slackhq/gh-stacked-diff/v2/util"
1213
)
@@ -17,7 +18,7 @@ func TestSdCodeOwners_OutputsOwnersOfChangedFiles(t *testing.T) {
1718

1819
testutil.AddCommit("first", "first-not-changed")
1920

20-
util.ExecuteOrDie(util.ExecuteOptions{}, "git", "push", "origin", util.GetLocalMainBranchOrDie())
21+
util.ExecuteOrDie(util.ExecuteOptions{}, "git", "push", "origin", gitutil.GetLocalMainBranchOrDie())
2122

2223
testutil.AddCommit("second", "second-changed")
2324

0 commit comments

Comments
 (0)