package giq import ( "bytes" "fmt" "math/rand" "os" "os/exec" "path/filepath" "strings" "time" ) func stringifyOutput(s []byte) string { return strings.TrimSpace(string(s)) } func (g *Sysgit) Whoami() string { return "I am Sysgit!" } func (g *Sysgit) AddBareWorktree(gitRepoPath, gitIndexPath, gitWorktree, gexe string) { tmpRepoPath := filepath.Join(os.TempDir(), gitWorktree) if _, err := os.Stat(tmpRepoPath); err == nil { err := os.RemoveAll(tmpRepoPath) check(err) } err := os.MkdirAll(tmpRepoPath, 0755) check(err) gitAddWorktree := exec.Command(gexe, "-C", gitRepoPath, "worktree", "add", "--detach", tmpRepoPath) gitAddWorktree.Env = os.Environ() gitAddWorktree.Env = append(gitAddWorktree.Env, fmt.Sprintf("GIT_INDEX_FILE=%s%s", gitRepoPath, gitIndexPath)) err = gitAddWorktree.Run() check(err) } func (g *Sysgit) RemoveBareWorktree(gitRepoPath, gitIndexPath, gitWorktree, gexe string) { gitRemoveWorktree := exec.Command(gexe, "-C", gitRepoPath, "worktree", "remove", gitWorktree) gitRemoveWorktree.Env = os.Environ() gitRemoveWorktree.Env = append(gitRemoveWorktree.Env, fmt.Sprintf("GIT_INDEX_FILE=%s%s", gitRepoPath, gitIndexPath)) gitRemoveWorktree.Run() } func isPublished(gitRepoPath, gitIndexPath, prevCommit, lastCommit string) bool { var sout bytes.Buffer //var serr bytes.Buffer commits := exec.Command("git", "-C", gitRepoPath, "rev-list", fmt.Sprintf("%s..%s", prevCommit, lastCommit)) commits.Env = os.Environ() commits.Env = append(commits.Env, fmt.Sprintf("GIT_INDEX_FILE=%s%s", gitRepoPath, gitIndexPath)) commits.Stdout = &sout //commits.Stderr = &serr err := commits.Run() check(err) for _, commit := range strings.Fields(sout.String()) { committedFiles, err := exec.Command("git", "-C", gitRepoPath, "diff-tree", "--no-commit-id", "--name-only", commit).Output() check(err) for _, commitFile := range strings.Fields(string(committedFiles)) { if commitFile == "PUBLISH.trigger.md" { return true } } commitMessages, err := exec.Command("git", "-C", gitRepoPath, "show", "-s", "--format=%B", commit).Output() check(err) if strings.Contains(string(commitMessages), "!publish!") { return true } } return false } func (g *Sysgit) GitStruct(hookPath, hookContext, hookStdinput, gexe string) Git { var git Git repositoryPath, err := exec.Command(gexe, "-C", hookPath, "rev-parse", "--git-dir").Output() check(err) repoPath := stringifyOutput(repositoryPath) gitBareOutput, err := exec.Command(gexe, "-C", repoPath, "rev-parse", "--is-bare-repository").Output() check(err) gitBare := stringifyOutput(gitBareOutput) if gitBare == "true" { git.IsBare = true } else { git.IsBare = false repoPath = strings.Replace(stringifyOutput(repositoryPath), ".git", "", 1) check(err) } gitLastCommit, err := exec.Command(gexe, "-C", repoPath, "rev-parse", "HEAD").Output() check(err) gitPreviousCommit, err := exec.Command(gexe, "-C", repoPath, "rev-parse", "HEAD^").Output() check(err) gitBranch, err := exec.Command(gexe, "-C", repoPath, "branch", "-a", "--contains", "HEAD").Output() check(err) rand.Seed(time.Now().UnixNano()) git.Worktree = fmt.Sprintf("sandpoints_repo_%06d", rand.Intn(100001)) git.TmpRepoPath = filepath.Join(os.TempDir(), git.Worktree) git.RepoPath = repoPath git.LastCommit = stringifyOutput(gitLastCommit) git.PreviousCommit = stringifyOutput(gitPreviousCommit) git.Branch = strings.Replace(stringifyOutput(gitBranch), "* ", "", 1) git.IndexPath = filepath.Join("/", ".git", "index") if git.IsBare { git.IndexPath = filepath.Join("/", "index") } git.Publish = isPublished(git.RepoPath, git.IndexPath, git.PreviousCommit, git.LastCommit) return git }