Skip to content

Commit 48d25ca

Browse files
pcloudsgitster
authored andcommitted
fetch: add --update-shallow to accept refs that update .git/shallow
The same steps are done as in when --update-shallow is not given. The only difference is we now add all shallow commits in "ours" and "theirs" to .git/shallow (aka "step 8"). Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 79d3a23 commit 48d25ca

File tree

7 files changed

+79
-1
lines changed

7 files changed

+79
-1
lines changed

Documentation/fetch-options.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
If the source repository is shallow, fetch as much as possible so that
2222
the current repository has the same history as the source repository.
2323

24+
--update-shallow::
25+
By default when fetching from a shallow repository,
26+
`git fetch` refuses refs that require updating
27+
.git/shallow. This option updates .git/shallow and accept such
28+
refs.
29+
2430
ifndef::git-pull[]
2531
--dry-run::
2632
Show what would be done, without making any changes.

builtin/fetch.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static int prune = -1; /* unspecified */
3636

3737
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
3838
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
39-
static int tags = TAGS_DEFAULT, unshallow;
39+
static int tags = TAGS_DEFAULT, unshallow, update_shallow;
4040
static const char *depth;
4141
static const char *upload_pack;
4242
static struct strbuf default_rla = STRBUF_INIT;
@@ -104,6 +104,8 @@ static struct option builtin_fetch_options[] = {
104104
{ OPTION_STRING, 0, "recurse-submodules-default",
105105
&recurse_submodules_default, NULL,
106106
N_("default mode for recursion"), PARSE_OPT_HIDDEN },
107+
OPT_BOOL(0, "update-shallow", &update_shallow,
108+
N_("accept refs that update .git/shallow")),
107109
OPT_END()
108110
};
109111

@@ -768,6 +770,8 @@ static struct transport *prepare_transport(struct remote *remote)
768770
set_option(transport, TRANS_OPT_KEEP, "yes");
769771
if (depth)
770772
set_option(transport, TRANS_OPT_DEPTH, depth);
773+
if (update_shallow)
774+
set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
771775
return transport;
772776
}
773777

fetch-pack.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,33 @@ static void update_shallow(struct fetch_pack_args *args,
993993
sha1_array_append(&ref, sought[i]->old_sha1);
994994
si->ref = &ref;
995995

996+
if (args->update_shallow) {
997+
/*
998+
* remote is also shallow, .git/shallow may be updated
999+
* so all refs can be accepted. Make sure we only add
1000+
* shallow roots that are actually reachable from new
1001+
* refs.
1002+
*/
1003+
struct sha1_array extra = SHA1_ARRAY_INIT;
1004+
unsigned char (*sha1)[20] = si->shallow->sha1;
1005+
assign_shallow_commits_to_refs(si, NULL, NULL);
1006+
if (!si->nr_ours && !si->nr_theirs) {
1007+
sha1_array_clear(&ref);
1008+
return;
1009+
}
1010+
for (i = 0; i < si->nr_ours; i++)
1011+
sha1_array_append(&extra, sha1[si->ours[i]]);
1012+
for (i = 0; i < si->nr_theirs; i++)
1013+
sha1_array_append(&extra, sha1[si->theirs[i]]);
1014+
setup_alternate_shallow(&shallow_lock,
1015+
&alternate_shallow_file,
1016+
&extra);
1017+
commit_lock_file(&shallow_lock);
1018+
sha1_array_clear(&extra);
1019+
sha1_array_clear(&ref);
1020+
return;
1021+
}
1022+
9961023
/*
9971024
* remote is also shallow, check what ref is safe to update
9981025
* without updating .git/shallow

fetch-pack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct fetch_pack_args {
2323
unsigned check_self_contained_and_connected:1;
2424
unsigned self_contained_and_connected:1;
2525
unsigned cloning:1;
26+
unsigned update_shallow:1;
2627
};
2728

2829
/*

t/t5537-fetch-shallow.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,36 @@ EOF
141141
)
142142
'
143143

144+
test_expect_success 'fetch --update-shallow' '
145+
(
146+
cd shallow &&
147+
git checkout master &&
148+
commit 7 &&
149+
git tag -m foo heavy-tag HEAD^ &&
150+
git tag light-tag HEAD^:tracked
151+
) &&
152+
(
153+
cd notshallow &&
154+
git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* &&
155+
git fsck &&
156+
git for-each-ref --sort=refname --format="%(refname)" >actual.refs &&
157+
cat <<EOF >expect.refs &&
158+
refs/remotes/shallow/master
159+
refs/remotes/shallow/no-shallow
160+
refs/tags/heavy-tag
161+
refs/tags/light-tag
162+
EOF
163+
test_cmp expect.refs actual.refs &&
164+
git log --format=%s shallow/master >actual &&
165+
cat <<EOF >expect &&
166+
7
167+
6
168+
5
169+
4
170+
3
171+
EOF
172+
test_cmp expect actual
173+
)
174+
'
175+
144176
test_done

transport.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ static int set_git_option(struct git_transport_options *opts,
477477
} else if (!strcmp(name, TRANS_OPT_KEEP)) {
478478
opts->keep = !!value;
479479
return 0;
480+
} else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) {
481+
opts->update_shallow = !!value;
482+
return 0;
480483
} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
481484
if (!value)
482485
opts->depth = 0;
@@ -543,6 +546,7 @@ static int fetch_refs_via_pack(struct transport *transport,
543546
args.check_self_contained_and_connected =
544547
data->options.check_self_contained_and_connected;
545548
args.cloning = transport->cloning;
549+
args.update_shallow = data->options.update_shallow;
546550

547551
if (!data->got_remote_heads) {
548552
connect_setup(transport, 0, 0);

transport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct git_transport_options {
1111
unsigned followtags : 1;
1212
unsigned check_self_contained_and_connected : 1;
1313
unsigned self_contained_and_connected : 1;
14+
unsigned update_shallow : 1;
1415
int depth;
1516
const char *uploadpack;
1617
const char *receivepack;
@@ -152,6 +153,9 @@ struct transport *transport_get(struct remote *, const char *);
152153
/* Aggressively fetch annotated tags if possible */
153154
#define TRANS_OPT_FOLLOWTAGS "followtags"
154155

156+
/* Accept refs that may update .git/shallow without --depth */
157+
#define TRANS_OPT_UPDATE_SHALLOW "updateshallow"
158+
155159
/**
156160
* Returns 0 if the option was used, non-zero otherwise. Prints a
157161
* message to stderr if the option is not used.

0 commit comments

Comments
 (0)