Skip to content

Commit ae3a18e

Browse files
authored
Remove context from git struct (#33793)
Argument is moved from struct init in command run, which lets us remove context from struct.
1 parent 6c8fb8d commit ae3a18e

File tree

98 files changed

+487
-497
lines changed

Some content is hidden

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

98 files changed

+487
-497
lines changed

Diff for: cmd/hook.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func runHookPostReceive(c *cli.Context) error {
316316
setup(ctx, c.Bool("debug"))
317317

318318
// First of all run update-server-info no matter what
319-
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
319+
if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil {
320320
return fmt.Errorf("Failed to call 'git update-server-info': %w", err)
321321
}
322322

Diff for: models/migrations/v1_12/v128.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,17 @@ func FixMergeBase(x *xorm.Engine) error {
8282

8383
if !pr.HasMerged {
8484
var err error
85-
pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(&git.RunOpts{Dir: repoPath})
85+
pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
8686
if err != nil {
8787
var err2 error
88-
pr.MergeBase, _, err2 = git.NewCommand(git.DefaultContext, "rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).RunStdString(&git.RunOpts{Dir: repoPath})
88+
pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
8989
if err2 != nil {
9090
log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2)
9191
continue
9292
}
9393
}
9494
} else {
95-
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
95+
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
9696
if err != nil {
9797
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
9898
continue
@@ -104,9 +104,9 @@ func FixMergeBase(x *xorm.Engine) error {
104104

105105
refs := append([]string{}, parents[1:]...)
106106
refs = append(refs, gitRefName)
107-
cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
107+
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
108108

109-
pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
109+
pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
110110
if err != nil {
111111
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
112112
continue

Diff for: models/migrations/v1_12/v134.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func RefixMergeBase(x *xorm.Engine) error {
7979

8080
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
8181

82-
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
82+
parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
8383
if err != nil {
8484
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
8585
continue
@@ -92,9 +92,9 @@ func RefixMergeBase(x *xorm.Engine) error {
9292
// we should recalculate
9393
refs := append([]string{}, parents[1:]...)
9494
refs = append(refs, gitRefName)
95-
cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
95+
cmd := git.NewCommand("merge-base").AddDashesAndList(refs...)
9696

97-
pr.MergeBase, _, err = cmd.RunStdString(&git.RunOpts{Dir: repoPath})
97+
pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath})
9898
if err != nil {
9999
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
100100
continue

Diff for: modules/git/batch_reader.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ type WriteCloserError interface {
2929
// This is needed otherwise the git cat-file will hang for invalid repositories.
3030
func ensureValidGitRepository(ctx context.Context, repoPath string) error {
3131
stderr := strings.Builder{}
32-
err := NewCommand(ctx, "rev-parse").
33-
Run(&RunOpts{
32+
err := NewCommand("rev-parse").
33+
Run(ctx, &RunOpts{
3434
Dir: repoPath,
3535
Stderr: &stderr,
3636
})
@@ -61,8 +61,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
6161

6262
go func() {
6363
stderr := strings.Builder{}
64-
err := NewCommand(ctx, "cat-file", "--batch-check").
65-
Run(&RunOpts{
64+
err := NewCommand("cat-file", "--batch-check").
65+
Run(ctx, &RunOpts{
6666
Dir: repoPath,
6767
Stdin: batchStdinReader,
6868
Stdout: batchStdoutWriter,
@@ -109,8 +109,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
109109

110110
go func() {
111111
stderr := strings.Builder{}
112-
err := NewCommand(ctx, "cat-file", "--batch").
113-
Run(&RunOpts{
112+
err := NewCommand("cat-file", "--batch").
113+
Run(ctx, &RunOpts{
114114
Dir: repoPath,
115115
Stdin: batchStdinReader,
116116
Stdout: batchStdoutWriter,

Diff for: modules/git/blame.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
135135
ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit)
136136
}
137137

138-
cmd := NewCommandContextNoGlobals(ctx, "blame", "--porcelain")
138+
cmd := NewCommandNoGlobals("blame", "--porcelain")
139139
if ignoreRevsFile != nil {
140140
// Possible improvement: use --ignore-revs-file /dev/stdin on unix
141141
// There is no equivalent on Windows. May be implemented if Gitea uses an external git backend.
@@ -155,7 +155,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath
155155
go func() {
156156
stderr := bytes.Buffer{}
157157
// TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close"
158-
err := cmd.Run(&RunOpts{
158+
err := cmd.Run(ctx, &RunOpts{
159159
UseContextTimeout: true,
160160
Dir: repoPath,
161161
Stdout: stdout,

Diff for: modules/git/command.go

+17-27
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ const DefaultLocale = "C"
4444
type Command struct {
4545
prog string
4646
args []string
47-
parentContext context.Context
4847
globalArgsLength int
4948
brokenArgs []string
5049
}
@@ -82,7 +81,7 @@ func (c *Command) LogString() string {
8281

8382
// NewCommand creates and returns a new Git Command based on given command and arguments.
8483
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
85-
func NewCommand(ctx context.Context, args ...internal.CmdArg) *Command {
84+
func NewCommand(args ...internal.CmdArg) *Command {
8685
// Make an explicit copy of globalCommandArgs, otherwise append might overwrite it
8786
cargs := make([]string, 0, len(globalCommandArgs)+len(args))
8887
for _, arg := range globalCommandArgs {
@@ -94,31 +93,23 @@ func NewCommand(ctx context.Context, args ...internal.CmdArg) *Command {
9493
return &Command{
9594
prog: GitExecutable,
9695
args: cargs,
97-
parentContext: ctx,
9896
globalArgsLength: len(globalCommandArgs),
9997
}
10098
}
10199

102-
// NewCommandContextNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
100+
// NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specified args and don't use global command args
103101
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
104-
func NewCommandContextNoGlobals(ctx context.Context, args ...internal.CmdArg) *Command {
102+
func NewCommandNoGlobals(args ...internal.CmdArg) *Command {
105103
cargs := make([]string, 0, len(args))
106104
for _, arg := range args {
107105
cargs = append(cargs, string(arg))
108106
}
109107
return &Command{
110-
prog: GitExecutable,
111-
args: cargs,
112-
parentContext: ctx,
108+
prog: GitExecutable,
109+
args: cargs,
113110
}
114111
}
115112

116-
// SetParentContext sets the parent context for this command
117-
func (c *Command) SetParentContext(ctx context.Context) *Command {
118-
c.parentContext = ctx
119-
return c
120-
}
121-
122113
// isSafeArgumentValue checks if the argument is safe to be used as a value (not an option)
123114
func isSafeArgumentValue(s string) bool {
124115
return s == "" || s[0] != '-'
@@ -277,11 +268,11 @@ func CommonCmdServEnvs() []string {
277268
var ErrBrokenCommand = errors.New("git command is broken")
278269

279270
// Run runs the command with the RunOpts
280-
func (c *Command) Run(opts *RunOpts) error {
281-
return c.run(1, opts)
271+
func (c *Command) Run(ctx context.Context, opts *RunOpts) error {
272+
return c.run(ctx, 1, opts)
282273
}
283274

284-
func (c *Command) run(skip int, opts *RunOpts) error {
275+
func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
285276
if len(c.brokenArgs) != 0 {
286277
log.Error("git command is broken: %s, broken args: %s", c.LogString(), strings.Join(c.brokenArgs, " "))
287278
return ErrBrokenCommand
@@ -305,19 +296,18 @@ func (c *Command) run(skip int, opts *RunOpts) error {
305296
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", callerInfo, logArgSanitize(opts.Dir), cmdLogString)
306297
log.Debug("git.Command: %s", desc)
307298

308-
_, span := gtprof.GetTracer().Start(c.parentContext, gtprof.TraceSpanGitRun)
299+
_, span := gtprof.GetTracer().Start(ctx, gtprof.TraceSpanGitRun)
309300
defer span.End()
310301
span.SetAttributeString(gtprof.TraceAttrFuncCaller, callerInfo)
311302
span.SetAttributeString(gtprof.TraceAttrGitCommand, cmdLogString)
312303

313-
var ctx context.Context
314304
var cancel context.CancelFunc
315305
var finished context.CancelFunc
316306

317307
if opts.UseContextTimeout {
318-
ctx, cancel, finished = process.GetManager().AddContext(c.parentContext, desc)
308+
ctx, cancel, finished = process.GetManager().AddContext(ctx, desc)
319309
} else {
320-
ctx, cancel, finished = process.GetManager().AddContextTimeout(c.parentContext, timeout, desc)
310+
ctx, cancel, finished = process.GetManager().AddContextTimeout(ctx, timeout, desc)
321311
}
322312
defer finished()
323313

@@ -410,8 +400,8 @@ func IsErrorExitCode(err error, code int) bool {
410400
}
411401

412402
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
413-
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
414-
stdoutBytes, stderrBytes, err := c.runStdBytes(opts)
403+
func (c *Command) RunStdString(ctx context.Context, opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
404+
stdoutBytes, stderrBytes, err := c.runStdBytes(ctx, opts)
415405
stdout = util.UnsafeBytesToString(stdoutBytes)
416406
stderr = util.UnsafeBytesToString(stderrBytes)
417407
if err != nil {
@@ -422,11 +412,11 @@ func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr Run
422412
}
423413

424414
// RunStdBytes runs the command with options and returns stdout/stderr as bytes. and store stderr to returned error (err combined with stderr).
425-
func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
426-
return c.runStdBytes(opts)
415+
func (c *Command) RunStdBytes(ctx context.Context, opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
416+
return c.runStdBytes(ctx, opts)
427417
}
428418

429-
func (c *Command) runStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
419+
func (c *Command) runStdBytes(ctx context.Context, opts *RunOpts) (stdout, stderr []byte, runErr RunStdError) {
430420
if opts == nil {
431421
opts = &RunOpts{}
432422
}
@@ -449,7 +439,7 @@ func (c *Command) runStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
449439
PipelineFunc: opts.PipelineFunc,
450440
}
451441

452-
err := c.run(2, newOpts)
442+
err := c.run(ctx, 2, newOpts)
453443
stderr = stderrBuf.Bytes()
454444
if err != nil {
455445
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}

Diff for: modules/git/command_race_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ func TestRunWithContextNoTimeout(t *testing.T) {
1515
maxLoops := 10
1616

1717
// 'git --version' does not block so it must be finished before the timeout triggered.
18-
cmd := NewCommand(t.Context(), "--version")
18+
cmd := NewCommand("--version")
1919
for i := 0; i < maxLoops; i++ {
20-
if err := cmd.Run(&RunOpts{}); err != nil {
20+
if err := cmd.Run(t.Context(), &RunOpts{}); err != nil {
2121
t.Fatal(err)
2222
}
2323
}
@@ -27,9 +27,9 @@ func TestRunWithContextTimeout(t *testing.T) {
2727
maxLoops := 10
2828

2929
// 'git hash-object --stdin' blocks on stdin so we can have the timeout triggered.
30-
cmd := NewCommand(t.Context(), "hash-object", "--stdin")
30+
cmd := NewCommand("hash-object", "--stdin")
3131
for i := 0; i < maxLoops; i++ {
32-
if err := cmd.Run(&RunOpts{Timeout: 1 * time.Millisecond}); err != nil {
32+
if err := cmd.Run(t.Context(), &RunOpts{Timeout: 1 * time.Millisecond}); err != nil {
3333
if err != context.DeadlineExceeded {
3434
t.Fatalf("Testing %d/%d: %v", i, maxLoops, err)
3535
}

Diff for: modules/git/command_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,32 @@ import (
1010
)
1111

1212
func TestRunWithContextStd(t *testing.T) {
13-
cmd := NewCommand(t.Context(), "--version")
14-
stdout, stderr, err := cmd.RunStdString(&RunOpts{})
13+
cmd := NewCommand("--version")
14+
stdout, stderr, err := cmd.RunStdString(t.Context(), &RunOpts{})
1515
assert.NoError(t, err)
1616
assert.Empty(t, stderr)
1717
assert.Contains(t, stdout, "git version")
1818

19-
cmd = NewCommand(t.Context(), "--no-such-arg")
20-
stdout, stderr, err = cmd.RunStdString(&RunOpts{})
19+
cmd = NewCommand("--no-such-arg")
20+
stdout, stderr, err = cmd.RunStdString(t.Context(), &RunOpts{})
2121
if assert.Error(t, err) {
2222
assert.Equal(t, stderr, err.Stderr())
2323
assert.Contains(t, err.Stderr(), "unknown option:")
2424
assert.Contains(t, err.Error(), "exit status 129 - unknown option:")
2525
assert.Empty(t, stdout)
2626
}
2727

28-
cmd = NewCommand(t.Context())
28+
cmd = NewCommand()
2929
cmd.AddDynamicArguments("-test")
30-
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
30+
assert.ErrorIs(t, cmd.Run(t.Context(), &RunOpts{}), ErrBrokenCommand)
3131

32-
cmd = NewCommand(t.Context())
32+
cmd = NewCommand()
3333
cmd.AddDynamicArguments("--test")
34-
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
34+
assert.ErrorIs(t, cmd.Run(t.Context(), &RunOpts{}), ErrBrokenCommand)
3535

3636
subCmd := "version"
37-
cmd = NewCommand(t.Context()).AddDynamicArguments(subCmd) // for test purpose only, the sub-command should never be dynamic for production
38-
stdout, stderr, err = cmd.RunStdString(&RunOpts{})
37+
cmd = NewCommand().AddDynamicArguments(subCmd) // for test purpose only, the sub-command should never be dynamic for production
38+
stdout, stderr, err = cmd.RunStdString(t.Context(), &RunOpts{})
3939
assert.NoError(t, err)
4040
assert.Empty(t, stderr)
4141
assert.Contains(t, stdout, "git version")
@@ -53,9 +53,9 @@ func TestGitArgument(t *testing.T) {
5353
}
5454

5555
func TestCommandString(t *testing.T) {
56-
cmd := NewCommandContextNoGlobals(t.Context(), "a", "-m msg", "it's a test", `say "hello"`)
56+
cmd := NewCommandNoGlobals("a", "-m msg", "it's a test", `say "hello"`)
5757
assert.EqualValues(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.LogString())
5858

59-
cmd = NewCommandContextNoGlobals(t.Context(), "url: https://a:b@c/", "/root/dir-a/dir-b")
59+
cmd = NewCommandNoGlobals("url: https://a:b@c/", "/root/dir-a/dir-b")
6060
assert.EqualValues(t, cmd.prog+` "url: https://sanitized-credential@c/" .../dir-a/dir-b`, cmd.LogString())
6161
}

0 commit comments

Comments
 (0)