Git fork

clone: set fetch.bundleURI if appropriate

Bundle providers may organize their bundle lists in a way that is
intended to improve incremental fetches, not just initial clones.
However, they do need to state that they have organized with that in
mind, or else the client will not expect to save time by downloading
bundles after the initial clone. This is done by specifying a
bundle.heuristic value.

There are two types of bundle lists: those at a static URI and those
that are advertised from a Git remote over protocol v2.

The new fetch.bundleURI config value applies for static bundle URIs that
are not advertised over protocol v2. If the user specifies a static URI
via 'git clone --bundle-uri', then Git can set this config as a reminder
for future 'git fetch' operations to check the bundle list before
connecting to the remote(s).

For lists provided over protocol v2, we will want to take a different
approach and create a property of the remote itself by creating a
remote.<id>.* type config key. That is not implemented in this change.

Later changes will update 'git fetch' to consume this option.

Signed-off-by: Derrick Stolee <derrickstolee@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Derrick Stolee and committed by
Junio C Hamano
4074d3c7 7903efb7

+63 -3
+8
Documentation/config/fetch.txt
··· 96 96 merge and the write may take longer. Having an updated commit-graph 97 97 file helps performance of many Git commands, including `git merge-base`, 98 98 `git push -f`, and `git log --graph`. Defaults to false. 99 + 100 + fetch.bundleURI:: 101 + This value stores a URI for downloading Git object data from a bundle 102 + URI before performing an incremental fetch from the origin Git server. 103 + This is similar to how the `--bundle-uri` option behaves in 104 + linkgit:git-clone[1]. `git clone --bundle-uri` will set the 105 + `fetch.bundleURI` value if the supplied bundle URI contains a bundle 106 + list that is organized for incremental fetches.
+5 -1
builtin/clone.c
··· 1248 1248 * data from the --bundle-uri option. 1249 1249 */ 1250 1250 if (bundle_uri) { 1251 + int has_heuristic = 0; 1252 + 1251 1253 /* At this point, we need the_repository to match the cloned repo. */ 1252 1254 if (repo_init(the_repository, git_dir, work_tree)) 1253 1255 warning(_("failed to initialize the repo, skipping bundle URI")); 1254 - else if (fetch_bundle_uri(the_repository, bundle_uri)) 1256 + else if (fetch_bundle_uri(the_repository, bundle_uri, &has_heuristic)) 1255 1257 warning(_("failed to fetch objects from bundle URI '%s'"), 1256 1258 bundle_uri); 1259 + else if (has_heuristic) 1260 + git_config_set_gently("fetch.bundleuri", bundle_uri); 1257 1261 } 1258 1262 1259 1263 strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
+4 -1
bundle-uri.c
··· 736 736 return 0; 737 737 } 738 738 739 - int fetch_bundle_uri(struct repository *r, const char *uri) 739 + int fetch_bundle_uri(struct repository *r, const char *uri, 740 + int *has_heuristic) 740 741 { 741 742 int result; 742 743 struct bundle_list list; ··· 756 757 result = unbundle_all_bundles(r, &list); 757 758 758 759 cleanup: 760 + if (has_heuristic) 761 + *has_heuristic = (list.heuristic != BUNDLE_HEURISTIC_NONE); 759 762 for_all_bundles_in_list(&list, unlink_bundle, NULL); 760 763 clear_bundle_list(&list); 761 764 clear_remote_bundle_info(&bundle, NULL);
+7 -1
bundle-uri.h
··· 124 124 * based on that information. 125 125 * 126 126 * Returns non-zero if no bundle information is found at the given 'uri'. 127 + * 128 + * If the pointer 'has_heuristic' is non-NULL, then the value it points to 129 + * will be set to be non-zero if and only if the fetched list has a 130 + * heuristic value. Such a value indicates that the list was designed for 131 + * incremental fetches. 127 132 */ 128 - int fetch_bundle_uri(struct repository *r, const char *uri); 133 + int fetch_bundle_uri(struct repository *r, const char *uri, 134 + int *has_heuristic); 129 135 130 136 /** 131 137 * Given a bundle list that was already advertised (likely by the
+39
t/t5558-clone-bundle-uri.sh
··· 432 432 --single-branch --branch=base --no-tags \ 433 433 "$HTTPD_URL/smart/fetch.git" clone-token-http && 434 434 435 + test_cmp_config -C clone-token-http "$HTTPD_URL/bundle-list" fetch.bundleuri && 436 + 435 437 cat >expect <<-EOF && 436 438 $HTTPD_URL/bundle-list 437 439 $HTTPD_URL/bundle-1.bundle ··· 439 441 440 442 test_remote_https_urls <trace-clone.txt >actual && 441 443 test_cmp expect actual 444 + ' 445 + 446 + test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' ' 447 + test_when_finished rm -rf fetch-http-4 trace*.txt && 448 + 449 + cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF && 450 + [bundle] 451 + version = 1 452 + mode = all 453 + heuristic = creationToken 454 + 455 + [bundle "bundle-1"] 456 + uri = bundle-1.bundle 457 + creationToken = 1 458 + EOF 459 + 460 + GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \ 461 + git clone --single-branch --branch=base \ 462 + --bundle-uri="$HTTPD_URL/bundle-list" \ 463 + "$HTTPD_URL/smart/fetch.git" fetch-http-4 && 464 + 465 + test_cmp_config -C fetch-http-4 "$HTTPD_URL/bundle-list" fetch.bundleuri && 466 + 467 + cat >expect <<-EOF && 468 + $HTTPD_URL/bundle-list 469 + $HTTPD_URL/bundle-1.bundle 470 + EOF 471 + 472 + test_remote_https_urls <trace-clone.txt >actual && 473 + test_cmp expect actual && 474 + 475 + # only received base ref from bundle-1 476 + git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs && 477 + cat >expect <<-\EOF && 478 + refs/bundles/base 479 + EOF 480 + test_cmp expect refs 442 481 ' 443 482 444 483 # Do not add tests here unless they use the HTTP server, as they will