<commit_before>package u6

import (
	"bytes"
	"fmt"
	"os/exec"

	"github.com/shurcooL/go/exp/13"
	"github.com/shurcooL/go/pipe_util"
	"github.com/shurcooL/go/vcs"
	"gopkg.in/pipe.v2"

	. "github.com/shurcooL/go/gists/gist5892738"
	. "github.com/shurcooL/go/gists/gist7480523"
)

// 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 *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", TrimLastNewline(string(line)))
				cmd.Dir = goPackage.Dir.Repo.Vcs.RootPath()
				out, err := cmd.Output()
				if err != nil && len(out) == 0 {
					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 ""
}

// Branches returns a Markdown table of branches with ahead/behind information relative to master branch.
func Branches(repo *exp13.VcsState) string {
	switch repo.Vcs.Type() {
	case vcs.Git:
		branchInfo := func(line []byte) []byte {
			branch := TrimLastNewline(string(line))

			cmd := exec.Command("git", "rev-list", "--count", "--left-right", "master..."+branch)
			cmd.Dir = repo.Vcs.RootPath()
			out, err := cmd.Output()
			if err != nil && len(out) == 0 {
				return []byte(err.Error())
			}

			behindAhead := bytes.Split(out, []byte("\t"))

			if branch == repo.VcsLocal.LocalBranch {
				return []byte(fmt.Sprintf("**%s** | %s | %s", branch, string(behindAhead[0]), string(behindAhead[1])))
			} else {
				return []byte(fmt.Sprintf("%s | %s | %s", branch, string(behindAhead[0]), string(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 ""
	}
}
<commit_msg>Add BranchesRemote and improve Branches.<commit_after>package u6

import (
	"fmt"
	"os/exec"
	"strings"

	"github.com/shurcooL/go/exp/13"
	"github.com/shurcooL/go/pipe_util"
	"github.com/shurcooL/go/vcs"
	"gopkg.in/pipe.v2"

	. "github.com/shurcooL/go/gists/gist5892738"
	. "github.com/shurcooL/go/gists/gist7480523"
)

// 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 *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", TrimLastNewline(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 ""
}

// Branches returns a Markdown table of branches with ahead/behind information relative to master branch.
func Branches(repo *exp13.VcsState) string {
	switch repo.Vcs.Type() {
	case vcs.Git:
		branchInfo := func(line []byte) []byte {
			branch := TrimLastNewline(string(line))

			cmd := exec.Command("git", "rev-list", "--count", "--left-right", "master..."+branch)
			cmd.Dir = repo.Vcs.RootPath()
			out, err := cmd.Output()
			if err != nil {
				return []byte(err.Error())
			}

			behindAhead := strings.Split(TrimLastNewline(string(out)), "\t")

			if branch == repo.VcsLocal.LocalBranch {
				return []byte(fmt.Sprintf("**%s** | %s | %s\n", branch, behindAhead[0], behindAhead[1]))
			} else {
				return []byte(fmt.Sprintf("%s | %s | %s\n", branch, 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 ""
	}
}

// Branches returns a Markdown table of branches with ahead/behind information relative to upstream.
func BranchesRemote(repo *exp13.VcsState) string {
	switch repo.Vcs.Type() {
	case vcs.Git:
		branchInfo := func(line []byte) []byte {
			branchUpstream := strings.Split(TrimLastNewline(string(line)), "\t")
			if len(branchUpstream) != 2 {
				return []byte("error: len(branchUpstream) != 2")
			}

			branch := branchUpstream[0]
			upstream := branchUpstream[1]
			if upstream == "" {
				return []byte(fmt.Sprintf("%s | | | \n", branch))
			}

			cmd := exec.Command("git", "rev-list", "--count", "--left-right", upstream+"..."+branch)
			cmd.Dir = repo.Vcs.RootPath()
			out, err := cmd.Output()
			if err != nil {
				return []byte(err.Error())
			}

			behindAhead := strings.Split(TrimLastNewline(string(out)), "\t")

			if branch == repo.VcsLocal.LocalBranch {
				return []byte(fmt.Sprintf("**%s** | %s | %s | %s\n", branch, upstream, behindAhead[0], behindAhead[1]))
			} else {
				return []byte(fmt.Sprintf("%s | %s | %s | %s\n", branch, upstream, behindAhead[0], behindAhead[1]))
			}
		}

		p := pipe.Script(
			pipe.Println("Branch | Upstream | Behind | Ahead"),
			pipe.Println("-------|----------|-------:|:-----"),
			pipe.Line(
				pipe.Exec("git", "for-each-ref", "--format=%(refname:short)\t%(upstream: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 ""
	}
}

{'fraction_non_alphanumeric': 0.19657494145199064, 'fraction_numerical': 0.008928571428571428, 'mean_word_length': 3.141212121212121, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4349578', 'n_tokens_mistral': 2877, 'n_tokens_neox': 2478, 'n_words': 519}