Skip to content

Commit 762afdf

Browse files
unknwonclaude
andcommitted
fix: address second round of PR review feedback
- Fix exit status matching: replace loose HasPrefix with isExitStatus helper that won't match "exit status 1" against "exit status 128" - Fix opt.Args ordering in ShowRefVerify and DeleteTag: move before --end-of-options so flag args work correctly - Fix gitRun log capture: capture partial stdout on error instead of logging empty output for failed commands - Quote args with special characters in log output for readability - Fix repo_pull_test: "bad_revision" causes exit 128, not exit 1 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c7ab9f2 commit 762afdf

7 files changed

Lines changed: 38 additions & 12 deletions

File tree

command.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io"
1313
"os"
1414
"os/exec"
15+
"strconv"
1516
"strings"
1617
"time"
1718

@@ -85,10 +86,9 @@ func gitRun(ctx context.Context, dir string, args []string, envs []string) ([]by
8586
// line-by-line which corrupts binary-ish output.
8687
stdout := new(bytes.Buffer)
8788
err := cmd.StdOut().Run().Stream(stdout)
88-
if err != nil {
89-
return nil, mapContextError(err, ctx)
90-
}
9189

90+
// Capture (partial) stdout for logging even on error, so failed commands
91+
// produce a useful log entry rather than an empty one.
9292
if logOutput != nil {
9393
data := stdout.Bytes()
9494
limit := len(data)
@@ -101,6 +101,9 @@ func gitRun(ctx context.Context, dir string, args []string, envs []string) ([]by
101101
}
102102
}
103103

104+
if err != nil {
105+
return nil, mapContextError(err, ctx)
106+
}
104107
return stdout.Bytes(), nil
105108
}
106109

@@ -152,7 +155,15 @@ func committerEnvs(committer *Signature) []string {
152155
func logf(dir string, args []string, output []byte) {
153156
cmdStr := "git"
154157
if len(args) > 0 {
155-
cmdStr = "git " + strings.Join(args, " ")
158+
quoted := make([]string, len(args))
159+
for i, a := range args {
160+
if strings.ContainsAny(a, " \t\n\"'\\<>") {
161+
quoted[i] = strconv.Quote(a)
162+
} else {
163+
quoted[i] = a
164+
}
165+
}
166+
cmdStr = "git " + strings.Join(quoted, " ")
156167
}
157168
if len(dir) == 0 {
158169
log("%s\n%s", cmdStr, output)
@@ -204,6 +215,18 @@ func mapContextError(err error, ctx context.Context) error {
204215
return err
205216
}
206217

218+
// isExitStatus reports whether err represents a specific process exit status
219+
// code. It handles both the bare "exit status N" format and the
220+
// "exit status N: <stderr>" format produced by sourcegraph/run.
221+
func isExitStatus(err error, code int) bool {
222+
if err == nil {
223+
return false
224+
}
225+
prefix := fmt.Sprintf("exit status %d", code)
226+
msg := err.Error()
227+
return msg == prefix || strings.HasPrefix(msg, prefix+":")
228+
}
229+
207230
// extractStderr attempts to extract the stderr portion from a sourcegraph/run
208231
// error. The error format is typically "exit status N: <stderr content>".
209232
func extractStderr(err error) string {

repo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ func (r *Repository) Commit(ctx context.Context, committer *Signature, message s
393393

394394
_, err := gitRun(ctx, r.path, args, envs)
395395
// No stderr but exit status 1 means nothing to commit.
396-
if err != nil && strings.HasPrefix(err.Error(), "exit status 1") {
396+
if isExitStatus(err, 1) {
397397
return nil
398398
}
399399
return err
@@ -480,7 +480,7 @@ func (r *Repository) RevParse(ctx context.Context, rev string, opts ...RevParseO
480480

481481
commitID, err := gitRun(ctx, r.path, args, opt.Envs)
482482
if err != nil {
483-
if strings.HasPrefix(err.Error(), "exit status 128") {
483+
if isExitStatus(err, 128) {
484484
return "", ErrRevisionNotExist
485485
}
486486
return "", err

repo_pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (r *Repository) MergeBase(ctx context.Context, base, head string, opts ...M
3131

3232
stdout, err := gitRun(ctx, r.path, args, opt.Envs)
3333
if err != nil {
34-
if strings.HasPrefix(err.Error(), "exit status 1") {
34+
if isExitStatus(err, 1) {
3535
return "", ErrNoMergeBase
3636
}
3737
return "", err

repo_pull_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ import (
1414
func TestRepository_MergeBase(t *testing.T) {
1515
ctx := context.Background()
1616

17-
t.Run("no merge base", func(t *testing.T) {
17+
t.Run("bad revision", func(t *testing.T) {
18+
// "bad_revision" doesn't exist, so git fails with exit status 128 (fatal),
19+
// not exit status 1 (no merge base).
1820
mb, err := testrepo.MergeBase(ctx, "0eedd79eba4394bbef888c804e899731644367fe", "bad_revision")
19-
assert.Equal(t, ErrNoMergeBase, err)
21+
assert.Error(t, err)
2022
assert.Empty(t, mb)
2123
})
2224

repo_reference.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ func (r *Repository) ShowRefVerify(ctx context.Context, ref string, opts ...Show
5151
opt = opts[0]
5252
}
5353

54-
args := []string{"show-ref", "--verify", "--end-of-options", ref}
54+
args := []string{"show-ref", "--verify"}
5555
args = append(args, opt.Args...)
56+
args = append(args, "--end-of-options", ref)
5657

5758
stdout, err := gitRun(ctx, r.path, args, opt.Envs)
5859
if err != nil {

repo_remote.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ func (r *Repository) RemoteRemove(ctx context.Context, name string, opts ...Remo
136136

137137
_, err := gitRun(ctx, r.path, args, opt.Envs)
138138
if err != nil {
139-
// the error status may differ from git clients
140139
if strings.Contains(err.Error(), "error: No such remote") ||
141140
strings.Contains(err.Error(), "fatal: No such remote") {
142141
return ErrRemoteNotExist

repo_tag.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,9 @@ func (r *Repository) DeleteTag(ctx context.Context, name string, opts ...DeleteT
234234
opt = opts[0]
235235
}
236236

237-
args := []string{"tag", "--delete", "--end-of-options", name}
237+
args := []string{"tag", "--delete"}
238238
args = append(args, opt.Args...)
239+
args = append(args, "--end-of-options", name)
239240

240241
_, err := gitRun(ctx, r.path, args, opt.Envs)
241242
return err

0 commit comments

Comments
 (0)