fetch: implement fetch.fsck.*

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@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ævar Arnfjörð Bjarmason 2018-07-27 14:37:17 +00:00 committed by Junio C Hamano
parent 8b55b9db23
commit 1362df0d41
3 changed files with 92 additions and 6 deletions

View File

@ -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

View File

@ -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)

View File

@ -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