In this mode, only trees within revs->narrow_prefix is traversed. This narrows down the whole repository to the given subtree. This mode will be used by upload-pack/pack-objects to create a narrow pack, and by all git operations in narrow repository (i.e. $GIT_DIR/narrow exists). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- list-objects.c | 36 +++++++++++++++++++++++++++++++++--- revision.h | 4 +++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/list-objects.c b/list-objects.c index 8953548..7014926 100644 --- a/list-objects.c +++ b/list-objects.c @@ -61,12 +61,15 @@ static void process_tree(struct rev_info *revs, struct tree *tree, show_object_fn show, struct name_path *path, - const char *name) + const char *name, + const char *subtree) { struct object *obj = &tree->object; struct tree_desc desc; struct name_entry entry; struct name_path me; + const char *slash = NULL; + int subtree_len; if (!revs->tree_objects) return; @@ -82,13 +85,34 @@ static void process_tree(struct rev_info *revs, me.elem = name; me.elem_len = strlen(name); + if (subtree) { + slash = strchr(subtree, '/'); + subtree_len = slash ? slash - subtree : strlen(subtree); + } + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { + /* + * FIXME, does not follow tree rename + * some sort of rename hints would be nice + * (because diff machinery should not be used + * here for detecting renames) + */ + if (!subtree) + ; /* no subtree restriction, go on */ + else if (S_ISDIR(entry.mode) && + !strncmp(entry.path, subtree, subtree_len) && + entry.path[subtree_len] == '\0') + ; /* inside subtree, go on */ + else + continue; /* stop */ + if (S_ISDIR(entry.mode)) process_tree(revs, lookup_tree(entry.sha1), - show, &me, entry.path); + show, &me, entry.path, + slash ? slash+1 : NULL); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, show, &me, entry.path); @@ -147,6 +171,11 @@ void traverse_commit_list(struct rev_info *revs, int i; struct commit *commit; + if (get_narrow_prefix() && !revs->narrow_tree) { + revs->narrow_tree = 1; + revs->narrow_prefix = get_narrow_prefix(); + } + while ((commit = get_revision(revs)) != NULL) { add_pending_tree(revs, commit->tree); show_commit(commit, data); @@ -164,7 +193,8 @@ void traverse_commit_list(struct rev_info *revs, } if (obj->type == OBJ_TREE) { process_tree(revs, (struct tree *)obj, show_object, - NULL, name); + NULL, name, + revs->narrow_tree ? revs->narrow_prefix : NULL); continue; } if (obj->type == OBJ_BLOB) { diff --git a/revision.h b/revision.h index 36fdf22..ccdf28a 100644 --- a/revision.h +++ b/revision.h @@ -33,6 +33,7 @@ struct rev_info { /* Basic information */ const char *prefix; + const char *narrow_prefix; const char *def; void *prune_data; unsigned int early_output; @@ -68,7 +69,8 @@ struct rev_info { cherry_pick:1, bisect:1, ancestry_path:1, - first_parent_only:1; + first_parent_only:1, + narrow_tree:1; /* Diff flags */ unsigned int diff:1, -- 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