Skip to content

Commit ad49136

Browse files
pcloudsgitster
authored andcommitted
make the sender advertise shallow commits to the receiver
If either receive-pack or upload-pack is called on a shallow repository, shallow commits (*) will be sent after the ref advertisement (but before the packet flush), so that the receiver has the full "shape" of the sender's commit graph. This will be needed for the receiver to update its .git/shallow if necessary. This breaks the protocol for all clients trying to push to a shallow repo, or fetch from one. Which is basically the same end result as today's "is_repository_shallow() && die()" in receive-pack and upload-pack. New clients will be made aware of shallow upstream and can make use of this information. The sender must send all shallow commits that are sent in the following pack. It may send more shallow commits than necessary. upload-pack for example may choose to advertise no shallow commits if it knows in advance that the pack it's going to send contains no shallow commits. But upload-pack is the server, so we choose the cheaper way, send full .git/shallow and let the client deal with it. Smart HTTP is not affected by this patch. Shallow support on smart-http comes later separately. (*) A shallow commit is a commit that terminates the revision walker. It is usually put in .git/shallow in order to keep the revision walker from going out of bound because there is no guarantee that objects behind this commit is available. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 606e435 commit ad49136

File tree

5 files changed

+26
-3
lines changed

5 files changed

+26
-3
lines changed

Documentation/technical/pack-protocol.txt

+3
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ MUST peel the ref if it's an annotated tag.
161161

162162
----
163163
advertised-refs = (no-refs / list-of-refs)
164+
*shallow
164165
flush-pkt
165166

166167
no-refs = PKT-LINE(zero-id SP "capabilities^{}"
@@ -174,6 +175,8 @@ MUST peel the ref if it's an annotated tag.
174175
other-tip = obj-id SP refname LF
175176
other-peeled = obj-id SP refname "^{}" LF
176177

178+
shallow = PKT-LINE("shallow" SP obj-id)
179+
177180
capability-list = capability *(SP capability)
178181
capability = 1*(LC_ALPHA / DIGIT / "-" / "_")
179182
LC_ALPHA = %x61-7A

builtin/receive-pack.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ static void write_head_info(void)
178178
if (!sent_capabilities)
179179
show_ref("capabilities^{}", null_sha1);
180180

181+
advertise_shallow_grafts(1);
182+
181183
/* EOF */
182184
packet_flush(1);
183185
}
@@ -998,7 +1000,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
9981000
if (!enter_repo(dir, 0))
9991001
die("'%s' does not appear to be a git repository", dir);
10001002

1001-
if (is_repository_shallow())
1003+
if (is_repository_shallow() && stateless_rpc)
10021004
die("attempt to push into a shallow repository");
10031005

10041006
git_config(receive_pack_config, NULL);

commit.h

+1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol);
205205
extern void setup_alternate_shallow(struct lock_file *shallow_lock,
206206
const char **alternate_shallow_file);
207207
extern char *setup_temporary_shallow(void);
208+
extern void advertise_shallow_grafts(int);
208209

209210
int is_descendant_of(struct commit *, struct commit_list *);
210211
int in_merge_bases(struct commit *, struct commit *);

shallow.c

+15
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,18 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
220220
*alternate_shallow_file = "";
221221
strbuf_release(&sb);
222222
}
223+
224+
static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void *cb)
225+
{
226+
int fd = *(int *)cb;
227+
if (graft->nr_parent == -1)
228+
packet_write(fd, "shallow %s\n", sha1_to_hex(graft->sha1));
229+
return 0;
230+
}
231+
232+
void advertise_shallow_grafts(int fd)
233+
{
234+
if (!is_repository_shallow())
235+
return;
236+
for_each_commit_graft(advertise_shallow_grafts_cb, &fd);
237+
}

upload-pack.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ static void upload_pack(void)
758758
reset_timeout();
759759
head_ref_namespaced(send_ref, &symref);
760760
for_each_namespaced_ref(send_ref, &symref);
761+
advertise_shallow_grafts(1);
761762
packet_flush(1);
762763
} else {
763764
head_ref_namespaced(mark_our_ref, NULL);
@@ -835,8 +836,9 @@ int main(int argc, char **argv)
835836

836837
if (!enter_repo(dir, strict))
837838
die("'%s' does not appear to be a git repository", dir);
838-
if (is_repository_shallow())
839-
die("attempt to fetch/clone from a shallow repository");
839+
if (is_repository_shallow() && stateless_rpc)
840+
die("attempt to push into a shallow repository");
841+
840842
git_config(upload_pack_config, NULL);
841843
upload_pack();
842844
return 0;

0 commit comments

Comments
 (0)