diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 22:56:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 22:56:58 -0700 |
commit | 9de48752fedc4923502c522af0e1f5b94c5fea2e (patch) | |
tree | 5fa9dc8ce4813f3433c65d14da5b99ae899e9119 /rev-list.c | |
parent | 023d66ed7b397c811a0693f34851d8590b69247b (diff) | |
download | git-9de48752fedc4923502c522af0e1f5b94c5fea2e.tar.gz |
git-rev-list: add option to list all objects (not just commits)
When you do
git-rev-list --objects $(git-rev-parse HEAD^..HEAD)
it now lists not only the "commit difference" between the parent of HEAD
and HEAD itself (which is normally just the parent, but in the case of a
merge will be all the newly merged commits), but also all the new tree
and blob objects that weren't in the original.
NOTE! It doesn't walk all the way to the root, so it doesn't do a full
object search in the full old history. Instead, it will only look as
far back in the history as it needs to resolve the commits. Thus, if
the commit reverts a blob (or tree) back to a state much further back in
history, we may end up listing some blobs (or trees) as "new" even
though they exist further back.
Regardless, the list of objects will be a superset (usually exact) list
of objects needed to go from the beginning commit to ending commit.
As a particularly obvious special case,
git-rev-list --objects HEAD
will end up listing every single object that is reachable from the HEAD
commit.
Side note: the objects are sorted by "recency", with commits first.
Diffstat (limited to 'rev-list.c')
-rw-r--r-- | rev-list.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/rev-list.c b/rev-list.c index 16920ef69e..6b35b61ec2 100644 --- a/rev-list.c +++ b/rev-list.c @@ -1,5 +1,7 @@ #include "cache.h" #include "commit.h" +#include "tree.h" +#include "blob.h" #include "epoch.h" #define SEEN (1u << 0) @@ -17,6 +19,8 @@ static const char rev_list_usage[] = " --merge-order [ --show-breaks ]"; static int bisect_list = 0; +static int tree_objects = 0; +static int blob_objects = 0; static int verbose_header = 0; static int show_parents = 0; static int hdr_termination = 0; @@ -94,20 +98,102 @@ static int process_commit(struct commit * commit) return CONTINUE; } +static struct object_list **add_object(struct object *obj, struct object_list **p) +{ + struct object_list *entry = xmalloc(sizeof(*entry)); + entry->item = obj; + entry->next = NULL; + *p = entry; + return &entry->next; +} + +static struct object_list **process_blob(struct blob *blob, struct object_list **p) +{ + struct object *obj = &blob->object; + + if (!blob_objects) + return p; + if (obj->flags & (UNINTERESTING | SEEN)) + return p; + obj->flags |= SEEN; + return add_object(obj, p); +} + +static struct object_list **process_tree(struct tree *tree, struct object_list **p) +{ + struct object *obj = &tree->object; + struct tree_entry_list *entry; + + if (!tree_objects) + return p; + if (obj->flags & (UNINTERESTING | SEEN)) + return p; + if (parse_tree(tree) < 0) + die("bad tree object %s", sha1_to_hex(obj->sha1)); + obj->flags |= SEEN; + p = add_object(obj, p); + for (entry = tree->entries ; entry ; entry = entry->next) { + if (entry->directory) + p = process_tree(entry->item.tree, p); + else + p = process_blob(entry->item.blob, p); + } + return p; +} + static void show_commit_list(struct commit_list *list) { + struct object_list *objects = NULL, **p = &objects; while (list) { struct commit *commit = pop_most_recent_commit(&list, SEEN); + p = process_tree(commit->tree, p); if (process_commit(commit) == STOP) break; } + while (objects) { + puts(sha1_to_hex(objects->item->sha1)); + objects = objects->next; + } +} + +static void mark_blob_uninteresting(struct blob *blob) +{ + if (!blob_objects) + return; + if (blob->object.flags & UNINTERESTING) + return; + blob->object.flags |= UNINTERESTING; +} + +static void mark_tree_uninteresting(struct tree *tree) +{ + struct object *obj = &tree->object; + struct tree_entry_list *entry; + + if (!tree_objects) + return; + if (obj->flags & UNINTERESTING) + return; + obj->flags |= UNINTERESTING; + if (parse_tree(tree) < 0) + die("bad tree %s", sha1_to_hex(obj->sha1)); + entry = tree->entries; + while (entry) { + if (entry->directory) + mark_tree_uninteresting(entry->item.tree); + else + mark_blob_uninteresting(entry->item.blob); + entry = entry->next; + } } static void mark_parents_uninteresting(struct commit *commit) { struct commit_list *parents = commit->parents; + if (tree_objects) + mark_tree_uninteresting(commit->tree); while (parents) { struct commit *commit = parents->item; commit->object.flags |= UNINTERESTING; @@ -276,6 +362,11 @@ int main(int argc, char **argv) bisect_list = 1; continue; } + if (!strcmp(arg, "--objects")) { + tree_objects = 1; + blob_objects = 1; + continue; + } if (!strncmp(arg, "--merge-order", 13)) { merge_order = 1; continue; |