When in narrow repo and a merge is met, just traverse every valid trees that could be found, regardless whether they are in narrow tree. This is a weak point because fsck won't be able to find out missing trees. Hopefully the remote end won't accept incomplete push. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- list-objects.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 58 insertions(+), 3 deletions(-) diff --git a/list-objects.c b/list-objects.c index 7014926..ccdd64b 100644 --- a/list-objects.c +++ b/list-objects.c @@ -62,7 +62,8 @@ static void process_tree(struct rev_info *revs, show_object_fn show, struct name_path *path, const char *name, - const char *subtree) + const char *subtree, + int recursive) { struct object *obj = &tree->object; struct tree_desc desc; @@ -81,6 +82,10 @@ static void process_tree(struct rev_info *revs, die("bad tree object %s", sha1_to_hex(obj->sha1)); obj->flags |= SEEN; show(obj, path, name); + + if (!recursive) + return; + me.up = path; me.elem = name; me.elem_len = strlen(name); @@ -112,7 +117,8 @@ static void process_tree(struct rev_info *revs, process_tree(revs, lookup_tree(entry.sha1), show, &me, entry.path, - slash ? slash+1 : NULL); + slash ? slash+1 : NULL, + 1); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, show, &me, entry.path); @@ -163,6 +169,48 @@ static void add_pending_tree(struct rev_info *revs, struct tree *tree) add_pending_object(revs, &tree->object, ""); } +static void add_pending_reachable_tree(struct rev_info *revs, + const unsigned char *sha1, + const char *base) +{ + struct name_entry entry; + struct object *subtree; + struct tree_desc desc; + enum object_type type; + unsigned long size; + void *buffer; + char *path = xmalloc(PATH_MAX); + int len; + + buffer = read_sha1_file(sha1, &type, &size); + if (!buffer) { + free(path); + return; + } + if (type != OBJ_TREE) + die("%s is not a tree", sha1_to_hex(sha1)); + + len = strlen(base); + memcpy(path, base, len); + path[len++] = '/'; + + init_tree_desc(&desc, buffer, size); + while (tree_entry(&desc, &entry)) { + if (!S_ISDIR(entry.mode)) + continue; + + subtree = lookup_object(entry.sha1); + strcpy(path+len, entry.path); + if (subtree) { + subtree->flags |= TMP_MARK; /* non recursive */ + add_pending_object(revs, subtree, xstrdup(path)); + } + add_pending_reachable_tree(revs, entry.sha1, path); + } + free(path); + free(buffer); +} + void traverse_commit_list(struct rev_info *revs, show_commit_fn show_commit, show_object_fn show_object, @@ -177,6 +225,8 @@ void traverse_commit_list(struct rev_info *revs, } while ((commit = get_revision(revs)) != NULL) { + if (get_narrow_prefix()) + add_pending_reachable_tree(revs, commit->tree->object.sha1, ""); add_pending_tree(revs, commit->tree); show_commit(commit, data); } @@ -194,7 +244,12 @@ void traverse_commit_list(struct rev_info *revs, if (obj->type == OBJ_TREE) { process_tree(revs, (struct tree *)obj, show_object, NULL, name, - revs->narrow_tree ? revs->narrow_prefix : NULL); + revs->narrow_tree ? revs->narrow_prefix : NULL, + (obj->flags & TMP_MARK) == 0); + if (obj->flags & TMP_MARK) { + obj->flags &= ~TMP_MARK; + //free((char*)name); + } continue; } if (obj->type == OBJ_BLOB) { -- 1.7.1.rc1.69.g24c2f7 -- 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