]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'js/filter-options-should-use-plain-int'
authorJunio C Hamano <gitster@pobox.com>
Tue, 5 Feb 2019 22:26:09 +0000 (14:26 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 Feb 2019 22:26:10 +0000 (14:26 -0800)
Update the protocol message specification to allow only the limited
use of scaled quantities.  This is ensure potential compatibility
issues will not go out of hand.

* js/filter-options-should-use-plain-int:
  filter-options: expand scaled numbers
  tree:<depth>: skip some trees even when collecting omits
  list-objects-filter: teach tree:# how to handle >0

1  2 
Documentation/rev-list-options.txt
builtin/clone.c
builtin/fetch.c
fetch-pack.c
transport-helper.c
upload-pack.c

index 98b538bc779635fcf59afd1a8cb366e9e57ed7ae,f8ab00f7c9e966b3c117a13fb19e152a9ae3a903..91b3a72bda173fe048d087a38625f1bdb3da2804
@@@ -13,6 -13,8 +13,6 @@@ has a line that matches `<pattern>`), u
  Note that these are applied before commit
  ordering and formatting options, such as `--reverse`.
  
 ---
 -
  -<number>::
  -n <number>::
  --max-count=<number>::
@@@ -306,6 -308,8 +306,6 @@@ ifdef::git-rev-list[
        `<header>` text will be printed with each progress update.
  endif::git-rev-list[]
  
 ---
 -
  History Simplification
  ~~~~~~~~~~~~~~~~~~~~~~
  
@@@ -730,8 -734,13 +730,13 @@@ specification contained in <path>
  +
  The form '--filter=tree:<depth>' omits all blobs and trees whose depth
  from the root tree is >= <depth> (minimum depth if an object is located
- at multiple depths in the commits traversed). Currently, only <depth>=0
- is supported, which omits all blobs and trees.
+ at multiple depths in the commits traversed). <depth>=0 will not include
+ any trees or blobs unless included explicitly in the command-line (or
+ standard input when --stdin is used). <depth>=1 will include only the
+ tree and blobs which are referenced directly by a commit reachable from
+ <commit> or an explicitly-given object. <depth>=2 is like <depth>=1
+ while also including trees and blobs one more level removed from an
+ explicitly-given commit or tree.
  
  --no-filter::
        Turn off any previous `--filter=` argument.
diff --combined builtin/clone.c
index 7c7f98c72c80cfcb12f3d3f61a13f46b19967a8f,8e05e8ad6c8d30cca723cb489a2e97b1ad75c3d9..739de68820c52a3d24f8f256bb36ed72877740b6
@@@ -548,7 -548,7 +548,7 @@@ static struct ref *find_remote_branch(c
  }
  
  static struct ref *wanted_peer_refs(const struct ref *refs,
 -              struct refspec_item *refspec)
 +              struct refspec *refspec)
  {
        struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
        struct ref *local_refs = head;
                        warning(_("Could not find remote branch %s to clone."),
                                option_branch);
                else {
 -                      get_fetch_map(remote_head, refspec, &tail, 0);
 +                      int i;
 +                      for (i = 0; i < refspec->nr; i++)
 +                              get_fetch_map(remote_head, &refspec->items[i],
 +                                            &tail, 0);
  
                        /* if --branch=tag, pull the requested tag explicitly */
                        get_fetch_map(remote_head, tag_refspec, &tail, 0);
                }
 -      } else
 -              get_fetch_map(refs, refspec, &tail, 0);
 +      } else {
 +              int i;
 +              for (i = 0; i < refspec->nr; i++)
 +                      get_fetch_map(refs, &refspec->items[i], &tail, 0);
 +      }
  
        if (!option_mirror && !option_single_branch && !option_no_tags)
                get_fetch_map(refs, tag_refspec, &tail, 0);
@@@ -896,8 -890,7 +896,8 @@@ int cmd_clone(int argc, const char **ar
        const struct ref *our_head_points_at;
        struct ref *mapped_refs;
        const struct ref *ref;
 -      struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
 +      struct strbuf key = STRBUF_INIT;
 +      struct strbuf default_refspec = STRBUF_INIT;
        struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
        struct transport *transport = NULL;
        const char *src_ref_prefix = "refs/heads/";
        int err = 0, complete_refs_before_fetch = 1;
        int submodule_progress;
  
 -      struct refspec rs = REFSPEC_INIT_FETCH;
        struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
  
        fetch_if_missing = 0;
                strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
        }
  
 -      strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
        strbuf_addf(&key, "remote.%s.url", option_origin);
        git_config_set(key.buf, repo);
        strbuf_reset(&key);
        if (option_required_reference.nr || option_optional_reference.nr)
                setup_reference();
  
 -      refspec_append(&rs, value.buf);
 +      remote = remote_get(option_origin);
  
 -      strbuf_reset(&value);
 +      strbuf_addf(&default_refspec, "+%s*:%s*", src_ref_prefix,
 +                  branch_top.buf);
 +      refspec_append(&remote->fetch, default_refspec.buf);
  
 -      remote = remote_get(option_origin);
        transport = transport_get(remote, remote->url[0]);
        transport_set_verbosity(transport, option_verbosity, option_progress);
        transport->family = family;
                                     option_upload_pack);
  
        if (filter_options.choice) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
+               expand_list_objects_filter_spec(&filter_options,
+                                               &expanded_filter_spec);
                transport_set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
-                                    filter_options.filter_spec);
+                                    expanded_filter_spec.buf);
                transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+               strbuf_release(&expanded_filter_spec);
        }
  
        if (transport->smart_options && !deepen && !filter_options.choice)
  
  
        argv_array_push(&ref_prefixes, "HEAD");
 -      refspec_ref_prefixes(&rs, &ref_prefixes);
 +      refspec_ref_prefixes(&remote->fetch, &ref_prefixes);
        if (option_branch)
                expand_ref_prefix(&ref_prefixes, option_branch);
        if (!option_no_tags)
        refs = transport_get_remote_refs(transport, &ref_prefixes);
  
        if (refs) {
 -              mapped_refs = wanted_peer_refs(refs, &rs.items[0]);
 +              mapped_refs = wanted_peer_refs(refs, &remote->fetch);
                /*
                 * transport_get_remote_refs() may return refs with null sha-1
                 * in mapped_refs (see struct transport->get_refs_list
        strbuf_release(&reflog_msg);
        strbuf_release(&branch_top);
        strbuf_release(&key);
 -      strbuf_release(&value);
 +      strbuf_release(&default_refspec);
        junk_mode = JUNK_LEAVE_ALL;
  
 -      refspec_clear(&rs);
        argv_array_clear(&ref_prefixes);
        return err;
  }
diff --combined builtin/fetch.c
index c316c03ba206b8b04b598cdab8dd259a59014ea5,8b8bb649214cbe5d555d8b00b791558fdf87da76..61a443031d9ace9f2019e1c02ff265e7da0ec960
@@@ -763,6 -763,9 +763,6 @@@ static int update_local_ref(struct ref 
                        what = _("[new ref]");
                }
  
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref(msg, ref, 0);
                format_display(display, r ? '!' : '*', what,
                               r ? _("unable to update local ref") : NULL,
                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                strbuf_addstr(&quickref, "..");
                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref("fast-forward", ref, 1);
                format_display(display, r ? '!' : ' ', quickref.buf,
                               r ? _("unable to update local ref") : NULL,
                strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
                strbuf_addstr(&quickref, "...");
                strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
 -              if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
 -                  (recurse_submodules != RECURSE_SUBMODULES_ON))
 -                      check_for_new_submodule_commits(&ref->new_oid);
                r = s_update_ref("forced-update", ref, 1);
                format_display(display, r ? '!' : '+', quickref.buf,
                               r ? _("unable to update local ref") : _("forced update"),
@@@ -883,8 -892,6 +883,8 @@@ static int store_updated_refs(const cha
                                ref->force = rm->peer_ref->force;
                        }
  
 +                      if (recurse_submodules != RECURSE_SUBMODULES_OFF)
 +                              check_for_new_submodule_commits(&rm->old_oid);
  
                        if (!strcmp(rm->name, "HEAD")) {
                                kind = "";
@@@ -1165,6 -1172,7 +1165,7 @@@ static void add_negotiation_tips(struc
  static struct transport *prepare_transport(struct remote *remote, int deepen)
  {
        struct transport *transport;
        transport = transport_get(remote, NULL);
        transport_set_verbosity(transport, verbosity, progress);
        transport->family = family;
        if (update_shallow)
                set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
        if (filter_options.choice) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
+               expand_list_objects_filter_spec(&filter_options,
+                                               &expanded_filter_spec);
                set_option(transport, TRANS_OPT_LIST_OBJECTS_FILTER,
-                          filter_options.filter_spec);
+                          expanded_filter_spec.buf);
                set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
+               strbuf_release(&expanded_filter_spec);
        }
        if (negotiation_tip.nr) {
                if (transport->smart_options)
@@@ -1471,8 -1483,7 +1476,8 @@@ static inline void fetch_one_setup_part
         */
        if (strcmp(remote->name, repository_format_partial_clone)) {
                if (filter_options.choice)
 -                      die(_("--filter can only be used with the remote configured in core.partialClone"));
 +                      die(_("--filter can only be used with the remote "
 +                            "configured in extensions.partialclone"));
                return;
        }
  
@@@ -1640,8 -1651,7 +1645,8 @@@ int cmd_fetch(int argc, const char **ar
                result = fetch_one(remote, argc, argv, prune_tags_ok);
        } else {
                if (filter_options.choice)
 -                      die(_("--filter can only be used with the remote configured in core.partialClone"));
 +                      die(_("--filter can only be used with the remote "
 +                            "configured in extensions.partialclone"));
                /* TODO should this also die if we have a previous partial-clone? */
                result = fetch_multiple(&list);
        }
diff --combined fetch-pack.c
index 577faa6229d073768195dff6bcb0f113e5fbd4be,485632fabee376003b631f63aece35f641b3c4e4..bf8984b8e8d663fb31fbe7bfeea150970e3d3d7e
@@@ -329,9 -329,14 +329,14 @@@ static int find_common(struct fetch_neg
                        packet_buf_write(&req_buf, "deepen-not %s", s->string);
                }
        }
-       if (server_supports_filtering && args->filter_options.choice)
+       if (server_supports_filtering && args->filter_options.choice) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
+               expand_list_objects_filter_spec(&args->filter_options,
+                                               &expanded_filter_spec);
                packet_buf_write(&req_buf, "filter %s",
-                                args->filter_options.filter_spec);
+                                expanded_filter_spec.buf);
+               strbuf_release(&expanded_filter_spec);
+       }
        packet_buf_flush(&req_buf);
        state_len = req_buf.len;
  
@@@ -636,6 -641,23 +641,6 @@@ struct loose_object_iter 
        struct ref *refs;
  };
  
 -/*
 - *  If the number of refs is not larger than the number of loose objects,
 - *  this function stops inserting.
 - */
 -static int add_loose_objects_to_set(const struct object_id *oid,
 -                                  const char *path,
 -                                  void *data)
 -{
 -      struct loose_object_iter *iter = data;
 -      oidset_insert(iter->loose_object_set, oid);
 -      if (iter->refs == NULL)
 -              return 1;
 -
 -      iter->refs = iter->refs->next;
 -      return 0;
 -}
 -
  /*
   * Mark recent commits available locally and reachable from a local ref as
   * COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
@@@ -653,14 -675,30 +658,14 @@@ static void mark_complete_and_common_re
        struct ref *ref;
        int old_save_commit_buffer = save_commit_buffer;
        timestamp_t cutoff = 0;
 -      struct oidset loose_oid_set = OIDSET_INIT;
 -      int use_oidset = 0;
 -      struct loose_object_iter iter = {&loose_oid_set, *refs};
 -
 -      /* Enumerate all loose objects or know refs are not so many. */
 -      use_oidset = !for_each_loose_object(add_loose_objects_to_set,
 -                                          &iter, 0);
  
        save_commit_buffer = 0;
  
        for (ref = *refs; ref; ref = ref->next) {
                struct object *o;
 -              unsigned int flags = OBJECT_INFO_QUICK;
  
 -              if (use_oidset &&
 -                  !oidset_contains(&loose_oid_set, &ref->old_oid)) {
 -                      /*
 -                       * I know this does not exist in the loose form,
 -                       * so check if it exists in a non-loose form.
 -                       */
 -                      flags |= OBJECT_INFO_IGNORE_LOOSE;
 -              }
 -
 -              if (!has_object_file_with_flags(&ref->old_oid, flags))
 +              if (!has_object_file_with_flags(&ref->old_oid,
 +                                              OBJECT_INFO_QUICK))
                        continue;
                o = parse_object(the_repository, &ref->old_oid);
                if (!o)
                }
        }
  
 -      oidset_clear(&loose_oid_set);
 -
        if (!args->deepen) {
                for_each_ref(mark_complete_oid, NULL);
                for_each_cached_alternate(NULL, mark_alternate_complete);
@@@ -1007,8 -1047,6 +1012,8 @@@ static void add_shallow_requests(struc
                        packet_buf_write(req_buf, "deepen-not %s", s->string);
                }
        }
 +      if (args->deepen_relative)
 +              packet_buf_write(req_buf, "deepen-relative\n");
  }
  
  static void add_wants(int no_dependents, const struct ref *wants, struct strbuf *req_buf)
@@@ -1122,9 -1160,13 +1127,13 @@@ static int send_fetch_request(struct fe
        /* Add filter */
        if (server_supports_feature("fetch", "filter", 0) &&
            args->filter_options.choice) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
                print_verbose(args, _("Server supports filter"));
+               expand_list_objects_filter_spec(&args->filter_options,
+                                               &expanded_filter_spec);
                packet_buf_write(&req_buf, "filter %s",
-                                args->filter_options.filter_spec);
+                                expanded_filter_spec.buf);
+               strbuf_release(&expanded_filter_spec);
        } else if (args->filter_options.choice) {
                warning("filtering not recognized by server, ignoring");
        }
@@@ -1234,8 -1276,6 +1243,8 @@@ static int process_acks(struct fetch_ne
  static void receive_shallow_info(struct fetch_pack_args *args,
                                 struct packet_reader *reader)
  {
 +      int line_received = 0;
 +
        process_section_header(reader, "shallow-info", 0);
        while (packet_reader_read(reader) == PACKET_READ_NORMAL) {
                const char *arg;
                        if (get_oid_hex(arg, &oid))
                                die(_("invalid shallow line: %s"), reader->line);
                        register_shallow(the_repository, &oid);
 +                      line_received = 1;
                        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;
                        continue;
                }
                die(_("expected shallow/unshallow, got %s"), reader->line);
            reader->status != PACKET_READ_DELIM)
                die(_("error processing shallow info: %d"), reader->status);
  
 -      setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL);
 -      args->deepen = 1;
 +      if (line_received) {
 +              setup_alternate_shallow(&shallow_lock, &alternate_shallow_file,
 +                                      NULL);
 +              args->deepen = 1;
 +      }
  }
  
  static void receive_wanted_refs(struct packet_reader *reader,
diff --combined transport-helper.c
index 6cf3bb324e149c0180d332497edf2b2c15a6b71c,01404bfac52d137b461a9f713472b3def1c2fd45..1f52c95fd87b1a02968727bde71dcc1eddc50410
@@@ -679,10 -679,15 +679,15 @@@ static int fetch(struct transport *tran
        if (data->transport_options.update_shallow)
                set_helper_option(transport, "update-shallow", "true");
  
-       if (data->transport_options.filter_options.choice)
-               set_helper_option(
-                       transport, "filter",
-                       data->transport_options.filter_options.filter_spec);
+       if (data->transport_options.filter_options.choice) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
+               expand_list_objects_filter_spec(
+                       &data->transport_options.filter_options,
+                       &expanded_filter_spec);
+               set_helper_option(transport, "filter",
+                                 expanded_filter_spec.buf);
+               strbuf_release(&expanded_filter_spec);
+       }
  
        if (data->transport_options.negotiation_tips)
                warning("Ignoring --negotiation-tip because the protocol does not support it.");
@@@ -1026,8 -1031,7 +1031,8 @@@ static int push_refs(struct transport *
  }
  
  
 -static int has_attribute(const char *attrs, const char *attr) {
 +static int has_attribute(const char *attrs, const char *attr)
 +{
        int len;
        if (!attrs)
                return 0;
@@@ -1226,8 -1230,9 +1231,8 @@@ static int udt_do_read(struct unidirect
                return 0;       /* No space for more. */
  
        transfer_debug("%s is readable", t->src_name);
 -      bytes = read(t->src, t->buf + t->bufuse, BUFFERSIZE - t->bufuse);
 -      if (bytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN &&
 -              errno != EINTR) {
 +      bytes = xread(t->src, t->buf + t->bufuse, BUFFERSIZE - t->bufuse);
 +      if (bytes < 0) {
                error_errno(_("read(%s) failed"), t->src_name);
                return -1;
        } else if (bytes == 0) {
@@@ -1254,7 -1259,7 +1259,7 @@@ static int udt_do_write(struct unidirec
  
        transfer_debug("%s is writable", t->dest_name);
        bytes = xwrite(t->dest, t->buf, t->bufuse);
 -      if (bytes < 0 && errno != EWOULDBLOCK) {
 +      if (bytes < 0) {
                error_errno(_("write(%s) failed"), t->dest_name);
                return -1;
        } else if (bytes > 0) {
diff --combined upload-pack.c
index 9df27b55a098135629ef4eccea4cb18aadb7dad3,1c6d73e5a2334635513f6b0a6c5c7a151f125f42..ee893815854bf59f6bcc7dbb7dc169750af41c2e
@@@ -43,6 -43,7 +43,6 @@@
  
  static timestamp_t oldest_have;
  
 -static int deepen_relative;
  static int multi_ack;
  static int no_done;
  static int use_thin_pack, use_ofs_delta, use_include_tag;
@@@ -139,14 -140,17 +139,17 @@@ static void create_pack_file(const stru
        if (use_include_tag)
                argv_array_push(&pack_objects.args, "--include-tag");
        if (filter_options.filter_spec) {
+               struct strbuf expanded_filter_spec = STRBUF_INIT;
+               expand_list_objects_filter_spec(&filter_options,
+                                               &expanded_filter_spec);
                if (pack_objects.use_shell) {
                        struct strbuf buf = STRBUF_INIT;
-                       sq_quote_buf(&buf, filter_options.filter_spec);
+                       sq_quote_buf(&buf, expanded_filter_spec.buf);
                        argv_array_pushf(&pack_objects.args, "--filter=%s", buf.buf);
                        strbuf_release(&buf);
                } else {
                        argv_array_pushf(&pack_objects.args, "--filter=%s",
-                                        filter_options.filter_spec);
+                                        expanded_filter_spec.buf);
                }
        }
  
@@@ -661,9 -665,6 +664,9 @@@ static void send_unshallow(const struc
        }
  }
  
 +static int check_ref(const char *refname_full, const struct object_id *oid,
 +                   int flag, void *cb_data);
 +
  static void deepen(int depth, int deepen_relative,
                   struct object_array *shallows, struct object_array *want_obj)
  {
                struct object_array reachable_shallows = OBJECT_ARRAY_INIT;
                struct commit_list *result;
  
 +              /*
 +               * Checking for reachable shallows requires that our refs be
 +               * marked with OUR_REF.
 +               */
 +              head_ref_namespaced(check_ref, NULL);
 +              for_each_namespaced_ref(check_ref, NULL);
 +
                get_reachable_list(shallows, &reachable_shallows);
                result = get_shallow_commits(&reachable_shallows,
                                             depth + 1,
@@@ -721,7 -715,6 +724,7 @@@ static void deepen_by_rev_list(int ac, 
  static int send_shallow_list(int depth, int deepen_rev_list,
                             timestamp_t deepen_since,
                             struct string_list *deepen_not,
 +                           int deepen_relative,
                             struct object_array *shallows,
                             struct object_array *want_obj)
  {
@@@ -844,7 -837,6 +847,7 @@@ static void receive_needs(struct object
        int has_non_tip = 0;
        timestamp_t deepen_since = 0;
        int deepen_rev_list = 0;
 +      int deepen_relative = 0;
  
        shallow_nr = 0;
        for (;;) {
                return;
  
        if (send_shallow_list(depth, deepen_rev_list, deepen_since,
 -                            &deepen_not, &shallows, want_obj))
 +                            &deepen_not, deepen_relative, &shallows,
 +                            want_obj))
                packet_flush(1);
        object_array_clear(&shallows);
  }
@@@ -1410,7 -1401,6 +1413,7 @@@ static void send_shallow_info(struct up
  
        if (!send_shallow_list(data->depth, data->deepen_rev_list,
                               data->deepen_since, &data->deepen_not,
 +                             data->deepen_relative,
                               &data->shallows, want_obj) &&
            is_repository_shallow(the_repository))
                deepen(INFINITE_DEPTH, data->deepen_relative, &data->shallows,