@matheusbsbs / matheus-bagliano / commits / dbd0f5c769
Fork 0

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 <gitster@pobox.com>

Junio C Hamano committed Aug 6, 2008 at 11:43 UTC dbd0f5c7692cce0c5fea535a06622b3a93df9598
6 files changed +72 -5
builtin-commit.c
+7 -4
@@ -45,7 +45,7 @@ static enum {
45 COMMIT_PARTIAL,
46 } commit_style;
47
48 -static char *logfile, *force_author;
48 +static const char *logfile, *force_author;
49 static const char *template_file;
50 static char *edit_message, *use_message;
51 static char *author_name, *author_email, *author_date;
@@ -700,11 +700,14 @@ static int message_is_empty(struct strbuf *sb, int start)
700 }
701
702 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)
705 {
706 int f = 0;
707
708 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);
711
712 if (logfile || message.len || use_message)
713 use_editor = 0;
@@ -814,7 +817,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
817 if (wt_status_use_color == -1)
818 wt_status_use_color = git_use_color_default;
819
817 - argc = parse_and_validate_options(argc, argv, builtin_status_usage);
820 + argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
821
822 index_file = prepare_index(argc, argv, prefix);
823
@@ -907,7 +910,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
910
911 git_config(git_commit_config, NULL);
912
910 - argc = parse_and_validate_options(argc, argv, builtin_commit_usage);
913 + argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
914
915 index_file = prepare_index(argc, argv, prefix);
916
builtin-tag.c
+2 -1
@@ -385,7 +385,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
385
386 int annotate = 0, sign = 0, force = 0, lines = 0,
387 list = 0, delete = 0, verify = 0;
388 - char *msgfile = NULL, *keyid = NULL;
388 + const char *msgfile = NULL, *keyid = NULL;
389 struct msg_arg msg = { 0, STRBUF_INIT };
390 struct option options[] = {
391 OPT_BOOLEAN('l', NULL, &list, "list tag names"),
@@ -411,6 +411,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
411 git_config(git_tag_config, NULL);
412
413 argc = parse_options(argc, argv, options, git_tag_usage, 0);
414 + msgfile = parse_options_fix_filename(prefix, msgfile);
415
416 if (keyid) {
417 sign = 1;
parse-options.c
+12
@@ -425,3 +425,15 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
425 *(unsigned long *)(opt->value) = approxidate(arg);
426 return 0;
427 }
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
+2
@@ -123,4 +123,6 @@ extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
123 "use <n> digits to display SHA-1s", \
124 PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
125
126 +extern const char *parse_options_fix_filename(const char *prefix, const char *file);
127 +
128 #endif
t/t7004-tag.sh
+20
@@ -1067,4 +1067,24 @@ test_expect_success \
1067 test_cmp expect actual
1068 '
1069
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 +
1090 test_done
t/t7500-commit.sh
+29
@@ -138,4 +138,33 @@ test_expect_success '--signoff' '
138 diff expect output
139 '
140
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 +
170 test_done