1/* 2 * GIT - The information manager from hell 3 * 4 * Copyright (C) Linus Torvalds, 2005 5 */ 6#include"cache.h" 7 8static int stage =0; 9 10static intunpack_tree(unsigned char*sha1) 11{ 12void*buffer; 13unsigned long size; 14 15 buffer =read_object_with_reference(sha1,"tree", &size,0); 16if(!buffer) 17return-1; 18returnread_tree(buffer, size, stage); 19} 20 21static char*lockfile_name; 22 23static voidremove_lock_file(void) 24{ 25if(lockfile_name) 26unlink(lockfile_name); 27} 28 29static intpath_matches(struct cache_entry *a,struct cache_entry *b) 30{ 31int len =ce_namelen(a); 32returnce_namelen(b) == len && 33!memcmp(a->name, b->name, len); 34} 35 36static intsame(struct cache_entry *a,struct cache_entry *b) 37{ 38return a->ce_mode == b->ce_mode && 39!memcmp(a->sha1, b->sha1,20); 40} 41 42 43/* 44 * This removes all trivial merges that don't change the tree 45 * and collapses them to state 0. 46 * 47 * _Any_ other merge is left to user policy. That includes "both 48 * created the same file", and "both removed the same file" - which are 49 * trivial, but the user might still want to _note_ it. 50 */ 51static struct cache_entry *merge_entries(struct cache_entry *a, 52struct cache_entry *b, 53struct cache_entry *c) 54{ 55int len =ce_namelen(a); 56 57/* 58 * Are they all the same filename? We won't do 59 * any name merging 60 */ 61if(ce_namelen(b) != len || 62ce_namelen(c) != len || 63memcmp(a->name, b->name, len) || 64memcmp(a->name, c->name, len)) 65return NULL; 66 67/* 68 * Ok, all three entries describe the same 69 * filename, but maybe the contents or file 70 * mode have changed? 71 * 72 * The trivial cases end up being the ones where two 73 * out of three files are the same: 74 * - both destinations the same, trivially take either 75 * - one of the destination versions hasn't changed, 76 * take the other. 77 * 78 * The "all entries exactly the same" case falls out as 79 * a special case of any of the "two same" cases. 80 * 81 * Here "a" is "original", and "b" and "c" are the two 82 * trees we are merging. 83 */ 84if(same(b,c)) 85return c; 86if(same(a,b)) 87return c; 88if(same(a,c)) 89return b; 90return NULL; 91} 92 93static voidtrivially_merge_cache(struct cache_entry **src,int nr) 94{ 95static struct cache_entry null_entry; 96struct cache_entry **dst = src; 97struct cache_entry *old = &null_entry; 98 99while(nr) { 100struct cache_entry *ce, *result; 101 102 ce = src[0]; 103 104/* We throw away original cache entries except for the stat information */ 105if(!ce_stage(ce)) { 106 old = ce; 107 src++; 108 nr--; 109 active_nr--; 110continue; 111} 112if(nr >2&& (result =merge_entries(ce, src[1], src[2])) != NULL) { 113/* 114 * See if we can re-use the old CE directly? 115 * That way we get the uptodate stat info. 116 */ 117if(path_matches(result, old) &&same(result, old)) 118*result = *old; 119 ce = result; 120 ce->ce_flags &= ~htons(CE_STAGEMASK); 121 src +=2; 122 nr -=2; 123 active_nr -=2; 124} 125*dst++ = ce; 126 src++; 127 nr--; 128} 129} 130 131static voidmerge_stat_info(struct cache_entry **src,int nr) 132{ 133static struct cache_entry null_entry; 134struct cache_entry **dst = src; 135struct cache_entry *old = &null_entry; 136 137while(nr) { 138struct cache_entry *ce; 139 140 ce = src[0]; 141 142/* We throw away original cache entries except for the stat information */ 143if(!ce_stage(ce)) { 144 old = ce; 145 src++; 146 nr--; 147 active_nr--; 148continue; 149} 150if(path_matches(ce, old) &&same(ce, old)) 151*ce = *old; 152 ce->ce_flags &= ~htons(CE_STAGEMASK); 153*dst++ = ce; 154 src++; 155 nr--; 156} 157} 158 159static char*read_tree_usage ="read-tree (<sha> | -m <sha1> [<sha2> <sha3>])"; 160 161intmain(int argc,char**argv) 162{ 163int i, newfd, merge; 164unsigned char sha1[20]; 165static char lockfile[MAXPATHLEN+1]; 166const char*indexfile =get_index_file(); 167 168snprintf(lockfile,sizeof(lockfile),"%s.lock", indexfile); 169 170 newfd =open(lockfile, O_RDWR | O_CREAT | O_EXCL,0600); 171if(newfd <0) 172die("unable to create new cachefile"); 173atexit(remove_lock_file); 174 lockfile_name = lockfile; 175 176 merge =0; 177for(i =1; i < argc; i++) { 178const char*arg = argv[i]; 179 180/* "-m" stands for "merge", meaning we start in stage 1 */ 181if(!strcmp(arg,"-m")) { 182int i; 183if(stage) 184die("-m needs to come first"); 185read_cache(); 186for(i =0; i < active_nr; i++) { 187if(ce_stage(active_cache[i])) 188die("you need to resolve your current index first"); 189} 190 stage =1; 191 merge =1; 192continue; 193} 194if(get_sha1_hex(arg, sha1) <0) 195usage(read_tree_usage); 196if(stage >3) 197usage(read_tree_usage); 198if(unpack_tree(sha1) <0) 199die("failed to unpack tree object%s", arg); 200 stage++; 201} 202if(merge) { 203switch(stage) { 204case4:/* Three-way merge */ 205trivially_merge_cache(active_cache, active_nr); 206break; 207case2:/* Just read a tree, merge with old cache contents */ 208merge_stat_info(active_cache, active_nr); 209break; 210default: 211die("just how do you expect me to merge%dtrees?", stage-1); 212} 213} 214if(write_cache(newfd, active_cache, active_nr) ||rename(lockfile, indexfile)) 215die("unable to write new index file"); 216 lockfile_name = NULL; 217return0; 218}