Add return value to 'traverse_tree()' callback

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@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Linus Torvalds 2008-03-05 19:44:06 -08:00 committed by Junio C Hamano
parent 40d934df72
commit 5803c6f8a2
3 changed files with 22 additions and 13 deletions

View File

@ -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 * The successful merge rules are the same as for the three-way merge
* in git-read-tree. * 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? */ /* Same in both? */
if (same_entry(entry+1, entry+2)) { if (same_entry(entry+1, entry+2)) {
if (entry[0].sha1) { if (entry[0].sha1) {
resolve(info, NULL, entry+1); resolve(info, NULL, entry+1);
return; return mask;
} }
} }
if (same_entry(entry+0, entry+1)) { if (same_entry(entry+0, entry+1)) {
if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) { if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) {
resolve(info, entry+1, entry+2); resolve(info, entry+1, entry+2);
return; return mask;
} }
} }
if (same_entry(entry+0, entry+2)) { if (same_entry(entry+0, entry+2)) {
if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) { if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
resolve(info, NULL, entry+1); resolve(info, NULL, entry+1);
return; return mask;
} }
} }
unresolved(info, entry); unresolved(info, entry);
return mask;
} }
static void merge_trees(struct tree_desc t[3], const char *base) static void merge_trees(struct tree_desc t[3], const char *base)

View File

@ -135,8 +135,9 @@ char *make_traverse_path(char *path, const struct traverse_info *info, const str
return path; 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)); struct name_entry *entry = xmalloc(n*sizeof(*entry));
for (;;) { for (;;) {
@ -171,19 +172,26 @@ void traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
break; break;
/* /*
* Update the tree entries we've walked, and clear * Clear all the unused name-entries.
* all the unused name-entries.
*/ */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (mask & (1ul << i)) { if (mask & (1ul << i))
update_tree_entry(t+i);
continue; continue;
}
entry_clear(entry + i); 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); free(entry);
return ret;
} }
static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode) static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char *result, unsigned *mode)

View File

@ -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); void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1);
struct traverse_info; struct traverse_info;
typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, struct traverse_info *); typedef int (*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); int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info);
struct traverse_info { struct traverse_info {
struct traverse_info *prev; struct traverse_info *prev;