You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.0 KiB
Go
193 lines
4.0 KiB
Go
package giq
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"math/rand"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
gogit "github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
)
|
|
|
|
func (g *Gogit) Whoami() string {
|
|
return "I am Gogit!"
|
|
}
|
|
|
|
func detectGitPath(path string) (string, error) {
|
|
path, err := filepath.Abs(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for {
|
|
fi, err := os.Stat(filepath.Join(path, ".git"))
|
|
if err == nil {
|
|
if !fi.IsDir() {
|
|
return "", fmt.Errorf(".git exist but is not a directory")
|
|
}
|
|
return filepath.Join(path, ".git"), nil
|
|
}
|
|
if !os.IsNotExist(err) {
|
|
return "", err
|
|
}
|
|
|
|
ok, err := isGitDir(path)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if ok {
|
|
return path, nil
|
|
}
|
|
|
|
if parent := filepath.Dir(path); parent == path {
|
|
return "", fmt.Errorf(".git not found")
|
|
} else {
|
|
path = parent
|
|
}
|
|
}
|
|
}
|
|
|
|
func isGitDir(path string) (bool, error) {
|
|
markers := []string{"HEAD", "objects", "refs"}
|
|
|
|
for _, marker := range markers {
|
|
_, err := os.Stat(filepath.Join(path, marker))
|
|
if err == nil {
|
|
continue
|
|
}
|
|
if !os.IsNotExist(err) {
|
|
return false, err
|
|
} else {
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func isPublish(r gogit.Repository, prevCommit, lastCommit string) bool {
|
|
ret := false
|
|
pCommit, err := r.ResolveRevision(plumbing.Revision(prevCommit))
|
|
check(err)
|
|
lCommit, err := r.ResolveRevision(plumbing.Revision(lastCommit))
|
|
check(err)
|
|
// fileName := "README.md"
|
|
hashCommitRange, err := r.Log(&gogit.LogOptions{
|
|
From: *lCommit,
|
|
// FileName: &fileName,
|
|
// Order:
|
|
})
|
|
check(err)
|
|
hashCommitMap := make(map[string]bool)
|
|
err = hashCommitRange.ForEach(func(c *object.Commit) error {
|
|
// fmt.Println(c.Hash.String(), c.Message)
|
|
hashCommitMap[c.Hash.String()] = true
|
|
ok := strings.Contains(c.Message, "!publish!")
|
|
if ok {
|
|
ret = true
|
|
return io.EOF
|
|
} else if c.Hash == *pCommit {
|
|
// return storer.ErrStop
|
|
return io.EOF
|
|
}
|
|
return nil
|
|
})
|
|
|
|
if ret {
|
|
return true
|
|
}
|
|
|
|
fileName := "PUBLISH_TRIGGER.md"
|
|
fileNameCommitRange, err := r.Log(&gogit.LogOptions{
|
|
FileName: &fileName,
|
|
})
|
|
check(err)
|
|
err = fileNameCommitRange.ForEach(func(c *object.Commit) error {
|
|
_, ok := hashCommitMap[c.Hash.String()]
|
|
if ok {
|
|
// return storer.ErrStop
|
|
ret = true
|
|
return io.EOF
|
|
}
|
|
return nil
|
|
})
|
|
|
|
// fmt.Println(hashCommitMap)
|
|
if ret {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (g *Gogit) AddBareWorktree(gitRepoPath, gitIndexPath, gitWorktree, gexe string) {
|
|
tmpRepoPath := filepath.Join(os.TempDir(), gitWorktree)
|
|
_, err := gogit.PlainClone(tmpRepoPath, false, &gogit.CloneOptions{
|
|
URL: gitRepoPath,
|
|
Depth: 1,
|
|
Tags: gogit.NoTags,
|
|
// NoCheckout: true,
|
|
})
|
|
check(err)
|
|
// fmt.Println("WORKTREE:", tmpRepoPath)
|
|
}
|
|
func (g *Gogit) RemoveBareWorktree(gitRepoPath, gitIndexPath, gitWorktree, gexe string) {
|
|
tmpRepoPath := filepath.Join(os.TempDir(), gitWorktree)
|
|
err := os.RemoveAll(tmpRepoPath)
|
|
check(err)
|
|
}
|
|
|
|
func (g *Gogit) GitStruct(hookPath, hookContext, hookStdinput, gexe string) Git {
|
|
var git Git
|
|
_ = gexe
|
|
|
|
gitBase, err := detectGitPath(hookPath)
|
|
check(err)
|
|
|
|
repoPath := gitBase
|
|
git.IsBare = true
|
|
|
|
base := path.Base(gitBase)
|
|
if base == ".git" {
|
|
git.IsBare = false
|
|
repoPath = strings.Replace(gitBase, ".git", "", 1)
|
|
}
|
|
|
|
r, err := gogit.PlainOpen(repoPath)
|
|
check(err)
|
|
|
|
gitPreviousCommit, err := r.ResolveRevision(plumbing.Revision("HEAD^"))
|
|
check(err)
|
|
headCommit, err := r.Head()
|
|
check(err)
|
|
|
|
prevCommit := gitPreviousCommit.String()
|
|
lastCommit := headCommit.Hash().String()
|
|
|
|
if hookContext == "PostReceive" {
|
|
revs := strings.Fields(hookStdinput)
|
|
prevCommit = revs[0]
|
|
lastCommit = revs[1]
|
|
}
|
|
|
|
git.Publish = isPublish(*r, prevCommit, lastCommit)
|
|
git.RepoPath = repoPath
|
|
git.PreviousCommit = prevCommit
|
|
git.LastCommit = lastCommit
|
|
git.Branch = headCommit.Name().Short()
|
|
|
|
git.IndexPath = filepath.Join("/", ".git", "index")
|
|
if git.IsBare {
|
|
git.IndexPath = filepath.Join("/", "index")
|
|
}
|
|
|
|
git.Worktree = fmt.Sprintf("sandpoints_repo_%06d", rand.Intn(100001))
|
|
git.TmpRepoPath = filepath.Join(os.TempDir(), git.Worktree)
|
|
return git
|
|
}
|