Merge branch 'sb/diff-orderfile-config'
authorJunio C Hamano <gitster@pobox.com>
Fri, 10 Jan 2014 18:32:42 +0000 (10:32 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 10 Jan 2014 18:32:42 +0000 (10:32 -0800)
Allow "git diff -O<file>" to be configured with a new configuration
variable.

* sb/diff-orderfile-config:
diff: add diff.orderfile configuration variable
diff: let "git diff -O" read orderfile from any file and fail properly
t4056: add new tests for "git diff -O"

1  2 
diff.c
diffcore-order.c
diff --combined diff.c
index f99bc83b733acc7992c24c26f4465a669f7a4467,0099b995993de0d29866b3d128bbe8893b7a0439..6b4cd0eb36b92167233a82691fbdba5f29555c1c
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -30,6 -30,7 +30,7 @@@ static int diff_use_color_default = -1
  static int diff_context_default = 3;
  static const char *diff_word_regex_cfg;
  static const char *external_diff_cmd_cfg;
+ static const char *diff_order_file_cfg;
  int diff_auto_refresh_index = 1;
  static int diff_mnemonic_prefix;
  static int diff_no_prefix;
@@@ -201,6 -202,8 +202,8 @@@ int git_diff_ui_config(const char *var
                return git_config_string(&external_diff_cmd_cfg, var, value);
        if (!strcmp(var, "diff.wordregex"))
                return git_config_string(&diff_word_regex_cfg, var, value);
+       if (!strcmp(var, "diff.orderfile"))
+               return git_config_pathname(&diff_order_file_cfg, var, value);
  
        if (!strcmp(var, "diff.ignoresubmodules"))
                handle_ignore_submodules_arg(&default_diff_options, value);
@@@ -235,7 -238,7 +238,7 @@@ int git_diff_basic_config(const char *v
        if (userdiff_config(var, value) < 0)
                return -1;
  
 -      if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
 +      if (starts_with(var, "diff.color.") || starts_with(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
                if (slot < 0)
                        return 0;
                return 0;
        }
  
 -      if (!prefixcmp(var, "submodule."))
 +      if (starts_with(var, "submodule."))
                return parse_submodule_config_option(var, value);
  
        return git_default_config(var, value, cb);
@@@ -1215,7 -1218,7 +1218,7 @@@ static void fn_out_consume(void *priv, 
                        diff_words_append(line, len,
                                          &ecbdata->diff_words->plus);
                        return;
 -              } else if (!prefixcmp(line, "\\ ")) {
 +              } else if (starts_with(line, "\\ ")) {
                        /*
                         * Eat the "no newline at eof" marker as if we
                         * saw a "+" or "-" line with nothing on it,
@@@ -2387,9 -2390,9 +2390,9 @@@ static void builtin_diff(const char *na
                        xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
                if (!diffopts)
                        ;
 -              else if (!prefixcmp(diffopts, "--unified="))
 +              else if (starts_with(diffopts, "--unified="))
                        xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
 -              else if (!prefixcmp(diffopts, "-u"))
 +              else if (starts_with(diffopts, "-u"))
                        xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
                if (o->word_diff)
                        init_diff_words_data(&ecbdata, o, one, two);
@@@ -2899,16 -2902,11 +2902,16 @@@ static void run_external_diff(const cha
                              struct diff_filespec *one,
                              struct diff_filespec *two,
                              const char *xfrm_msg,
 -                            int complete_rewrite)
 +                            int complete_rewrite,
 +                            struct diff_options *o)
  {
        const char *spawn_arg[10];
        int retval;
        const char **arg = &spawn_arg[0];
 +      struct diff_queue_struct *q = &diff_queued_diff;
 +      const char *env[3] = { NULL };
 +      char env_counter[50];
 +      char env_total[50];
  
        if (one && two) {
                struct diff_tempfile *temp_one, *temp_two;
        }
        *arg = NULL;
        fflush(NULL);
 -      retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
 +
 +      env[0] = env_counter;
 +      snprintf(env_counter, sizeof(env_counter), "GIT_DIFF_PATH_COUNTER=%d",
 +               ++o->diff_path_counter);
 +      env[1] = env_total;
 +      snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
 +
 +      retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env);
        remove_tempfile();
        if (retval) {
                fprintf(stderr, "external diff died, stopping at %s.\n", name);
@@@ -3054,7 -3045,7 +3057,7 @@@ static void run_diff_cmd(const char *pg
  
        if (pgm) {
                run_external_diff(pgm, name, other, one, two, xfrm_msg,
 -                                complete_rewrite);
 +                                complete_rewrite, o);
                return;
        }
        if (one && two)
@@@ -3219,6 -3210,8 +3222,8 @@@ void diff_setup(struct diff_options *op
        options->detect_rename = diff_detect_rename_default;
        options->xdl_opts |= diff_algorithm;
  
+       options->orderfile = diff_order_file_cfg;
        if (diff_no_prefix) {
                options->a_prefix = options->b_prefix = "";
        } else if (!diff_mnemonic_prefix) {
@@@ -3329,8 -3322,6 +3334,8 @@@ void diff_setup_done(struct diff_option
                options->output_format = DIFF_FORMAT_NO_OUTPUT;
                DIFF_OPT_SET(options, EXIT_WITH_STATUS);
        }
 +
 +      options->diff_path_counter = 0;
  }
  
  static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
@@@ -3405,7 -3396,7 +3410,7 @@@ int parse_long_opt(const char *opt, con
        if (arg[0] != '-' || arg[1] != '-')
                return 0;
        arg += strlen("--");
 -      if (prefixcmp(arg, opt))
 +      if (!starts_with(arg, opt))
                return 0;
        arg += strlen(opt);
        if (*arg == '=') { /* stuck form: --option=value */
@@@ -3436,7 -3427,7 +3441,7 @@@ static int stat_opt(struct diff_option
  
        switch (*arg) {
        case '-':
 -              if (!prefixcmp(arg, "-width")) {
 +              if (starts_with(arg, "-width")) {
                        arg += strlen("-width");
                        if (*arg == '=')
                                width = strtoul(arg + 1, &end, 10);
                                width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
 -              } else if (!prefixcmp(arg, "-name-width")) {
 +              } else if (starts_with(arg, "-name-width")) {
                        arg += strlen("-name-width");
                        if (*arg == '=')
                                name_width = strtoul(arg + 1, &end, 10);
                                name_width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
 -              } else if (!prefixcmp(arg, "-graph-width")) {
 +              } else if (starts_with(arg, "-graph-width")) {
                        arg += strlen("-graph-width");
                        if (*arg == '=')
                                graph_width = strtoul(arg + 1, &end, 10);
                                graph_width = strtoul(av[1], &end, 10);
                                argcount = 2;
                        }
 -              } else if (!prefixcmp(arg, "-count")) {
 +              } else if (starts_with(arg, "-count")) {
                        arg += strlen("-count");
                        if (*arg == '=')
                                count = strtoul(arg + 1, &end, 10);
@@@ -3628,15 -3619,15 +3633,15 @@@ int diff_opt_parse(struct diff_options 
                options->output_format |= DIFF_FORMAT_SHORTSTAT;
        else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
                return parse_dirstat_opt(options, "");
 -      else if (!prefixcmp(arg, "-X"))
 +      else if (starts_with(arg, "-X"))
                return parse_dirstat_opt(options, arg + 2);
 -      else if (!prefixcmp(arg, "--dirstat="))
 +      else if (starts_with(arg, "--dirstat="))
                return parse_dirstat_opt(options, arg + 10);
        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 (!prefixcmp(arg, "--dirstat-by-file=")) {
 +      else if (starts_with(arg, "--dirstat-by-file=")) {
                parse_dirstat_opt(options, "files");
                return parse_dirstat_opt(options, arg + 18);
        }
                options->output_format |= DIFF_FORMAT_NAME_STATUS;
        else if (!strcmp(arg, "-s") || !strcmp(arg, "--no-patch"))
                options->output_format |= DIFF_FORMAT_NO_OUTPUT;
 -      else if (!prefixcmp(arg, "--stat"))
 +      else if (starts_with(arg, "--stat"))
                /* --stat, --stat-width, --stat-name-width, or --stat-count */
                return stat_opt(options, av);
  
        /* renames options */
 -      else if (!prefixcmp(arg, "-B") || !prefixcmp(arg, "--break-rewrites=") ||
 +      else if (starts_with(arg, "-B") || starts_with(arg, "--break-rewrites=") ||
                 !strcmp(arg, "--break-rewrites")) {
                if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
                        return error("invalid argument to -B: %s", arg+2);
        }
 -      else if (!prefixcmp(arg, "-M") || !prefixcmp(arg, "--find-renames=") ||
 +      else if (starts_with(arg, "-M") || starts_with(arg, "--find-renames=") ||
                 !strcmp(arg, "--find-renames")) {
                if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
                        return error("invalid argument to -M: %s", arg+2);
        else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
                options->irreversible_delete = 1;
        }
 -      else if (!prefixcmp(arg, "-C") || !prefixcmp(arg, "--find-copies=") ||
 +      else if (starts_with(arg, "-C") || starts_with(arg, "--find-copies=") ||
                 !strcmp(arg, "--find-copies")) {
                if (options->detect_rename == DIFF_DETECT_COPY)
                        DIFF_OPT_SET(options, FIND_COPIES_HARDER);
                DIFF_OPT_CLR(options, RENAME_EMPTY);
        else if (!strcmp(arg, "--relative"))
                DIFF_OPT_SET(options, RELATIVE_NAME);
 -      else if (!prefixcmp(arg, "--relative=")) {
 +      else if (starts_with(arg, "--relative=")) {
                DIFF_OPT_SET(options, RELATIVE_NAME);
                options->prefix = arg + 11;
        }
                DIFF_OPT_CLR(options, FOLLOW_RENAMES);
        else if (!strcmp(arg, "--color"))
                options->use_color = 1;
 -      else if (!prefixcmp(arg, "--color=")) {
 +      else if (starts_with(arg, "--color=")) {
                int value = git_config_colorbool(NULL, arg+8);
                if (value < 0)
                        return error("option `color' expects \"always\", \"auto\", or \"never\"");
                options->use_color = 1;
                options->word_diff = DIFF_WORDS_COLOR;
        }
 -      else if (!prefixcmp(arg, "--color-words=")) {
 +      else if (starts_with(arg, "--color-words=")) {
                options->use_color = 1;
                options->word_diff = DIFF_WORDS_COLOR;
                options->word_regex = arg + 14;
                if (options->word_diff == DIFF_WORDS_NONE)
                        options->word_diff = DIFF_WORDS_PLAIN;
        }
 -      else if (!prefixcmp(arg, "--word-diff=")) {
 +      else if (starts_with(arg, "--word-diff=")) {
                const char *type = arg + 12;
                if (!strcmp(type, "plain"))
                        options->word_diff = DIFF_WORDS_PLAIN;
        else if (!strcmp(arg, "--ignore-submodules")) {
                DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(options, "all");
 -      } else if (!prefixcmp(arg, "--ignore-submodules=")) {
 +      } else if (starts_with(arg, "--ignore-submodules=")) {
                DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(options, arg + 20);
        } else if (!strcmp(arg, "--submodule"))
                DIFF_OPT_SET(options, SUBMODULE_LOG);
 -      else if (!prefixcmp(arg, "--submodule="))
 +      else if (starts_with(arg, "--submodule="))
                return parse_submodule_opt(options, arg + 12);
  
        /* misc options */
        }
        else if (!strcmp(arg, "--abbrev"))
                options->abbrev = DEFAULT_ABBREV;
 -      else if (!prefixcmp(arg, "--abbrev=")) {
 +      else if (starts_with(arg, "--abbrev=")) {
                options->abbrev = strtoul(arg + 9, NULL, 10);
                if (options->abbrev < MINIMUM_ABBREV)
                        options->abbrev = MINIMUM_ABBREV;
@@@ -3921,15 -3912,15 +3926,15 @@@ static int diff_scoreopt_parse(const ch
        cmd = *opt++;
        if (cmd == '-') {
                /* convert the long-form arguments into short-form versions */
 -              if (!prefixcmp(opt, "break-rewrites")) {
 +              if (starts_with(opt, "break-rewrites")) {
                        opt += strlen("break-rewrites");
                        if (*opt == 0 || *opt++ == '=')
                                cmd = 'B';
 -              } else if (!prefixcmp(opt, "find-copies")) {
 +              } else if (starts_with(opt, "find-copies")) {
                        opt += strlen("find-copies");
                        if (*opt == 0 || *opt++ == '=')
                                cmd = 'C';
 -              } else if (!prefixcmp(opt, "find-renames")) {
 +              } else if (starts_with(opt, "find-renames")) {
                        opt += strlen("find-renames");
                        if (*opt == 0 || *opt++ == '=')
                                cmd = 'M';
@@@ -4339,7 -4330,7 +4344,7 @@@ static void patch_id_consume(void *priv
        int new_len;
  
        /* Ignore line numbers when computing the SHA1 of the patch */
 -      if (!prefixcmp(line, "@@ -"))
 +      if (starts_with(line, "@@ -"))
                return;
  
        new_len = remove_space(line, len);
diff --combined diffcore-order.c
index 50c089bb2b3343458fb3929d4c9eac37966063cf,a63f332d2edd87225d141843904c46af2c9964f8..fe7f1f4647a16a5882cc4c1e63738c7faa4bc677
@@@ -10,28 -10,21 +10,21 @@@ static int order_cnt
  
  static void prepare_order(const char *orderfile)
  {
-       int fd, cnt, pass;
+       int cnt, pass;
+       struct strbuf sb = STRBUF_INIT;
        void *map;
        char *cp, *endp;
-       struct stat st;
-       size_t sz;
+       ssize_t sz;
  
        if (order)
                return;
  
-       fd = open(orderfile, O_RDONLY);
-       if (fd < 0)
-               return;
-       if (fstat(fd, &st)) {
-               close(fd);
-               return;
-       }
-       sz = xsize_t(st.st_size);
-       map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
-       close(fd);
-       if (map == MAP_FAILED)
-               return;
+       sz = strbuf_read_file(&sb, orderfile, 0);
+       if (sz < 0)
+               die_errno(_("failed to read orderfile '%s'"), orderfile);
+       map = strbuf_detach(&sb, NULL);
        endp = (char *) map + sz;
        for (pass = 0; pass < 2; pass++) {
                cnt = 0;
                cp = map;
@@@ -73,16 -66,15 +66,16 @@@ struct pair_order 
  static int match_order(const char *path)
  {
        int i;
 -      char p[PATH_MAX];
 +      static struct strbuf p = STRBUF_INIT;
  
        for (i = 0; i < order_cnt; i++) {
 -              strcpy(p, path);
 -              while (p[0]) {
 +              strbuf_reset(&p);
 +              strbuf_addstr(&p, path);
 +              while (p.buf[0]) {
                        char *cp;
 -                      if (!fnmatch(order[i], p, 0))
 +                      if (!fnmatch(order[i], p.buf, 0))
                                return i;
 -                      cp = strrchr(p, '/');
 +                      cp = strrchr(p.buf, '/');
                        if (!cp)
                                break;
                        *cp = 0;