Skip to content

Commit ef830cc

Browse files
jonathantanmygitster
authored andcommitted
promisor-remote: teach lazy-fetch in any repo
This is one step towards supporting partial clone submodules. Even after this patch, we will still lack partial clone submodules support, primarily because a lot of Git code that accesses submodule objects does so by adding their object stores as alternates, meaning that any lazy fetches that would occur in the submodule would be done based on the config of the superproject, not of the submodule. This also prevents testing of the functionality in this patch by user-facing commands. So for now, test this mechanism using a test helper. Besides that, there is some code that uses the wrapper functions like has_promisor_remote(). Those will need to be checked to see if they could support the non-wrapper functions instead (and thus support any repository, not just the_repository). Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]> Reviewed-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d1fa943 commit ef830cc

File tree

7 files changed

+76
-9
lines changed

7 files changed

+76
-9
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ TEST_BUILTINS_OBJS += test-oidmap.o
725725
TEST_BUILTINS_OBJS += test-online-cpus.o
726726
TEST_BUILTINS_OBJS += test-parse-options.o
727727
TEST_BUILTINS_OBJS += test-parse-pathspec-file.o
728+
TEST_BUILTINS_OBJS += test-partial-clone.o
728729
TEST_BUILTINS_OBJS += test-path-utils.o
729730
TEST_BUILTINS_OBJS += test-pcre2-config.o
730731
TEST_BUILTINS_OBJS += test-pkt-line.o

object-file.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,15 +1570,12 @@ static int do_oid_object_info_extended(struct repository *r,
15701570
}
15711571

15721572
/* Check if it is a missing object */
1573-
if (fetch_if_missing && has_promisor_remote() &&
1574-
!already_retried && r == the_repository &&
1573+
if (fetch_if_missing && repo_has_promisor_remote(r) &&
1574+
!already_retried &&
15751575
!(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) {
15761576
/*
15771577
* TODO Investigate checking promisor_remote_get_direct()
15781578
* TODO return value and stopping on error here.
1579-
* TODO Pass a repository struct through
1580-
* promisor_remote_get_direct(), such that arbitrary
1581-
* repositories work.
15821579
*/
15831580
promisor_remote_get_direct(r, real, 1);
15841581
already_retried = 1;

promisor-remote.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ struct promisor_remote_config {
1010
struct promisor_remote **promisors_tail;
1111
};
1212

13-
static int fetch_objects(const char *remote_name,
13+
static int fetch_objects(struct repository *repo,
14+
const char *remote_name,
1415
const struct object_id *oids,
1516
int oid_nr)
1617
{
@@ -20,6 +21,8 @@ static int fetch_objects(const char *remote_name,
2021

2122
child.git_cmd = 1;
2223
child.in = -1;
24+
if (repo != the_repository)
25+
prepare_other_repo_env(&child.env_array, repo->gitdir);
2326
strvec_pushl(&child.args, "-c", "fetch.negotiationAlgorithm=noop",
2427
"fetch", remote_name, "--no-tags",
2528
"--no-write-fetch-head", "--recurse-submodules=no",
@@ -240,10 +243,8 @@ int promisor_remote_get_direct(struct repository *repo,
240243

241244
promisor_remote_init(repo);
242245

243-
if (repo != the_repository)
244-
BUG("only the_repository is supported for now");
245246
for (r = repo->promisor_remote_config->promisors; r; r = r->next) {
246-
if (fetch_objects(r->name, remaining_oids, remaining_nr) < 0) {
247+
if (fetch_objects(repo, r->name, remaining_oids, remaining_nr) < 0) {
247248
if (remaining_nr == 1)
248249
continue;
249250
remaining_nr = remove_fetched_oids(repo, &remaining_oids,

t/helper/test-partial-clone.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "cache.h"
2+
#include "test-tool.h"
3+
#include "repository.h"
4+
#include "object-store.h"
5+
6+
/*
7+
* Prints the size of the object corresponding to the given hash in a specific
8+
* gitdir. This is similar to "git -C gitdir cat-file -s", except that this
9+
* exercises the code that accesses the object of an arbitrary repository that
10+
* is not the_repository. ("git -C gitdir" makes it so that the_repository is
11+
* the one in gitdir.)
12+
*/
13+
static void object_info(const char *gitdir, const char *oid_hex)
14+
{
15+
struct repository r;
16+
struct object_id oid;
17+
unsigned long size;
18+
struct object_info oi = {.sizep = &size};
19+
const char *p;
20+
21+
if (repo_init(&r, gitdir, NULL))
22+
die("could not init repo");
23+
if (parse_oid_hex(oid_hex, &oid, &p))
24+
die("could not parse oid");
25+
if (oid_object_info_extended(&r, &oid, &oi, 0))
26+
die("could not obtain object info");
27+
printf("%d\n", (int) size);
28+
}
29+
30+
int cmd__partial_clone(int argc, const char **argv)
31+
{
32+
setup_git_directory();
33+
34+
if (argc < 4)
35+
die("too few arguments");
36+
37+
if (!strcmp(argv[1], "object-info"))
38+
object_info(argv[2], argv[3]);
39+
else
40+
die("invalid argument '%s'", argv[1]);
41+
42+
return 0;
43+
}

t/helper/test-tool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ static struct test_cmd cmds[] = {
4646
{ "online-cpus", cmd__online_cpus },
4747
{ "parse-options", cmd__parse_options },
4848
{ "parse-pathspec-file", cmd__parse_pathspec_file },
49+
{ "partial-clone", cmd__partial_clone },
4950
{ "path-utils", cmd__path_utils },
5051
{ "pcre2-config", cmd__pcre2_config },
5152
{ "pkt-line", cmd__pkt_line },

t/helper/test-tool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ int cmd__oidmap(int argc, const char **argv);
3535
int cmd__online_cpus(int argc, const char **argv);
3636
int cmd__parse_options(int argc, const char **argv);
3737
int cmd__parse_pathspec_file(int argc, const char** argv);
38+
int cmd__partial_clone(int argc, const char **argv);
3839
int cmd__path_utils(int argc, const char **argv);
3940
int cmd__pcre2_config(int argc, const char **argv);
4041
int cmd__pkt_line(int argc, const char **argv);

t/t0410-partial-clone.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,29 @@ test_expect_success 'do not fetch when checking existence of tree we construct o
604604
git -C repo cherry-pick side1
605605
'
606606

607+
test_expect_success 'lazy-fetch when accessing object not in the_repository' '
608+
rm -rf full partial.git &&
609+
test_create_repo full &&
610+
test_commit -C full create-a-file file.txt &&
611+
612+
test_config -C full uploadpack.allowfilter 1 &&
613+
test_config -C full uploadpack.allowanysha1inwant 1 &&
614+
git clone --filter=blob:none --bare "file://$(pwd)/full" partial.git &&
615+
FILE_HASH=$(git -C full rev-parse HEAD:file.txt) &&
616+
617+
# Sanity check that the file is missing
618+
git -C partial.git rev-list --objects --missing=print HEAD >out &&
619+
grep "[?]$FILE_HASH" out &&
620+
621+
git -C full cat-file -s "$FILE_HASH" >expect &&
622+
test-tool partial-clone object-info partial.git "$FILE_HASH" >actual &&
623+
test_cmp expect actual &&
624+
625+
# Sanity check that the file is now present
626+
git -C partial.git rev-list --objects --missing=print HEAD >out &&
627+
! grep "[?]$FILE_HASH" out
628+
'
629+
607630
. "$TEST_DIRECTORY"/lib-httpd.sh
608631
start_httpd
609632

0 commit comments

Comments
 (0)