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