This allows the callback to return an error value, but it can also specify which of the tree entries that it actually used up by returning a positive mask value. Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> --- merge-tree.c | 9 +++++---- tree-walk.c | 22 +++++++++++++++------- tree-walk.h | 4 ++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/merge-tree.c b/merge-tree.c index a3511b7..8be0b9f 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -287,31 +287,32 @@ static void unresolved(const struct traverse_info *info, struct name_entry n[3]) * The successful merge rules are the same as for the three-way merge * in git-read-tree. */ -static void threeway_callback(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *info) +static int threeway_callback(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *info) { /* Same in both? */ if (same_entry(entry+1, entry+2)) { if (entry[0].sha1) { resolve(info, NULL, entry+1); - return; + return mask; } } if (same_entry(entry+0, entry+1)) { if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) { resolve(info, entry+1, entry+2); - return; + return mask; } } if (same_entry(entry+0, entry+2)) { if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) { resolve(info, NULL, entry+1); - return; + return mask; } } unresolved(info, entry); + return mask; } static void merge_trees(struct tree_desc t[3], const char *base) diff --git a/tree-walk.c b/tree-walk.c index f9f7d22..7170e37 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -135,8 +135,9 @@ char *make_traverse_path(char *path, const struct traverse_info *info, const str return path; } -void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) +int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) { + int ret = 0; struct name_entry *entry = xmalloc(n*sizeof(*entry)); for (;;) { @@ -171,19 +172,26 @@ void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info) break; /* - * Update the tree entries we've walked, and clear - * all the unused name-entries. + * Clear all the unused name-entries. */ for (i = 0; i < n; i++) { - if (mask & (1ul << i)) { - update_tree_entry(t+i); + if (mask & (1ul << i)) continue; - } entry_clear(entry + i); } - info->fn(n, mask, entry, info); + ret = info->fn(n, mask, entry, info); + if (ret < 0) + break; + if (ret) + mask &= ret; + ret = 0; + for (i = 0; i < n; i++) { + if (mask & (1ul << i)) + update_tree_entry(t + i); + } } free(entry); + return ret; } static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode) diff --git a/tree-walk.h b/tree-walk.h index 7c4ae64..c123cfe 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -34,8 +34,8 @@ int tree_entry(struct tree_desc *, struct name_entry *); void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1); struct traverse_info; -typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *); -void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info); +typedef int (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *); +int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info); struct traverse_info { struct traverse_info *prev; -- 1.5.4.3.452.g67136 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html