// Input is a line containing tab-separated local branch and remote branch. // For example, "master\torigin/master". func branchRemoteInfo(repo *exp13.VcsState) func(line []byte) []byte { return func(line []byte) []byte { branchRemote := strings.Split(trim.LastNewline(string(line)), "\t") if len(branchRemote) != 2 { return []byte("error: len(branchRemote) != 2") } branch := branchRemote[0] branchDisplay := branch if branch == repo.VcsLocal.LocalBranch { branchDisplay = "**" + branch + "**" } remote := branchRemote[1] if remote == "" { return []byte(fmt.Sprintf("%s | | | \n", branchDisplay)) } cmd := exec.Command("git", "rev-list", "--count", "--left-right", remote+"..."+branch) cmd.Dir = repo.Vcs.RootPath() out, err := cmd.Output() if err != nil { // This usually happens when the remote branch is gone. remoteDisplay := "~~" + remote + "~~" return []byte(fmt.Sprintf("%s | %s | | \n", branchDisplay, remoteDisplay)) } behindAhead := strings.Split(trim.LastNewline(string(out)), "\t") return []byte(fmt.Sprintf("%s | %s | %s | %s\n", branchDisplay, remote, behindAhead[0], behindAhead[1])) } }
func Example() { fmt.Printf("%q\n", trim.LastNewline("String\n")) fmt.Printf("%q\n", trim.LastNewline("String")) fmt.Printf("%q\n", trim.LastNewline("")) fmt.Printf("%q\n", trim.LastNewline("\n")) // Output: // "String" // "String" // "" // "" }
func (this *gitVcs) GetRemote() string { cmd := exec.Command("git", "ls-remote", "--get-url", "origin") cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { return trim.LastNewline(string(out)) } else { return "" } }
func getHgRepoRoot(path string) (isHgRepo bool, rootPath string) { cmd := exec.Command("hg", "root") cmd.Dir = path if out, err := cmd.Output(); err == nil { return true, trim.LastNewline(string(out)) } else { return false, "" } }
func (this *hgVcs) GetLocalBranch() string { cmd := exec.Command("hg", "branch") cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { return trim.LastNewline(string(out)) } else { return "" } }
func (this *hgVcs) GetRemote() string { cmd := exec.Command("hg", "paths", "default") cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { return trim.LastNewline(string(out)) } else { return "" } }
func (this *gitVcs) IsContained(rev string) bool { cmd := exec.Command("git", "branch", "--list", "--contains", rev, this.GetDefaultBranch()) cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { if len(out) >= 2 && trim.LastNewline(string(out[2:])) == this.GetDefaultBranch() { return true } } return false }
func (this *gitVcs) GetLocalBranch() string { cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { // Since rev-parse is considered porcelain and may change, need to error-check its output. return trim.LastNewline(string(out)) } else { return "" } }
func getGitRepoRoot(path string) (isGitRepo bool, rootPath string) { cmd := exec.Command("git", "rev-parse", "--show-toplevel") cmd.Dir = path if out, err := cmd.Output(); err == nil { // Since rev-parse is considered porcelain and may change, need to error-check its output return true, trim.LastNewline(string(out)) } else { return false, "" } }
// Branches returns a Markdown table of branches with ahead/behind information relative to master branch. func Branches(repo *exp13.VcsState, opt BranchesOptions) string { opt.defaults() switch repo.Vcs.Type() { case vcs.Git: branchInfo := func(line []byte) []byte { branch := trim.LastNewline(string(line)) branchDisplay := branch if branch == repo.VcsLocal.LocalBranch { branchDisplay = "**" + branch + "**" } cmd := exec.Command("git", "rev-list", "--count", "--left-right", opt.Base+"..."+branch) cmd.Dir = repo.Vcs.RootPath() out, err := cmd.Output() if err != nil { log.Printf("error running %v: %v\n", cmd.Args, err) return []byte(fmt.Sprintf("%s | ? | ?\n", branchDisplay)) } behindAhead := strings.Split(trim.LastNewline(string(out)), "\t") return []byte(fmt.Sprintf("%s | %s | %s\n", branchDisplay, behindAhead[0], behindAhead[1])) } p := pipe.Script( pipe.Println("Branch | Behind | Ahead"), pipe.Println("-------|-------:|:-----"), pipe.Line( pipe.Exec("git", "for-each-ref", "--format=%(refname:short)", "refs/heads"), pipe.Replace(branchInfo), ), ) out, err := pipe_util.OutputDir(p, repo.Vcs.RootPath()) if err != nil { return err.Error() } return string(out) default: return "" } }
func (this *hgVcs) GetRemoteRev() string { // TODO: Make this more robust and proper, etc. cmd := exec.Command("hg", "--debug", "identify", "-i", "--rev", this.GetDefaultBranch(), "default") cmd.Dir = this.rootPath if out, err := cmd.Output(); err == nil { // Get the last line of output. if lines := GetLines(trim.LastNewline(string(out))); len(lines) > 0 { return lines[len(lines)-1] } } return "" }
// Show the difference between the working directory and the most recent commit. // Precondition is that goPackage.Dir.Repo is not nil, and VcsLocal is updated. // TODO: Support for non-git. func GoPackageWorkingDiff(goPackage *gist7480523.GoPackage) string { // git diff if goPackage.Dir.Repo.VcsLocal.Status != "" { switch goPackage.Dir.Repo.Vcs.Type() { case vcs.Git: newFileDiff := func(line []byte) []byte { cmd := exec.Command("git", "diff", "--no-ext-diff", "--", "/dev/null", trim.LastNewline(string(line))) cmd.Dir = goPackage.Dir.Repo.Vcs.RootPath() out, err := cmd.Output() if len(out) > 0 { // diff exits with a non-zero status when the files don't match. // Ignore that failure as long as we get output. err = nil } if err != nil { return []byte(err.Error()) } return out } p := pipe.Script( pipe.Exec("git", "diff", "--no-ext-diff", "HEAD"), pipe.Line( pipe.Exec("git", "ls-files", "--others", "--exclude-standard"), pipe.Replace(newFileDiff), ), ) out, err := pipe_util.OutputDir(p, goPackage.Dir.Repo.Vcs.RootPath()) if err != nil { return err.Error() } return string(out) } } return "" }
func main() { flag.Usage = usage flag.Parse() if flag.NArg() < 1 { flag.Usage() os.Exit(2) return } switch *compilerFlag { case "gc", "gopherjs": default: flag.Usage() os.Exit(2) return } args := flag.Args() importPaths := args[:len(args)-1] // All but last. cmd := args[len(args)-1] // Last one. if *stdinFlag { stdin, err := ioutil.ReadAll(os.Stdin) if err != nil { panic(err) } cmd += "(" + trim.LastNewline(string(stdin)) + ")" } if !*quietFlag { cmd = "goon.Dump(" + cmd + ")" } // Generate source code. src := `package main import ( ` if !*quietFlag { src += ` "github.com/shurcooL/go-goon" ` } for _, importPath := range importPaths { src += ` . "` + importPath + `" ` } src += `) func main() { ` + cmd + ` } ` // Run `goimports` on the source code. { out, err := imports.Process("", []byte(src), nil) if err != nil { fmt.Print(src) fmt.Print("imports.Process: gen.go:", err, "\n") // No space after colon so the ouput is like "gen.go:8:18: expected ...". os.Exit(1) } src = string(out) } if *nFlag { fmt.Print(src) return } // Run the program. err := run(src) if err != nil { fmt.Println("### Error ###") fmt.Println(err) } }