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

Teach --[no-]rerere-autoupdate option to merge, revert and friends

Introduce a command line option to override rerere.autoupdate configuration variable to make it more useful. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Dec 4, 2009 at 00:20 UTC cb6020bb017405cc3e7f1faea6f30d4fd1b62e70
12 files changed +77 -18
Documentation/git-merge.txt
+6 -1
@@ -10,7 +10,7 @@ SYNOPSIS
10 --------
11 [verse]
12 'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
13 - [-m <msg>] <remote>...
13 + [--[no-]rerere-autoupdate] [-m <msg>] <remote>...
14 'git merge' <msg> HEAD <remote>...
15
16 DESCRIPTION
@@ -33,6 +33,11 @@ include::merge-options.txt[]
33 used to give a good default for automated 'git merge'
34 invocations.
35
36 +--rerere-autoupdate::
37 +--no-rerere-autoupdate::
38 + Allow the rerere mechanism to update the index with the
39 + result of auto-conflict resolution if possible.
40 +
41 <remote>...::
42 Other branch heads to merge into our branch. You need at
43 least one <remote>. Specifying more than one <remote>
builtin-commit.c
+1 -1
@@ -1150,7 +1150,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
1150 "new_index file. Check that disk is not full or quota is\n"
1151 "not exceeded, and then \"git reset HEAD\" to recover.");
1152
1153 - rerere();
1153 + rerere(0);
1154 run_hook(get_index_file(), "post-commit", NULL);
1155 if (!quiet)
1156 print_summary(prefix, commit_sha1);
builtin-merge.c
+3 -1
@@ -52,6 +52,7 @@ static struct strategy **use_strategies;
52 static size_t use_strategies_nr, use_strategies_alloc;
53 static const char *branch;
54 static int verbosity;
55 +static int allow_rerere_auto;
56
57 static struct strategy all_strategy[] = {
58 { "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -170,6 +171,7 @@ static struct option builtin_merge_options[] = {
171 "allow fast-forward (default)"),
172 OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
173 "abort if fast-forward is not possible"),
174 + OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
175 OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
176 "merge strategy to use", option_parse_strategy),
177 OPT_CALLBACK('m', "message", &merge_msg, "message",
@@ -790,7 +792,7 @@ static int suggest_conflicts(void)
792 }
793 }
794 fclose(fp);
793 - rerere();
795 + rerere(allow_rerere_auto);
796 printf("Automatic merge failed; "
797 "fix conflicts and then commit the result.\n");
798 return 1;
builtin-rerere.c
+16 -7
@@ -101,15 +101,24 @@ static int diff_two(const char *file1, const char *label1,
101 int cmd_rerere(int argc, const char **argv, const char *prefix)
102 {
103 struct string_list merge_rr = { NULL, 0, 0, 1 };
104 - int i, fd;
105 -
104 + int i, fd, flags = 0;
105 +
106 + if (2 < argc) {
107 + if (!strcmp(argv[1], "-h"))
108 + usage(git_rerere_usage);
109 + if (!strcmp(argv[1], "--rerere-autoupdate"))
110 + flags = RERERE_AUTOUPDATE;
111 + else if (!strcmp(argv[1], "--no-rerere-autoupdate"))
112 + flags = RERERE_NOAUTOUPDATE;
113 + if (flags) {
114 + argc--;
115 + argv++;
116 + }
117 + }
118 if (argc < 2)
107 - return rerere();
108 -
109 - if (!strcmp(argv[1], "-h"))
110 - usage(git_rerere_usage);
119 + return rerere(flags);
120
112 - fd = setup_rerere(&merge_rr);
121 + fd = setup_rerere(&merge_rr, flags);
122 if (fd < 0)
123 return 0;
124
builtin-revert.c
+3 -1
@@ -38,6 +38,7 @@ static const char * const cherry_pick_usage[] = {
38 static int edit, no_replay, no_commit, mainline, signoff;
39 static enum { REVERT, CHERRY_PICK } action;
40 static struct commit *commit;
41 +static int allow_rerere_auto;
42
43 static const char *me;
44
@@ -57,6 +58,7 @@ static void parse_args(int argc, const char **argv)
58 OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
59 OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
60 OPT_INTEGER('m', "mainline", &mainline, "parent number"),
61 + OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
62 OPT_END(),
63 };
64
@@ -395,7 +397,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
397 die ("Error wrapping up %s", defmsg);
398 fprintf(stderr, "Automatic %s failed.%s\n",
399 me, help_msg(commit->object.sha1));
398 - rerere();
400 + rerere(allow_rerere_auto);
401 exit(1);
402 }
403 if (commit_lock_file(&msg_file) < 0)
git-am.sh
+5 -1
@@ -30,6 +30,7 @@ skip skip the current patch
30 abort restore the original branch and abort the patching operation.
31 committer-date-is-author-date lie about committer date
32 ignore-date use current timestamp for author date
33 +rerere-autoupdate update the index with reused conflict resolution if possible
34 rebasing* (internal use for git-rebase)"
35
36 . git-sh-setup
@@ -135,7 +136,7 @@ It does not apply to blobs recorded in its index."
136 export GIT_MERGE_VERBOSITY=0
137 fi
138 git-merge-recursive $orig_tree -- HEAD $his_tree || {
138 - git rerere
139 + git rerere $allow_rerere_autoupdate
140 echo Failed to merge in the changes.
141 exit 1
142 }
@@ -293,6 +294,7 @@ resolvemsg= resume= scissors= no_inbody_headers=
294 git_apply_opt=
295 committer_date_is_author_date=
296 ignore_date=
297 +allow_rerere_autoupdate=
298
299 while test $# != 0
300 do
@@ -340,6 +342,8 @@ do
342 committer_date_is_author_date=t ;;
343 --ignore-date)
344 ignore_date=t ;;
345 + --rerere-autoupdate|--no-rerere-autoupdate)
346 + allow_rerere_autoupdate="$1" ;;
347 -q|--quiet)
348 GIT_QUIET=t ;;
349 --)
git-rebase.sh
+5 -1
@@ -50,6 +50,7 @@ diffstat=$(git config --bool rebase.stat)
50 git_am_opt=
51 rebase_root=
52 force_rebase=
53 +allow_rerere_autoupdate=
54
55 continue_merge () {
56 test -n "$prev_head" || die "prev_head must be defined"
@@ -118,7 +119,7 @@ call_merge () {
119 return
120 ;;
121 1)
121 - git rerere
122 + git rerere $allow_rerere_autoupdate
123 die "$RESOLVEMSG"
124 ;;
125 2)
@@ -349,6 +350,9 @@ do
350 -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
351 force_rebase=t
352 ;;
353 + --rerere-autoupdate|--no-rerere-autoupdate)
354 + allow_rerere_autoupdate="$1"
355 + ;;
356 -*)
357 usage
358 ;;
parse-options.c
+7
@@ -633,3 +633,10 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
633 commit_list_insert(commit, opt->value);
634 return 0;
635 }
636 +
637 +int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
638 +{
639 + int *target = opt->value;
640 + *target = unset ? 2 : 1;
641 + return 0;
642 +}
parse-options.h
+3
@@ -123,6 +123,8 @@ struct option {
123 (h), PARSE_OPT_NOARG, NULL, (p) }
124 #define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), "n", (h) }
125 #define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
126 +#define OPT_UYN(s, l, v, h) { OPTION_CALLBACK, (s), (l), (v), NULL, \
127 + (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
128 #define OPT_DATE(s, l, v, h) \
129 { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
130 parse_opt_approxidate_cb }
@@ -190,6 +192,7 @@ extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
192 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
193 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
194 extern int parse_opt_with_commit(const struct option *, const char *, int);
195 +extern int parse_opt_tertiary(const struct option *, const char *, int);
196
197 #define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
198 #define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
rerere.c
+5 -3
@@ -367,7 +367,7 @@ static int is_rerere_enabled(void)
367 return 1;
368 }
369
370 -int setup_rerere(struct string_list *merge_rr)
370 +int setup_rerere(struct string_list *merge_rr, int flags)
371 {
372 int fd;
373
@@ -375,6 +375,8 @@ int setup_rerere(struct string_list *merge_rr)
375 if (!is_rerere_enabled())
376 return -1;
377
378 + if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
379 + rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
380 merge_rr_path = git_pathdup("MERGE_RR");
381 fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
382 LOCK_DIE_ON_ERROR);
@@ -382,12 +384,12 @@ int setup_rerere(struct string_list *merge_rr)
384 return fd;
385 }
386
385 -int rerere(void)
387 +int rerere(int flags)
388 {
389 struct string_list merge_rr = { NULL, 0, 0, 1 };
390 int fd;
391
390 - fd = setup_rerere(&merge_rr);
392 + fd = setup_rerere(&merge_rr, flags);
393 if (fd < 0)
394 return 0;
395 return do_plain_rerere(&merge_rr, fd);
rerere.h
+8 -2
@@ -3,9 +3,15 @@
3
4 #include "string-list.h"
5
6 -extern int setup_rerere(struct string_list *);
7 -extern int rerere(void);
6 +#define RERERE_AUTOUPDATE 01
7 +#define RERERE_NOAUTOUPDATE 02
8 +
9 +extern int setup_rerere(struct string_list *, int);
10 +extern int rerere(int);
11 extern const char *rerere_path(const char *hex, const char *file);
12 extern int has_rerere_resolution(const char *hex);
13
14 +#define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
15 + "update the index with reused conflict resolution if possible")
16 +
17 #endif
t/t4200-rerere.sh
+15
@@ -217,7 +217,22 @@ test_expect_success 'rerere.autoupdate' '
217 git checkout version2 &&
218 test_must_fail git merge fifth &&
219 test 0 = $(git ls-files -u | wc -l)
220 +'
221
222 +test_expect_success 'merge --rerere-autoupdate' '
223 + git config --unset rerere.autoupdate
224 + git reset --hard &&
225 + git checkout version2 &&
226 + test_must_fail git merge --rerere-autoupdate fifth &&
227 + test 0 = $(git ls-files -u | wc -l)
228 +'
229 +
230 +test_expect_success 'merge --no-rerere-autoupdate' '
231 + git config rerere.autoupdate true
232 + git reset --hard &&
233 + git checkout version2 &&
234 + test_must_fail git merge --no-rerere-autoupdate fifth &&
235 + test 2 = $(git ls-files -u | wc -l)
236 '
237
238 test_done