return remaining_nr;
}
+static int try_promisor_remotes(struct repository *repo,
+ struct object_id **remaining_oids,
+ int *remaining_nr, int *to_free,
+ bool accepted_only)
+{
+ struct promisor_remote *r = repo->promisor_remote_config->promisors;
+
+ for (; r; r = r->next) {
+ if (accepted_only != r->accepted)
+ continue;
+ if (fetch_objects(repo, r->name, *remaining_oids, *remaining_nr) < 0) {
+ if (*remaining_nr == 1)
+ continue;
+ *remaining_nr = remove_fetched_oids(repo, remaining_oids,
+ *remaining_nr, *to_free);
+ if (*remaining_nr) {
+ *to_free = 1;
+ continue;
+ }
+ }
+ return 1; /* all fetched */
+ }
+ return 0;
+}
+
void promisor_remote_get_direct(struct repository *repo,
const struct object_id *oids,
int oid_nr)
{
- struct promisor_remote *r;
struct object_id *remaining_oids = (struct object_id *)oids;
int remaining_nr = oid_nr;
int to_free = 0;
promisor_remote_init(repo);
- for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
- if (fetch_objects(repo, r->name, remaining_oids, remaining_nr) < 0) {
- if (remaining_nr == 1)
- continue;
- remaining_nr = remove_fetched_oids(repo, &remaining_oids,
- remaining_nr, to_free);
- if (remaining_nr) {
- to_free = 1;
- continue;
- }
- }
+ /* Try accepted remotes first (those the server told us to use) */
+ if (try_promisor_remotes(repo, &remaining_oids, &remaining_nr,
+ &to_free, true))
+ goto all_fetched;
+ if (try_promisor_remotes(repo, &remaining_oids, &remaining_nr,
+ &to_free, false))
goto all_fetched;
- }
for (i = 0; i < remaining_nr; i++) {
if (is_promisor_object(repo, &remaining_oids[i]))
check_missing_objects server 1 "$oid"
'
+test_expect_success "clone with two promisors but only one advertised" '
+ git -C server config promisor.advertise true &&
+ test_when_finished "rm -rf client unused_lop" &&
+
+ # Create a promisor that will be configured but not be used
+ git init --bare unused_lop &&
+
+ # Clone from server to create a client
+ GIT_TRACE="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \
+ -c remote.unused_lop.promisor=true \
+ -c remote.unused_lop.fetch="+refs/heads/*:refs/remotes/unused_lop/*" \
+ -c remote.unused_lop.url="file://$(pwd)/unused_lop" \
+ -c remote.lop.promisor=true \
+ -c remote.lop.fetch="+refs/heads/*:refs/remotes/lop/*" \
+ -c remote.lop.url="file://$(pwd)/lop" \
+ -c promisor.acceptfromserver=All \
+ --no-local --filter="blob:limit=5k" server client &&
+
+ # Check that "unused_lop" appears before "lop" in the config
+ printf "remote.%s.promisor true\n" "unused_lop" "lop" "origin" >expect &&
+ git -C client config get --all --show-names --regexp "^remote\..*\.promisor$" >actual &&
+ test_cmp expect actual &&
+
+ # Check that "lop" was tried
+ test_grep " fetch lop " trace &&
+ # Check that "unused_lop" was not contacted
+ # This means "lop", the accepted promisor, was tried first
+ test_grep ! " fetch unused_lop " trace &&
+
+ # Check that the largest object is still missing on the server
+ check_missing_objects server 1 "$oid"
+'
+
+test_expect_success "init + fetch two promisors but only one advertised" '
+ git -C server config promisor.advertise true &&
+ test_when_finished "rm -rf client unused_lop" &&
+
+ # Create a promisor that will be configured but not be used
+ git init --bare unused_lop &&
+
+ mkdir client &&
+ git -C client init &&
+ git -C client config remote.unused_lop.promisor true &&
+ git -C client config remote.unused_lop.fetch "+refs/heads/*:refs/remotes/unused_lop/*" &&
+ git -C client config remote.unused_lop.url "file://$(pwd)/unused_lop" &&
+ git -C client config remote.lop.promisor true &&
+ git -C client config remote.lop.fetch "+refs/heads/*:refs/remotes/lop/*" &&
+ git -C client config remote.lop.url "file://$(pwd)/lop" &&
+ git -C client config remote.server.url "file://$(pwd)/server" &&
+ git -C client config remote.server.fetch "+refs/heads/*:refs/remotes/server/*" &&
+ git -C client config promisor.acceptfromserver All &&
+
+ # Check that "unused_lop" appears before "lop" in the config
+ printf "remote.%s.promisor true\n" "unused_lop" "lop" >expect &&
+ git -C client config get --all --show-names --regexp "^remote\..*\.promisor$" >actual &&
+ test_cmp expect actual &&
+
+ GIT_TRACE="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git -C client fetch --filter="blob:limit=5k" server &&
+
+ # Check that "lop" was tried
+ test_grep " fetch lop " trace &&
+ # Check that "unused_lop" was not contacted
+ # This means "lop", the accepted promisor, was tried first
+ test_grep ! " fetch unused_lop " trace &&
+
+ # Check that the largest object is still missing on the server
+ check_missing_objects server 1 "$oid"
+'
+
test_expect_success "clone with promisor.acceptfromserver set to 'KnownName'" '
git -C server config promisor.advertise true &&
test_when_finished "rm -rf client" &&