Merge branch 'cc/skip-to-optional-val'
authorJunio C Hamano <gitster@pobox.com>
Thu, 28 Dec 2017 22:08:46 +0000 (14:08 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 28 Dec 2017 22:08:46 +0000 (14:08 -0800)
Introduce a helper to simplify code to parse a common pattern that
expects either "--key" or "--key=<something>".

* cc/skip-to-optional-val:
t4045: reindent to make helpers readable
diff: add tests for --relative without optional prefix value
diff: use skip_to_optional_arg_default() in parsing --relative
diff: use skip_to_optional_arg_default()
diff: use skip_to_optional_arg()
index-pack: use skip_to_optional_arg()
git-compat-util: introduce skip_to_optional_arg()

1  2 
diff.c
strbuf.c
diff --combined diff.c
index 3fb445a54d94f5f48aabed0fcfd06c378bee6719,3f14cdace6930140657423d26277c6ff38d22da5..fb22b19f09ab13032b0484e64326fef92bb0681f
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -3210,8 -3210,6 +3210,8 @@@ static void builtin_diff(const char *na
                ecbdata.opt = o;
                ecbdata.header = header.len ? &header : NULL;
                xpp.flags = o->xdl_opts;
 +              xpp.anchors = o->anchors;
 +              xpp.anchors_nr = o->anchors_nr;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
@@@ -3304,8 -3302,6 +3304,8 @@@ static void builtin_diffstat(const cha
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = o->xdl_opts;
 +              xpp.anchors = o->anchors;
 +              xpp.anchors_nr = o->anchors_nr;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
                if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
@@@ -4512,17 -4508,12 +4512,12 @@@ int diff_opt_parse(struct diff_options 
                options->output_format |= DIFF_FORMAT_NUMSTAT;
        else if (!strcmp(arg, "--shortstat"))
                options->output_format |= DIFF_FORMAT_SHORTSTAT;
-       else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
-               return parse_dirstat_opt(options, "");
-       else if (skip_prefix(arg, "-X", &arg))
-               return parse_dirstat_opt(options, arg);
-       else if (skip_prefix(arg, "--dirstat=", &arg))
+       else if (skip_prefix(arg, "-X", &arg) ||
+                skip_to_optional_arg(arg, "--dirstat", &arg))
                return parse_dirstat_opt(options, arg);
        else if (!strcmp(arg, "--cumulative"))
                return parse_dirstat_opt(options, "cumulative");
-       else if (!strcmp(arg, "--dirstat-by-file"))
-               return parse_dirstat_opt(options, "files");
-       else if (skip_prefix(arg, "--dirstat-by-file=", &arg)) {
+       else if (skip_to_optional_arg(arg, "--dirstat-by-file", &arg)) {
                parse_dirstat_opt(options, "files");
                return parse_dirstat_opt(options, arg);
        }
                return stat_opt(options, av);
  
        /* renames options */
-       else if (starts_with(arg, "-B") || starts_with(arg, "--break-rewrites=") ||
-                !strcmp(arg, "--break-rewrites")) {
+       else if (starts_with(arg, "-B") ||
+                skip_to_optional_arg(arg, "--break-rewrites", NULL)) {
                if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
                        return error("invalid argument to -B: %s", arg+2);
        }
-       else if (starts_with(arg, "-M") || starts_with(arg, "--find-renames=") ||
-                !strcmp(arg, "--find-renames")) {
+       else if (starts_with(arg, "-M") ||
+                skip_to_optional_arg(arg, "--find-renames", NULL)) {
                if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
                        return error("invalid argument to -M: %s", arg+2);
                options->detect_rename = DIFF_DETECT_RENAME;
        else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
                options->irreversible_delete = 1;
        }
-       else if (starts_with(arg, "-C") || starts_with(arg, "--find-copies=") ||
-                !strcmp(arg, "--find-copies")) {
+       else if (starts_with(arg, "-C") ||
+                skip_to_optional_arg(arg, "--find-copies", NULL)) {
                if (options->detect_rename == DIFF_DETECT_COPY)
                        options->flags.find_copies_harder = 1;
                if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
                options->flags.rename_empty = 1;
        else if (!strcmp(arg, "--no-rename-empty"))
                options->flags.rename_empty = 0;
-       else if (!strcmp(arg, "--relative"))
-               options->flags.relative_name = 1;
-       else if (skip_prefix(arg, "--relative=", &arg)) {
+       else if (skip_to_optional_arg_default(arg, "--relative", &arg, NULL)) {
                options->flags.relative_name = 1;
-               options->prefix = arg;
+               if (arg)
+                       options->prefix = arg;
        }
  
        /* xdiff options */
                DIFF_XDL_SET(options, INDENT_HEURISTIC);
        else if (!strcmp(arg, "--no-indent-heuristic"))
                DIFF_XDL_CLR(options, INDENT_HEURISTIC);
 -      else if (!strcmp(arg, "--patience"))
 +      else if (!strcmp(arg, "--patience")) {
 +              int i;
                options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
 -      else if (!strcmp(arg, "--histogram"))
 +              /*
 +               * Both --patience and --anchored use PATIENCE_DIFF
 +               * internally, so remove any anchors previously
 +               * specified.
 +               */
 +              for (i = 0; i < options->anchors_nr; i++)
 +                      free(options->anchors[i]);
 +              options->anchors_nr = 0;
 +      } else if (!strcmp(arg, "--histogram"))
                options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
        else if ((argcount = parse_long_opt("diff-algorithm", av, &optarg))) {
                long value = parse_algorithm_value(optarg);
                options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
                options->xdl_opts |= value;
                return argcount;
 +      } else if (skip_prefix(arg, "--anchored=", &arg)) {
 +              options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
 +              ALLOC_GROW(options->anchors, options->anchors_nr + 1,
 +                         options->anchors_alloc);
 +              options->anchors[options->anchors_nr++] = xstrdup(arg);
        }
  
        /* flags options */
        else if (!strcmp(arg, "--no-follow")) {
                options->flags.follow_renames = 0;
                options->flags.default_follow_renames = 0;
-       } else if (!strcmp(arg, "--color"))
-               options->use_color = 1;
-       else if (skip_prefix(arg, "--color=", &arg)) {
+       } else if (skip_to_optional_arg_default(arg, "--color", &arg, "always")) {
                int value = git_config_colorbool(NULL, arg);
                if (value < 0)
                        return error("option `color' expects \"always\", \"auto\", or \"never\"");
                if (cm < 0)
                        die("bad --color-moved argument: %s", arg);
                options->color_moved = cm;
-       } else if (!strcmp(arg, "--color-words")) {
-               options->use_color = 1;
-               options->word_diff = DIFF_WORDS_COLOR;
-       }
-       else if (skip_prefix(arg, "--color-words=", &arg)) {
+       } else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) {
                options->use_color = 1;
                options->word_diff = DIFF_WORDS_COLOR;
-               options->word_regex = arg;
        }
        else if (!strcmp(arg, "--word-diff")) {
                if (options->word_diff == DIFF_WORDS_NONE)
                options->flags.textconv_set_via_cmdline = 1;
        } else if (!strcmp(arg, "--no-textconv"))
                options->flags.allow_textconv = 0;
-       else if (!strcmp(arg, "--ignore-submodules")) {
-               options->flags.override_submodule_config = 1;
-               handle_ignore_submodules_arg(options, "all");
-       } else if (skip_prefix(arg, "--ignore-submodules=", &arg)) {
+       else if (skip_to_optional_arg_default(arg, "--ignore-submodules", &arg, "all")) {
                options->flags.override_submodule_config = 1;
                handle_ignore_submodules_arg(options, arg);
-       } else if (!strcmp(arg, "--submodule"))
-               options->submodule_format = DIFF_SUBMODULE_LOG;
-       else if (skip_prefix(arg, "--submodule=", &arg))
+       } else if (skip_to_optional_arg_default(arg, "--submodule", &arg, "log"))
                return parse_submodule_opt(options, arg);
        else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
                return parse_ws_error_highlight_opt(options, arg);
@@@ -4920,20 -4884,14 +4902,20 @@@ const char *diff_aligned_abbrev(const s
        int abblen;
        const char *abbrev;
  
 +      /* Do we want all 40 hex characters? */
        if (len == GIT_SHA1_HEXSZ)
                return oid_to_hex(oid);
  
 +      /* An abbreviated value is fine, possibly followed by an ellipsis. */
        abbrev = diff_abbrev_oid(oid, len);
 +
 +      if (!print_sha1_ellipsis())
 +              return abbrev;
 +
        abblen = strlen(abbrev);
  
        /*
 -       * In well-behaved cases, where the abbbreviated result is the
 +       * In well-behaved cases, where the abbreviated result is the
         * same as the requested length, append three dots after the
         * abbreviation (hence the whole logic is limited to the case
         * where abblen < 37); when the actual abbreviated result is a
@@@ -5478,7 -5436,7 +5460,7 @@@ void diff_warn_rename_limit(const char 
                warning(_(rename_limit_warning));
        else
                return;
 -      if (0 < needed && needed < 32767)
 +      if (0 < needed)
                warning(_(rename_limit_advice), varname, needed);
  }
  
diff --combined strbuf.c
index ac5a7ab62d554fb292d29df9cb618a336c5336c0,29169b8ef8b75a6638b5594501b95dee3e1f4b4b..8007be8fbafdc3f4542e27cfc9344044f71d43dc
+++ b/strbuf.c
@@@ -11,6 -11,28 +11,28 @@@ int starts_with(const char *str, const 
                        return 0;
  }
  
+ int skip_to_optional_arg_default(const char *str, const char *prefix,
+                                const char **arg, const char *def)
+ {
+       const char *p;
+       if (!skip_prefix(str, prefix, &p))
+               return 0;
+       if (!*p) {
+               if (arg)
+                       *arg = def;
+               return 1;
+       }
+       if (*p != '=')
+               return 0;
+       if (arg)
+               *arg = p + 1;
+       return 1;
+ }
  /*
   * Used as the default ->buf value, so that people can always assume
   * buf is non NULL and ->buf is NUL terminated even for a freshly
@@@ -386,15 -408,12 +408,15 @@@ ssize_t strbuf_read(struct strbuf *sb, 
  
  ssize_t strbuf_read_once(struct strbuf *sb, int fd, size_t hint)
  {
 +      size_t oldalloc = sb->alloc;
        ssize_t cnt;
  
        strbuf_grow(sb, hint ? hint : 8192);
        cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
        if (cnt > 0)
                strbuf_setlen(sb, sb->len + cnt);
 +      else if (oldalloc == 0)
 +              strbuf_release(sb);
        return cnt;
  }