s
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileCommitResult struct {
|
||||
Commit Commit `json:"commit"`
|
||||
}
|
||||
|
||||
func (r *Repository) CreateOrUpdateFile(branch, path, content, message, authorName, authorEmail, expectedSHA string) (*FileCommitResult, error) {
|
||||
parent, err := r.refSHA("refs/heads/" + branch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if parent == "" && expectedSHA != "" {
|
||||
return nil, fmt.Errorf("branch %q does not exist but expectedSHA %s given", branch, expectedSHA)
|
||||
}
|
||||
if parent != "" && expectedSHA != "" && parent != expectedSHA {
|
||||
return nil, fmt.Errorf("branch %q moved: expected %s, current %s", branch, expectedSHA, parent)
|
||||
}
|
||||
|
||||
blobSHA, err := r.hashObject(content, r.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newTree, err := r.withTempIndex(func(idx string) (string, error) {
|
||||
return r.buildTree(idx, parent, path, blobSHA, false)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var parents []string
|
||||
if parent != "" {
|
||||
parents = []string{parent}
|
||||
}
|
||||
commitSHA, err := r.commitTree(newTree, message, authorName, authorEmail, r.Path, parents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.updateRef("refs/heads/"+branch, commitSHA, expectedSHA); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit, err := r.GetCommit(commitSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FileCommitResult{Commit: *commit}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) DeleteFile(branch, path, message, authorName, authorEmail, expectedSHA string) (*FileCommitResult, error) {
|
||||
parent, err := r.refSHA("refs/heads/" + branch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if parent == "" {
|
||||
return nil, fmt.Errorf("branch %q is empty; nothing to delete", branch)
|
||||
}
|
||||
if expectedSHA != "" && parent != expectedSHA {
|
||||
return nil, fmt.Errorf("branch %q moved: expected %s, current %s", branch, expectedSHA, parent)
|
||||
}
|
||||
|
||||
newTree, err := r.withTempIndex(func(idx string) (string, error) {
|
||||
return r.buildTree(idx, parent, path, "", true)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
commitSHA, err := r.commitTree(newTree, message, authorName, authorEmail, r.Path, parent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.updateRef("refs/heads/"+branch, commitSHA, expectedSHA); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit, err := r.GetCommit(commitSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FileCommitResult{Commit: *commit}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) withTempIndex(fn func(idx string) (string, error)) (string, error) {
|
||||
f, err := os.CreateTemp("", "simplegit-index-*")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
name := f.Name()
|
||||
f.Close()
|
||||
|
||||
_ = os.Remove(name)
|
||||
defer os.Remove(name)
|
||||
return fn(name)
|
||||
}
|
||||
|
||||
func (r *Repository) buildTree(indexFile, parent, path, blobSHA string, remove bool) (string, error) {
|
||||
env := "GIT_INDEX_FILE=" + indexFile
|
||||
|
||||
if parent != "" {
|
||||
if _, _, err := NewCommand("read-tree").
|
||||
AddDynamicArguments(parent).
|
||||
WithDir(r.Path).WithEnv(env).
|
||||
RunStdString(r.ctx); err != nil {
|
||||
return "", fmt.Errorf("read-tree: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if remove {
|
||||
if err := r.removePathFromIndex(r.Path, path, env); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
|
||||
if _, _, err := NewCommand("update-index", "--add", "--replace", "--cacheinfo").
|
||||
AddDynamicArguments("100644," + blobSHA + "," + path).
|
||||
WithDir(r.Path).WithEnv(env).
|
||||
RunStdString(r.ctx); err != nil {
|
||||
return "", fmt.Errorf("update-index --cacheinfo: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
out, _, err := NewCommand("write-tree").
|
||||
WithDir(r.Path).WithEnv(env).
|
||||
RunStdString(r.ctx)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("write-tree: %w", err)
|
||||
}
|
||||
return strings.TrimSpace(out), nil
|
||||
}
|
||||
Reference in New Issue
Block a user