Merge branch 'jk/peel-ref' into maint
authorJunio C Hamano <gitster@pobox.com>
Thu, 4 Apr 2013 19:59:55 +0000 (12:59 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 4 Apr 2013 19:59:55 +0000 (12:59 -0700)
* jk/peel-ref:
upload-pack: load non-tip "want" objects from disk
upload-pack: make sure "want" objects are parsed
upload-pack: drop lookup-before-parse optimization

1  2 
t/t5500-fetch-pack.sh
upload-pack.c
diff --combined t/t5500-fetch-pack.sh
index 354d32c584741daffa03891c5bee7fdc469a20da,e202383e4f289bfb78ce2a960c522cc4c04103d8..d574085696e81522669119c9b7480ba4c682c968
@@@ -130,25 -130,16 +130,25 @@@ test_expect_success 'single given branc
        test_must_fail git --git-dir=branch-a/.git rev-parse origin/B
  '
  
 +test_expect_success 'clone shallow depth 1' '
 +      git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 &&
 +      test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1
 +'
 +
  test_expect_success 'clone shallow' '
        git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow
  '
  
 +test_expect_success 'clone shallow depth count' '
 +      test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 2
 +'
 +
  test_expect_success 'clone shallow object count' '
        (
                cd shallow &&
                git count-objects -v
        ) > count.shallow &&
 -      grep "^in-pack: 18" count.shallow
 +      grep "^in-pack: 12" count.shallow
  '
  
  test_expect_success 'clone shallow object count (part 2)' '
@@@ -265,36 -256,12 +265,36 @@@ test_expect_success 'additional simple 
        )
  '
  
 +test_expect_success 'clone shallow depth count' '
 +      test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 11
 +'
 +
  test_expect_success 'clone shallow object count' '
        (
                cd shallow &&
                git count-objects -v
        ) > count.shallow &&
 -      grep "^count: 52" count.shallow
 +      grep "^count: 55" count.shallow
 +'
 +
 +test_expect_success 'fetch --no-shallow on full repo' '
 +      test_must_fail git fetch --noshallow
 +'
 +
 +test_expect_success 'fetch --depth --no-shallow' '
 +      (
 +              cd shallow &&
 +              test_must_fail git fetch --depth=1 --noshallow
 +      )
 +'
 +
 +test_expect_success 'turn shallow to complete repository' '
 +      (
 +              cd shallow &&
 +              git fetch --unshallow &&
 +              ! test -f .git/shallow &&
 +              git fsck --full
 +      )
  '
  
  test_expect_success 'clone shallow without --no-single-branch' '
@@@ -306,7 -273,7 +306,7 @@@ test_expect_success 'clone shallow obje
                cd shallow2 &&
                git count-objects -v
        ) > count.shallow2 &&
 -      grep "^in-pack: 6" count.shallow2
 +      grep "^in-pack: 3" count.shallow2
  '
  
  test_expect_success 'clone shallow with --branch' '
  '
  
  test_expect_success 'clone shallow object count' '
 -      echo "in-pack: 6" > count3.expected &&
 +      echo "in-pack: 3" > count3.expected &&
        GIT_DIR=shallow3/.git git count-objects -v |
                grep "^in-pack" > count3.actual &&
        test_cmp count3.expected count3.actual
@@@ -343,7 -310,7 +343,7 @@@ EO
        GIT_DIR=shallow6/.git git tag -l >taglist.actual &&
        test_cmp taglist.expected taglist.actual &&
  
 -      echo "in-pack: 7" > count6.expected &&
 +      echo "in-pack: 4" > count6.expected &&
        GIT_DIR=shallow6/.git git count-objects -v |
                grep "^in-pack" > count6.actual &&
        test_cmp count6.expected count6.actual
@@@ -358,12 -325,21 +358,21 @@@ EO
        GIT_DIR=shallow7/.git git tag -l >taglist.actual &&
        test_cmp taglist.expected taglist.actual &&
  
 -      echo "in-pack: 7" > count7.expected &&
 +      echo "in-pack: 4" > count7.expected &&
        GIT_DIR=shallow7/.git git count-objects -v |
                grep "^in-pack" > count7.actual &&
        test_cmp count7.expected count7.actual
  '
  
+ test_expect_success 'clone shallow with packed refs' '
+       git pack-refs --all &&
+       git clone --depth 1 --branch A "file://$(pwd)/." shallow8 &&
+       echo "in-pack: 4" > count8.expected &&
+       GIT_DIR=shallow8/.git git count-objects -v |
+               grep "^in-pack" > count8.actual &&
+       test_cmp count8.expected count8.actual
+ '
  test_expect_success 'setup tests for the --stdin parameter' '
        for head in C D E F
        do
@@@ -424,55 -400,10 +433,55 @@@ test_expect_success 'fetch mixed refs f
  test_expect_success 'test duplicate refs from stdin' '
        (
        cd client &&
 -      test_must_fail git fetch-pack --stdin --no-progress .. <../input.dup
 +      git fetch-pack --stdin --no-progress .. <../input.dup
        ) >output &&
        cut -d " " -f 2 <output | sort >actual &&
        test_cmp expect actual
  '
  
 +test_expect_success 'set up tests of missing reference' '
 +      cat >expect-error <<-\EOF
 +      error: no such remote ref refs/heads/xyzzy
 +      EOF
 +'
 +
 +test_expect_success 'test lonely missing ref' '
 +      (
 +              cd client &&
 +              test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
 +      ) >/dev/null 2>error-m &&
 +      test_cmp expect-error error-m
 +'
 +
 +test_expect_success 'test missing ref after existing' '
 +      (
 +              cd client &&
 +              test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
 +      ) >/dev/null 2>error-em &&
 +      test_cmp expect-error error-em
 +'
 +
 +test_expect_success 'test missing ref before existing' '
 +      (
 +              cd client &&
 +              test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
 +      ) >/dev/null 2>error-me &&
 +      test_cmp expect-error error-me
 +'
 +
 +test_expect_success 'test --all, --depth, and explicit head' '
 +      (
 +              cd client &&
 +              git fetch-pack --no-progress --all --depth=1 .. refs/heads/A
 +      ) >out-adh 2>error-adh
 +'
 +
 +test_expect_success 'test --all, --depth, and explicit tag' '
 +      git tag OLDTAG refs/heads/B~5 &&
 +      (
 +              cd client &&
 +              git fetch-pack --no-progress --all --depth=1 .. refs/tags/OLDTAG
 +      ) >out-adt 2>error-adt
 +'
 +
  test_done
diff --combined upload-pack.c
index 30146a04f7a271ffaa033c0c6567ad1036f4bc49,6152a9875735a5ccb76f500838a60a49d82ba1b6..948cfffe13376742cc46276652048cd6f5edaa7c
@@@ -12,7 -12,6 +12,7 @@@
  #include "run-command.h"
  #include "sigchain.h"
  #include "version.h"
 +#include "string-list.h"
  
  static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
  
@@@ -29,7 -28,7 +29,7 @@@
  
  static unsigned long oldest_have;
  
 -static int multi_ack, nr_our_refs;
 +static int multi_ack;
  static int no_done;
  static int use_thin_pack, use_ofs_delta, use_include_tag;
  static int no_progress, daemon_mode;
@@@ -140,6 -139,7 +140,6 @@@ static void create_pack_file(void
  {
        struct async rev_list;
        struct child_process pack_objects;
 -      int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
        char data[8193], progress[128];
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
        argv[arg++] = "pack-objects";
        if (!shallow_nr) {
                argv[arg++] = "--revs";
 -              if (create_full_pack)
 -                      argv[arg++] = "--all";
 -              else if (use_thin_pack)
 +              if (use_thin_pack)
                        argv[arg++] = "--thin";
        }
  
        }
        else {
                FILE *pipe_fd = xfdopen(pack_objects.in, "w");
 -              if (!create_full_pack) {
 -                      int i;
 -                      for (i = 0; i < want_obj.nr; i++)
 -                              fprintf(pipe_fd, "%s\n", sha1_to_hex(want_obj.objects[i].item->sha1));
 -                      fprintf(pipe_fd, "--not\n");
 -                      for (i = 0; i < have_obj.nr; i++)
 -                              fprintf(pipe_fd, "%s\n", sha1_to_hex(have_obj.objects[i].item->sha1));
 -              }
 +              int i;
  
 +              for (i = 0; i < want_obj.nr; i++)
 +                      fprintf(pipe_fd, "%s\n",
 +                              sha1_to_hex(want_obj.objects[i].item->sha1));
 +              fprintf(pipe_fd, "--not\n");
 +              for (i = 0; i < have_obj.nr; i++)
 +                      fprintf(pipe_fd, "%s\n",
 +                              sha1_to_hex(have_obj.objects[i].item->sha1));
                fprintf(pipe_fd, "\n");
                fflush(pipe_fd);
                fclose(pipe_fd);
@@@ -325,9 -327,7 +325,7 @@@ static int got_sha1(char *hex, unsigne
        if (!has_sha1_file(sha1))
                return -1;
  
-       o = lookup_object(sha1);
-       if (!(o && o->parsed))
-               o = parse_object(sha1);
+       o = parse_object(sha1);
        if (!o)
                die("oops (%s)", sha1_to_hex(sha1));
        if (o->type == OBJ_COMMIT) {
@@@ -601,8 -601,6 +599,8 @@@ static void receive_needs(void
                        object = parse_object(sha1);
                        if (!object)
                                die("did not find object for %s", line);
 +                      if (object->type != OBJ_COMMIT)
 +                              die("invalid shallow object %s", sha1_to_hex(sha1));
                        object->flags |= CLIENT_SHALLOW;
                        add_object_array(object, NULL, &shallows);
                        continue;
                if (parse_feature_request(features, "include-tag"))
                        use_include_tag = 1;
  
-               o = lookup_object(sha1_buf);
+               o = parse_object(sha1_buf);
                if (!o)
                        die("git upload-pack: not our ref %s",
                            sha1_to_hex(sha1_buf));
        if (depth == 0 && shallows.nr == 0)
                return;
        if (depth > 0) {
 -              struct commit_list *result, *backup;
 +              struct commit_list *result = NULL, *backup = NULL;
                int i;
 -              backup = result = get_shallow_commits(&want_obj, depth,
 -                      SHALLOW, NOT_SHALLOW);
 +              if (depth == INFINITE_DEPTH)
 +                      for (i = 0; i < shallows.nr; i++) {
 +                              struct object *object = shallows.objects[i].item;
 +                              object->flags |= NOT_SHALLOW;
 +                      }
 +              else
 +                      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))) {
        free(shallows.objects);
  }
  
 +/* return non-zero if the ref is hidden, otherwise 0 */
 +static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 +{
 +      struct object *o = lookup_unknown_object(sha1);
 +
 +      if (ref_is_hidden(refname))
 +              return 1;
 +      if (!o)
 +              die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 +      o->flags |= OUR_REF;
 +      return 0;
 +}
 +
  static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
  {
        static const char *capabilities = "multi_ack thin-pack side-band"
                " side-band-64k ofs-delta shallow no-progress"
                " include-tag multi_ack_detailed";
 -      struct object *o = lookup_unknown_object(sha1);
        const char *refname_nons = strip_namespace(refname);
        unsigned char peeled[20];
  
 +      if (mark_our_ref(refname, sha1, flag, cb_data))
 +              return 0;
 +
        if (capabilities)
                packet_write(1, "%s %s%c%s%s agent=%s\n",
                             sha1_to_hex(sha1), refname_nons,
        else
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
        capabilities = NULL;
 -      if (!(o->flags & OUR_REF)) {
 -              o->flags |= OUR_REF;
 -              nr_our_refs++;
 -      }
        if (!peel_ref(refname, peeled))
                packet_write(1, "%s %s^{}\n", sha1_to_hex(peeled), refname_nons);
        return 0;
  }
  
 -static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 -{
 -      struct object *o = parse_object(sha1);
 -      if (!o)
 -              die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 -      if (!(o->flags & OUR_REF)) {
 -              o->flags |= OUR_REF;
 -              nr_our_refs++;
 -      }
 -      return 0;
 -}
 -
  static void upload_pack(void)
  {
        if (advertise_refs || !stateless_rpc) {
        }
  }
  
 +static int upload_pack_config(const char *var, const char *value, void *unused)
 +{
 +      return parse_hide_refs_config(var, value, "uploadpack");
 +}
 +
  int main(int argc, char **argv)
  {
        char *dir;
                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);
        if (getenv("GIT_DEBUG_SEND_PACK"))
                debug_fd = atoi(getenv("GIT_DEBUG_SEND_PACK"));
        upload_pack();