Fossil SCM
Properly update the execute bit if it has changed in the commit being merged, and add info about changed permissions to the merge command's output.
Commit
3683508e989bf09b62bdff2de22b3bd2ab78da07
Parent
c8421e923c6e9e7…
2 files changed
+23
-2
+93
+23
-2
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -505,12 +505,12 @@ | ||
| 505 | 505 | "UPDATE fv SET" |
| 506 | 506 | " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 507 | 507 | " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 508 | 508 | " islinkm=coalesce((SELECT islink FROM vfile" |
| 509 | 509 | " WHERE vid=%d AND fnm=pathname),0)," |
| 510 | - " isexe=coalesce(isexe," | |
| 511 | - " (SELECT isexe FROM vfile WHERE vid=%d AND fnm=pathname))", | |
| 510 | + " isexe=coalesce((SELECT isexe FROM vfile WHERE vid=%d AND fnm=pathname)," | |
| 511 | + " isexe)", | |
| 512 | 512 | mid, mid, mid, mid |
| 513 | 513 | ); |
| 514 | 514 | |
| 515 | 515 | if( debugFlag ){ |
| 516 | 516 | db_prepare(&q, |
| @@ -534,10 +534,31 @@ | ||
| 534 | 534 | fossil_print(" fnn = [%s]\n", db_column_text(&q, 11)); |
| 535 | 535 | } |
| 536 | 536 | db_finalize(&q); |
| 537 | 537 | } |
| 538 | 538 | |
| 539 | + /* | |
| 540 | + ** Update the execute bit on files where it's changed from P->M but not P->V | |
| 541 | + */ | |
| 542 | + db_prepare(&q, | |
| 543 | + "SELECT idv, fn, fv.isexe FROM fv, vfile p, vfile v" | |
| 544 | + " WHERE p.id=idp AND v.id=idv AND fv.isexe!=p.isexe AND v.isexe=p.isexe" | |
| 545 | + ); | |
| 546 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 547 | + int idv = db_column_int(&q, 0); | |
| 548 | + const char *zName = db_column_text(&q, 1); | |
| 549 | + int isExe = db_column_int(&q, 2); | |
| 550 | + fossil_print("%s %s\n", isExe ? "EXECUTABLE" : "UNEXEC", zName); | |
| 551 | + if( !dryRunFlag ){ | |
| 552 | + char *zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); | |
| 553 | + file_wd_setexe(zFullPath, isExe); | |
| 554 | + free(zFullPath); | |
| 555 | + db_multi_exec("UPDATE vfile SET isexe=%d WHERE id=%d", isExe, idv); | |
| 556 | + } | |
| 557 | + } | |
| 558 | + db_finalize(&q); | |
| 559 | + | |
| 539 | 560 | /* |
| 540 | 561 | ** Find files in M and V but not in P and report conflicts. |
| 541 | 562 | ** The file in M will be ignored. It will be treated as if it |
| 542 | 563 | ** does not exist. |
| 543 | 564 | */ |
| 544 | 565 | |
| 545 | 566 | ADDED test/merge_exe.test |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -505,12 +505,12 @@ | |
| 505 | "UPDATE fv SET" |
| 506 | " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 507 | " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 508 | " islinkm=coalesce((SELECT islink FROM vfile" |
| 509 | " WHERE vid=%d AND fnm=pathname),0)," |
| 510 | " isexe=coalesce(isexe," |
| 511 | " (SELECT isexe FROM vfile WHERE vid=%d AND fnm=pathname))", |
| 512 | mid, mid, mid, mid |
| 513 | ); |
| 514 | |
| 515 | if( debugFlag ){ |
| 516 | db_prepare(&q, |
| @@ -534,10 +534,31 @@ | |
| 534 | fossil_print(" fnn = [%s]\n", db_column_text(&q, 11)); |
| 535 | } |
| 536 | db_finalize(&q); |
| 537 | } |
| 538 | |
| 539 | /* |
| 540 | ** Find files in M and V but not in P and report conflicts. |
| 541 | ** The file in M will be ignored. It will be treated as if it |
| 542 | ** does not exist. |
| 543 | */ |
| 544 | |
| 545 | DDED test/merge_exe.test |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -505,12 +505,12 @@ | |
| 505 | "UPDATE fv SET" |
| 506 | " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 507 | " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND fnm=pathname),0)," |
| 508 | " islinkm=coalesce((SELECT islink FROM vfile" |
| 509 | " WHERE vid=%d AND fnm=pathname),0)," |
| 510 | " isexe=coalesce((SELECT isexe FROM vfile WHERE vid=%d AND fnm=pathname)," |
| 511 | " isexe)", |
| 512 | mid, mid, mid, mid |
| 513 | ); |
| 514 | |
| 515 | if( debugFlag ){ |
| 516 | db_prepare(&q, |
| @@ -534,10 +534,31 @@ | |
| 534 | fossil_print(" fnn = [%s]\n", db_column_text(&q, 11)); |
| 535 | } |
| 536 | db_finalize(&q); |
| 537 | } |
| 538 | |
| 539 | /* |
| 540 | ** Update the execute bit on files where it's changed from P->M but not P->V |
| 541 | */ |
| 542 | db_prepare(&q, |
| 543 | "SELECT idv, fn, fv.isexe FROM fv, vfile p, vfile v" |
| 544 | " WHERE p.id=idp AND v.id=idv AND fv.isexe!=p.isexe AND v.isexe=p.isexe" |
| 545 | ); |
| 546 | while( db_step(&q)==SQLITE_ROW ){ |
| 547 | int idv = db_column_int(&q, 0); |
| 548 | const char *zName = db_column_text(&q, 1); |
| 549 | int isExe = db_column_int(&q, 2); |
| 550 | fossil_print("%s %s\n", isExe ? "EXECUTABLE" : "UNEXEC", zName); |
| 551 | if( !dryRunFlag ){ |
| 552 | char *zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); |
| 553 | file_wd_setexe(zFullPath, isExe); |
| 554 | free(zFullPath); |
| 555 | db_multi_exec("UPDATE vfile SET isexe=%d WHERE id=%d", isExe, idv); |
| 556 | } |
| 557 | } |
| 558 | db_finalize(&q); |
| 559 | |
| 560 | /* |
| 561 | ** Find files in M and V but not in P and report conflicts. |
| 562 | ** The file in M will be ignored. It will be treated as if it |
| 563 | ** does not exist. |
| 564 | */ |
| 565 | |
| 566 | DDED test/merge_exe.test |
+93
| --- a/test/merge_exe.test | ||
| +++ b/test/merge_exe.test | ||
| @@ -0,0 +1,93 @@ | ||
| 1 | +# | |
| 2 | +# Copyright (c) 2016 D. Richard Hipp | |
| 3 | +# | |
| 4 | +# This program is free software; you can redistribute it and/or | |
| 5 | +# modify it under the terms of the Simplified BSD License (also | |
| 6 | +# known as the "2-Clause License" or "FreeBSD License".) | |
| 7 | +# | |
| 8 | +# This program is distributed in the hope that it will be useful, | |
| 9 | +# but without any warranty; without even the implied warranty of | |
| 10 | +# merchantability or fitness for a particular purpose. | |
| 11 | +# | |
| 12 | +# Author contact information: | |
| 13 | +# [email protected] | |
| 14 | +# http://www.hwaci.com/drh/ | |
| 15 | +# | |
| 16 | +############################################################################ | |
| 17 | +# | |
| 18 | +# Testing changes to a file's execute bit caused by a merge | |
| 19 | +# | |
| 20 | + | |
| 21 | +if {$tcl_platform(platform) eq "unix"} { | |
| 22 | + proc setx {fn isexe} { | |
| 23 | + file attributes $fn -permissions [expr {$isexe ? "+" : "-"}]x | |
| 24 | + } | |
| 25 | + | |
| 26 | + proc test_exe {fn expected} { | |
| 27 | + test merge_exe-$fn {[file executable $fn]==$expected} | |
| 28 | + } | |
| 29 | +} else { | |
| 30 | + # WARNING: This is a hack for setting and testing a file's execute bit | |
| 31 | + # on Windows. Never operate directly on Fossil database files like this | |
| 32 | + # unless you really need to and really know what you're doing. | |
| 33 | + | |
| 34 | + proc query {sql} { | |
| 35 | + return [exec $::fossilexe sqlite3 --no-repository _FOSSIL_ $sql] | |
| 36 | + } | |
| 37 | + | |
| 38 | + proc setx {fn isexe} { | |
| 39 | + set isexe [expr {bool($isexe)}] | |
| 40 | + query "UPDATE vfile SET isexe=$isexe WHERE pathname='$fn'" | |
| 41 | + } | |
| 42 | + | |
| 43 | + proc test_exe {fn expected} { | |
| 44 | + set result [query "SELECT isexe FROM vfile WHERE pathname='$fn'"] | |
| 45 | + test merge_exe-$fn {$result==$expected} | |
| 46 | + } | |
| 47 | +} | |
| 48 | + | |
| 49 | +test_setup | |
| 50 | + | |
| 51 | +write_file f1 "line" | |
| 52 | +write_file f2 "line" | |
| 53 | +write_file f3 "line" | |
| 54 | +write_file f4 "line" | |
| 55 | +fossil addremove | |
| 56 | +setx f3 1 | |
| 57 | +setx f4 1 | |
| 58 | +fossil commit -m "add files" | |
| 59 | + | |
| 60 | +write_file f0 "f0" | |
| 61 | +fossil add f0 | |
| 62 | +setx f0 1 | |
| 63 | +fossil mv --hard f1 f1n | |
| 64 | +setx f1n 1 | |
| 65 | +write_file f2 "line\nline2" | |
| 66 | +setx f2 1 | |
| 67 | +write_file f3 "line\nline2" | |
| 68 | +setx f3 0 | |
| 69 | +setx f4 0 | |
| 70 | +fossil commit -b b -m "changes" | |
| 71 | + | |
| 72 | +fossil update trunk | |
| 73 | +write_file f3 "line3\nline" | |
| 74 | +fossil commit -m "edit f3" | |
| 75 | + | |
| 76 | +fossil merge b | |
| 77 | +test_status_list merge_exe-mrg $RESULT { | |
| 78 | + EXECUTABLE f1 | |
| 79 | + EXECUTABLE f2 | |
| 80 | + UNEXEC f3 | |
| 81 | + UNEXEC f4 | |
| 82 | + UPDATE f2 | |
| 83 | + MERGE f3 | |
| 84 | + RENAME f1 -> f1n | |
| 85 | + ADDED f0 | |
| 86 | +} | |
| 87 | +foreach {fn isexe} {f0 1 f1n 1 f2 1 f3 0 f4 0} { | |
| 88 | + test_exe $fn $isexe | |
| 89 | +} | |
| 90 | + | |
| 91 | +############################################################################### | |
| 92 | + | |
| 93 | +test_cleanup |
| --- a/test/merge_exe.test | |
| +++ b/test/merge_exe.test | |
| @@ -0,0 +1,93 @@ | |
| --- a/test/merge_exe.test | |
| +++ b/test/merge_exe.test | |
| @@ -0,0 +1,93 @@ | |
| 1 | # |
| 2 | # Copyright (c) 2016 D. Richard Hipp |
| 3 | # |
| 4 | # This program is free software; you can redistribute it and/or |
| 5 | # modify it under the terms of the Simplified BSD License (also |
| 6 | # known as the "2-Clause License" or "FreeBSD License".) |
| 7 | # |
| 8 | # This program is distributed in the hope that it will be useful, |
| 9 | # but without any warranty; without even the implied warranty of |
| 10 | # merchantability or fitness for a particular purpose. |
| 11 | # |
| 12 | # Author contact information: |
| 13 | # [email protected] |
| 14 | # http://www.hwaci.com/drh/ |
| 15 | # |
| 16 | ############################################################################ |
| 17 | # |
| 18 | # Testing changes to a file's execute bit caused by a merge |
| 19 | # |
| 20 | |
| 21 | if {$tcl_platform(platform) eq "unix"} { |
| 22 | proc setx {fn isexe} { |
| 23 | file attributes $fn -permissions [expr {$isexe ? "+" : "-"}]x |
| 24 | } |
| 25 | |
| 26 | proc test_exe {fn expected} { |
| 27 | test merge_exe-$fn {[file executable $fn]==$expected} |
| 28 | } |
| 29 | } else { |
| 30 | # WARNING: This is a hack for setting and testing a file's execute bit |
| 31 | # on Windows. Never operate directly on Fossil database files like this |
| 32 | # unless you really need to and really know what you're doing. |
| 33 | |
| 34 | proc query {sql} { |
| 35 | return [exec $::fossilexe sqlite3 --no-repository _FOSSIL_ $sql] |
| 36 | } |
| 37 | |
| 38 | proc setx {fn isexe} { |
| 39 | set isexe [expr {bool($isexe)}] |
| 40 | query "UPDATE vfile SET isexe=$isexe WHERE pathname='$fn'" |
| 41 | } |
| 42 | |
| 43 | proc test_exe {fn expected} { |
| 44 | set result [query "SELECT isexe FROM vfile WHERE pathname='$fn'"] |
| 45 | test merge_exe-$fn {$result==$expected} |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | test_setup |
| 50 | |
| 51 | write_file f1 "line" |
| 52 | write_file f2 "line" |
| 53 | write_file f3 "line" |
| 54 | write_file f4 "line" |
| 55 | fossil addremove |
| 56 | setx f3 1 |
| 57 | setx f4 1 |
| 58 | fossil commit -m "add files" |
| 59 | |
| 60 | write_file f0 "f0" |
| 61 | fossil add f0 |
| 62 | setx f0 1 |
| 63 | fossil mv --hard f1 f1n |
| 64 | setx f1n 1 |
| 65 | write_file f2 "line\nline2" |
| 66 | setx f2 1 |
| 67 | write_file f3 "line\nline2" |
| 68 | setx f3 0 |
| 69 | setx f4 0 |
| 70 | fossil commit -b b -m "changes" |
| 71 | |
| 72 | fossil update trunk |
| 73 | write_file f3 "line3\nline" |
| 74 | fossil commit -m "edit f3" |
| 75 | |
| 76 | fossil merge b |
| 77 | test_status_list merge_exe-mrg $RESULT { |
| 78 | EXECUTABLE f1 |
| 79 | EXECUTABLE f2 |
| 80 | UNEXEC f3 |
| 81 | UNEXEC f4 |
| 82 | UPDATE f2 |
| 83 | MERGE f3 |
| 84 | RENAME f1 -> f1n |
| 85 | ADDED f0 |
| 86 | } |
| 87 | foreach {fn isexe} {f0 1 f1n 1 f2 1 f3 0 f4 0} { |
| 88 | test_exe $fn $isexe |
| 89 | } |
| 90 | |
| 91 | ############################################################################### |
| 92 | |
| 93 | test_cleanup |