upload-pack: make sure deepening preserves shallow roots
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Thu, 5 Dec 2013 13:02:41 +0000 (20:02 +0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 Dec 2013 00:14:17 +0000 (16:14 -0800)
When "fetch --depth=N" where N exceeds the longest chain of history in
the source repo, usually we just send an "unshallow" line to the
client so full history is obtained.

When the source repo is shallow we need to make sure to "unshallow"
the current shallow point _and_ "shallow" again when the commit
reaches its shallow bottom in the source repo.

This should fix both cases: large <N> and --unshallow.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/fetch-options.txt
shallow.c
t/t5537-fetch-shallow.sh
upload-pack.c
index ba1fe4958227dce5ab146a39374cf02c127c0c65..a83d2b4778a016e8d8f6ead29d9122a7eff49fdb 100644 (file)
        branch history. Tags for the deepened commits are not fetched.
 
 --unshallow::
-       Convert a shallow repository to a complete one, removing all
-       the limitations imposed by shallow repositories.
+       If the source repository is complete, convert a shallow
+       repository to a complete one, removing all the limitations
+       imposed by shallow repositories.
++
+If the source repository is shallow, fetch as much as possible so that
+the current repository has the same history as the source repository.
 
 ifndef::git-pull[]
 --dry-run::
index fb6069ba0c2c97d4f47c7c8df2aa29f14b43babc..52268544fd5895fc444b74f8fec1ef1c472b8f46 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -75,6 +75,7 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
        struct commit_list *result = NULL;
        struct object_array stack = OBJECT_ARRAY_INIT;
        struct commit *commit = NULL;
+       struct commit_graft *graft;
 
        while (commit || i < heads->nr || stack.nr) {
                struct commit_list *p;
@@ -99,7 +100,10 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
                if (parse_commit(commit))
                        die("invalid commit");
                cur_depth++;
-               if (cur_depth >= depth) {
+               if ((depth != INFINITE_DEPTH && cur_depth >= depth) ||
+                   (is_repository_shallow() && !commit->parents &&
+                    (graft = lookup_commit_graft(commit->object.sha1)) != NULL &&
+                    graft->nr_parent < 0)) {
                        commit_list_insert(commit, &result);
                        commit->object.flags |= shallow_flag;
                        commit = NULL;
index d2110527ef33e5687601e73e36649e121fc21730..022cb2c990152c858810d263c64e32f8f75ffb75 100755 (executable)
@@ -79,6 +79,22 @@ EOF
        )
 '
 
+test_expect_success 'fetch --unshallow from shallow clone' '
+       (
+       cd shallow2 &&
+       git fetch --unshallow &&
+       git fsck &&
+       git log --format=%s origin/master >actual &&
+       cat <<EOF >expect &&
+6
+5
+4
+3
+EOF
+       test_cmp expect actual
+       )
+'
+
 test_expect_success 'fetch something upstream has but hidden by clients shallow boundaries' '
        # the blob "1" is available in .git but hidden by the
        # shallow2/.git/shallow and it should be resent
index f082f069ce28c70a2d7d14f974cc6e8c2f50ed02..28269c7462e18bc1e7bee77d30535f0eaeb9185b 100644 (file)
@@ -619,7 +619,7 @@ static void receive_needs(void)
        if (depth > 0) {
                struct commit_list *result = NULL, *backup = NULL;
                int i;
-               if (depth == INFINITE_DEPTH)
+               if (depth == INFINITE_DEPTH && !is_repository_shallow())
                        for (i = 0; i < shallows.nr; i++) {
                                struct object *object = shallows.objects[i].item;
                                object->flags |= NOT_SHALLOW;