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