| package git | |
| import ( | |
| "fmt" | |
| "io" | |
| "os/exec" | |
| "strings" | |
| ) | |
| // IsClean checks if the repo in the current directory is clean. | |
| // | |
| // Untracked files are okay, but modified, added, or deleted files are not. | |
| func IsClean() (bool, error) { | |
| cmd := exec.Command("git", "status", "--porcelain") | |
| out, err := cmd.Output() | |
| if err != nil { | |
| return false, fmt.Errorf("git status failed: %v", err) | |
| } | |
| lines := strings.Split(string(out), "\n") | |
| for _, line := range lines { | |
| if line == "" { | |
| continue | |
| } | |
| // Ignore untracked files. | |
| if !strings.HasPrefix(line, "??") { | |
| return false, nil | |
| } | |
| } | |
| return true, nil | |
| } | |
| // ApplyPatches applies a list of patches to the current repo with `git am <paths>`. | |
| // | |
| // The combined output of the command is written to the given writer. | |
| func ApplyPatches(paths []string, writer io.Writer) error { | |
| cmd := exec.Command("git", append([]string{"am"}, paths...)...) | |
| cmd.Stdout = writer | |
| cmd.Stderr = writer | |
| if err := cmd.Run(); err != nil { | |
| return fmt.Errorf("`git am` command failed: %v", err) | |
| } | |
| return nil | |
| } | |
| // Add adds a list of files to the current repo with `git add <files>`. | |
| // | |
| // The combined output of the command is written to the given writer. | |
| func Add(files []string, writer io.Writer) error { | |
| cmd := exec.Command("git", append([]string{"add"}, files...)...) | |
| cmd.Stdout = writer | |
| cmd.Stderr = writer | |
| if err := cmd.Run(); err != nil { | |
| return fmt.Errorf("`git add` command failed: %v", err) | |
| } | |
| return nil | |
| } | |
| // Commit commits changes to the current repo with `git commit <message>`. | |
| // | |
| // The combined output of the command is written to the given writer. | |
| func Commit(message string, writer io.Writer) error { | |
| cmd := exec.Command("git", "commit", "-m", message) | |
| cmd.Stdout = writer | |
| cmd.Stderr = writer | |
| if err := cmd.Run(); err != nil { | |
| return fmt.Errorf("`git commit` command failed: %v", err) | |
| } | |
| return nil | |
| } | |
| // SwitchToNewBranch creates a branch in the current repo and switches to | |
| // it using `git switch -c <branch>`. | |
| // | |
| // The combined output of the command is written to the given writer. | |
| func SwitchToNewBranch(branch string, writer io.Writer) error { | |
| cmd := exec.Command("git", "switch", "-c", branch) | |
| cmd.Stdout = writer | |
| cmd.Stderr = writer | |
| if err := cmd.Run(); err != nil { | |
| return fmt.Errorf("command %s failed: %v", cmd, err) | |
| } | |
| return nil | |
| } | |
| // FindCommitByPattern searches the git log for the provided pattern and | |
| // returns the first commit hash it finds. | |
| func FindCommitByPattern(pattern string) (string, error) { | |
| cmd := exec.Command("git", "log", "-n1", "--format=%H", "--grep", pattern) | |
| out, err := cmd.CombinedOutput() | |
| if err != nil { | |
| return "", fmt.Errorf("command %s failed: %v", cmd, err) | |
| } | |
| return strings.TrimSpace(string(out)), nil | |
| } | |
| // FormatPatch formats a revision range as patches and writes them to the | |
| // provided output directory. | |
| // | |
| // The combined output of the command is written to the given writer. | |
| func FormatPatch(revisionRange, outDir string, writer io.Writer) error { | |
| cmd := exec.Command("git", "format-patch", revisionRange, "-o", outDir) | |
| cmd.Stdout = writer | |
| cmd.Stderr = writer | |
| if err := cmd.Run(); err != nil { | |
| return fmt.Errorf("command %s failed: %v", cmd, err) | |
| } | |
| return nil | |
| } |