// Make commit and rollback functions for things that mess with // the git config file. This works by saving the contents of the // git config file, and then discarding the saved changes or writing them out. func configCheckpointer(r *git.Repo) (commit, rollback func(chan<- bool)) { configPath := filepath.Join(r.GitDir, "config") stat, err := os.Stat(configPath) if err != nil { log.Printf("Error stat'ing %s:\n", configPath) panic(err) } if !stat.Mode().IsRegular() { log.Panicf("Git config file %s is not a file!\n", configPath) } configContents, err := ioutil.ReadFile(configPath) if err != nil { log.Printf("Error opening %s\n", configPath) panic(err) } // By now we have saved the current config file contents. // No action for commit, we want to leave the new config alone. commit = noopCommit // On rollback, restore the old config. rollback = func(c chan<- bool) { err := ioutil.WriteFile(configPath, configContents, os.FileMode(777)) if err != nil { log.Printf("Failed to restore old config file %s\n", configPath) c <- false } else { c <- true } r.ReloadConfig() } return commit, rollback }
// Make commit and rollback functions for a specific repo where we will // be messing with the branches. func branchCheckpointer(r *git.Repo) (commit, rollback func(chan<- bool)) { // We only care about branch refernces, and we only want to save // the SHA references to the branches. refs := make(map[string]string) for _, ref := range r.Branches() { refs[ref.Name()] = ref.SHA } // There is no commit action. commit = noopCommit // On rollback, force all the branches back to where we were. rollback = func(c chan<- bool) { res := true for name, sha := range refs { cmd, _, _ := r.Git("branch", "-f", name, sha) res = res && (cmd.Run() == nil) } c <- res } return }
func updateRepo(repo *git.Repo, branch string) { Info.Print("Updating GIT repo") repo.Checkout(branch) repo.Fetch([]string{"origin"}) res, err := repo.Ref("remotes/origin/" + branch) if err != nil { Error.Fatal("Failed to get ref to origin/master: ", err) } currentRes, err := repo.CurrentRef() if err != nil { Error.Fatal("Failed to get ref to master: ", err) } err = currentRes.MergeWith(res) if err != nil { Error.Fatal("Failed to merge to master: ", err) } }
// Switch a repository to the empty branch, which will be created // if it does not exist. func switchToEmptyBranch(r *git.Repo) error { contents := bytes.NewBufferString("This branch intentionally left blank\n") readme := filepath.Join(r.WorkDir, "README.empty-branch") if ref, err := r.Ref("empty-branch"); err == nil { return ref.Checkout() } cmd, _, _ := r.Git("checkout", "--orphan", "empty-branch") if cmd.Run() != nil { return fmt.Errorf("Could not create empty-branch") } cmd, _, _ = r.Git("rm", "-r", "--cached", ".") if cmd.Run() != nil { return fmt.Errorf("Could not remove index from empty-branch") } cmd, _, _ = r.Git("clean", "-f", "-x", "-d") if cmd.Run() != nil { return fmt.Errorf("Could not clean working tree for empty-branch") } if ioutil.WriteFile(readme, contents.Bytes(), os.FileMode(0644)) != nil { return fmt.Errorf("Could not create README.empty-branch") } cmd, _, _ = r.Git("add", "README.empty-branch") if cmd.Run() != nil { return fmt.Errorf("Could not add README.empty-branch to empty-branch") } cmd, _, _ = r.Git("commit", "-m", "Created empty branch.") if cmd.Run() != nil { return fmt.Errorf("Could not create initial commit to empty-branch") } return nil }