Fossil SCM
Handle merges with a specified baseline that comes after a commit with renames.
Commit
8da901bb98dbe06c39cf22c82079a31e59e8b5f4
Parent
0e9d50b1481dc80…
2 files changed
+14
-2
+35
+14
-2
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -227,10 +227,11 @@ | ||
| 227 | 227 | const char *zBinGlob; /* The value of --binary */ |
| 228 | 228 | const char *zPivot; /* The value of --baseline */ |
| 229 | 229 | int debugFlag; /* True if --debug is present */ |
| 230 | 230 | int nConflict = 0; /* Number of conflicts seen */ |
| 231 | 231 | int nOverwrite = 0; /* Number of unmanaged files overwritten */ |
| 232 | + char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */ | |
| 232 | 233 | Stmt q; |
| 233 | 234 | |
| 234 | 235 | |
| 235 | 236 | /* Notation: |
| 236 | 237 | ** |
| @@ -383,10 +384,21 @@ | ||
| 383 | 384 | fossil_fatal("missing content, unable to merge"); |
| 384 | 385 | } |
| 385 | 386 | if( load_vfile_from_rid(pid) && !forceMissingFlag ){ |
| 386 | 387 | fossil_fatal("missing content, unable to merge"); |
| 387 | 388 | } |
| 389 | + if( zPivot ){ | |
| 390 | + vAncestor = db_exists( | |
| 391 | + "WITH RECURSIVE ancestor(id) AS (" | |
| 392 | + " VALUES(%d)" | |
| 393 | + " UNION ALL" | |
| 394 | + " SELECT pid FROM plink, ancestor" | |
| 395 | + " WHERE cid=ancestor.id AND pid!=%d AND cid!=%d)" | |
| 396 | + "SELECT 1 FROM ancestor WHERE id=%d LIMIT 1", | |
| 397 | + vid, nid, pid, pid | |
| 398 | + ) ? 'p' : 'n'; | |
| 399 | + } | |
| 388 | 400 | if( debugFlag ){ |
| 389 | 401 | char *z; |
| 390 | 402 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid); |
| 391 | 403 | fossil_print("N=%d %z\n", nid, z); |
| 392 | 404 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid); |
| @@ -433,18 +445,18 @@ | ||
| 433 | 445 | |
| 434 | 446 | /* |
| 435 | 447 | ** Add files found in V |
| 436 | 448 | */ |
| 437 | 449 | db_multi_exec( |
| 438 | - "UPDATE OR IGNORE fv SET fn=coalesce(fnp,fnn) WHERE fn IS NULL;" | |
| 450 | + "UPDATE OR IGNORE fv SET fn=coalesce(fn%c,fnn) WHERE fn IS NULL;" | |
| 439 | 451 | "REPLACE INTO fv(fn,fnp,fnm,fnn,idv,ridv,islinkv,isexe,chnged)" |
| 440 | 452 | " SELECT pathname, fnp, fnm, fnn, id, rid, islink, vf.isexe, vf.chnged" |
| 441 | 453 | " FROM vfile vf" |
| 442 | 454 | " LEFT JOIN fv ON fn=coalesce(origname,pathname)" |
| 443 | 455 | " AND rid>0 AND vf.chnged NOT IN (3,5)" |
| 444 | 456 | " WHERE vid=%d;", |
| 445 | - vid | |
| 457 | + vAncestor, vid | |
| 446 | 458 | ); |
| 447 | 459 | |
| 448 | 460 | /* |
| 449 | 461 | ** Add files found in P |
| 450 | 462 | */ |
| 451 | 463 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -227,10 +227,11 @@ | |
| 227 | const char *zBinGlob; /* The value of --binary */ |
| 228 | const char *zPivot; /* The value of --baseline */ |
| 229 | int debugFlag; /* True if --debug is present */ |
| 230 | int nConflict = 0; /* Number of conflicts seen */ |
| 231 | int nOverwrite = 0; /* Number of unmanaged files overwritten */ |
| 232 | Stmt q; |
| 233 | |
| 234 | |
| 235 | /* Notation: |
| 236 | ** |
| @@ -383,10 +384,21 @@ | |
| 383 | fossil_fatal("missing content, unable to merge"); |
| 384 | } |
| 385 | if( load_vfile_from_rid(pid) && !forceMissingFlag ){ |
| 386 | fossil_fatal("missing content, unable to merge"); |
| 387 | } |
| 388 | if( debugFlag ){ |
| 389 | char *z; |
| 390 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid); |
| 391 | fossil_print("N=%d %z\n", nid, z); |
| 392 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid); |
| @@ -433,18 +445,18 @@ | |
| 433 | |
| 434 | /* |
| 435 | ** Add files found in V |
| 436 | */ |
| 437 | db_multi_exec( |
| 438 | "UPDATE OR IGNORE fv SET fn=coalesce(fnp,fnn) WHERE fn IS NULL;" |
| 439 | "REPLACE INTO fv(fn,fnp,fnm,fnn,idv,ridv,islinkv,isexe,chnged)" |
| 440 | " SELECT pathname, fnp, fnm, fnn, id, rid, islink, vf.isexe, vf.chnged" |
| 441 | " FROM vfile vf" |
| 442 | " LEFT JOIN fv ON fn=coalesce(origname,pathname)" |
| 443 | " AND rid>0 AND vf.chnged NOT IN (3,5)" |
| 444 | " WHERE vid=%d;", |
| 445 | vid |
| 446 | ); |
| 447 | |
| 448 | /* |
| 449 | ** Add files found in P |
| 450 | */ |
| 451 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -227,10 +227,11 @@ | |
| 227 | const char *zBinGlob; /* The value of --binary */ |
| 228 | const char *zPivot; /* The value of --baseline */ |
| 229 | int debugFlag; /* True if --debug is present */ |
| 230 | int nConflict = 0; /* Number of conflicts seen */ |
| 231 | int nOverwrite = 0; /* Number of unmanaged files overwritten */ |
| 232 | char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */ |
| 233 | Stmt q; |
| 234 | |
| 235 | |
| 236 | /* Notation: |
| 237 | ** |
| @@ -383,10 +384,21 @@ | |
| 384 | fossil_fatal("missing content, unable to merge"); |
| 385 | } |
| 386 | if( load_vfile_from_rid(pid) && !forceMissingFlag ){ |
| 387 | fossil_fatal("missing content, unable to merge"); |
| 388 | } |
| 389 | if( zPivot ){ |
| 390 | vAncestor = db_exists( |
| 391 | "WITH RECURSIVE ancestor(id) AS (" |
| 392 | " VALUES(%d)" |
| 393 | " UNION ALL" |
| 394 | " SELECT pid FROM plink, ancestor" |
| 395 | " WHERE cid=ancestor.id AND pid!=%d AND cid!=%d)" |
| 396 | "SELECT 1 FROM ancestor WHERE id=%d LIMIT 1", |
| 397 | vid, nid, pid, pid |
| 398 | ) ? 'p' : 'n'; |
| 399 | } |
| 400 | if( debugFlag ){ |
| 401 | char *z; |
| 402 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nid); |
| 403 | fossil_print("N=%d %z\n", nid, z); |
| 404 | z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid); |
| @@ -433,18 +445,18 @@ | |
| 445 | |
| 446 | /* |
| 447 | ** Add files found in V |
| 448 | */ |
| 449 | db_multi_exec( |
| 450 | "UPDATE OR IGNORE fv SET fn=coalesce(fn%c,fnn) WHERE fn IS NULL;" |
| 451 | "REPLACE INTO fv(fn,fnp,fnm,fnn,idv,ridv,islinkv,isexe,chnged)" |
| 452 | " SELECT pathname, fnp, fnm, fnn, id, rid, islink, vf.isexe, vf.chnged" |
| 453 | " FROM vfile vf" |
| 454 | " LEFT JOIN fv ON fn=coalesce(origname,pathname)" |
| 455 | " AND rid>0 AND vf.chnged NOT IN (3,5)" |
| 456 | " WHERE vid=%d;", |
| 457 | vAncestor, vid |
| 458 | ); |
| 459 | |
| 460 | /* |
| 461 | ** Add files found in P |
| 462 | */ |
| 463 |
+35
| --- test/merge_renames.test | ||
| +++ test/merge_renames.test | ||
| @@ -387,10 +387,45 @@ | ||
| 387 | 387 | } |
| 388 | 388 | |
| 389 | 389 | test_file_contents merge_renames-10-9 f1 "f2.1" |
| 390 | 390 | test_file_contents merge_renames-10-10 f2 "f1.1" |
| 391 | 391 | |
| 392 | +############################################ | |
| 393 | +# Test 11 # | |
| 394 | +# Specifying a baseline # | |
| 395 | +############################################ | |
| 396 | + | |
| 397 | +test_setup | |
| 398 | + | |
| 399 | +write_file f1 "line" | |
| 400 | +fossil add f1 | |
| 401 | +fossil commit -m "add f1" | |
| 402 | + | |
| 403 | +write_file f1 "line\nline2" | |
| 404 | +fossil commit -b b -m "edit f2" --tag p1 | |
| 405 | + | |
| 406 | +fossil mv --hard f1 f2 | |
| 407 | +fossil commit -m "f1 -> f2" | |
| 408 | + | |
| 409 | +write_file f2 "line\nline2\nline3" | |
| 410 | +fossil commit -m "edit f2" --tag p2 | |
| 411 | + | |
| 412 | +write_file f2 "line\nline2\nline3\nline4" | |
| 413 | +fossil commit -m "edit f2" | |
| 414 | + | |
| 415 | +fossil update trunk | |
| 416 | +fossil merge --baseline p1 b | |
| 417 | +test_status_list merge_renames-11-1 $RESULT { | |
| 418 | + MERGE f1 | |
| 419 | + RENAME f1 -> f2 | |
| 420 | +} | |
| 421 | +test_file_contents merge_renames-11-2 f2 "line\nline3\nline4" | |
| 422 | +fossil revert | |
| 423 | +fossil merge --baseline p2 b | |
| 424 | +test_status_list merge_renames-11-3 $RESULT {MERGE f1} | |
| 425 | +test_file_contents merge_renames-11-4 f1 "line\nline4" | |
| 426 | + | |
| 392 | 427 | ###################################### |
| 393 | 428 | # |
| 394 | 429 | # Tests for troubles not specifically linked with renames but that I'd like to |
| 395 | 430 | # write: |
| 396 | 431 | # [c26c63eb1b] - 'merge --backout' does not handle conflicts properly |
| 397 | 432 |
| --- test/merge_renames.test | |
| +++ test/merge_renames.test | |
| @@ -387,10 +387,45 @@ | |
| 387 | } |
| 388 | |
| 389 | test_file_contents merge_renames-10-9 f1 "f2.1" |
| 390 | test_file_contents merge_renames-10-10 f2 "f1.1" |
| 391 | |
| 392 | ###################################### |
| 393 | # |
| 394 | # Tests for troubles not specifically linked with renames but that I'd like to |
| 395 | # write: |
| 396 | # [c26c63eb1b] - 'merge --backout' does not handle conflicts properly |
| 397 |
| --- test/merge_renames.test | |
| +++ test/merge_renames.test | |
| @@ -387,10 +387,45 @@ | |
| 387 | } |
| 388 | |
| 389 | test_file_contents merge_renames-10-9 f1 "f2.1" |
| 390 | test_file_contents merge_renames-10-10 f2 "f1.1" |
| 391 | |
| 392 | ############################################ |
| 393 | # Test 11 # |
| 394 | # Specifying a baseline # |
| 395 | ############################################ |
| 396 | |
| 397 | test_setup |
| 398 | |
| 399 | write_file f1 "line" |
| 400 | fossil add f1 |
| 401 | fossil commit -m "add f1" |
| 402 | |
| 403 | write_file f1 "line\nline2" |
| 404 | fossil commit -b b -m "edit f2" --tag p1 |
| 405 | |
| 406 | fossil mv --hard f1 f2 |
| 407 | fossil commit -m "f1 -> f2" |
| 408 | |
| 409 | write_file f2 "line\nline2\nline3" |
| 410 | fossil commit -m "edit f2" --tag p2 |
| 411 | |
| 412 | write_file f2 "line\nline2\nline3\nline4" |
| 413 | fossil commit -m "edit f2" |
| 414 | |
| 415 | fossil update trunk |
| 416 | fossil merge --baseline p1 b |
| 417 | test_status_list merge_renames-11-1 $RESULT { |
| 418 | MERGE f1 |
| 419 | RENAME f1 -> f2 |
| 420 | } |
| 421 | test_file_contents merge_renames-11-2 f2 "line\nline3\nline4" |
| 422 | fossil revert |
| 423 | fossil merge --baseline p2 b |
| 424 | test_status_list merge_renames-11-3 $RESULT {MERGE f1} |
| 425 | test_file_contents merge_renames-11-4 f1 "line\nline4" |
| 426 | |
| 427 | ###################################### |
| 428 | # |
| 429 | # Tests for troubles not specifically linked with renames but that I'd like to |
| 430 | # write: |
| 431 | # [c26c63eb1b] - 'merge --backout' does not handle conflicts properly |
| 432 |