Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1190)

Unified Diff: go/src/infra/libs/git/diff_tree.go

Issue 662113003: Drover's back, baby! (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git/+/master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: go/src/infra/libs/git/diff_tree.go
diff --git a/go/src/infra/libs/git/diff_tree.go b/go/src/infra/libs/git/diff_tree.go
new file mode 100644
index 0000000000000000000000000000000000000000..8d39194447573c28519e1b3343a54c84912a6f8e
--- /dev/null
+++ b/go/src/infra/libs/git/diff_tree.go
@@ -0,0 +1,97 @@
+package git
+
+import "fmt"
+import "strconv"
+import "strings"
+
+// TreeDiff represents the difference between two Treeish objects
+type TreeDiff []TreeDiffEntry
+
+// TreeDiffEntry represents the before and after of one path in the repo.
+// Note that the Old.Name and New.Name may be different if this item was
+// Moved or Copied.
+type TreeDiffEntry struct {
+ // Actino is one of "ACDMRTUX"
+ // U is for unmerged... if you're just comparing trees you should never see this
+ // X is probably a bug in git... you should also never see this.
+ // T is a type change, so if a tree turned into a blob, for example
+ Action string
+
+ // For Action types 'R' or 'C', what percentage (from 0-100) are the old and
+ // new blobs similar.
+ Similarity int
+
+ Old TreeDiffEntryHalf
+ New TreeDiffEntryHalf
+}
+
+// TreeDiffEntryHalf is one entry in a TreeDiffEntry, either the Old or New half.
+type TreeDiffEntryHalf struct {
+ Child
+ Name string
+}
+
+func (t TreeDiffEntryHalf) String() string {
M-A Ruel 2014/10/18 00:47:05 Use a pointer, otherwise is copy the struct
iannucci 2014/10/20 21:11:57 Done.
+ return fmt.Sprintf("%s: %s", t.Name, t.Child)
+}
+
+// DiffTree computes the 2-tree diff (with copy/rename detection) and returns
+// a parsed TreeDiff of what it found.
+//
+// This diff-tree invocation is done with -t, which implies that it is recursive,
+// and that the actual intermediate tree objects will also be contianed in the
+// return value.
+func (r *Repo) DiffTree(left, right string) (ret TreeDiff) {
+ atoi := func(s string, base int) int {
+ ret, err := strconv.ParseInt(s, base, 0)
+ if err != nil {
+ panic(err)
+ }
+ return int(ret)
+ }
+
+ lines := strings.Split(strings.TrimRight(
+ r.RunOutput("diff-tree", "-t", "-z", "-M", "-M", "-C", left, right), "\000"),
+ "\000")
+
+ infoStream := make(chan string, len(lines))
+ for _, line := range lines {
+ infoStream <- line
+ }
+ close(infoStream)
+ for header := range infoStream {
+ if len(header) == 0 {
+ break
+ }
+ if header[0] != ':' {
+ panic("git.DiffTree: desynchronized parsing error")
M-A Ruel 2014/10/18 00:47:05 [BTW I know it's usual to use panic() all around w
+ }
+ info := strings.Fields(strings.TrimLeft(header, ":"))
+ // old_mode new_mode old_id new_id action
+ // oldPath (if action[0] in "RC")
+ // newPath
+ action := info[4]
+ similarity := 0
+ oldPath := <-infoStream
+ newPath := oldPath
+ if action[0] == 'R' || action[0] == 'C' {
+ newPath = <-infoStream
+ similarity = atoi(action[1:], 10)
+ }
+
+ ret = append(ret, (TreeDiffEntry{
+ Action: action,
+ Similarity: similarity,
+ Old: TreeDiffEntryHalf{
+ *NewEmptyChild(Mode(atoi(info[0], 8)), MakeObjectID(info[2])),
+ oldPath,
+ },
+ New: TreeDiffEntryHalf{
+ *NewEmptyChild(Mode(atoi(info[1], 8)), MakeObjectID(info[3])),
+ newPath,
+ },
+ }))
+ }
+
+ return
+}

Powered by Google App Engine
This is Rietveld 408576698