Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/gitaly-git2go/submodule.go')
-rw-r--r--cmd/gitaly-git2go/submodule.go136
1 files changed, 136 insertions, 0 deletions
diff --git a/cmd/gitaly-git2go/submodule.go b/cmd/gitaly-git2go/submodule.go
new file mode 100644
index 000000000..d256188b1
--- /dev/null
+++ b/cmd/gitaly-git2go/submodule.go
@@ -0,0 +1,136 @@
+// +build static,system_libgit2
+
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "time"
+
+ git "github.com/libgit2/git2go/v30"
+ "gitlab.com/gitlab-org/gitaly/internal/git2go"
+)
+
+type submoduleSubcommand struct {
+ request string
+}
+
+func (cmd *submoduleSubcommand) Flags() *flag.FlagSet {
+ flags := flag.NewFlagSet("submodule", flag.ExitOnError)
+ flags.StringVar(&cmd.request, "request", "", "git2go.SubmoduleCommand")
+ return flags
+}
+
+func (cmd *submoduleSubcommand) Run(_ context.Context, _ io.Reader, w io.Writer) error {
+ request, err := git2go.SubmoduleCommandFromSerialized(cmd.request)
+ if err != nil {
+ return fmt.Errorf("deserializing submodule command request: %w", err)
+ }
+
+ if request.AuthorDate.IsZero() {
+ request.AuthorDate = time.Now()
+ }
+
+ smCommitOID, err := git.NewOid(request.CommitSHA)
+ if err != nil {
+ return fmt.Errorf("converting %s to OID: %w", request.CommitSHA, err)
+ }
+
+ repo, err := git.OpenRepository(request.Repository)
+ if err != nil {
+ return fmt.Errorf("open repository: %w", err)
+ }
+
+ fullBranchRefName := "refs/heads/" + request.Branch
+ o, err := repo.RevparseSingle(fullBranchRefName)
+ if err != nil {
+ return fmt.Errorf("%s: %w", git2go.LegacyErrPrefixInvalidBranch, err) //nolint
+ }
+
+ startCommit, err := o.AsCommit()
+ if err != nil {
+ return fmt.Errorf("peeling %s as a commit: %w", o.Id(), err)
+ }
+
+ rootTree, err := startCommit.Tree()
+ if err != nil {
+ return fmt.Errorf("root tree from starting commit: %w", err)
+ }
+
+ index, err := git.NewIndex()
+ if err != nil {
+ return fmt.Errorf("creating new index: %w", err)
+ }
+
+ if err := index.ReadTree(rootTree); err != nil {
+ return fmt.Errorf("reading root tree into index: %w", err)
+ }
+
+ smEntry, err := index.EntryByPath(request.Submodule, 0)
+ if err != nil {
+ return fmt.Errorf(
+ "%s: %w",
+ git2go.LegacyErrPrefixInvalidSubmodulePath, err,
+ ) //nolint
+ }
+
+ if smEntry.Id.Cmp(smCommitOID) == 0 {
+ //nolint
+ return fmt.Errorf(
+ "The submodule %s is already at %s",
+ request.Submodule, request.CommitSHA,
+ )
+ }
+
+ if smEntry.Mode != git.FilemodeCommit {
+ return fmt.Errorf(
+ "%s: %w",
+ git2go.LegacyErrPrefixInvalidSubmodulePath, err,
+ ) //nolint
+ }
+
+ newEntry := *smEntry // copy by value
+ newEntry.Id = smCommitOID // assign new commit SHA
+ if err := index.Add(&newEntry); err != nil {
+ return fmt.Errorf("add new submodule entry to index: %w", err)
+ }
+
+ newRootTreeOID, err := index.WriteTreeTo(repo)
+ if err != nil {
+ return fmt.Errorf("write index to repo: %w", err)
+ }
+
+ newTree, err := repo.LookupTree(newRootTreeOID)
+ if err != nil {
+ return fmt.Errorf("looking up new submodule entry root tree: %w", err)
+ }
+
+ committer := git.Signature(
+ git2go.NewSignature(
+ request.AuthorName,
+ request.AuthorMail,
+ request.AuthorDate,
+ ),
+ )
+ newCommitOID, err := repo.CreateCommit(
+ "", // caller should update branch with hooks
+ &committer,
+ &committer,
+ request.Message,
+ newTree,
+ startCommit,
+ )
+ if err != nil {
+ // nolint
+ return fmt.Errorf(
+ "%s: %w",
+ git2go.LegacyErrPrefixFailedCommit, err,
+ )
+ }
+
+ return git2go.SubmoduleResult{
+ CommitID: newCommitOID.String(),
+ }.SerializeTo(w)
+}