built-in rebase --skip/--abort: clean up stale .git/<name> files
[gitweb.git] / list-objects-filter-options.c
index 4c5b34e9499433e12b55a34f425aace38d9ecfaa..e8da2e8581b2df956411f19e796ceb94adcef903 100644 (file)
  * subordinate commands when necessary.  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)) {
+               unsigned long depth;
+               if (!git_parse_ulong(v0, &depth) || depth != 0) {
+                       if (errbuf) {
+                               strbuf_addstr(
+                                       errbuf,
+                                       _("only 'tree:0' is supported"));
+                       }
+                       return 1;
+               }
+               filter_options->choice = LOFC_TREE_NONE;
                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;
 
@@ -57,15 +76,26 @@ int parse_list_objects_filter(struct list_objects_filter_options *filter_options
                        filter_options->sparse_oid_value = oiddup(&sparse_oid);
                filter_options->choice = LOFC_SPARSE_OID;
                return 0;
-       }
 
-       if (skip_prefix(arg, "sparse:path=", &v0)) {
+       } else if (skip_prefix(arg, "sparse:path=", &v0)) {
                filter_options->choice = LOFC_SPARSE_PATH;
                filter_options->sparse_path_value = strdup(v0);
                return 0;
        }
 
-       die(_("invalid filter-spec expression '%s'"), arg);
+       if (errbuf)
+               strbuf_addf(errbuf, "invalid filter-spec '%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,7 +105,7 @@ 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;
        }
 
@@ -90,3 +120,46 @@ void list_objects_filter_release(
        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);
+}