@@ -125,44 +125,19 @@ static void unresolved(const char *base, struct name_entry n[3])
125
125
printf ("3 %06o %s %s%s\n" , n [2 ].mode , sha1_to_hex (n [2 ].sha1 ), base , n [2 ].path );
126
126
}
127
127
128
- /*
129
- * Merge two trees together (t[1] and t[2]), using a common base (t[0])
130
- * as the origin.
131
- *
132
- * This walks the (sorted) trees in lock-step, checking every possible
133
- * name. Note that directories automatically sort differently from other
134
- * files (see "base_name_compare"), so you'll never see file/directory
135
- * conflicts, because they won't ever compare the same.
136
- *
137
- * IOW, if a directory changes to a filename, it will automatically be
138
- * seen as the directory going away, and the filename being created.
139
- *
140
- * Think of this as a three-way diff.
141
- *
142
- * The output will be either:
143
- * - successful merge
144
- * "0 mode sha1 filename"
145
- * NOTE NOTE NOTE! FIXME! We really really need to walk the index
146
- * in parallel with this too!
147
- *
148
- * - conflict:
149
- * "1 mode sha1 filename"
150
- * "2 mode sha1 filename"
151
- * "3 mode sha1 filename"
152
- * where not all of the 1/2/3 lines may exist, of course.
153
- *
154
- * The successful merge rules are the same as for the three-way merge
155
- * in git-read-tree.
156
- */
157
- static void merge_trees (struct tree_desc t [3 ], const char * base )
128
+ typedef void (* traverse_callback_t )(int n , unsigned long mask , struct name_entry * entry , const char * base );
129
+
130
+ static void traverse_trees (int n , struct tree_desc * t , const char * base , traverse_callback_t callback )
158
131
{
132
+ struct name_entry * entry = xmalloc (n * sizeof (* entry ));
133
+
159
134
for (;;) {
160
135
struct name_entry entry [3 ];
161
- unsigned int mask = 0 ;
136
+ unsigned long mask = 0 ;
162
137
int i , last ;
163
138
164
139
last = -1 ;
165
- for (i = 0 ; i < 3 ; i ++ ) {
140
+ for (i = 0 ; i < n ; i ++ ) {
166
141
if (!t [i ].size )
167
142
continue ;
168
143
entry_extract (t + i , entry + i );
@@ -182,7 +157,7 @@ static void merge_trees(struct tree_desc t[3], const char *base)
182
157
if (cmp < 0 )
183
158
mask = 0 ;
184
159
}
185
- mask |= 1u << i ;
160
+ mask |= 1ul << i ;
186
161
last = i ;
187
162
}
188
163
if (!mask )
@@ -192,38 +167,77 @@ static void merge_trees(struct tree_desc t[3], const char *base)
192
167
* Update the tree entries we've walked, and clear
193
168
* all the unused name-entries.
194
169
*/
195
- for (i = 0 ; i < 3 ; i ++ ) {
196
- if (mask & (1u << i )) {
170
+ for (i = 0 ; i < n ; i ++ ) {
171
+ if (mask & (1ul << i )) {
197
172
update_tree_entry (t + i );
198
173
continue ;
199
174
}
200
175
entry_clear (entry + i );
201
176
}
177
+ callback (n , mask , entry , base );
178
+ }
179
+ free (entry );
180
+ }
202
181
203
- /* Same in both? */
204
- if (same_entry (entry + 1 , entry + 2 )) {
205
- if (entry [0 ].sha1 ) {
206
- resolve (base , NULL , entry + 1 );
207
- continue ;
208
- }
182
+ /*
183
+ * Merge two trees together (t[1] and t[2]), using a common base (t[0])
184
+ * as the origin.
185
+ *
186
+ * This walks the (sorted) trees in lock-step, checking every possible
187
+ * name. Note that directories automatically sort differently from other
188
+ * files (see "base_name_compare"), so you'll never see file/directory
189
+ * conflicts, because they won't ever compare the same.
190
+ *
191
+ * IOW, if a directory changes to a filename, it will automatically be
192
+ * seen as the directory going away, and the filename being created.
193
+ *
194
+ * Think of this as a three-way diff.
195
+ *
196
+ * The output will be either:
197
+ * - successful merge
198
+ * "0 mode sha1 filename"
199
+ * NOTE NOTE NOTE! FIXME! We really really need to walk the index
200
+ * in parallel with this too!
201
+ *
202
+ * - conflict:
203
+ * "1 mode sha1 filename"
204
+ * "2 mode sha1 filename"
205
+ * "3 mode sha1 filename"
206
+ * where not all of the 1/2/3 lines may exist, of course.
207
+ *
208
+ * The successful merge rules are the same as for the three-way merge
209
+ * in git-read-tree.
210
+ */
211
+ static void threeway_callback (int n , unsigned long mask , struct name_entry * entry , const char * base )
212
+ {
213
+ /* Same in both? */
214
+ if (same_entry (entry + 1 , entry + 2 )) {
215
+ if (entry [0 ].sha1 ) {
216
+ resolve (base , NULL , entry + 1 );
217
+ return ;
209
218
}
219
+ }
210
220
211
- if (same_entry (entry + 0 , entry + 1 )) {
212
- if (entry [2 ].sha1 && !S_ISDIR (entry [2 ].mode )) {
213
- resolve (base , entry + 1 , entry + 2 );
214
- continue ;
215
- }
221
+ if (same_entry (entry + 0 , entry + 1 )) {
222
+ if (entry [2 ].sha1 && !S_ISDIR (entry [2 ].mode )) {
223
+ resolve (base , entry + 1 , entry + 2 );
224
+ return ;
216
225
}
226
+ }
217
227
218
- if (same_entry (entry + 0 , entry + 2 )) {
219
- if (entry [1 ].sha1 && !S_ISDIR (entry [1 ].mode )) {
220
- resolve (base , NULL , entry + 1 );
221
- continue ;
222
- }
228
+ if (same_entry (entry + 0 , entry + 2 )) {
229
+ if (entry [1 ].sha1 && !S_ISDIR (entry [1 ].mode )) {
230
+ resolve (base , NULL , entry + 1 );
231
+ return ;
223
232
}
224
-
225
- unresolved (base , entry );
226
233
}
234
+
235
+ unresolved (base , entry );
236
+ }
237
+
238
+ static void merge_trees (struct tree_desc t [3 ], const char * base )
239
+ {
240
+ traverse_trees (3 , t , base , threeway_callback );
227
241
}
228
242
229
243
static void * get_tree_descriptor (struct tree_desc * desc , const char * rev )
0 commit comments