diff options
Diffstat (limited to 'git/git.go')
-rw-r--r-- | git/git.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/git/git.go b/git/git.go new file mode 100644 index 0000000..c22de51 --- /dev/null +++ b/git/git.go @@ -0,0 +1,77 @@ +package git + +import ( + "bufio" + "bytes" + "errors" + "os/exec" + "regexp" +) + +type TreeEntry struct { + Mode, Type, Object, Name string +} + +var reTreeEntry = regexp.MustCompile("^(\\d+) (\\w+) ([0-9a-f]+)\t(.*)$") + +var ( + ErrUnexpectedLsTreeOutput = errors.New("Unexpected git ls-tree output") +) + +func splitZero(data []byte, atEOF bool) (advance int, token []byte, err error) { + if atEOF && len(data) == 0 { + return 0, nil, nil + } + if i := bytes.IndexByte(data, '\x00'); i >= 0 { + return i + 1, data[0:i], nil + } + if atEOF { + return len(data), data, nil + } + + return 0, nil, nil +} + +func ReadTree(repoPath string, ref string) ([]TreeEntry, error) { + cmd := exec.Command("git", "-C", repoPath, "ls-tree", "--full-tree", "-z", ref) + var out bytes.Buffer + cmd.Stdout = &out + + if err := cmd.Run(); err != nil { + return nil, err + } + + scanner := bufio.NewScanner(&out) + scanner.Split(splitZero) + + entries := []TreeEntry{} + for scanner.Scan() { + line := scanner.Bytes() + m := reTreeEntry.FindSubmatch(line) + if m == nil { + return nil, ErrUnexpectedLsTreeOutput + } + + entries = append(entries, TreeEntry{ + Mode: string(m[1]), + Type: string(m[2]), + Object: string(m[3]), + Name: string(m[4]), + }) + } + + return entries, nil +} + +func ReadBlob(repoPath string, ref string) ([]byte, error) { + var buf bytes.Buffer + + cmd := exec.Command("git", "-C", repoPath, "cat-file", "blob", ref) + cmd.Stdout = &buf + + if err := cmd.Run(); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} |