mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-01 08:20:36 +00:00
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:
+10
-6
@@ -42,30 +42,34 @@ func CreateBundle(ctx context.Context, repo RepositoryFacade, commit string, out
|
||||
// git update-ref refs/bundle/temp-{timestamp} {commit}
|
||||
// git bundle create - refs/bundle/temp-{timestamp}
|
||||
// git update-ref -d refs/bundle/temp-{timestamp}
|
||||
tmp, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-bundle")
|
||||
tmpDir, cleanup, err := setting.AppDataTempDir("git-repo-content").MkdirTempRandom("gitea-bundle")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(gitcmd.RepoLocalPath(repo), "objects"))
|
||||
_, _, err = gitcmd.NewCommand("init", "--bare").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
gitTmpCmd := func() *gitcmd.Command {
|
||||
return gitcmd.NewCommand().WithDir(tmpDir).WithEnv(env)
|
||||
}
|
||||
|
||||
_, _, err = gitTmpCmd().AddArguments("init", "--bare").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
_, _, err = gitTmpCmd().AddArguments("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = gitcmd.NewCommand("branch", "-m", "bundle").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
_, _, err = gitTmpCmd().AddArguments("branch", "-m", "bundle").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpFile := filepath.Join(tmp, "bundle")
|
||||
_, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").WithDir(tmp).WithEnv(env).RunStdString(ctx)
|
||||
tmpFile := filepath.Join(tmpDir, "bundle")
|
||||
_, _, err = gitTmpCmd().AddArguments("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,8 +6,10 @@ package git
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
type BufferedReader interface {
|
||||
@@ -49,8 +51,11 @@ type CatFileBatchCloser interface {
|
||||
// The CatFileBatch and the readers create by it should only be used in the same goroutine.
|
||||
func NewBatch(ctx context.Context, repo RepositoryFacade) (CatFileBatchCloser, error) {
|
||||
repoPath := gitcmd.RepoLocalPath(repo)
|
||||
if DefaultFeatures().SupportCatFileBatchCommand {
|
||||
return newCatFileBatchCommand(ctx, repoPath)
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", repo.LogString())
|
||||
}
|
||||
return newCatFileBatchLegacy(ctx, repoPath)
|
||||
if DefaultFeatures().SupportCatFileBatchCommand {
|
||||
return newCatFileBatchCommand(ctx, repo), nil
|
||||
}
|
||||
return newCatFileBatchLegacy(ctx, repo), nil
|
||||
}
|
||||
|
||||
@@ -5,38 +5,32 @@ package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// catFileBatchCommand implements the CatFileBatch interface using the "cat-file --batch-command" command
|
||||
// for git version >= 2.36
|
||||
// ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch-command
|
||||
type catFileBatchCommand struct {
|
||||
ctx context.Context
|
||||
repoPath string
|
||||
batch *catFileBatchCommunicator
|
||||
ctx context.Context
|
||||
repo RepositoryFacade
|
||||
batch *catFileBatchCommunicator
|
||||
}
|
||||
|
||||
var _ CatFileBatch = (*catFileBatchCommand)(nil)
|
||||
|
||||
func newCatFileBatchCommand(ctx context.Context, repoPath string) (*catFileBatchCommand, error) {
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", filepath.Base(repoPath))
|
||||
}
|
||||
return &catFileBatchCommand{ctx: ctx, repoPath: repoPath}, nil
|
||||
func newCatFileBatchCommand(ctx context.Context, repo RepositoryFacade) *catFileBatchCommand {
|
||||
return &catFileBatchCommand{ctx: ctx, repo: repo}
|
||||
}
|
||||
|
||||
func (b *catFileBatchCommand) getBatch() *catFileBatchCommunicator {
|
||||
if b.batch != nil {
|
||||
return b.batch
|
||||
}
|
||||
b.batch = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch-command"))
|
||||
b.batch = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch-command"))
|
||||
return b.batch
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,10 @@ package git
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
// catFileBatchLegacy implements the CatFileBatch interface using the "cat-file --batch" command and "cat-file --batch-check" command
|
||||
@@ -21,25 +18,22 @@ import (
|
||||
// ref: https://git-scm.com/docs/git-cat-file#Documentation/git-cat-file.txt---batch
|
||||
type catFileBatchLegacy struct {
|
||||
ctx context.Context
|
||||
repoPath string
|
||||
repo RepositoryFacade
|
||||
batchContent *catFileBatchCommunicator
|
||||
batchCheck *catFileBatchCommunicator
|
||||
}
|
||||
|
||||
var _ CatFileBatchCloser = (*catFileBatchLegacy)(nil)
|
||||
|
||||
func newCatFileBatchLegacy(ctx context.Context, repoPath string) (*catFileBatchLegacy, error) {
|
||||
if _, err := os.Stat(repoPath); err != nil {
|
||||
return nil, util.NewNotExistErrorf("repo %q doesn't exist", filepath.Base(repoPath))
|
||||
}
|
||||
return &catFileBatchLegacy{ctx: ctx, repoPath: repoPath}, nil
|
||||
func newCatFileBatchLegacy(ctx context.Context, repo RepositoryFacade) *catFileBatchLegacy {
|
||||
return &catFileBatchLegacy{ctx: ctx, repo: repo}
|
||||
}
|
||||
|
||||
func (b *catFileBatchLegacy) getBatchContent() *catFileBatchCommunicator {
|
||||
if b.batchContent != nil {
|
||||
return b.batchContent
|
||||
}
|
||||
b.batchContent = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch"))
|
||||
b.batchContent = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch"))
|
||||
return b.batchContent
|
||||
}
|
||||
|
||||
@@ -47,7 +41,7 @@ func (b *catFileBatchLegacy) getBatchCheck() *catFileBatchCommunicator {
|
||||
if b.batchCheck != nil {
|
||||
return b.batchCheck
|
||||
}
|
||||
b.batchCheck = newCatFileBatch(b.ctx, b.repoPath, gitcmd.NewCommand("cat-file", "--batch-check"))
|
||||
b.batchCheck = newCatFileBatch(b.ctx, b.repo, gitcmd.NewCommand("cat-file", "--batch-check"))
|
||||
return b.batchCheck
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func (b *catFileBatchCommunicator) Close(err ...error) {
|
||||
}
|
||||
|
||||
// newCatFileBatch opens git cat-file --batch/--batch-check/--batch-command command and prepares the stdin/stdout pipes for communication.
|
||||
func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Command) *catFileBatchCommunicator {
|
||||
func newCatFileBatch(ctx context.Context, repo RepositoryFacade, cmdCatFile *gitcmd.Command) *catFileBatchCommunicator {
|
||||
ctx, ctxCancel := context.WithCancelCause(ctx)
|
||||
stdinWriter, stdoutReader, stdPipeClose := cmdCatFile.MakeStdinStdoutPipe()
|
||||
ret := &catFileBatchCommunicator{
|
||||
@@ -47,7 +47,7 @@ func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Co
|
||||
stdPipeClose()
|
||||
}))
|
||||
|
||||
err := cmdCatFile.WithDir(repoPath).StartWithStderr(ctx)
|
||||
err := cmdCatFile.WithRepo(repo).StartWithStderr(ctx)
|
||||
if err != nil {
|
||||
log.Error("Unable to start git command %v: %v", cmdCatFile.LogString(), err)
|
||||
// ideally here it should return the error, but it would require refactoring all callers
|
||||
@@ -59,7 +59,7 @@ func newCatFileBatch(ctx context.Context, repoPath string, cmdCatFile *gitcmd.Co
|
||||
go func() {
|
||||
err := cmdCatFile.WaitWithStderr()
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
log.Error("cat-file --batch command failed in repo %s, error: %v", repoPath, err)
|
||||
log.Error("cat-file --batch command failed in repo %s, error: %v", repo.LogString(), err)
|
||||
}
|
||||
ret.Close(err)
|
||||
}()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -25,7 +25,7 @@ type RepositoryFacade interface {
|
||||
}
|
||||
|
||||
func (c *Command) WithRepo(repo RepositoryFacade) *Command {
|
||||
c.opts.Dir = RepoLocalPath(repo)
|
||||
c.gitDir = RepoLocalPath(repo)
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@@ -15,19 +15,19 @@ import (
|
||||
)
|
||||
|
||||
// CatFileBatchCheck runs cat-file with --batch-check
|
||||
func CatFileBatchCheck(ctx context.Context, cmd *gitcmd.Command, tmpBasePath string) error {
|
||||
func CatFileBatchCheck(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
cmd.AddArguments("cat-file", "--batch-check")
|
||||
return cmd.WithDir(tmpBasePath).RunWithStderr(ctx)
|
||||
return cmd.WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// CatFileBatchCheckAllObjects runs cat-file with --batch-check --batch-all
|
||||
func CatFileBatchCheckAllObjects(ctx context.Context, cmd *gitcmd.Command, gitRepo *git.Repository) error {
|
||||
return cmd.AddArguments("cat-file", "--batch-check", "--batch-all-objects").WithRepo(gitRepo).RunWithStderr(ctx)
|
||||
func CatFileBatchCheckAllObjects(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch-check", "--batch-all-objects").WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// CatFileBatch runs cat-file --batch
|
||||
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, gitRepo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch").WithRepo(gitRepo).RunWithStderr(ctx)
|
||||
func CatFileBatch(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade) error {
|
||||
return cmd.AddArguments("cat-file", "--batch").WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// BlobsLessThan1024FromCatFileBatchCheck reads a pipeline from cat-file --batch-check and returns the blobs <1024 in size
|
||||
|
||||
@@ -9,16 +9,17 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/git"
|
||||
"gitea.dev/modules/git/gitcmd"
|
||||
)
|
||||
|
||||
// RevListObjects run rev-list --objects from headSHA to baseSHA
|
||||
func RevListObjects(ctx context.Context, cmd *gitcmd.Command, tmpBasePath, headSHA, baseSHA string) error {
|
||||
func RevListObjects(ctx context.Context, cmd *gitcmd.Command, repo git.RepositoryFacade, headSHA, baseSHA string) error {
|
||||
cmd.AddArguments("rev-list", "--objects").AddDynamicArguments(headSHA)
|
||||
if baseSHA != "" {
|
||||
cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA)
|
||||
}
|
||||
return cmd.WithDir(tmpBasePath).RunWithStderr(ctx)
|
||||
return cmd.WithRepo(repo).RunWithStderr(ctx)
|
||||
}
|
||||
|
||||
// BlobsFromRevListObjects reads a RevListAllObjects and only selects blobs
|
||||
|
||||
+5
-5
@@ -105,8 +105,8 @@ func IsRepoURLAccessible(ctx context.Context, url string) bool {
|
||||
}
|
||||
|
||||
// InitRepositoryLocal initializes a new Git repository.
|
||||
func InitRepositoryLocal(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
|
||||
err := os.MkdirAll(repoPath, os.ModePerm)
|
||||
func InitRepositoryLocal(ctx context.Context, localRepoPath string, bare bool, objectFormatName string) error {
|
||||
err := os.MkdirAll(localRepoPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func InitRepositoryLocal(ctx context.Context, repoPath string, bare bool, object
|
||||
if bare {
|
||||
cmd.AddArguments("--bare")
|
||||
}
|
||||
_, _, err = cmd.WithDir(repoPath).RunStdString(ctx)
|
||||
_, _, err = cmd.WithDir(localRepoPath).RunStdString(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ type PushOptions struct {
|
||||
}
|
||||
|
||||
// Push pushs local commits to given remote branch.
|
||||
func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
func Push(ctx context.Context, localRepoPath string, opts PushOptions) error {
|
||||
cmd := gitcmd.NewCommand("push")
|
||||
if opts.ForceWithLease != "" {
|
||||
cmd.AddOptionFormat("--force-with-lease=%s", opts.ForceWithLease)
|
||||
@@ -256,7 +256,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
|
||||
}
|
||||
cmd.AddDashesAndList(remoteBranchArgs...)
|
||||
|
||||
stdout, stderr, err := cmd.WithEnv(opts.Env).WithTimeout(opts.Timeout).WithDir(repoPath).RunStdString(ctx)
|
||||
stdout, stderr, err := cmd.WithEnv(opts.Env).WithTimeout(opts.Timeout).WithDir(localRepoPath).RunStdString(ctx)
|
||||
if err != nil {
|
||||
if strings.Contains(stderr, "non-fast-forward") {
|
||||
return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err}
|
||||
|
||||
@@ -19,11 +19,11 @@ type TemplateSubmoduleCommit struct {
|
||||
|
||||
// GetTemplateSubmoduleCommits returns a list of submodules paths and their commits from a repository
|
||||
// This function is only for generating new repos based on existing template, the template couldn't be too large.
|
||||
func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submoduleCommits []TemplateSubmoduleCommit, _ error) {
|
||||
func GetTemplateSubmoduleCommits(ctx context.Context, repo gitcmd.RepositoryFacade) (submoduleCommits []TemplateSubmoduleCommit, _ error) {
|
||||
cmd := gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD")
|
||||
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
|
||||
defer stdoutReaderClose()
|
||||
err := cmd.WithDir(repoPath).
|
||||
err := cmd.WithRepo(repo).
|
||||
WithPipelineFunc(func(ctx gitcmd.Context) error {
|
||||
scanner := bufio.NewScanner(stdoutReader)
|
||||
for scanner.Scan() {
|
||||
@@ -46,11 +46,11 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul
|
||||
|
||||
// AddTemplateSubmoduleIndexes Adds the given submodules to the git index.
|
||||
// It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir.
|
||||
func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||
func AddTemplateSubmoduleIndexes(ctx context.Context, tmpRepoPath string, submodules []TemplateSubmoduleCommit) error {
|
||||
for _, submodule := range submodules {
|
||||
cmd := gitcmd.NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path)
|
||||
if stdout, _, err := cmd.WithDir(repoPath).RunStdString(ctx); err != nil {
|
||||
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err)
|
||||
if stdout, _, err := cmd.WithDir(tmpRepoPath).RunStdString(ctx); err != nil {
|
||||
log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, tmpRepoPath, stdout, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGetTemplateSubmoduleCommits(t *testing.T) {
|
||||
testRepoPath := filepath.Join(testReposDir, "repo4_submodules")
|
||||
testRepoPath := mockRepository("repo4_submodules")
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), testRepoPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
_, _, err = gitcmd.NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").WithDir(tmpDir).RunStdString(ctx)
|
||||
require.NoError(t, err)
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir)
|
||||
submodules, err := GetTemplateSubmoduleCommits(t.Context(), mockRepository(tmpDir))
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, submodules, 1)
|
||||
assert.Equal(t, "new-dir", submodules[0].Path)
|
||||
|
||||
Reference in New Issue
Block a user