mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
This removes slightly more lines than it adds, but the real reason for doing this is that future optimizations will require more setup of the tree descriptor, and so we want to do it in one place. Also renamed the "desc.buf" field to "desc.buffer" just to trigger compiler errors for old-style manual initializations, making sure I didn't miss anything. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
140 lines
3.3 KiB
C
140 lines
3.3 KiB
C
#include "cache.h"
|
|
#include "tag.h"
|
|
#include "commit.h"
|
|
#include "tree.h"
|
|
#include "blob.h"
|
|
#include "diff.h"
|
|
#include "tree-walk.h"
|
|
#include "revision.h"
|
|
#include "list-objects.h"
|
|
|
|
static void process_blob(struct rev_info *revs,
|
|
struct blob *blob,
|
|
struct object_array *p,
|
|
struct name_path *path,
|
|
const char *name)
|
|
{
|
|
struct object *obj = &blob->object;
|
|
|
|
if (!revs->blob_objects)
|
|
return;
|
|
if (obj->flags & (UNINTERESTING | SEEN))
|
|
return;
|
|
obj->flags |= SEEN;
|
|
name = xstrdup(name);
|
|
add_object(obj, p, path, name);
|
|
}
|
|
|
|
static void process_tree(struct rev_info *revs,
|
|
struct tree *tree,
|
|
struct object_array *p,
|
|
struct name_path *path,
|
|
const char *name)
|
|
{
|
|
struct object *obj = &tree->object;
|
|
struct tree_desc desc;
|
|
struct name_entry entry;
|
|
struct name_path me;
|
|
|
|
if (!revs->tree_objects)
|
|
return;
|
|
if (obj->flags & (UNINTERESTING | SEEN))
|
|
return;
|
|
if (parse_tree(tree) < 0)
|
|
die("bad tree object %s", sha1_to_hex(obj->sha1));
|
|
obj->flags |= SEEN;
|
|
name = xstrdup(name);
|
|
add_object(obj, p, path, name);
|
|
me.up = path;
|
|
me.elem = name;
|
|
me.elem_len = strlen(name);
|
|
|
|
init_tree_desc(&desc, tree->buffer, tree->size);
|
|
|
|
while (tree_entry(&desc, &entry)) {
|
|
if (S_ISDIR(entry.mode))
|
|
process_tree(revs,
|
|
lookup_tree(entry.sha1),
|
|
p, &me, entry.path);
|
|
else
|
|
process_blob(revs,
|
|
lookup_blob(entry.sha1),
|
|
p, &me, entry.path);
|
|
}
|
|
free(tree->buffer);
|
|
tree->buffer = NULL;
|
|
}
|
|
|
|
static void mark_edge_parents_uninteresting(struct commit *commit,
|
|
struct rev_info *revs,
|
|
show_edge_fn show_edge)
|
|
{
|
|
struct commit_list *parents;
|
|
|
|
for (parents = commit->parents; parents; parents = parents->next) {
|
|
struct commit *parent = parents->item;
|
|
if (!(parent->object.flags & UNINTERESTING))
|
|
continue;
|
|
mark_tree_uninteresting(parent->tree);
|
|
if (revs->edge_hint && !(parent->object.flags & SHOWN)) {
|
|
parent->object.flags |= SHOWN;
|
|
show_edge(parent);
|
|
}
|
|
}
|
|
}
|
|
|
|
void mark_edges_uninteresting(struct commit_list *list,
|
|
struct rev_info *revs,
|
|
show_edge_fn show_edge)
|
|
{
|
|
for ( ; list; list = list->next) {
|
|
struct commit *commit = list->item;
|
|
|
|
if (commit->object.flags & UNINTERESTING) {
|
|
mark_tree_uninteresting(commit->tree);
|
|
continue;
|
|
}
|
|
mark_edge_parents_uninteresting(commit, revs, show_edge);
|
|
}
|
|
}
|
|
|
|
void traverse_commit_list(struct rev_info *revs,
|
|
void (*show_commit)(struct commit *),
|
|
void (*show_object)(struct object_array_entry *))
|
|
{
|
|
int i;
|
|
struct commit *commit;
|
|
struct object_array objects = { 0, 0, NULL };
|
|
|
|
while ((commit = get_revision(revs)) != NULL) {
|
|
process_tree(revs, commit->tree, &objects, NULL, "");
|
|
show_commit(commit);
|
|
}
|
|
for (i = 0; i < revs->pending.nr; i++) {
|
|
struct object_array_entry *pending = revs->pending.objects + i;
|
|
struct object *obj = pending->item;
|
|
const char *name = pending->name;
|
|
if (obj->flags & (UNINTERESTING | SEEN))
|
|
continue;
|
|
if (obj->type == OBJ_TAG) {
|
|
obj->flags |= SEEN;
|
|
add_object_array(obj, name, &objects);
|
|
continue;
|
|
}
|
|
if (obj->type == OBJ_TREE) {
|
|
process_tree(revs, (struct tree *)obj, &objects,
|
|
NULL, name);
|
|
continue;
|
|
}
|
|
if (obj->type == OBJ_BLOB) {
|
|
process_blob(revs, (struct blob *)obj, &objects,
|
|
NULL, name);
|
|
continue;
|
|
}
|
|
die("unknown pending object %s (%s)",
|
|
sha1_to_hex(obj->sha1), name);
|
|
}
|
|
for (i = 0; i < objects.nr; i++)
|
|
show_object(&objects.objects[i]);
|
|
}
|