If either receive-pack or upload-pack is called on a shallow
repository, shallow graft points will be sent after the ref
advertisement (but before the packet flush).

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.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 Documentation/technical/pack-protocol.txt |  3 +++
 builtin/receive-pack.c                    |  5 ++---
 commit.h                                  |  1 +
 shallow.c                                 | 16 ++++++++++++++++
 upload-pack.c                             |  3 +--
 5 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/Documentation/technical/pack-protocol.txt 
b/Documentation/technical/pack-protocol.txt
index b898e97..eb8edd1 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -161,6 +161,7 @@ MUST peel the ref if it's an annotated tag.
 
 ----
   advertised-refs  =  (no-refs / list-of-refs)
+                     *shallow
                      flush-pkt
 
   no-refs          =  PKT-LINE(zero-id SP "capabilities^{}"
@@ -174,6 +175,8 @@ MUST peel the ref if it's an annotated tag.
   other-tip        =  obj-id SP refname LF
   other-peeled     =  obj-id SP refname "^{}" LF
 
+  shallow          =  PKT-LINE("shallow" SP obj-id)
+
   capability-list  =  capability *(SP capability)
   capability       =  1*(LC_ALPHA / DIGIT / "-" / "_")
   LC_ALPHA         =  %x61-7A
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index e3eb5fc..2d8e19b 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -176,6 +176,8 @@ static void write_head_info(void)
        if (!sent_capabilities)
                show_ref("capabilities^{}", null_sha1);
 
+       advertise_shallow_grafts(1);
+
        /* EOF */
        packet_flush(1);
 }
@@ -990,9 +992,6 @@ int cmd_receive_pack(int argc, const char **argv, const 
char *prefix)
        if (!enter_repo(dir, 0))
                die("'%s' does not appear to be a git repository", dir);
 
-       if (is_repository_shallow())
-               die("attempt to push into a shallow repository");
-
        git_config(receive_pack_config, NULL);
 
        if (0 <= transfer_unpack_limit)
diff --git a/commit.h b/commit.h
index 4d452dc..e0688c3 100644
--- a/commit.h
+++ b/commit.h
@@ -187,6 +187,7 @@ extern struct commit_list *get_shallow_commits(struct 
object_array *heads,
                int depth, int shallow_flag, int not_shallow_flag);
 extern void check_shallow_file_for_update(void);
 extern void set_alternate_shallow_file(const char *path);
+extern void advertise_shallow_grafts(int);
 
 int is_descendant_of(struct commit *, struct commit_list *);
 int in_merge_bases(struct commit *, struct commit *);
diff --git a/shallow.c b/shallow.c
index cbe2526..ccdfefc 100644
--- a/shallow.c
+++ b/shallow.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "commit.h"
 #include "tag.h"
+#include "pkt-line.h"
 
 static int is_shallow = -1;
 static struct stat shallow_stat;
@@ -146,3 +147,18 @@ void check_shallow_file_for_update(void)
                   )
                die("shallow file was changed during fetch");
 }
+
+static int advertise_shallow_grafts_cb(const struct commit_graft *graft, void 
*cb)
+{
+       int fd = *(int*)cb;
+       if (graft->nr_parent == -1)
+               packet_write(fd, "shallow %s\n", sha1_to_hex(graft->sha1));
+       return 0;
+}
+
+void advertise_shallow_grafts(int fd)
+{
+       if (!is_repository_shallow())
+               return;
+       for_each_commit_graft(advertise_shallow_grafts_cb, &fd);
+}
diff --git a/upload-pack.c b/upload-pack.c
index 127e59a..6cefe43 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -766,6 +766,7 @@ static void upload_pack(void)
                reset_timeout();
                head_ref_namespaced(send_ref, NULL);
                for_each_namespaced_ref(send_ref, NULL);
+               advertise_shallow_grafts(1);
                packet_flush(1);
        } else {
                head_ref_namespaced(mark_our_ref, NULL);
@@ -837,8 +838,6 @@ int main(int argc, char **argv)
 
        if (!enter_repo(dir, strict))
                die("'%s' does not appear to be a git repository", dir);
-       if (is_repository_shallow())
-               die("attempt to fetch/clone from a shallow repository");
        git_config(upload_pack_config, NULL);
        upload_pack();
        return 0;
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to