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>

Ævar Arnfjörð Bjarmason committed Jul 27, 2018 at 14:37 UTC 1362df0d41311beac8c778030ad0e8dcc2ef9af2
3 files changed +92 -6
Documentation/config.txt
+16 -4
@@ -1467,6 +1467,16 @@ fetch.fsckObjects::
1467 checked. Defaults to false. If not set, the value of
1468 `transfer.fsckObjects` is used instead.
1469
1470 +fetch.fsck.<msg-id>::
1471 + Acts like `fsck.<msg-id>`, but is used by
1472 + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
1473 + the `fsck.<msg-id>` documentation for details.
1474 +
1475 +fetch.fsck.skipList::
1476 + Acts like `fsck.skipList`, but is used by
1477 + linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
1478 + the `fsck.skipList` documentation for details.
1479 +
1480 fetch.unpackLimit::
1481 If the number of objects fetched over the Git native
1482 transfer is below this
@@ -1602,10 +1612,12 @@ fsck.<msg-id>::
1612 repositories containing such data.
1613 +
1614 Setting `fsck.<msg-id>` will be picked up by linkgit:git-fsck[1], but
1605 -to accept pushes of such data set `receive.fsck.<msg-id>` instead.
1615 +to accept pushes of such data set `receive.fsck.<msg-id>` instead, or
1616 +to clone or fetch it set `fetch.fsck.<msg-id>`.
1617 +
1618 The rest of the documentation discusses `fsck.*` for brevity, but the
1608 -same applies for the corresponding `receive.fsck.*` variables.
1619 +same applies for the corresponding `receive.fsck.*` and
1620 +`fetch.<msg-id>.*`. variables.
1621 +
1622 When `fsck.<msg-id>` is set, errors can be switched to warnings and
1623 vice versa by configuring the `fsck.<msg-id>` setting where the
@@ -1628,8 +1640,8 @@ fsck.skipList::
1640 can be safely ignored such as invalid committer email addresses.
1641 Note: corrupt objects cannot be skipped with this setting.
1642 +
1631 -Like `fsck.<msg-id>` this variable has a corresponding
1632 -`receive.fsck.skipList` variant.
1643 +Like `fsck.<msg-id>` this variable has corresponding
1644 +`receive.fsck.skipList` and `fetch.fsck.skipList` variants.
1645
1646 gc.aggressiveDepth::
1647 The depth parameter used in the delta compression
fetch-pack.c
+30 -2
@@ -21,6 +21,7 @@
21 #include "packfile.h"
22 #include "object-store.h"
23 #include "connected.h"
24 +#include "fsck.h"
25
26 static int transfer_unpack_limit = -1;
27 static int fetch_unpack_limit = -1;
@@ -35,6 +36,7 @@ static int agent_supported;
36 static int server_supports_filtering;
37 static struct lock_file shallow_lock;
38 static const char *alternate_shallow_file;
39 +static struct strbuf fsck_msg_types = STRBUF_INIT;
40
41 /* Remember to update object flag allocation in object.h */
42 #define COMPLETE (1U << 0)
@@ -937,7 +939,8 @@ static int get_pack(struct fetch_pack_args *args,
939 */
940 argv_array_push(&cmd.args, "--fsck-objects");
941 else
940 - argv_array_push(&cmd.args, "--strict");
942 + argv_array_pushf(&cmd.args, "--strict%s",
943 + fsck_msg_types.buf);
944 }
945
946 cmd.in = demux.out;
@@ -1458,6 +1461,31 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1461 return ref;
1462 }
1463
1464 +static int fetch_pack_config_cb(const char *var, const char *value, void *cb)
1465 +{
1466 + if (strcmp(var, "fetch.fsck.skiplist") == 0) {
1467 + const char *path;
1468 +
1469 + if (git_config_pathname(&path, var, value))
1470 + return 1;
1471 + strbuf_addf(&fsck_msg_types, "%cskiplist=%s",
1472 + fsck_msg_types.len ? ',' : '=', path);
1473 + free((char *)path);
1474 + return 0;
1475 + }
1476 +
1477 + if (skip_prefix(var, "fetch.fsck.", &var)) {
1478 + if (is_valid_msg_type(var, value))
1479 + strbuf_addf(&fsck_msg_types, "%c%s=%s",
1480 + fsck_msg_types.len ? ',' : '=', var, value);
1481 + else
1482 + warning("Skipping unknown msg id '%s'", var);
1483 + return 0;
1484 + }
1485 +
1486 + return git_default_config(var, value, cb);
1487 +}
1488 +
1489 static void fetch_pack_config(void)
1490 {
1491 git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit);
@@ -1466,7 +1494,7 @@ static void fetch_pack_config(void)
1494 git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
1495 git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
1496
1469 - git_config(git_default_config, NULL);
1497 + git_config(fetch_pack_config_cb, NULL);
1498 }
1499
1500 static void fetch_pack_setup(void)
t/t5504-fetch-receive-strict.sh
+46
@@ -145,6 +145,20 @@ test_expect_success 'push with receive.fsck.skipList' '
145 git push --porcelain dst bogus
146 '
147
148 +test_expect_success 'fetch with fetch.fsck.skipList' '
149 + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
150 + refspec=refs/heads/bogus:refs/heads/bogus &&
151 + git push . $commit:refs/heads/bogus &&
152 + rm -rf dst &&
153 + git init dst &&
154 + git --git-dir=dst/.git config fetch.fsckObjects true &&
155 + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
156 + git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP &&
157 + echo $commit >dst/.git/SKIP &&
158 + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec
159 +'
160 +
161 +
162 test_expect_success 'push with receive.fsck.missingEmail=warn' '
163 commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
164 git push . $commit:refs/heads/bogus &&
@@ -163,6 +177,27 @@ test_expect_success 'push with receive.fsck.missingEmail=warn' '
177 ! grep "missingEmail" act
178 '
179
180 +test_expect_success 'fetch with fetch.fsck.missingEmail=warn' '
181 + commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
182 + refspec=refs/heads/bogus:refs/heads/bogus &&
183 + git push . $commit:refs/heads/bogus &&
184 + rm -rf dst &&
185 + git init dst &&
186 + git --git-dir=dst/.git config fetch.fsckobjects true &&
187 + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
188 + git --git-dir=dst/.git config \
189 + fetch.fsck.missingEmail warn &&
190 + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
191 + grep "missingEmail" act &&
192 + rm -rf dst &&
193 + git init dst &&
194 + git --git-dir=dst/.git config fetch.fsckobjects true &&
195 + git --git-dir=dst/.git config \
196 + fetch.fsck.missingEmail ignore &&
197 + git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
198 + ! grep "missingEmail" act
199 +'
200 +
201 test_expect_success \
202 'receive.fsck.unterminatedHeader=warn triggers error' '
203 rm -rf dst &&
@@ -174,4 +209,15 @@ test_expect_success \
209 grep "Cannot demote unterminatedheader" act
210 '
211
212 +test_expect_success \
213 + 'fetch.fsck.unterminatedHeader=warn triggers error' '
214 + rm -rf dst &&
215 + git init dst &&
216 + git --git-dir=dst/.git config fetch.fsckobjects true &&
217 + git --git-dir=dst/.git config \
218 + fetch.fsck.unterminatedheader warn &&
219 + test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD &&
220 + grep "Cannot demote unterminatedheader" act
221 +'
222 +
223 test_done