Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Simplifications to the merge and update logic. Fix update so that it correctly carries file edits across name changes. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
fd8698c8e0e2e57478cd25190900fb4d |
| User & Date: | drh 2010-12-14 15:44:29.000 |
Context
|
2010-12-15
| ||
| 01:36 | Change the merge conflict marks to identify which part is original content and which part is the content merged in. check-in: 76ae862ec9 user: drh tags: trunk | |
|
2010-12-14
| ||
| 15:44 | Simplifications to the merge and update logic. Fix update so that it correctly carries file edits across name changes. check-in: fd8698c8e0 user: drh tags: trunk | |
| 00:36 | Merge in the experimental clone speed enhancement. check-in: 3543ed62bb user: drh tags: trunk | |
Changes
Changes to src/merge.c.
| ︙ | ︙ | |||
151 152 153 154 155 156 157 |
");"
);
/* Add files found in V
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
| | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
");"
);
/* Add files found in V
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
" SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, chnged "
" FROM vfile WHERE vid=%d",
vid
);
/*
** Compute name changes from P->V
*/
|
| ︙ | ︙ | |||
175 176 177 178 179 180 181 |
);
free(z);
}
fossil_free(aChng);
db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
}
| | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
);
free(z);
}
fossil_free(aChng);
db_multi_exec("UPDATE fv SET fnm=fnp WHERE fnp!=fn");
}
/* Add files found in P but not in V
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
" SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
" FROM vfile"
" WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)",
pid
|
| ︙ | ︙ | |||
201 202 203 204 205 206 207 |
" WHERE fnp=(SELECT name FROM filename WHERE fnid=%d)",
aChng[i*2+1], aChng[i*2]
);
}
fossil_free(aChng);
}
| | | | < < < < | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
" WHERE fnp=(SELECT name FROM filename WHERE fnid=%d)",
aChng[i*2+1], aChng[i*2]
);
}
fossil_free(aChng);
}
/* Add files found in M but not in P or V.
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)"
" SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 "
" FROM vfile"
" WHERE vid=%d"
" AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)",
mid
);
/*
** Compute the file version ids for P and M.
*/
db_multi_exec(
"UPDATE fv SET"
" idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
" ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
" idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
" ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",
pid, pid, mid, mid
);
if( debugFlag ){
db_prepare(&q,
"SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv"
);
while( db_step(&q)==SQLITE_ROW ){
|
| ︙ | ︙ |
Changes to src/update.c.
| ︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
void update_cmd(void){
int vid; /* Current version */
int tid=0; /* Target version - version we are changing to */
Stmt q;
int latestFlag; /* --latest. Pick the latest version if true */
int nochangeFlag; /* -n or --nochange. Do a dry run */
int verboseFlag; /* -v or --verbose. Output extra information */
url_proxy_options();
latestFlag = find_option("latest",0, 0)!=0;
nochangeFlag = find_option("nochange","n",0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("cannot find current version");
}
if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
fossil_fatal("cannot update an uncommitted merge");
| > > > > > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
void update_cmd(void){
int vid; /* Current version */
int tid=0; /* Target version - version we are changing to */
Stmt q;
int latestFlag; /* --latest. Pick the latest version if true */
int nochangeFlag; /* -n or --nochange. Do a dry run */
int verboseFlag; /* -v or --verbose. Output extra information */
int debugFlag; /* --debug option */
int nChng; /* Number of file renames */
int *aChng; /* Array of file renames */
int i; /* Loop counter */
url_proxy_options();
latestFlag = find_option("latest",0, 0)!=0;
nochangeFlag = find_option("nochange","n",0)!=0;
verboseFlag = find_option("verbose","v",0)!=0;
debugFlag = find_option("debug",0,0)!=0;
db_must_be_within_tree();
vid = db_lget_int("checkout", 0);
if( vid==0 ){
fossil_fatal("cannot find current version");
}
if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
fossil_fatal("cannot update an uncommitted merge");
|
| ︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
fossil_fatal("no such version: %s", g.argv[2]);
}else if( !is_a_version(tid) ){
fossil_fatal("no such version: %s", g.argv[2]);
}
}
}
if( tid==0 ){
int closeCode = 1;
compute_leaves(vid, closeCode);
if( !db_exists("SELECT 1 FROM leaves") ){
closeCode = 0;
compute_leaves(vid, closeCode);
}
| > > > > > > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
fossil_fatal("no such version: %s", g.argv[2]);
}else if( !is_a_version(tid) ){
fossil_fatal("no such version: %s", g.argv[2]);
}
}
}
/* If no VERSION is specified on the command-line, then look for a
** descendent of the current version. If there are multiple descendents,
** look for one from the same branch as the current version. If there
** are still multiple descendents, show them all and refuse to update
** until the user selects one.
*/
if( tid==0 ){
int closeCode = 1;
compute_leaves(vid, closeCode);
if( !db_exists("SELECT 1 FROM leaves") ){
closeCode = 0;
compute_leaves(vid, closeCode);
}
|
| ︙ | ︙ | |||
146 147 148 149 150 151 152 |
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
" fn TEXT PRIMARY KEY," /* The filename relative to root */
" idv INTEGER," /* VFILE entry for current version */
" idt INTEGER," /* VFILE entry for target version */
" chnged BOOLEAN," /* True if current version has been edited */
" ridv INTEGER," /* Record ID for current version */
| | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | < < < | > > | > | | < | | > > | | | < > | | < | | > | | | | < | | < | | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
"DROP TABLE IF EXISTS fv;"
"CREATE TEMP TABLE fv("
" fn TEXT PRIMARY KEY," /* The filename relative to root */
" idv INTEGER," /* VFILE entry for current version */
" idt INTEGER," /* VFILE entry for target version */
" chnged BOOLEAN," /* True if current version has been edited */
" ridv INTEGER," /* Record ID for current version */
" ridt INTEGER," /* Record ID for target */
" fnt TEXT" /* Filename of same file on target version */
");"
);
/* Add files found in the current version
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
" SELECT pathname, pathname, id, 0, rid, 0, chnged FROM vfile WHERE vid=%d",
vid
);
/* Compute file name changes on V->T. Record name changes in files that
** have changed locally.
*/
find_filename_changes(vid, tid, &nChng, &aChng);
if( nChng ){
for(i=0; i<nChng; i++){
db_multi_exec(
"UPDATE fv"
" SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
" WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
aChng[i*2+1], aChng[i*2]
);
}
fossil_free(aChng);
}
/* Add files found in the target version T but missing from the current
** version V.
*/
db_multi_exec(
"INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)"
" SELECT pathname, pathname, 0, 0, 0, 0, 0 FROM vfile"
" WHERE vid=%d"
" AND pathname NOT IN (SELECT fnt FROM fv)",
tid
);
/*
** Compute the file version ids for T
*/
db_multi_exec(
"UPDATE fv SET"
" idt=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnt),0),"
" ridt=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnt),0)",
tid, tid
);
if( debugFlag ){
db_prepare(&q,
"SELECT rowid, fn, fnt, chnged, ridv, ridt FROM fv"
);
while( db_step(&q)==SQLITE_ROW ){
printf("%3d: ridv=%-4d ridt=%-4d chnged=%d\n",
db_column_int(&q, 0),
db_column_int(&q, 4),
db_column_int(&q, 5),
db_column_int(&q, 3));
printf(" fnv = [%s]\n", db_column_text(&q, 1));
printf(" fnt = [%s]\n", db_column_text(&q, 2));
}
db_finalize(&q);
}
/* If FILES appear on the command-line, remove from the "fv" table
** every entry that is not named on the command-line or which is not
** in a directory named on the command-line.
*/
if( g.argc>=4 ){
Blob sql; /* SQL statement to purge unwanted entries */
|
| ︙ | ︙ | |||
213 214 215 216 217 218 219 220 |
zSep = "AND ";
blob_reset(&treename);
}
db_multi_exec(blob_str(&sql));
blob_reset(&sql);
}
db_prepare(&q,
| > > > > | > > > > > < > | > < < < > > > | > | | > | > > | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
zSep = "AND ";
blob_reset(&treename);
}
db_multi_exec(blob_str(&sql));
blob_reset(&sql);
}
/*
** Alter the content of the checkout so that it conforms with the
** target
*/
db_prepare(&q,
"SELECT fn, idv, ridv, idt, ridt, chnged, fnt FROM fv ORDER BY 1"
);
assert( g.zLocalRoot!=0 );
assert( strlen(g.zLocalRoot)>1 );
assert( g.zLocalRoot[strlen(g.zLocalRoot)-1]=='/' );
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0); /* The filename from root */
int idv = db_column_int(&q, 1); /* VFILE entry for current */
int ridv = db_column_int(&q, 2); /* RecordID for current */
int idt = db_column_int(&q, 3); /* VFILE entry for target */
int ridt = db_column_int(&q, 4); /* RecordID for target */
int chnged = db_column_int(&q, 5); /* Current is edited */
const char *zNewName = db_column_text(&q,6);/* New filename */
char *zFullPath; /* Full pathname of the file */
char *zFullNewPath; /* Full pathname of dest */
char nameChng; /* True if the name changed */
zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
nameChng = strcmp(zName, zNewName);
if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
/* Conflict. This file has been added to the current checkout
** but also exists in the target checkout. Use the current version.
*/
printf("CONFLICT %s\n", zName);
}else if( idt>0 && idv==0 ){
/* File added in the target. */
printf("ADD %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
}else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
/* The file is unedited. Change it to the target version */
undo_save(zName);
printf("UPDATE %s\n", zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
}else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
/* The file missing from the local check-out. Restore it to the
** version that appears in the target. */
printf("UPDATE %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
}else if( idt==0 && idv>0 ){
if( ridv==0 ){
/* Added in current checkout. Continue to hold the file as
** as an addition */
db_multi_exec("UPDATE vfile SET vid=%d WHERE id=%d", tid, idv);
}else if( chnged ){
/* Edited locally but deleted from the target. Do not track the
** file but keep the edited version around. */
printf("CONFLICT %s\n", zName);
}else{
printf("REMOVE %s\n", zName);
undo_save(zName);
if( !nochangeFlag ) unlink(zFullPath);
}
}else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
/* Merge the changes in the current tree into the target version */
Blob e, r, t, v;
int rc;
if( nameChng ){
printf("MERGE %s -> %s\n", zName, zNewName);
}else{
printf("MERGE %s\n", zName);
}
undo_save(zName);
content_get(ridt, &t);
content_get(ridv, &v);
blob_zero(&e);
blob_read_from_file(&e, zFullPath);
rc = blob_merge(&v, &e, &t, &r);
if( rc>=0 ){
if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath);
if( rc>0 ){
printf("***** %d merge conflicts in %s\n", rc, zNewName);
}
}else{
if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
printf("***** Cannot merge binary file %s\n", zNewName);
}
if( nameChng && !nochangeFlag ) unlink(zFullPath);
blob_reset(&v);
blob_reset(&e);
blob_reset(&t);
blob_reset(&r);
}else if( verboseFlag ){
if( chnged ){
printf("EDITED %s\n", zName);
}else{
printf("UNCHANGED %s\n", zName);
}
}
free(zFullPath);
free(zFullNewPath);
}
db_finalize(&q);
printf("--------------\n");
show_common_info(tid, "updated-to:", 1, 0);
/*
** Clean up the mid and pid VFILE entries. Then commit the changes.
|
| ︙ | ︙ |