list-objects.con commit Allow fetch-pack to decide keeping the fetched pack without exploding (9e10fd1)
   1#include "cache.h"
   2#include "tag.h"
   3#include "commit.h"
   4#include "tree.h"
   5#include "blob.h"
   6#include "diff.h"
   7#include "tree-walk.h"
   8#include "revision.h"
   9#include "list-objects.h"
  10
  11static void process_blob(struct rev_info *revs,
  12                         struct blob *blob,
  13                         struct object_array *p,
  14                         struct name_path *path,
  15                         const char *name)
  16{
  17        struct object *obj = &blob->object;
  18
  19        if (!revs->blob_objects)
  20                return;
  21        if (obj->flags & (UNINTERESTING | SEEN))
  22                return;
  23        obj->flags |= SEEN;
  24        name = xstrdup(name);
  25        add_object(obj, p, path, name);
  26}
  27
  28static void process_tree(struct rev_info *revs,
  29                         struct tree *tree,
  30                         struct object_array *p,
  31                         struct name_path *path,
  32                         const char *name)
  33{
  34        struct object *obj = &tree->object;
  35        struct tree_desc desc;
  36        struct name_entry entry;
  37        struct name_path me;
  38
  39        if (!revs->tree_objects)
  40                return;
  41        if (obj->flags & (UNINTERESTING | SEEN))
  42                return;
  43        if (parse_tree(tree) < 0)
  44                die("bad tree object %s", sha1_to_hex(obj->sha1));
  45        obj->flags |= SEEN;
  46        name = xstrdup(name);
  47        add_object(obj, p, path, name);
  48        me.up = path;
  49        me.elem = name;
  50        me.elem_len = strlen(name);
  51
  52        desc.buf = tree->buffer;
  53        desc.size = tree->size;
  54
  55        while (tree_entry(&desc, &entry)) {
  56                if (S_ISDIR(entry.mode))
  57                        process_tree(revs,
  58                                     lookup_tree(entry.sha1),
  59                                     p, &me, entry.path);
  60                else
  61                        process_blob(revs,
  62                                     lookup_blob(entry.sha1),
  63                                     p, &me, entry.path);
  64        }
  65        free(tree->buffer);
  66        tree->buffer = NULL;
  67}
  68
  69static void mark_edge_parents_uninteresting(struct commit *commit,
  70                                            struct rev_info *revs,
  71                                            show_edge_fn show_edge)
  72{
  73        struct commit_list *parents;
  74
  75        for (parents = commit->parents; parents; parents = parents->next) {
  76                struct commit *parent = parents->item;
  77                if (!(parent->object.flags & UNINTERESTING))
  78                        continue;
  79                mark_tree_uninteresting(parent->tree);
  80                if (revs->edge_hint && !(parent->object.flags & SHOWN)) {
  81                        parent->object.flags |= SHOWN;
  82                        show_edge(parent);
  83                }
  84        }
  85}
  86
  87void mark_edges_uninteresting(struct commit_list *list,
  88                              struct rev_info *revs,
  89                              show_edge_fn show_edge)
  90{
  91        for ( ; list; list = list->next) {
  92                struct commit *commit = list->item;
  93
  94                if (commit->object.flags & UNINTERESTING) {
  95                        mark_tree_uninteresting(commit->tree);
  96                        continue;
  97                }
  98                mark_edge_parents_uninteresting(commit, revs, show_edge);
  99        }
 100}
 101
 102void traverse_commit_list(struct rev_info *revs,
 103                          void (*show_commit)(struct commit *),
 104                          void (*show_object)(struct object_array_entry *))
 105{
 106        int i;
 107        struct commit *commit;
 108        struct object_array objects = { 0, 0, NULL };
 109
 110        while ((commit = get_revision(revs)) != NULL) {
 111                process_tree(revs, commit->tree, &objects, NULL, "");
 112                show_commit(commit);
 113        }
 114        for (i = 0; i < revs->pending.nr; i++) {
 115                struct object_array_entry *pending = revs->pending.objects + i;
 116                struct object *obj = pending->item;
 117                const char *name = pending->name;
 118                if (obj->flags & (UNINTERESTING | SEEN))
 119                        continue;
 120                if (obj->type == OBJ_TAG) {
 121                        obj->flags |= SEEN;
 122                        add_object_array(obj, name, &objects);
 123                        continue;
 124                }
 125                if (obj->type == OBJ_TREE) {
 126                        process_tree(revs, (struct tree *)obj, &objects,
 127                                     NULL, name);
 128                        continue;
 129                }
 130                if (obj->type == OBJ_BLOB) {
 131                        process_blob(revs, (struct blob *)obj, &objects,
 132                                     NULL, name);
 133                        continue;
 134                }
 135                die("unknown pending object %s (%s)",
 136                    sha1_to_hex(obj->sha1), name);
 137        }
 138        for (i = 0; i < objects.nr; i++)
 139                show_object(&objects.objects[i]);
 140}