diff: make -O and --output work in subdirectory

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Duy Nguyen committed Jan 21, 2016 at 18:48 UTC a97262c62f1a31fcc7edf7629d313058bc7d66b5
6 files changed +21 -8
builtin/am.c
+1 -1
@@ -1653,7 +1653,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
1653
1654 init_revisions(&rev_info, NULL);
1655 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
1656 - diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1);
1656 + diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
1657 add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
1658 diff_setup_done(&rev_info.diffopt);
1659 run_diff_index(&rev_info, 1);
diff-no-index.c
+2 -1
@@ -254,7 +254,8 @@ void diff_no_index(struct rev_info *revs,
254 else if (!strcmp(argv[i], "--"))
255 i++;
256 else {
257 - j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
257 + j = diff_opt_parse(&revs->diffopt, argv + i, argc - i,
258 + revs->prefix);
259 if (j <= 0)
260 die("invalid diff option/value: %s", argv[i]);
261 i += j;
diff.c
+10 -4
@@ -3695,12 +3695,16 @@ static int parse_ws_error_highlight(struct diff_options *opt, const char *arg)
3695 return 1;
3696 }
3697
3698 -int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3698 +int diff_opt_parse(struct diff_options *options,
3699 + const char **av, int ac, const char *prefix)
3700 {
3701 const char *arg = av[0];
3702 const char *optarg;
3703 int argcount;
3704
3705 + if (!prefix)
3706 + prefix = "";
3707 +
3708 /* Output format options */
3709 if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch")
3710 || opt_arg(arg, 'U', "unified", &options->context))
@@ -3917,7 +3921,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3921 else if (!strcmp(arg, "--pickaxe-regex"))
3922 options->pickaxe_opts |= DIFF_PICKAXE_REGEX;
3923 else if ((argcount = short_opt('O', av, &optarg))) {
3920 - options->orderfile = optarg;
3924 + const char *path = prefix_filename(prefix, strlen(prefix), optarg);
3925 + options->orderfile = xstrdup(path);
3926 return argcount;
3927 }
3928 else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
@@ -3956,9 +3961,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3961 else if (!strcmp(arg, "--no-function-context"))
3962 DIFF_OPT_CLR(options, FUNCCONTEXT);
3963 else if ((argcount = parse_long_opt("output", av, &optarg))) {
3959 - options->file = fopen(optarg, "w");
3964 + const char *path = prefix_filename(prefix, strlen(prefix), optarg);
3965 + options->file = fopen(path, "w");
3966 if (!options->file)
3961 - die_errno("Could not open '%s'", optarg);
3967 + die_errno("Could not open '%s'", path);
3968 options->close_file = 1;
3969 return argcount;
3970 } else
diff.h
+1 -1
@@ -268,7 +268,7 @@ extern int parse_long_opt(const char *opt, const char **argv,
268 extern int git_diff_basic_config(const char *var, const char *value, void *cb);
269 extern int git_diff_ui_config(const char *var, const char *value, void *cb);
270 extern void diff_setup(struct diff_options *);
271 -extern int diff_opt_parse(struct diff_options *, const char **, int);
271 +extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
272 extern void diff_setup_done(struct diff_options *);
273
274 #define DIFF_DETECT_RENAME 1
revision.c
+1 -1
@@ -2049,7 +2049,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
2049 } else if (!strcmp(arg, "--ignore-missing")) {
2050 revs->ignore_missing = 1;
2051 } else {
2052 - int opts = diff_opt_parse(&revs->diffopt, argv, argc);
2052 + int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
2053 if (!opts)
2054 unkv[(*unkc)++] = arg;
2055 return opts;
t/t4056-diff-order.sh
+6
@@ -68,6 +68,12 @@ test_expect_success POSIXPERM,SANITY 'unreadable orderfile' '
68 test_must_fail git diff -Ounreadable_file --name-only HEAD^..HEAD
69 '
70
71 +test_expect_success "orderfile using option from subdir with --output" '
72 + mkdir subdir &&
73 + git -C subdir diff -O../order_file_1 --output ../actual --name-only HEAD^..HEAD &&
74 + test_cmp expect_1 actual
75 +'
76 +
77 for i in 1 2
78 do
79 test_expect_success "orderfile using option ($i)" '