package git import ( "fmt" "os/exec" "strings" ) func snapshotPrefix(taskID string) string { return "refs/byre/tasks/" + taskID + "/snap/" } func SnapshotRef(taskID string, n int) string { return fmt.Sprintf("%s%d", snapshotPrefix(taskID), n) } func CommitSnapshot(dir, tree, ref, message string, env []string) (string, error) { head, err := Head(dir) if err != nil { return "", err } commit, err := runEnv(dir, env, "commit-tree", tree, "-p", head, "-m", message) if err != nil { return "", err } _, err = run(dir, "update-ref", ref, commit, "") if err != nil { return "", err } return commit, nil } func SnapshotRefs(repo, taskID string) ([]string, error) { out, err := run(repo, "for-each-ref", "--format=%(refname)", snapshotPrefix(taskID)) if err != nil { return nil, err } if out == "" { return []string{}, nil } return strings.Split(out, "\n"), nil } func DeleteSnapshotRefs(repo, taskID string) error { refs, err := SnapshotRefs(repo, taskID) if err != nil { return err } if len(refs) == 0 { return nil } b := &strings.Builder{} for _, ref := range refs { fmt.Fprintf(b, "delete %s\n", ref) } cmd := exec.Command("git", "update-ref", "--stdin") cmd.Dir = repo cmd.Stdin = strings.NewReader(b.String()) out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("git update-ref --stdin: %w: %s", err, strings.TrimSpace(string(out))) } return nil }