list-objects.con commit gitweb: Allow forks with project list file (c2b8b13)
   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        init_tree_desc(&desc, tree->buffer, tree->size);
  53
  54        while (tree_entry(&desc, &entry)) {
  55                if (S_ISDIR(entry.mode))
  56                        process_tree(revs,
  57                                     lookup_tree(entry.sha1),
  58                                     p, &me, entry.path);
  59                else
  60                        process_blob(revs,
  61                                     lookup_blob(entry.sha1),
  62                                     p, &me, entry.path);
  63        }
  64        free(tree->buffer);
  65        tree->buffer = NULL;
  66}
  67
  68static void mark_edge_parents_uninteresting(struct commit *commit,
  69                                            struct rev_info *revs,
  70                                            show_edge_fn show_edge)
  71{
  72        struct commit_list *parents;
  73
  74        for (parents = commit->parents; parents; parents = parents->next) {
  75                struct commit *parent = parents->item;
  76                if (!(parent->object.flags & UNINTERESTING))
  77                        continue;
  78                mark_tree_uninteresting(parent->tree);
  79                if (revs->edge_hint && !(parent->object.flags & SHOWN)) {
  80                        parent->object.flags |= SHOWN;
  81                        show_edge(parent);
  82                }
  83        }
  84}
  85
  86void mark_edges_uninteresting(struct commit_list *list,
  87                              struct rev_info *revs,
  88                              show_edge_fn show_edge)
  89{
  90        for ( ; list; list = list->next) {
  91                struct commit *commit = list->item;
  92
  93                if (commit->object.flags & UNINTERESTING) {
  94                        mark_tree_uninteresting(commit->tree);
  95                        continue;
  96                }
  97                mark_edge_parents_uninteresting(commit, revs, show_edge);
  98        }
  99}
 100
 101void traverse_commit_list(struct rev_info *revs,
 102                          void (*show_commit)(struct commit *),
 103                          void (*show_object)(struct object_array_entry *))
 104{
 105        int i;
 106        struct commit *commit;
 107        struct object_array objects = { 0, 0, NULL };
 108
 109        while ((commit = get_revision(revs)) != NULL) {
 110                process_tree(revs, commit->tree, &objects, NULL, "");
 111                show_commit(commit);
 112        }
 113        for (i = 0; i < revs->pending.nr; i++) {
 114                struct object_array_entry *pending = revs->pending.objects + i;
 115                struct object *obj = pending->item;
 116                const char *name = pending->name;
 117                if (obj->flags & (UNINTERESTING | SEEN))
 118                        continue;
 119                if (obj->type == OBJ_TAG) {
 120                        obj->flags |= SEEN;
 121                        add_object_array(obj, name, &objects);
 122                        continue;
 123                }
 124                if (obj->type == OBJ_TREE) {
 125                        process_tree(revs, (struct tree *)obj, &objects,
 126                                     NULL, name);
 127                        continue;
 128                }
 129                if (obj->type == OBJ_BLOB) {
 130                        process_blob(revs, (struct blob *)obj, &objects,
 131                                     NULL, name);
 132                        continue;
 133                }
 134                die("unknown pending object %s (%s)",
 135                    sha1_to_hex(obj->sha1), name);
 136        }
 137        for (i = 0; i < objects.nr; i++)
 138                show_object(&objects.objects[i]);
 139}