1#include "cache.h" 2#include "refs.h" 3#include "tag.h" 4#include "commit.h" 5#include "blob.h" 6#include "diff.h" 7#include "revision.h" 8#include "reachable.h" 9#include "cache-tree.h" 10#include "progress.h" 11#include "list-objects.h" 12 13struct connectivity_progress { 14 struct progress *progress; 15 unsigned long count; 16}; 17 18static void update_progress(struct connectivity_progress *cp) 19{ 20 cp->count++; 21 if ((cp->count & 1023) == 0) 22 display_progress(cp->progress, cp->count); 23} 24 25static int add_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) 26{ 27 struct object *object = parse_object_or_die(sha1, path); 28 struct rev_info *revs = (struct rev_info *)cb_data; 29 30 add_pending_object(revs, object, ""); 31 32 return 0; 33} 34 35static void add_one_tree(const unsigned char *sha1, struct rev_info *revs) 36{ 37 struct tree *tree = lookup_tree(sha1); 38 if (tree) 39 add_pending_object(revs, &tree->object, ""); 40} 41 42static void add_cache_tree(struct cache_tree *it, struct rev_info *revs) 43{ 44 int i; 45 46 if (it->entry_count >= 0) 47 add_one_tree(it->sha1, revs); 48 for (i = 0; i < it->subtree_nr; i++) 49 add_cache_tree(it->down[i]->cache_tree, revs); 50} 51 52static void add_cache_refs(struct rev_info *revs) 53{ 54 int i; 55 56 read_cache(); 57 for (i = 0; i < active_nr; i++) { 58 struct blob *blob; 59 60 /* 61 * The index can contain blobs and GITLINKs, GITLINKs are hashes 62 * that don't actually point to objects in the repository, it's 63 * almost guaranteed that they are NOT blobs, so we don't call 64 * lookup_blob() on them, to avoid populating the hash table 65 * with invalid information 66 */ 67 if (S_ISGITLINK(active_cache[i]->ce_mode)) 68 continue; 69 70 blob = lookup_blob(active_cache[i]->sha1); 71 if (blob) 72 blob->object.flags |= SEEN; 73 74 /* 75 * We could add the blobs to the pending list, but quite 76 * frankly, we don't care. Once we've looked them up, and 77 * added them as objects, we've really done everything 78 * there is to do for a blob 79 */ 80 } 81 if (active_cache_tree) 82 add_cache_tree(active_cache_tree, revs); 83} 84 85/* 86 * The traversal will have already marked us as SEEN, so we 87 * only need to handle any progress reporting here. 88 */ 89static void mark_object(struct object *obj, const struct name_path *path, 90 const char *name, void *data) 91{ 92 update_progress(data); 93} 94 95static void mark_commit(struct commit *c, void *data) 96{ 97 mark_object(&c->object, NULL, NULL, data); 98} 99 100void mark_reachable_objects(struct rev_info *revs, int mark_reflog, 101 struct progress *progress) 102{ 103 struct connectivity_progress cp; 104 105 /* 106 * Set up revision parsing, and mark us as being interested 107 * in all object types, not just commits. 108 */ 109 revs->tag_objects = 1; 110 revs->blob_objects = 1; 111 revs->tree_objects = 1; 112 113 /* Add all refs from the index file */ 114 add_cache_refs(revs); 115 116 /* Add all external refs */ 117 for_each_ref(add_one_ref, revs); 118 119 /* detached HEAD is not included in the list above */ 120 head_ref(add_one_ref, revs); 121 122 /* Add all reflog info */ 123 if (mark_reflog) 124 add_reflogs_to_pending(revs, 0); 125 126 cp.progress = progress; 127 cp.count = 0; 128 129 /* 130 * Set up the revision walk - this will move all commits 131 * from the pending list to the commit walking list. 132 */ 133 if (prepare_revision_walk(revs)) 134 die("revision walk setup failed"); 135 traverse_commit_list(revs, mark_commit, mark_object, &cp); 136 display_progress(cp.progress, cp.count); 137}