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.
This commit is contained in:
Linus Torvalds 2005-06-24 22:56:58 -07:00
parent 023d66ed7b
commit 9de48752fe

View File

@ -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;