refactor: use WithRepo instead of WithDir for most git operations, clean up model migrations (#38555)

by the way, remove some unnecessary "models" imports from model
migration package, fix migration test model init bug
(modelmigration/migrationtest/tests.go)
This commit is contained in:
wxiaoguang
2026-07-21 20:18:00 +08:00
committed by GitHub
parent 8731ea4bbb
commit 91eb14c944
45 changed files with 211 additions and 217 deletions

View File

@@ -35,7 +35,14 @@ type Command struct {
args []string
preErrors []error
configArgs []string
opts runOpts
// Dir is the working dir for the git command, however:
// FIXME: this could be incorrect in many cases, for example:
// * /some/path/.git
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
// The correct approach is to use `--git-dir" global argument or "GIT_DIR=..." environment variable.
gitDir string
cmd *exec.Cmd
@@ -44,10 +51,15 @@ type Command struct {
cmdFinished process.FinishedFunc
cmdStartTime time.Time
pipelineFunc func(Context) error
parentPipeFiles []*os.File
parentPipeReaders []*os.File
childrenPipeFiles []*os.File
cmdEnv []string
cmdTimeout time.Duration
// only os.Pipe and in-memory buffers can work with Stdin safely, see https://github.com/golang/go/issues/77227 if the command would exit unexpectedly
cmdStdin io.Reader
cmdStdout io.Writer
@@ -204,23 +216,6 @@ func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
return ret
}
type runOpts struct {
// TODO: this struct should be removed, the fields can be just merged into the command
Env []string
Timeout time.Duration
// Dir is the working dir for the git command, however:
// FIXME: this could be incorrect in many cases, for example:
// * /some/path/.git
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
// The correct approach is to use `--git-dir" global argument or "GIT_DIR=..." environment variable.
Dir string
PipelineFunc func(Context) error
}
func commonBaseEnvs() []string {
envs := []string{
// Make Gitea use internal git config only, to prevent conflicts with user's git config
@@ -262,17 +257,17 @@ func CommonCmdServEnvs() []string {
var ErrBrokenCommand = errors.New("git command is broken")
func (c *Command) WithDir(dir string) *Command {
c.opts.Dir = dir
c.gitDir = dir
return c
}
func (c *Command) WithEnv(env []string) *Command {
c.opts.Env = env
c.cmdEnv = env
return c
}
func (c *Command) WithTimeout(timeout time.Duration) *Command {
c.opts.Timeout = timeout
c.cmdTimeout = timeout
return c
}
@@ -361,7 +356,7 @@ func (c *Command) WithStdoutCopy(w io.Writer) *Command {
// The returned error of Run / Wait can be joined errors from the pipeline function, context cause, and command exit error.
// Caller can get the pipeline function's error (if any) by UnwrapPipelineError.
func (c *Command) WithPipelineFunc(f func(ctx Context) error) *Command {
c.opts.PipelineFunc = f
c.pipelineFunc = f
return c
}
@@ -418,7 +413,7 @@ func (c *Command) Start(ctx context.Context) (retErr error) {
c.WithParentCallerInfo()
}
// these logs are for debugging purposes only, so no guarantee of correctness or stability
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", c.callerInfo, logArgSanitize(c.opts.Dir), cmdLogString)
desc := fmt.Sprintf("git.Run(by:%s, repo:%s): %s", c.callerInfo, logArgSanitize(c.gitDir), cmdLogString)
log.Debug("git.Command: %s", desc)
_, span := gtprof.GetTracer().Start(ctx, gtprof.TraceSpanGitRun)
@@ -426,24 +421,24 @@ func (c *Command) Start(ctx context.Context) (retErr error) {
span.SetAttributeString(gtprof.TraceAttrFuncCaller, c.callerInfo)
span.SetAttributeString(gtprof.TraceAttrGitCommand, cmdLogString)
if c.opts.Timeout <= 0 {
if c.cmdTimeout <= 0 {
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContext(ctx, desc)
} else {
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContextTimeout(ctx, c.opts.Timeout, desc)
c.cmdCtx, c.cmdCancel, c.cmdFinished = process.GetManager().AddContextTimeout(ctx, c.cmdTimeout, desc)
}
c.cmdStartTime = time.Now()
c.cmd = exec.CommandContext(c.cmdCtx, c.prog, append(c.configArgs, c.args...)...)
if c.opts.Env == nil {
if c.cmdEnv == nil {
c.cmd.Env = os.Environ()
} else {
c.cmd.Env = c.opts.Env
c.cmd.Env = c.cmdEnv
}
process.SetSysProcAttribute(c.cmd)
c.cmd.Env = append(c.cmd.Env, CommonGitCmdEnvs()...)
c.cmd.Dir = c.opts.Dir
c.cmd.Dir = c.gitDir
c.cmd.Stdout = c.cmdStdout
c.cmd.Stdin = c.cmdStdin
c.cmd.Stderr = c.cmdStderr
@@ -481,8 +476,8 @@ func (c *Command) Wait() error {
c.cmdFinished()
}()
if c.opts.PipelineFunc != nil {
errPipeline := c.opts.PipelineFunc(&cmdContext{Context: c.cmdCtx, cmd: c})
if c.pipelineFunc != nil {
errPipeline := c.pipelineFunc(&cmdContext{Context: c.cmdCtx, cmd: c})
if context.Cause(c.cmdCtx) == nil {
// if the context is not canceled explicitly, we need to discard the unread data,