]> git.ipfire.org Git - thirdparty/git.git/blobdiff - list-objects-filter-options.c
Git 2.22.2
[thirdparty/git.git] / list-objects-filter-options.c
index 4c5b34e9499433e12b55a34f425aace38d9ecfaa..a15d0f782923f6bbb0aa9534c80f53c2942e7a79 100644 (file)
  * See Documentation/rev-list-options.txt for allowed values for <arg>.
  *
  * Capture the given arg as the "filter_spec".  This can be forwarded to
- * subordinate commands when necessary.  We also "intern" the arg for
- * the convenience of the current command.
+ * subordinate commands when necessary (although it's better to pass it through
+ * expand_list_objects_filter_spec() first).  We also "intern" the arg for the
+ * convenience of the current command.
  */
-int parse_list_objects_filter(struct list_objects_filter_options *filter_options,
-                             const char *arg)
+static int gently_parse_list_objects_filter(
+       struct list_objects_filter_options *filter_options,
+       const char *arg,
+       struct strbuf *errbuf)
 {
        const char *v0;
 
-       if (filter_options->choice)
-               die(_("multiple object filter types cannot be combined"));
+       if (filter_options->choice) {
+               if (errbuf) {
+                       strbuf_addstr(
+                               errbuf,
+                               _("multiple filter-specs cannot be combined"));
+               }
+               return 1;
+       }
 
        filter_options->filter_spec = strdup(arg);
 
        if (!strcmp(arg, "blob:none")) {
                filter_options->choice = LOFC_BLOB_NONE;
                return 0;
-       }
 
-       if (skip_prefix(arg, "blob:limit=", &v0)) {
-               if (!git_parse_ulong(v0, &filter_options->blob_limit_value))
-                       die(_("invalid filter-spec expression '%s'"), arg);
-               filter_options->choice = LOFC_BLOB_LIMIT;
+       } else if (skip_prefix(arg, "blob:limit=", &v0)) {
+               if (git_parse_ulong(v0, &filter_options->blob_limit_value)) {
+                       filter_options->choice = LOFC_BLOB_LIMIT;
+                       return 0;
+               }
+
+       } else if (skip_prefix(arg, "tree:", &v0)) {
+               if (!git_parse_ulong(v0, &filter_options->tree_exclude_depth)) {
+                       if (errbuf) {
+                               strbuf_addstr(
+                                       errbuf,
+                                       _("expected 'tree:<depth>'"));
+                       }
+                       return 1;
+               }
+               filter_options->choice = LOFC_TREE_DEPTH;
                return 0;
-       }
 
-       if (skip_prefix(arg, "sparse:oid=", &v0)) {
+       } else if (skip_prefix(arg, "sparse:oid=", &v0)) {
                struct object_context oc;
                struct object_id sparse_oid;
 
@@ -52,20 +71,38 @@ int parse_list_objects_filter(struct list_objects_filter_options *filter_options
                 * command, but DO NOT complain if we don't have the blob or
                 * ref locally.
                 */
-               if (!get_oid_with_context(v0, GET_OID_BLOB,
+               if (!get_oid_with_context(the_repository, v0, GET_OID_BLOB,
                                          &sparse_oid, &oc))
                        filter_options->sparse_oid_value = oiddup(&sparse_oid);
                filter_options->choice = LOFC_SPARSE_OID;
                return 0;
-       }
 
-       if (skip_prefix(arg, "sparse:path=", &v0)) {
-               filter_options->choice = LOFC_SPARSE_PATH;
-               filter_options->sparse_path_value = strdup(v0);
-               return 0;
+       } else if (skip_prefix(arg, "sparse:path=", &v0)) {
+               if (errbuf) {
+                       strbuf_addstr(
+                               errbuf,
+                               _("sparse:path filters support has been dropped"));
+               }
+               return 1;
        }
+       /*
+        * Please update _git_fetch() in git-completion.bash when you
+        * add new filters
+        */
+
+       if (errbuf)
+               strbuf_addf(errbuf, "invalid filter-spec '%s'", arg);
 
-       die(_("invalid filter-spec expression '%s'"), arg);
+       memset(filter_options, 0, sizeof(*filter_options));
+       return 1;
+}
+
+int parse_list_objects_filter(struct list_objects_filter_options *filter_options,
+                             const char *arg)
+{
+       struct strbuf buf = STRBUF_INIT;
+       if (gently_parse_list_objects_filter(filter_options, arg, &buf))
+               die("%s", buf.buf);
        return 0;
 }
 
@@ -75,18 +112,75 @@ int opt_parse_list_objects_filter(const struct option *opt,
        struct list_objects_filter_options *filter_options = opt->value;
 
        if (unset || !arg) {
-               list_objects_filter_release(filter_options);
+               list_objects_filter_set_no_filter(filter_options);
                return 0;
        }
 
        return parse_list_objects_filter(filter_options, arg);
 }
 
+void expand_list_objects_filter_spec(
+       const struct list_objects_filter_options *filter,
+       struct strbuf *expanded_spec)
+{
+       strbuf_init(expanded_spec, strlen(filter->filter_spec));
+       if (filter->choice == LOFC_BLOB_LIMIT)
+               strbuf_addf(expanded_spec, "blob:limit=%lu",
+                           filter->blob_limit_value);
+       else if (filter->choice == LOFC_TREE_DEPTH)
+               strbuf_addf(expanded_spec, "tree:%lu",
+                           filter->tree_exclude_depth);
+       else
+               strbuf_addstr(expanded_spec, filter->filter_spec);
+}
+
 void list_objects_filter_release(
        struct list_objects_filter_options *filter_options)
 {
        free(filter_options->filter_spec);
        free(filter_options->sparse_oid_value);
-       free(filter_options->sparse_path_value);
        memset(filter_options, 0, sizeof(*filter_options));
 }
+
+void partial_clone_register(
+       const char *remote,
+       const struct list_objects_filter_options *filter_options)
+{
+       /*
+        * Record the name of the partial clone remote in the
+        * config and in the global variable -- the latter is
+        * used throughout to indicate that partial clone is
+        * enabled and to expect missing objects.
+        */
+       if (repository_format_partial_clone &&
+           *repository_format_partial_clone &&
+           strcmp(remote, repository_format_partial_clone))
+               die(_("cannot change partial clone promisor remote"));
+
+       git_config_set("core.repositoryformatversion", "1");
+       git_config_set("extensions.partialclone", remote);
+
+       repository_format_partial_clone = xstrdup(remote);
+
+       /*
+        * Record the initial filter-spec in the config as
+        * the default for subsequent fetches from this remote.
+        */
+       core_partial_clone_filter_default =
+               xstrdup(filter_options->filter_spec);
+       git_config_set("core.partialclonefilter",
+                      core_partial_clone_filter_default);
+}
+
+void partial_clone_get_default_filter_spec(
+       struct list_objects_filter_options *filter_options)
+{
+       /*
+        * Parse default value, but silently ignore it if it is invalid.
+        */
+       if (!core_partial_clone_filter_default)
+               return;
+       gently_parse_list_objects_filter(filter_options,
+                                        core_partial_clone_filter_default,
+                                        NULL);
+}