Fossil SCM
Fix 'fossil revert' to fully revert renames
Commit
eef34741a998489ca6c1e6e36a00cf588c431aba
Parent
461a4d11d180dfd…
2 files changed
+25
-6
+26
+25
-6
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -667,10 +667,13 @@ | ||
| 667 | 667 | ** Usage: %fossil revert ?-r REVISION? ?FILE ...? |
| 668 | 668 | ** |
| 669 | 669 | ** Revert to the current repository version of FILE, or to |
| 670 | 670 | ** the version associated with baseline REVISION if the -r flag |
| 671 | 671 | ** appears. |
| 672 | +** | |
| 673 | +** If FILE was part of a rename operation, both the original file | |
| 674 | +** and the renamed file are reverted. | |
| 672 | 675 | ** |
| 673 | 676 | ** Revert all files if no file name is provided. |
| 674 | 677 | ** |
| 675 | 678 | ** If a file is reverted accidently, it can be restored using |
| 676 | 679 | ** the "fossil undo" command. |
| @@ -706,11 +709,22 @@ | ||
| 706 | 709 | if( g.argc>2 ){ |
| 707 | 710 | for(i=2; i<g.argc; i++){ |
| 708 | 711 | Blob fname; |
| 709 | 712 | zFile = mprintf("%/", g.argv[i]); |
| 710 | 713 | file_tree_name(zFile, &fname, 1); |
| 711 | - db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname); | |
| 714 | + db_multi_exec( | |
| 715 | + "REPLACE INTO torevert VALUES(%B);" | |
| 716 | + "INSERT OR IGNORE INTO torevert" | |
| 717 | + " SELECT pathname" | |
| 718 | + " FROM vfile" | |
| 719 | + " WHERE origname IN(%B)" | |
| 720 | + " UNION ALL" | |
| 721 | + " SELECT origname" | |
| 722 | + " FROM vfile" | |
| 723 | + " WHERE pathname IN(%B) AND origname IS NOT NULL;", | |
| 724 | + &fname, &fname, &fname | |
| 725 | + ); | |
| 712 | 726 | blob_reset(&fname); |
| 713 | 727 | } |
| 714 | 728 | }else{ |
| 715 | 729 | int vid; |
| 716 | 730 | vid = db_lget_int("checkout", 0); |
| @@ -748,11 +762,17 @@ | ||
| 748 | 762 | }else{ |
| 749 | 763 | undo_save(zFile); |
| 750 | 764 | file_delete(zFull); |
| 751 | 765 | fossil_print("DELETE: %s\n", zFile); |
| 752 | 766 | } |
| 753 | - db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile); | |
| 767 | + db_multi_exec( | |
| 768 | + "UPDATE vfile" | |
| 769 | + " SET pathname=origname, origname=NULL" | |
| 770 | + " WHERE pathname=%Q AND origname!=pathname AND origname IS NOT NULL;" | |
| 771 | + "DELETE FROM vfile WHERE pathname=%Q", | |
| 772 | + zFile, zFile | |
| 773 | + ); | |
| 754 | 774 | }else{ |
| 755 | 775 | sqlite3_int64 mtime; |
| 756 | 776 | undo_save(zFile); |
| 757 | 777 | if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){ |
| 758 | 778 | file_delete(zFull); |
| @@ -765,18 +785,17 @@ | ||
| 765 | 785 | file_wd_setexe(zFull, isExe); |
| 766 | 786 | fossil_print("REVERTED: %s\n", zFile); |
| 767 | 787 | mtime = file_wd_mtime(zFull); |
| 768 | 788 | db_multi_exec( |
| 769 | 789 | "UPDATE vfile" |
| 770 | - " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid," | |
| 771 | - " pathname=coalesce(origname,pathname), origname=NULL" | |
| 772 | - " WHERE pathname=%Q", | |
| 773 | - mtime, isExe, isLink, zFile | |
| 790 | + " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid" | |
| 791 | + " WHERE pathname=%Q OR origname=%Q", | |
| 792 | + mtime, isExe, isLink, zFile, zFile | |
| 774 | 793 | ); |
| 775 | 794 | } |
| 776 | 795 | blob_reset(&record); |
| 777 | 796 | free(zFull); |
| 778 | 797 | } |
| 779 | 798 | db_finalize(&q); |
| 780 | 799 | undo_finish(); |
| 781 | 800 | db_end_transaction(0); |
| 782 | 801 | } |
| 783 | 802 | |
| 784 | 803 | ADDED test/revert.test |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -667,10 +667,13 @@ | |
| 667 | ** Usage: %fossil revert ?-r REVISION? ?FILE ...? |
| 668 | ** |
| 669 | ** Revert to the current repository version of FILE, or to |
| 670 | ** the version associated with baseline REVISION if the -r flag |
| 671 | ** appears. |
| 672 | ** |
| 673 | ** Revert all files if no file name is provided. |
| 674 | ** |
| 675 | ** If a file is reverted accidently, it can be restored using |
| 676 | ** the "fossil undo" command. |
| @@ -706,11 +709,22 @@ | |
| 706 | if( g.argc>2 ){ |
| 707 | for(i=2; i<g.argc; i++){ |
| 708 | Blob fname; |
| 709 | zFile = mprintf("%/", g.argv[i]); |
| 710 | file_tree_name(zFile, &fname, 1); |
| 711 | db_multi_exec("REPLACE INTO torevert VALUES(%B)", &fname); |
| 712 | blob_reset(&fname); |
| 713 | } |
| 714 | }else{ |
| 715 | int vid; |
| 716 | vid = db_lget_int("checkout", 0); |
| @@ -748,11 +762,17 @@ | |
| 748 | }else{ |
| 749 | undo_save(zFile); |
| 750 | file_delete(zFull); |
| 751 | fossil_print("DELETE: %s\n", zFile); |
| 752 | } |
| 753 | db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile); |
| 754 | }else{ |
| 755 | sqlite3_int64 mtime; |
| 756 | undo_save(zFile); |
| 757 | if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){ |
| 758 | file_delete(zFull); |
| @@ -765,18 +785,17 @@ | |
| 765 | file_wd_setexe(zFull, isExe); |
| 766 | fossil_print("REVERTED: %s\n", zFile); |
| 767 | mtime = file_wd_mtime(zFull); |
| 768 | db_multi_exec( |
| 769 | "UPDATE vfile" |
| 770 | " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid," |
| 771 | " pathname=coalesce(origname,pathname), origname=NULL" |
| 772 | " WHERE pathname=%Q", |
| 773 | mtime, isExe, isLink, zFile |
| 774 | ); |
| 775 | } |
| 776 | blob_reset(&record); |
| 777 | free(zFull); |
| 778 | } |
| 779 | db_finalize(&q); |
| 780 | undo_finish(); |
| 781 | db_end_transaction(0); |
| 782 | } |
| 783 | |
| 784 | DDED test/revert.test |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -667,10 +667,13 @@ | |
| 667 | ** Usage: %fossil revert ?-r REVISION? ?FILE ...? |
| 668 | ** |
| 669 | ** Revert to the current repository version of FILE, or to |
| 670 | ** the version associated with baseline REVISION if the -r flag |
| 671 | ** appears. |
| 672 | ** |
| 673 | ** If FILE was part of a rename operation, both the original file |
| 674 | ** and the renamed file are reverted. |
| 675 | ** |
| 676 | ** Revert all files if no file name is provided. |
| 677 | ** |
| 678 | ** If a file is reverted accidently, it can be restored using |
| 679 | ** the "fossil undo" command. |
| @@ -706,11 +709,22 @@ | |
| 709 | if( g.argc>2 ){ |
| 710 | for(i=2; i<g.argc; i++){ |
| 711 | Blob fname; |
| 712 | zFile = mprintf("%/", g.argv[i]); |
| 713 | file_tree_name(zFile, &fname, 1); |
| 714 | db_multi_exec( |
| 715 | "REPLACE INTO torevert VALUES(%B);" |
| 716 | "INSERT OR IGNORE INTO torevert" |
| 717 | " SELECT pathname" |
| 718 | " FROM vfile" |
| 719 | " WHERE origname IN(%B)" |
| 720 | " UNION ALL" |
| 721 | " SELECT origname" |
| 722 | " FROM vfile" |
| 723 | " WHERE pathname IN(%B) AND origname IS NOT NULL;", |
| 724 | &fname, &fname, &fname |
| 725 | ); |
| 726 | blob_reset(&fname); |
| 727 | } |
| 728 | }else{ |
| 729 | int vid; |
| 730 | vid = db_lget_int("checkout", 0); |
| @@ -748,11 +762,17 @@ | |
| 762 | }else{ |
| 763 | undo_save(zFile); |
| 764 | file_delete(zFull); |
| 765 | fossil_print("DELETE: %s\n", zFile); |
| 766 | } |
| 767 | db_multi_exec( |
| 768 | "UPDATE vfile" |
| 769 | " SET pathname=origname, origname=NULL" |
| 770 | " WHERE pathname=%Q AND origname!=pathname AND origname IS NOT NULL;" |
| 771 | "DELETE FROM vfile WHERE pathname=%Q", |
| 772 | zFile, zFile |
| 773 | ); |
| 774 | }else{ |
| 775 | sqlite3_int64 mtime; |
| 776 | undo_save(zFile); |
| 777 | if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){ |
| 778 | file_delete(zFull); |
| @@ -765,18 +785,17 @@ | |
| 785 | file_wd_setexe(zFull, isExe); |
| 786 | fossil_print("REVERTED: %s\n", zFile); |
| 787 | mtime = file_wd_mtime(zFull); |
| 788 | db_multi_exec( |
| 789 | "UPDATE vfile" |
| 790 | " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d,mrid=rid" |
| 791 | " WHERE pathname=%Q OR origname=%Q", |
| 792 | mtime, isExe, isLink, zFile, zFile |
| 793 | ); |
| 794 | } |
| 795 | blob_reset(&record); |
| 796 | free(zFull); |
| 797 | } |
| 798 | db_finalize(&q); |
| 799 | undo_finish(); |
| 800 | db_end_transaction(0); |
| 801 | } |
| 802 | |
| 803 | DDED test/revert.test |
+26
| --- a/test/revert.test | ||
| +++ b/test/revert.test | ||
| @@ -0,0 +1,26 @@ | ||
| 1 | +puts res=$# Fossil will write dexec rm f1po_init# Copytcatch {exec $::exec mvitory} $res]} { | |
| 2 | + puts stderr "Cannot ris test within anif {[llength $args] % 2} { | |
| 3 | + set revertArgs [lindex $args 0] | |
| 4 | + # set args [lrange $args 1 end] | |
| 5 | + } else { | |
| 6 | + set revertArgs {} | |
| 7 | + }VERTED: f3 | |
| 8 | + DELETE:j@,1X@Se,4:: f0G@YW,21@UT,3:ED:1w@WW,3:ED:3t@YT,G:ED: f3 | |
| 9 | + DELETE:K@hF,O@YG:ED: f3 | |
| 10 | + DELETE:K@hF,O@Yl,1 | |
| 11 | + DELETE:a@nd,1WvoIq;-testnormalize-status-list] | |
| 12 | + set r] | |
| 13 | + if {$result ne $expected} { | |
| 14 | + set passed 0 | |
| 15 | + protOut " Expected:\n [join $expected "\n "]" | |
| 16 | + protOut " Got:\n [joh {exec $::fossilexe info} res | |
| 17 | +if {![regexp {use --repository} $res]} { | |
| 18 | + puts stderr "Cannot run this test within an open checkout" | |
| 19 | + return | |
| 20 | +} | |
| 21 | +repo_init# Copytcatch {exec $::fossilexe info} res | |
| 22 | +if {![regexp {use --repository} $res]} { | |
| 23 | + puts stderr "Cannot run this test witt# Copytcatch {exec $::fossilexe info} res | |
| 24 | +if {![regexp {use --repository} $res]} { | |
| 25 | + put12 f03 f1 {exec $::fossilexe info}t# Copytcatch #ft# Copytcatch {exec $::foss5 f3 {exec $::fossilexe info} res | |
| 26 | +if {![rexec $::foss5 f3 {exec $:: |
| --- a/test/revert.test | |
| +++ b/test/revert.test | |
| @@ -0,0 +1,26 @@ | |
| --- a/test/revert.test | |
| +++ b/test/revert.test | |
| @@ -0,0 +1,26 @@ | |
| 1 | puts res=$# Fossil will write dexec rm f1po_init# Copytcatch {exec $::exec mvitory} $res]} { |
| 2 | puts stderr "Cannot ris test within anif {[llength $args] % 2} { |
| 3 | set revertArgs [lindex $args 0] |
| 4 | # set args [lrange $args 1 end] |
| 5 | } else { |
| 6 | set revertArgs {} |
| 7 | }VERTED: f3 |
| 8 | DELETE:j@,1X@Se,4:: f0G@YW,21@UT,3:ED:1w@WW,3:ED:3t@YT,G:ED: f3 |
| 9 | DELETE:K@hF,O@YG:ED: f3 |
| 10 | DELETE:K@hF,O@Yl,1 |
| 11 | DELETE:a@nd,1WvoIq;-testnormalize-status-list] |
| 12 | set r] |
| 13 | if {$result ne $expected} { |
| 14 | set passed 0 |
| 15 | protOut " Expected:\n [join $expected "\n "]" |
| 16 | protOut " Got:\n [joh {exec $::fossilexe info} res |
| 17 | if {![regexp {use --repository} $res]} { |
| 18 | puts stderr "Cannot run this test within an open checkout" |
| 19 | return |
| 20 | } |
| 21 | repo_init# Copytcatch {exec $::fossilexe info} res |
| 22 | if {![regexp {use --repository} $res]} { |
| 23 | puts stderr "Cannot run this test witt# Copytcatch {exec $::fossilexe info} res |
| 24 | if {![regexp {use --repository} $res]} { |
| 25 | put12 f03 f1 {exec $::fossilexe info}t# Copytcatch #ft# Copytcatch {exec $::foss5 f3 {exec $::fossilexe info} res |
| 26 | if {![rexec $::foss5 f3 {exec $:: |