@@ -33,12 +33,54 @@ const (
33
33
34
34
type Change struct {
35
35
Action
36
- Name string
37
- Files [2 ]* File
36
+ From ChangeEntry
37
+ To ChangeEntry
38
+ }
39
+
40
+ type ChangeEntry struct {
41
+ Name string
42
+ Tree * Tree
43
+ TreeEntry TreeEntry
44
+ }
45
+
46
+ func (c * Change ) Files () (from * File , to * File , err error ) {
47
+ if c .Action == Insert || c .Action == Modify {
48
+ to , err = newFileFromTreeEntry (c .To .Tree , & c .To .TreeEntry )
49
+ if err != nil {
50
+ return
51
+ }
52
+
53
+ }
54
+
55
+ if c .Action == Delete || c .Action == Modify {
56
+ from , err = newFileFromTreeEntry (c .From .Tree , & c .From .TreeEntry )
57
+ if err != nil {
58
+ return
59
+ }
60
+ }
61
+
62
+ return
63
+ }
64
+
65
+ func newFileFromTreeEntry (t * Tree , e * TreeEntry ) (* File , error ) {
66
+ blob , err := t .r .Blob (e .Hash )
67
+ if err != nil {
68
+ return nil , err
69
+ }
70
+
71
+ return NewFile (e .Name , e .Mode , blob ), nil
38
72
}
39
73
40
74
func (c * Change ) String () string {
41
- return fmt .Sprintf ("<Action: %s, Path: %s>" , c .Action , c .Name )
75
+ return fmt .Sprintf ("<Action: %s, Path: %s>" , c .Action , c .name ())
76
+ }
77
+
78
+ func (c * Change ) name () string {
79
+ if c .From .Name != "" {
80
+ return c .From .Name
81
+ }
82
+
83
+ return c .To .Name
42
84
}
43
85
44
86
type Changes []* Change
@@ -68,7 +110,7 @@ func (c Changes) Swap(i, j int) {
68
110
}
69
111
70
112
func (c Changes ) Less (i , j int ) bool {
71
- return strings .Compare (c [i ].Name , c [j ].Name ) < 0
113
+ return strings .Compare (c [i ].name () , c [j ].name () ) < 0
72
114
}
73
115
74
116
func (c Changes ) String () string {
@@ -98,29 +140,34 @@ func newWithEmpty(a, b *Tree) (Changes, error) {
98
140
tree = a
99
141
}
100
142
101
- iter := tree .Files ( )
102
- defer iter .Close ()
143
+ w := NewTreeWalker ( tree .r , tree )
144
+ defer w .Close ()
103
145
104
146
for {
105
- file , err := iter .Next ()
147
+ path , entry , err := w .Next ()
106
148
if err == io .EOF {
107
149
break
108
150
} else if err != nil {
109
151
return nil , fmt .Errorf ("cannot get next file: %s" , err )
110
152
}
111
153
112
- var files [2 ]* File
154
+ if entry .Mode .IsDir () {
155
+ continue
156
+ }
157
+
158
+ c := & Change {Action : action }
159
+
113
160
if action == Insert {
114
- files [1 ] = file
161
+ c .To .Name = path
162
+ c .To .TreeEntry = entry
163
+ c .To .Tree = tree
115
164
} else {
116
- files [0 ] = file
165
+ c .From .Name = path
166
+ c .From .TreeEntry = entry
167
+ c .From .Tree = tree
117
168
}
118
169
119
- changes = append (changes , & Change {
120
- Action : action ,
121
- Name : file .Name ,
122
- Files : files ,
123
- })
170
+ changes = append (changes , c )
124
171
}
125
172
126
173
return changes , nil
@@ -146,19 +193,16 @@ func newDiffTree(a, b *Tree) ([]*Change, error) {
146
193
sort .Sort (bChanges )
147
194
148
195
for len (aChanges ) > 0 && len (bChanges ) > 0 {
149
- switch comp := strings .Compare (aChanges [0 ].Name , bChanges [0 ].Name ); {
196
+ switch comp := strings .Compare (aChanges [0 ].name () , bChanges [0 ].name () ); {
150
197
case comp == 0 : // append as "Modify" or ignore if not changed
151
- modified , err := hasChange (a , b , aChanges [0 ].Name )
198
+ modified , err := hasChange (a , b , aChanges [0 ].name () )
152
199
if err != nil {
153
200
return nil , err
154
201
}
155
202
156
203
if modified {
157
- result = append (result , & Change {
158
- Action : Modify ,
159
- Name : aChanges [0 ].Name ,
160
- Files : [2 ]* File {aChanges [0 ].Files [0 ], bChanges [0 ].Files [1 ]},
161
- })
204
+ c := mergeInsertAndDeleteIntoModify (aChanges [0 ], bChanges [0 ])
205
+ result = append (result , c )
162
206
}
163
207
164
208
aChanges = aChanges [1 :]
@@ -180,6 +224,18 @@ func newDiffTree(a, b *Tree) ([]*Change, error) {
180
224
return result , nil
181
225
}
182
226
227
+ func mergeInsertAndDeleteIntoModify (a , b * Change ) * Change {
228
+ c := & Change {Action : Modify }
229
+ c .From .Name = a .From .Name
230
+ c .From .Tree = a .From .Tree
231
+ c .From .TreeEntry = a .From .TreeEntry
232
+ c .To .Name = b .To .Name
233
+ c .To .Tree = b .To .Tree
234
+ c .To .TreeEntry = b .To .TreeEntry
235
+
236
+ return c
237
+ }
238
+
183
239
func hasChange (a , b * Tree , path string ) (bool , error ) {
184
240
ha , err := hash (a , path )
185
241
if err != nil {
0 commit comments