Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 package git | |
| 2 | |
| 3 import "fmt" | |
| 4 import "strconv" | |
| 5 import "strings" | |
| 6 | |
| 7 // TreeDiff represents the difference between two Treeish objects | |
| 8 type TreeDiff []TreeDiffEntry | |
| 9 | |
| 10 // TreeDiffEntry represents the before and after of one path in the repo. | |
| 11 // Note that the Old.Name and New.Name may be different if this item was | |
| 12 // Moved or Copied. | |
| 13 type TreeDiffEntry struct { | |
| 14 // Actino is one of "ACDMRTUX" | |
| 15 // U is for unmerged... if you're just comparing trees you should never see this | |
| 16 // X is probably a bug in git... you should also never see this. | |
| 17 // T is a type change, so if a tree turned into a blob, for example | |
| 18 Action string | |
| 19 | |
| 20 // For Action types 'R' or 'C', what percentage (from 0-100) are the old and | |
| 21 // new blobs similar. | |
| 22 Similarity int | |
| 23 | |
| 24 Old TreeDiffEntryHalf | |
| 25 New TreeDiffEntryHalf | |
| 26 } | |
| 27 | |
| 28 // TreeDiffEntryHalf is one entry in a TreeDiffEntry, either the Old or New half . | |
| 29 type TreeDiffEntryHalf struct { | |
| 30 Child | |
| 31 Name string | |
| 32 } | |
| 33 | |
| 34 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.
| |
| 35 return fmt.Sprintf("%s: %s", t.Name, t.Child) | |
| 36 } | |
| 37 | |
| 38 // DiffTree computes the 2-tree diff (with copy/rename detection) and returns | |
| 39 // a parsed TreeDiff of what it found. | |
| 40 // | |
| 41 // This diff-tree invocation is done with -t, which implies that it is recursive , | |
| 42 // and that the actual intermediate tree objects will also be contianed in the | |
| 43 // return value. | |
| 44 func (r *Repo) DiffTree(left, right string) (ret TreeDiff) { | |
| 45 atoi := func(s string, base int) int { | |
| 46 ret, err := strconv.ParseInt(s, base, 0) | |
| 47 if err != nil { | |
| 48 panic(err) | |
| 49 } | |
| 50 return int(ret) | |
| 51 } | |
| 52 | |
| 53 lines := strings.Split(strings.TrimRight( | |
| 54 r.RunOutput("diff-tree", "-t", "-z", "-M", "-M", "-C", left, rig ht), "\000"), | |
| 55 "\000") | |
| 56 | |
| 57 infoStream := make(chan string, len(lines)) | |
| 58 for _, line := range lines { | |
| 59 infoStream <- line | |
| 60 } | |
| 61 close(infoStream) | |
| 62 for header := range infoStream { | |
| 63 if len(header) == 0 { | |
| 64 break | |
| 65 } | |
| 66 if header[0] != ':' { | |
| 67 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
| |
| 68 } | |
| 69 info := strings.Fields(strings.TrimLeft(header, ":")) | |
| 70 // old_mode new_mode old_id new_id action | |
| 71 // oldPath (if action[0] in "RC") | |
| 72 // newPath | |
| 73 action := info[4] | |
| 74 similarity := 0 | |
| 75 oldPath := <-infoStream | |
| 76 newPath := oldPath | |
| 77 if action[0] == 'R' || action[0] == 'C' { | |
| 78 newPath = <-infoStream | |
| 79 similarity = atoi(action[1:], 10) | |
| 80 } | |
| 81 | |
| 82 ret = append(ret, (TreeDiffEntry{ | |
| 83 Action: action, | |
| 84 Similarity: similarity, | |
| 85 Old: TreeDiffEntryHalf{ | |
| 86 *NewEmptyChild(Mode(atoi(info[0], 8)), MakeObjec tID(info[2])), | |
| 87 oldPath, | |
| 88 }, | |
| 89 New: TreeDiffEntryHalf{ | |
| 90 *NewEmptyChild(Mode(atoi(info[1], 8)), MakeObjec tID(info[3])), | |
| 91 newPath, | |
| 92 }, | |
| 93 })) | |
| 94 } | |
| 95 | |
| 96 return | |
| 97 } | |
| OLD | NEW |