Implement support for fetch.fsck.* corresponding with the existing receive.fsck.*. This allows for pedantically cloning repositories with specific issues without turning off fetch.fsckObjects. One such repository is https://github.com/robbyrussell/oh-my-zsh.git which before this change will emit this error when cloned with fetch.fsckObjects: error: object 2b7227859263b6aabcc28355b0b994995b7148b6: zeroPaddedFilemode: contains zero-padded file modes fatal: Error in object fatal: index-pack failed Now with fetch.fsck.zeroPaddedFilemode=warn we'll warn about that issue, but the clone will succeed: warning: object 2b7227859263b6aabcc28355b0b994995b7148b6: zeroPaddedFilemode: contains zero-padded file modes warning: object a18c4d13c2a5fa2d4ecd5346c50e119b999b807d: zeroPaddedFilemode: contains zero-padded file modes warning: object 84df066176c8da3fd59b13731a86d90f4f1e5c9d: zeroPaddedFilemode: contains zero-padded file modes The motivation for this is to be able to turn on fetch.fsckObjects globally across a fleet of computers but still be able to manually clone various legacy repositories by either white-listing specific issues, or better yet whitelist specific objects. The use of --git-dir=* instead of -C in the tests could be considered somewhat archaic, but the tests I'm adding here are duplicating the corresponding receive.* tests with as few changes as possible. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@xxxxxxxxx> --- Documentation/config.txt | 20 +++++++++++--- fetch-pack.c | 32 +++++++++++++++++++++-- t/t5504-fetch-receive-strict.sh | 46 +++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 7ff453c53b..8dace49daa 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1467,6 +1467,16 @@ fetch.fsckObjects:: checked. Defaults to false. If not set, the value of `transfer.fsckObjects` is used instead. +fetch.fsck.<msg-id>:: + Acts like `fsck.<msg-id>`, but is used by + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See + the `fsck.<msg-id>` documentation for details. + +fetch.fsck.skipList:: + Acts like `fsck.skipList`, but is used by + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See + the `fsck.skipList` documentation for details. + fetch.unpackLimit:: If the number of objects fetched over the Git native transfer is below this @@ -1602,10 +1612,12 @@ fsck.<msg-id>:: repositories containing such data. + Setting `fsck.<msg-id>` will be picked up by linkgit:git-fsck[1], but -to accept pushes of such data set `receive.fsck.<msg-id>` instead. +to accept pushes of such data set `receive.fsck.<msg-id>` instead, or +to clone or fetch it set `fetch.fsck.<msg-id>`. + The rest of the documentation discusses `fsck.*` for brevity, but the -same applies for the corresponding `receive.fsck.*` variables. +same applies for the corresponding `receive.fsck.*` and +`fetch.<msg-id>.*`. variables. + When `fsck.<msg-id>` is set, errors can be switched to warnings and vice versa by configuring the `fsck.<msg-id>` setting where the @@ -1628,8 +1640,8 @@ fsck.skipList:: can be safely ignored such as invalid committer email addresses. Note: corrupt objects cannot be skipped with this setting. + -Like `fsck.<msg-id>` this variable has a corresponding -`receive.fsck.skipList` variant. +Like `fsck.<msg-id>` this variable has corresponding +`receive.fsck.skipList` and `fetch.fsck.skipList` variants. gc.aggressiveDepth:: The depth parameter used in the delta compression diff --git a/fetch-pack.c b/fetch-pack.c index 7ccb9c0d45..aea2f6cf26 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -21,6 +21,7 @@ #include "packfile.h" #include "object-store.h" #include "connected.h" +#include "fsck.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -35,6 +36,7 @@ static int agent_supported; static int server_supports_filtering; static struct lock_file shallow_lock; static const char *alternate_shallow_file; +static struct strbuf fsck_msg_types = STRBUF_INIT; /* Remember to update object flag allocation in object.h */ #define COMPLETE (1U << 0) @@ -937,7 +939,8 @@ static int get_pack(struct fetch_pack_args *args, */ argv_array_push(&cmd.args, "--fsck-objects"); else - argv_array_push(&cmd.args, "--strict"); + argv_array_pushf(&cmd.args, "--strict%s", + fsck_msg_types.buf); } cmd.in = demux.out; @@ -1458,6 +1461,31 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, return ref; } +static int fetch_pack_config_cb(const char *var, const char *value, void *cb) +{ + if (strcmp(var, "fetch.fsck.skiplist") == 0) { + const char *path; + + if (git_config_pathname(&path, var, value)) + return 1; + strbuf_addf(&fsck_msg_types, "%cskiplist=%s", + fsck_msg_types.len ? ',' : '=', path); + free((char *)path); + return 0; + } + + if (skip_prefix(var, "fetch.fsck.", &var)) { + if (is_valid_msg_type(var, value)) + strbuf_addf(&fsck_msg_types, "%c%s=%s", + fsck_msg_types.len ? ',' : '=', var, value); + else + warning("Skipping unknown msg id '%s'", var); + return 0; + } + + return git_default_config(var, value, cb); +} + static void fetch_pack_config(void) { git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit); @@ -1466,7 +1494,7 @@ static void fetch_pack_config(void) git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects); git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects); - git_config(git_default_config, NULL); + git_config(fetch_pack_config_cb, NULL); } static void fetch_pack_setup(void) diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 57ff78c201..004bfebe98 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -145,6 +145,20 @@ test_expect_success 'push with receive.fsck.skipList' ' git push --porcelain dst bogus ' +test_expect_success 'fetch with fetch.fsck.skipList' ' + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && + refspec=refs/heads/bogus:refs/heads/bogus && + git push . $commit:refs/heads/bogus && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckObjects true && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && + echo $commit >dst/.git/SKIP && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec +' + + test_expect_success 'push with receive.fsck.missingEmail=warn' ' commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && git push . $commit:refs/heads/bogus && @@ -163,6 +177,27 @@ test_expect_success 'push with receive.fsck.missingEmail=warn' ' ! grep "missingEmail" act ' +test_expect_success 'fetch with fetch.fsck.missingEmail=warn' ' + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" && + refspec=refs/heads/bogus:refs/heads/bogus && + git push . $commit:refs/heads/bogus && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && + git --git-dir=dst/.git config \ + fetch.fsck.missingEmail warn && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && + grep "missingEmail" act && + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + git --git-dir=dst/.git config \ + fetch.fsck.missingEmail ignore && + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && + ! grep "missingEmail" act +' + test_expect_success \ 'receive.fsck.unterminatedHeader=warn triggers error' ' rm -rf dst && @@ -174,4 +209,15 @@ test_expect_success \ grep "Cannot demote unterminatedheader" act ' +test_expect_success \ + 'fetch.fsck.unterminatedHeader=warn triggers error' ' + rm -rf dst && + git init dst && + git --git-dir=dst/.git config fetch.fsckobjects true && + git --git-dir=dst/.git config \ + fetch.fsck.unterminatedheader warn && + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD && + grep "Cannot demote unterminatedheader" act +' + test_done -- 2.18.0.345.g5c9ce644c3