summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-11-02 09:35:03 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-11-02 09:35:03 -0400
commit60632ea541ac6fc57c8158bf44c625c526e1b215 (patch)
treed34f26d88bdad2d8542b41e5961445810ae49f32
parent9f78b3df5aa2b56bba885ccb7e3068724b81f5ad (diff)
fix git bindings
-rw-r--r--src/edit/git.go111
1 files changed, 73 insertions, 38 deletions
diff --git a/src/edit/git.go b/src/edit/git.go
index 183e84c..5679e49 100644
--- a/src/edit/git.go
+++ b/src/edit/git.go
@@ -11,7 +11,7 @@ import (
)
func GitPull() error {
- return exec.Command("git", "pull").Run()
+ return exec.Command("git", "fetch").Run()
}
func GitPush() error {
@@ -93,53 +93,88 @@ type GitFile struct {
type GitTree map[string]GitFile
-var ParseError = errors.New("git ls-tree parse error")
+var (
+ ParseErrorSpaces = errors.New("parse: git ls-tree: not enough spaces")
+ ParseErrorTab = errors.New("parse: git ls-tree: no tab")
+ ParseErrorNull = errors.New("parse: git ls-tree: no trailing null")
+)
-func GitLsTree() (GitTree, error) {
- data, err := exec.Command("git", "ls-tree", "-trlz", "HEAD").Output()
+func parseGitTreeLine(line []byte) (rname string, rfile GitFile, err error) {
+ // There is probably a better, shorter way of doing this
+
+ // line = mode SP type SP hash SP size TAB name
+ a := bytes.SplitN(line, []byte{' '}, 4)
+ if len(a) != 4 {
+ err = ParseErrorSpaces
+ return
+ }
+ b := bytes.SplitN(a[3], []byte{'\t'}, 2)
+ if len(b) != 2 {
+ err = ParseErrorTab
+ return
+ }
+ fmode := a[0]
+ ftype := a[1]
+ fhash := a[2]
+ fsize := b[0]
+ fname := b[1]
+
+ // convert datatypes
+ fmodeN, err := strconv.ParseInt(string(fmode), 10, 19)
if err != nil {
- return nil, err
+ return
}
- lines := bytes.Split(data, []byte{0})
- ret := make(GitTree, len(lines)-1)
- for _, line := range lines[:len(ret)] {
- // trim the trailing "\0"
- if line[len(line)-1] != 0 {
- return nil, ParseError
- }
- line = line[:len(line)-1]
- // line = mode SP type SP hash SP size TAB name
- a := bytes.SplitN(line, []byte{' '}, 4)
- if len(a) != 4 {
- return nil, ParseError
- }
- b := bytes.SplitN(a[3], []byte{'\t'}, 2)
- if len(b) != 2 {
- return nil, ParseError
- }
- fmode := a[0]
- ftype := a[1]
- fhash := a[2]
- fsize := b[0]
- fname := b[1]
- fmodeN, err := strconv.ParseInt(string(fmode), 10, 19)
+ fsizeN := int64(-1)
+ fsizeS := string(bytes.TrimLeft(fsize, " "))
+ if fsizeS != "-" {
+ fsizeN, err = strconv.ParseInt(fsizeS, 10, 64)
if err != nil {
- return nil, err
+ return
}
- fsizeN := int64(-1)
- fsizeS := string(fsize)
- if fsizeS != "-" {
- fsizeN, err = strconv.ParseInt(fsizeS, 10, 64)
- if err != nil {
- return nil, err
- }
- }
- ret[string(fname)] = GitFile{
+ }
+
+ rname = string(fname)
+ rfile = GitFile{
Mode: int32(fmodeN),
Type: string(ftype),
Hash: string(fhash),
Size: fsizeN,
+ }
+ return
+}
+
+func GitLsTree() (GitTree, error) {
+ // Get the root tree-ish
+ data, err := exec.Command("git", "rev-parse", "HEAD:").Output()
+ if err != nil {
+ return nil, err
+ }
+ treeish := string(bytes.TrimSuffix(data, []byte{'\n'}))
+
+ // Recursively read said tree-ish
+ data, err = exec.Command("git", "ls-tree", "-trlz", treeish).Output()
+ if err != nil {
+ return nil, err
+ }
+ lines := bytes.Split(data, []byte{0})
+ // The last line is empty line so se can ignore it
+ // (`len(lines)-1`), but because it doesn't include a line for
+ // the root tree, we have to +1.
+ ret := make(GitTree, len(lines))
+ // Add the root tree
+ ret[""] = GitFile{
+ Mode: int32(40000),
+ Type: "tree",
+ Hash: treeish,
+ Size: -1,
+ }
+ // Parse the lines from git ls-tree
+ for _, line := range lines[:len(ret)] {
+ name, file, err := parseGitTreeLine(line)
+ if err != nil {
+ return nil, err
}
+ ret[name] = file
}
return ret, nil
}