Merge branch 'jt/fetch-no-update-shallow-in-proto-v2'
authorJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:16 +0000 (16:41 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Apr 2019 07:41:16 +0000 (16:41 +0900)
Fix for protocol v2 support in "git fetch-pack" of shallow clones.

* jt/fetch-no-update-shallow-in-proto-v2:
fetch-pack: respect --no-update-shallow in v2
fetch-pack: call prepare_shallow_info only if v0

1  2 
commit.h
fetch-pack.c
diff --combined commit.h
index 5d33477e788633e12bf4cfb5319a79d5a7abf586,a3f2b2eddb3d1d8f16c2170c7cfc46b4000d985a..8f1f39f4c39b05327ee342018091d847ea7ee5c4
+++ b/commit.h
@@@ -89,12 -89,6 +89,12 @@@ static inline int repo_parse_commit(str
  {
        return repo_parse_commit_gently(r, item, 0);
  }
 +
 +static inline int parse_commit_no_graph(struct commit *commit)
 +{
 +      return repo_parse_commit_internal(the_repository, commit, 0, 0);
 +}
 +
  #ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
  #define parse_commit_internal(item, quiet, use) repo_parse_commit_internal(the_repository, item, quiet, use)
  #define parse_commit_gently(item, quiet) repo_parse_commit_gently(the_repository, item, quiet)
@@@ -263,6 -257,10 +263,10 @@@ extern void setup_alternate_shallow(str
  extern const char *setup_temporary_shallow(const struct oid_array *extra);
  extern void advertise_shallow_grafts(int);
  
+ /*
+  * Initialize with prepare_shallow_info() or zero-initialize (equivalent to
+  * prepare_shallow_info with a NULL oid_array).
+  */
  struct shallow_info {
        struct oid_array *shallow;
        int *ours, nr_ours;
diff --combined fetch-pack.c
index 01cdee01b45e105072e1ebafac19be4d0f530a89,4831eb6a25ab07df73b03c87d321a6fc14126580..0f158776b07cc8f87b98ba152a66a378cec64076
@@@ -1253,9 -1253,11 +1253,11 @@@ static int process_acks(struct fetch_ne
  }
  
  static void receive_shallow_info(struct fetch_pack_args *args,
-                                struct packet_reader *reader)
+                                struct packet_reader *reader,
+                                struct oid_array *shallows,
+                                struct shallow_info *si)
  {
-       int line_received = 0;
+       int unshallow_received = 0;
  
        process_section_header(reader, "shallow-info", 0);
        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
                if (skip_prefix(reader->line, "shallow ", &arg)) {
                        if (get_oid_hex(arg, &oid))
                                die(_("invalid shallow line: %s"), reader->line);
-                       register_shallow(the_repository, &oid);
-                       line_received = 1;
+                       oid_array_append(shallows, &oid);
                        continue;
                }
                if (skip_prefix(reader->line, "unshallow ", &arg)) {
                                die(_("error in object: %s"), reader->line);
                        if (unregister_shallow(&oid))
                                die(_("no shallow found: %s"), reader->line);
-                       line_received = 1;
+                       unshallow_received = 1;
                        continue;
                }
                die(_("expected shallow/unshallow, got %s"), reader->line);
            reader->status != PACKET_READ_DELIM)
                die(_("error processing shallow info: %d"), reader->status);
  
-       if (line_received) {
+       if (args->deepen || unshallow_received) {
+               /*
+                * Treat these as shallow lines caused by our depth settings.
+                * In v0, these lines cannot cause refs to be rejected; do the
+                * same.
+                */
+               int i;
+               for (i = 0; i < shallows->nr; i++)
+                       register_shallow(the_repository, &shallows->oid[i]);
                setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
                                        NULL);
                args->deepen = 1;
+       } else if (shallows->nr) {
+               /*
+                * Treat these as shallow lines caused by the remote being
+                * shallow. In v0, remote refs that reach these objects are
+                * rejected (unless --update-shallow is set); do the same.
+                */
+               prepare_shallow_info(si, shallows);
+               if (si->nr_ours || si->nr_theirs)
+                       alternate_shallow_file =
+                               setup_temporary_shallow(si->shallow);
+               else
+                       alternate_shallow_file = NULL;
        } else {
                alternate_shallow_file = NULL;
        }
  }
  
 +static int cmp_name_ref(const void *name, const void *ref)
 +{
 +      return strcmp(name, (*(struct ref **)ref)->name);
 +}
 +
  static void receive_wanted_refs(struct packet_reader *reader,
                                struct ref **sought, int nr_sought)
  {
        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
                struct object_id oid;
                const char *end;
 -              int i;
 +              struct ref **found;
  
                if (parse_oid_hex(reader->line, &oid, &end) || *end++ != ' ')
                        die(_("expected wanted-ref, got '%s'"), reader->line);
  
 -              for (i = 0; i < nr_sought; i++) {
 -                      if (!strcmp(end, sought[i]->name)) {
 -                              oidcpy(&sought[i]->old_oid, &oid);
 -                              break;
 -                      }
 -              }
 -
 -              if (i == nr_sought)
 +              found = bsearch(end, sought, nr_sought, sizeof(*sought),
 +                              cmp_name_ref);
 +              if (!found)
                        die(_("unexpected wanted-ref: '%s'"), reader->line);
 +              oidcpy(&(*found)->old_oid, &oid);
        }
  
        if (reader->status != PACKET_READ_DELIM)
@@@ -1338,6 -1359,8 +1360,8 @@@ static struct ref *do_fetch_pack_v2(str
                                    int fd[2],
                                    const struct ref *orig_ref,
                                    struct ref **sought, int nr_sought,
+                                   struct oid_array *shallows,
+                                   struct shallow_info *si,
                                    char **pack_lockfile)
  {
        struct ref *ref = copy_ref_list(orig_ref);
                case FETCH_GET_PACK:
                        /* Check for shallow-info section */
                        if (process_section_header(&reader, "shallow-info", 1))
-                               receive_shallow_info(args, &reader);
+                               receive_shallow_info(args, &reader, shallows, si);
  
                        if (process_section_header(&reader, "wanted-refs", 1))
                                receive_wanted_refs(&reader, sought, nr_sought);
@@@ -1616,8 -1639,9 +1640,8 @@@ static int iterate_ref_map(void *cb_dat
  }
  
  struct ref *fetch_pack(struct fetch_pack_args *args,
 -                     int fd[], struct child_process *conn,
 +                     int fd[],
                       const struct ref *ref,
 -                     const char *dest,
                       struct ref **sought, int nr_sought,
                       struct oid_array *shallow,
                       char **pack_lockfile,
  {
        struct ref *ref_cpy;
        struct shallow_info si;
+       struct oid_array shallows_scratch = OID_ARRAY_INIT;
  
        fetch_pack_setup();
        if (nr_sought)
                packet_flush(fd[1]);
                die(_("no matching remote head"));
        }
-       prepare_shallow_info(&si, shallow);
-       if (version == protocol_v2)
+       if (version == protocol_v2) {
+               if (shallow->nr)
+                       BUG("Protocol V2 does not provide shallows at this point in the fetch");
+               memset(&si, 0, sizeof(si));
                ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought,
+                                          &shallows_scratch, &si,
                                           pack_lockfile);
-       else
+       } else {
+               prepare_shallow_info(&si, shallow);
                ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought,
                                        &si, pack_lockfile);
+       }
        reprepare_packed_git(the_repository);
  
        if (!args->cloning && args->deepen) {
        update_shallow(args, sought, nr_sought, &si);
  cleanup:
        clear_shallow_info(&si);
+       oid_array_clear(&shallows_scratch);
        return ref_cpy;
  }