list-objects-filter-options.con commit t3404: todo list with commented-out commands only aborts (d078c39)
   1#include "cache.h"
   2#include "commit.h"
   3#include "config.h"
   4#include "revision.h"
   5#include "argv-array.h"
   6#include "list-objects.h"
   7#include "list-objects-filter.h"
   8#include "list-objects-filter-options.h"
   9
  10/*
  11 * Parse value of the argument to the "filter" keyword.
  12 * On the command line this looks like:
  13 *       --filter=<arg>
  14 * and in the pack protocol as:
  15 *       "filter" SP <arg>
  16 *
  17 * The filter keyword will be used by many commands.
  18 * See Documentation/rev-list-options.txt for allowed values for <arg>.
  19 *
  20 * Capture the given arg as the "filter_spec".  This can be forwarded to
  21 * subordinate commands when necessary.  We also "intern" the arg for
  22 * the convenience of the current command.
  23 */
  24static int gently_parse_list_objects_filter(
  25        struct list_objects_filter_options *filter_options,
  26        const char *arg,
  27        struct strbuf *errbuf)
  28{
  29        const char *v0;
  30
  31        if (filter_options->choice) {
  32                if (errbuf) {
  33                        strbuf_init(errbuf, 0);
  34                        strbuf_addstr(
  35                                errbuf,
  36                                _("multiple filter-specs cannot be combined"));
  37                }
  38                return 1;
  39        }
  40
  41        filter_options->filter_spec = strdup(arg);
  42
  43        if (!strcmp(arg, "blob:none")) {
  44                filter_options->choice = LOFC_BLOB_NONE;
  45                return 0;
  46
  47        } else if (skip_prefix(arg, "blob:limit=", &v0)) {
  48                if (git_parse_ulong(v0, &filter_options->blob_limit_value)) {
  49                        filter_options->choice = LOFC_BLOB_LIMIT;
  50                        return 0;
  51                }
  52
  53        } else if (skip_prefix(arg, "sparse:oid=", &v0)) {
  54                struct object_context oc;
  55                struct object_id sparse_oid;
  56
  57                /*
  58                 * Try to parse <oid-expression> into an OID for the current
  59                 * command, but DO NOT complain if we don't have the blob or
  60                 * ref locally.
  61                 */
  62                if (!get_oid_with_context(v0, GET_OID_BLOB,
  63                                          &sparse_oid, &oc))
  64                        filter_options->sparse_oid_value = oiddup(&sparse_oid);
  65                filter_options->choice = LOFC_SPARSE_OID;
  66                return 0;
  67
  68        } else if (skip_prefix(arg, "sparse:path=", &v0)) {
  69                filter_options->choice = LOFC_SPARSE_PATH;
  70                filter_options->sparse_path_value = strdup(v0);
  71                return 0;
  72        }
  73
  74        if (errbuf) {
  75                strbuf_init(errbuf, 0);
  76                strbuf_addf(errbuf, "invalid filter-spec '%s'", arg);
  77        }
  78        memset(filter_options, 0, sizeof(*filter_options));
  79        return 1;
  80}
  81
  82int parse_list_objects_filter(struct list_objects_filter_options *filter_options,
  83                              const char *arg)
  84{
  85        struct strbuf buf = STRBUF_INIT;
  86        if (gently_parse_list_objects_filter(filter_options, arg, &buf))
  87                die("%s", buf.buf);
  88        return 0;
  89}
  90
  91int opt_parse_list_objects_filter(const struct option *opt,
  92                                  const char *arg, int unset)
  93{
  94        struct list_objects_filter_options *filter_options = opt->value;
  95
  96        if (unset || !arg) {
  97                list_objects_filter_set_no_filter(filter_options);
  98                return 0;
  99        }
 100
 101        return parse_list_objects_filter(filter_options, arg);
 102}
 103
 104void list_objects_filter_release(
 105        struct list_objects_filter_options *filter_options)
 106{
 107        free(filter_options->filter_spec);
 108        free(filter_options->sparse_oid_value);
 109        free(filter_options->sparse_path_value);
 110        memset(filter_options, 0, sizeof(*filter_options));
 111}
 112
 113void partial_clone_register(
 114        const char *remote,
 115        const struct list_objects_filter_options *filter_options)
 116{
 117        /*
 118         * Record the name of the partial clone remote in the
 119         * config and in the global variable -- the latter is
 120         * used throughout to indicate that partial clone is
 121         * enabled and to expect missing objects.
 122         */
 123        if (repository_format_partial_clone &&
 124            *repository_format_partial_clone &&
 125            strcmp(remote, repository_format_partial_clone))
 126                die(_("cannot change partial clone promisor remote"));
 127
 128        git_config_set("core.repositoryformatversion", "1");
 129        git_config_set("extensions.partialclone", remote);
 130
 131        repository_format_partial_clone = xstrdup(remote);
 132
 133        /*
 134         * Record the initial filter-spec in the config as
 135         * the default for subsequent fetches from this remote.
 136         */
 137        core_partial_clone_filter_default =
 138                xstrdup(filter_options->filter_spec);
 139        git_config_set("core.partialclonefilter",
 140                       core_partial_clone_filter_default);
 141}
 142
 143void partial_clone_get_default_filter_spec(
 144        struct list_objects_filter_options *filter_options)
 145{
 146        /*
 147         * Parse default value, but silently ignore it if it is invalid.
 148         */
 149        if (!core_partial_clone_filter_default)
 150                return;
 151        gently_parse_list_objects_filter(filter_options,
 152                                         core_partial_clone_filter_default,
 153                                         NULL);
 154}