Commit 682c7d2 (upload-pack: fix off-by-one depth calculation in shallow
clone) changed the meaning of the fetch depth sent over the wire to mean
the total number of commits to return, instead of the number of commits
beyond the first. However, when this change is deployed on some servers
but not others, this can cause a client to behave differently based on
the server version, which is unexpected.

To prevent this, the new, fixed, depth behaviour is advertised as a server
feature and the old behaviour is restored when the feature is not
requested by the client.

Signed-off-by: Matthijs Kooijman <matth...@stdin.nl>
---
 upload-pack.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/upload-pack.c b/upload-pack.c
index 127e59a..59f43d1 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -46,6 +46,7 @@ static unsigned int timeout;
 static int use_sideband;
 static int advertise_refs;
 static int stateless_rpc;
+static int fixed_depth;
 
 static void reset_timeout(void)
 {
@@ -633,6 +634,8 @@ static void receive_needs(void)
                        no_progress = 1;
                if (parse_feature_request(features, "include-tag"))
                        use_include_tag = 1;
+               if (parse_feature_request(features, "fixed-off-by-one-depth"))
+                       fixed_depth = 1;
 
                o = parse_object(sha1_buf);
                if (!o)
@@ -669,10 +672,14 @@ static void receive_needs(void)
                                struct object *object = 
shallows.objects[i].item;
                                object->flags |= NOT_SHALLOW;
                        }
-               else
+               else {
+                       /* Emulate off-by-one bug in older versions */
+                       if (!fixed_depth)
+                               depth++;
                        backup = result =
                                get_shallow_commits(&want_obj, depth,
                                                    SHALLOW, NOT_SHALLOW);
+               }
                while (result) {
                        struct object *object = &result->item->object;
                        if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
@@ -738,7 +745,7 @@ static int send_ref(const char *refname, const unsigned 
char *sha1, int flag, vo
 {
        static const char *capabilities = "multi_ack thin-pack side-band"
                " side-band-64k ofs-delta shallow no-progress"
-               " include-tag multi_ack_detailed";
+               " include-tag multi_ack_detailed fixed-off-by-one-depth";
        const char *refname_nons = strip_namespace(refname);
        unsigned char peeled[20];
 
-- 
1.8.3.rc1

--
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