Skip to content

Commit 0d25292

Browse files
authored
Prevent panic in doctor command when running default checks (#21791) (#21807)
Backport #21791 There was a bug introduced in #21352 due to a change of behaviour caused by #19280. This causes a panic on running the default doctor checks because the panic introduced by #19280 assumes that the only way opts.StdOut and opts.Stderr can be set in RunOpts is deliberately. Unfortunately, when running a git.Command the provided RunOpts can be set, therefore if you share a common set of RunOpts these two values can be set by the previous commands. This PR stops using common RunOpts for the commands in that doctor check but secondly stops RunCommand variants from changing the provided RunOpts. Signed-off-by: Andrew Thornton <art27@cantab.net>
1 parent ac409fc commit 0d25292

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

modules/doctor/heads.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool)
1919
numReposUpdated := 0
2020
err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
2121
numRepos++
22-
runOpts := &git.RunOpts{Dir: repo.RepoPath()}
22+
_, _, defaultBranchErr := git.NewCommand(ctx, "rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
2323

24-
_, _, defaultBranchErr := git.NewCommand(ctx, "rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(runOpts)
25-
26-
head, _, headErr := git.NewCommand(ctx, "symbolic-ref", "--short", "HEAD").RunStdString(runOpts)
24+
head, _, headErr := git.NewCommand(ctx, "symbolic-ref", "--short", "HEAD").RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
2725

2826
// what we expect: default branch is valid, and HEAD points to it
2927
if headErr == nil && defaultBranchErr == nil && head == repo.DefaultBranch {
@@ -49,7 +47,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool)
4947
}
5048

5149
// otherwise, let's try fixing HEAD
52-
err := git.NewCommand(ctx, "symbolic-ref").AddDashesAndList("HEAD", repo.DefaultBranch).Run(runOpts)
50+
err := git.NewCommand(ctx, "symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(&git.RunOpts{Dir: repo.RepoPath()})
5351
if err != nil {
5452
logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err)
5553
return nil
@@ -65,7 +63,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool)
6563
logger.Info("Out of %d repos, HEADs for %d are now fixed and HEADS for %d are still broken", numRepos, numReposUpdated, numDefaultBranchesBroken+numHeadsBroken-numReposUpdated)
6664
} else {
6765
if numHeadsBroken == 0 && numDefaultBranchesBroken == 0 {
68-
logger.Info("All %d repos have their HEADs in the correct state")
66+
logger.Info("All %d repos have their HEADs in the correct state", numRepos)
6967
} else {
7068
if numHeadsBroken == 0 && numDefaultBranchesBroken != 0 {
7169
logger.Critical("Default branches are broken for %d/%d repos", numDefaultBranchesBroken, numRepos)

modules/git/command.go

+20-6
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,11 @@ func (c *Command) Run(opts *RunOpts) error {
202202
if opts == nil {
203203
opts = &RunOpts{}
204204
}
205-
if opts.Timeout <= 0 {
206-
opts.Timeout = defaultCommandExecutionTimeout
205+
206+
// We must not change the provided options
207+
timeout := opts.Timeout
208+
if timeout <= 0 {
209+
timeout = defaultCommandExecutionTimeout
207210
}
208211

209212
if len(opts.Dir) == 0 {
@@ -238,7 +241,7 @@ func (c *Command) Run(opts *RunOpts) error {
238241
if opts.UseContextTimeout {
239242
ctx, cancel, finished = process.GetManager().AddContext(c.parentContext, desc)
240243
} else {
241-
ctx, cancel, finished = process.GetManager().AddContextTimeout(c.parentContext, opts.Timeout, desc)
244+
ctx, cancel, finished = process.GetManager().AddContextTimeout(c.parentContext, timeout, desc)
242245
}
243246
defer finished()
244247

@@ -339,9 +342,20 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
339342
}
340343
stdoutBuf := &bytes.Buffer{}
341344
stderrBuf := &bytes.Buffer{}
342-
opts.Stdout = stdoutBuf
343-
opts.Stderr = stderrBuf
344-
err := c.Run(opts)
345+
346+
// We must not change the provided options as it could break future calls - therefore make a copy.
347+
newOpts := &RunOpts{
348+
Env: opts.Env,
349+
Timeout: opts.Timeout,
350+
UseContextTimeout: opts.UseContextTimeout,
351+
Dir: opts.Dir,
352+
Stdout: stdoutBuf,
353+
Stderr: stderrBuf,
354+
Stdin: opts.Stdin,
355+
PipelineFunc: opts.PipelineFunc,
356+
}
357+
358+
err := c.Run(newOpts)
345359
stderr = stderrBuf.Bytes()
346360
if err != nil {
347361
return nil, stderr, &runStdError{err: err, stderr: bytesToString(stderr)}

0 commit comments

Comments
 (0)