Skip to content

Commit dbd0f5c

Browse files
committed
Files given on the command line are relative to $cwd
When running "git commit -F file" and "git tag -F file" from a subdirectory, we should take it as relative to the directory we started from, not relative to the top-level directory. This adds a helper function "parse_options_fix_filename()" to make it more convenient to fix this class of issues. Ideally, parse_options() should support a new type of option, "OPT_FILENAME", to do this uniformly, but this patch is meant to go to 'maint' to fix it minimally. One thing to note is that value for "commit template file" that comes from the command line is taken as relative to $cwd just like other parameters, but when it comes from the configuration varilable 'commit.template', it is taken as relative to the working tree root as before. I think this difference actually is sensible (not that I particularly think commit.template itself is sensible). Signed-off-by: Junio C Hamano <[email protected]>
1 parent eabbc99 commit dbd0f5c

File tree

6 files changed

+72
-5
lines changed

6 files changed

+72
-5
lines changed

builtin-commit.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static enum {
4545
COMMIT_PARTIAL,
4646
} commit_style;
4747

48-
static char *logfile, *force_author;
48+
static const char *logfile, *force_author;
4949
static const char *template_file;
5050
static char *edit_message, *use_message;
5151
static char *author_name, *author_email, *author_date;
@@ -700,11 +700,14 @@ static int message_is_empty(struct strbuf *sb, int start)
700700
}
701701

702702
static int parse_and_validate_options(int argc, const char *argv[],
703-
const char * const usage[])
703+
const char * const usage[],
704+
const char *prefix)
704705
{
705706
int f = 0;
706707

707708
argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
709+
logfile = parse_options_fix_filename(prefix, logfile);
710+
template_file = parse_options_fix_filename(prefix, template_file);
708711

709712
if (logfile || message.len || use_message)
710713
use_editor = 0;
@@ -814,7 +817,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
814817
if (wt_status_use_color == -1)
815818
wt_status_use_color = git_use_color_default;
816819

817-
argc = parse_and_validate_options(argc, argv, builtin_status_usage);
820+
argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
818821

819822
index_file = prepare_index(argc, argv, prefix);
820823

@@ -907,7 +910,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
907910

908911
git_config(git_commit_config, NULL);
909912

910-
argc = parse_and_validate_options(argc, argv, builtin_commit_usage);
913+
argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
911914

912915
index_file = prepare_index(argc, argv, prefix);
913916

builtin-tag.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
385385

386386
int annotate = 0, sign = 0, force = 0, lines = 0,
387387
list = 0, delete = 0, verify = 0;
388-
char *msgfile = NULL, *keyid = NULL;
388+
const char *msgfile = NULL, *keyid = NULL;
389389
struct msg_arg msg = { 0, STRBUF_INIT };
390390
struct option options[] = {
391391
OPT_BOOLEAN('l', NULL, &list, "list tag names"),
@@ -411,6 +411,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
411411
git_config(git_tag_config, NULL);
412412

413413
argc = parse_options(argc, argv, options, git_tag_usage, 0);
414+
msgfile = parse_options_fix_filename(prefix, msgfile);
414415

415416
if (keyid) {
416417
sign = 1;

parse-options.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,15 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
425425
*(unsigned long *)(opt->value) = approxidate(arg);
426426
return 0;
427427
}
428+
429+
/*
430+
* This should really be OPTION_FILENAME type as a part of
431+
* parse_options that take prefix to do this while parsing.
432+
*/
433+
extern const char *parse_options_fix_filename(const char *prefix, const char *file)
434+
{
435+
if (!file || !prefix || is_absolute_path(file) || !strcmp("-", file))
436+
return file;
437+
return prefix_filename(prefix, strlen(prefix), file);
438+
}
439+

parse-options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,6 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
123123
"use <n> digits to display SHA-1s", \
124124
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
125125

126+
extern const char *parse_options_fix_filename(const char *prefix, const char *file);
127+
126128
#endif

t/t7004-tag.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,4 +1067,24 @@ test_expect_success \
10671067
test_cmp expect actual
10681068
'
10691069
1070+
test_expect_success 'filename for the message is relative to cwd' '
1071+
mkdir subdir &&
1072+
echo "Tag message in top directory" >msgfile-5 &&
1073+
echo "Tag message in sub directory" >subdir/msgfile-5 &&
1074+
(
1075+
cd subdir &&
1076+
git tag -a -F msgfile-5 tag-from-subdir
1077+
) &&
1078+
git cat-file tag tag-from-subdir | grep "in sub directory"
1079+
'
1080+
1081+
test_expect_success 'filename for the message is relative to cwd' '
1082+
echo "Tag message in sub directory" >subdir/msgfile-6 &&
1083+
(
1084+
cd subdir &&
1085+
git tag -a -F msgfile-6 tag-from-subdir-2
1086+
) &&
1087+
git cat-file tag tag-from-subdir-2 | grep "in sub directory"
1088+
'
1089+
10701090
test_done

t/t7500-commit.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,33 @@ test_expect_success '--signoff' '
138138
diff expect output
139139
'
140140

141+
test_expect_success 'commit message from file (1)' '
142+
mkdir subdir &&
143+
echo "Log in top directory" >log &&
144+
echo "Log in sub directory" >subdir/log &&
145+
(
146+
cd subdir &&
147+
git commit --allow-empty -F log
148+
) &&
149+
commit_msg_is "Log in sub directory"
150+
'
151+
152+
test_expect_success 'commit message from file (2)' '
153+
rm -f log &&
154+
echo "Log in sub directory" >subdir/log &&
155+
(
156+
cd subdir &&
157+
git commit --allow-empty -F log
158+
) &&
159+
commit_msg_is "Log in sub directory"
160+
'
161+
162+
test_expect_success 'commit message from stdin' '
163+
(
164+
cd subdir &&
165+
echo "Log with foo word" | git commit --allow-empty -F -
166+
) &&
167+
commit_msg_is "Log with foo word"
168+
'
169+
141170
test_done

0 commit comments

Comments
 (0)