1//go:build static && system_libgit2 2// +build static,system_libgit2 3 4package commit 5 6import ( 7 "context" 8 "encoding/gob" 9 "errors" 10 "fmt" 11 "io" 12 13 git "github.com/libgit2/git2go/v31" 14 "gitlab.com/gitlab-org/gitaly/v14/cmd/gitaly-git2go/git2goutil" 15 "gitlab.com/gitlab-org/gitaly/v14/internal/git2go" 16) 17 18// Run runs the commit subcommand. 19func Run(ctx context.Context, stdin io.Reader, stdout io.Writer) error { 20 var params git2go.CommitParams 21 if err := gob.NewDecoder(stdin).Decode(¶ms); err != nil { 22 return err 23 } 24 25 commitID, err := commit(ctx, params) 26 return gob.NewEncoder(stdout).Encode(git2go.Result{ 27 CommitID: commitID, 28 Error: git2go.SerializableError(err), 29 }) 30} 31 32func commit(ctx context.Context, params git2go.CommitParams) (string, error) { 33 repo, err := git2goutil.OpenRepository(params.Repository) 34 if err != nil { 35 return "", fmt.Errorf("open repository: %w", err) 36 } 37 38 index, err := git.NewIndex() 39 if err != nil { 40 return "", fmt.Errorf("new index: %w", err) 41 } 42 43 var parents []*git.Oid 44 if params.Parent != "" { 45 parentOID, err := git.NewOid(params.Parent) 46 if err != nil { 47 return "", fmt.Errorf("parse base commit oid: %w", err) 48 } 49 50 parents = []*git.Oid{parentOID} 51 52 baseCommit, err := repo.LookupCommit(parentOID) 53 if err != nil { 54 return "", fmt.Errorf("lookup commit: %w", err) 55 } 56 57 baseTree, err := baseCommit.Tree() 58 if err != nil { 59 return "", fmt.Errorf("lookup tree: %w", err) 60 } 61 62 if err := index.ReadTree(baseTree); err != nil { 63 return "", fmt.Errorf("read tree: %w", err) 64 } 65 } 66 67 for _, action := range params.Actions { 68 if err := apply(action, repo, index); err != nil { 69 if git.IsErrorClass(err, git.ErrClassIndex) { 70 err = git2go.IndexError(err.Error()) 71 } 72 73 return "", fmt.Errorf("apply action %T: %w", action, err) 74 } 75 } 76 77 treeOID, err := index.WriteTreeTo(repo) 78 if err != nil { 79 return "", fmt.Errorf("write tree: %w", err) 80 } 81 82 author := git.Signature(params.Author) 83 committer := git.Signature(params.Committer) 84 commitID, err := repo.CreateCommitFromIds("", &author, &committer, params.Message, treeOID, parents...) 85 if err != nil { 86 if git.IsErrorClass(err, git.ErrClassInvalid) { 87 return "", git2go.InvalidArgumentError(err.Error()) 88 } 89 90 return "", fmt.Errorf("create commit: %w", err) 91 } 92 93 return commitID.String(), nil 94} 95 96func apply(action git2go.Action, repo *git.Repository, index *git.Index) error { 97 switch action := action.(type) { 98 case git2go.ChangeFileMode: 99 return applyChangeFileMode(action, index) 100 case git2go.CreateDirectory: 101 return applyCreateDirectory(action, repo, index) 102 case git2go.CreateFile: 103 return applyCreateFile(action, index) 104 case git2go.DeleteFile: 105 return applyDeleteFile(action, index) 106 case git2go.MoveFile: 107 return applyMoveFile(action, index) 108 case git2go.UpdateFile: 109 return applyUpdateFile(action, index) 110 default: 111 return errors.New("unsupported action") 112 } 113} 114