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