Enable "git rerere" by the config variable rerere.enabled

Earlier, "git rerere" was enabled by creating the directory
.git/rr-cache.  That is definitely not in line with most other
features, which are enabled by a config variable.

So, check the config variable "rerere.enabled". If it is set
to "false" explicitely, do not activate rerere, even if
.git/rr-cache exists. This should help when you want to disable
rerere temporarily.

If "rerere.enabled" is not set at all, fall back to detection
of the directory .git/rr-cache.

[jc: with minimum tweaks]

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2007-07-06 13:05:59 +01:00 committed by Junio C Hamano
parent b2493649fe
commit b4372ef136
9 changed files with 64 additions and 40 deletions

View File

@ -448,6 +448,11 @@ gc.rerereunresolved::
kept for this many days when `git rerere gc` is run. kept for this many days when `git rerere gc` is run.
The default is 15 days. See gitlink:git-rerere[1]. The default is 15 days. See gitlink:git-rerere[1].
rerere.enabled::
Activate recording of resolved conflicts, so that identical
conflict hunks can be resolved automatically, should they
be encountered again. See gitlink:git-rerere[1].
gitcvs.enabled:: gitcvs.enabled::
Whether the cvs server interface is enabled for this repository. Whether the cvs server interface is enabled for this repository.
See gitlink:git-cvsserver[1]. See gitlink:git-cvsserver[1].

View File

@ -23,7 +23,7 @@ initial manual merge, and later by noticing the same automerge
results and applying the previously recorded hand resolution. results and applying the previously recorded hand resolution.
[NOTE] [NOTE]
You need to create `$GIT_DIR/rr-cache` directory to enable this You need to set the config variable rerere.enabled to enable this
command. command.
@ -171,7 +171,7 @@ records it if it is a new conflict, or reuses the earlier hand
resolve when it is not. `git-commit` also invokes `git-rerere` resolve when it is not. `git-commit` also invokes `git-rerere`
when recording a merge result. What this means is that you do when recording a merge result. What this means is that you do
not have to do anything special yourself (Note: you still have not have to do anything special yourself (Note: you still have
to create `$GIT_DIR/rr-cache` directory to enable this command). to set the config variable rerere.enabled to enable this command).
In our example, when you did the test merge, the manual In our example, when you did the test merge, the manual
resolution is recorded, and it will be reused when you do the resolution is recorded, and it will be reused when you do the

View File

@ -12,6 +12,9 @@ static const char git_rerere_usage[] =
static int cutoff_noresolve = 15; static int cutoff_noresolve = 15;
static int cutoff_resolve = 60; static int cutoff_resolve = 60;
/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
static int rerere_enabled = -1;
static char *merge_rr_path; static char *merge_rr_path;
static const char *rr_path(const char *name, const char *file) static const char *rr_path(const char *name, const char *file)
@ -387,21 +390,41 @@ static int git_rerere_config(const char *var, const char *value)
cutoff_resolve = git_config_int(var, value); cutoff_resolve = git_config_int(var, value);
else if (!strcmp(var, "gc.rerereunresolved")) else if (!strcmp(var, "gc.rerereunresolved"))
cutoff_noresolve = git_config_int(var, value); cutoff_noresolve = git_config_int(var, value);
else if (!strcmp(var, "rerere.enabled"))
rerere_enabled = git_config_bool(var, value);
else else
return git_default_config(var, value); return git_default_config(var, value);
return 0; return 0;
} }
static int is_rerere_enabled(void)
{
struct stat st;
const char *rr_cache;
int rr_cache_exists;
if (!rerere_enabled)
return 0;
rr_cache = git_path("rr-cache");
rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
if (rerere_enabled < 0)
return rr_cache_exists;
if (!rr_cache_exists &&
(mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
die("Could not create directory %s", rr_cache);
return 1;
}
int cmd_rerere(int argc, const char **argv, const char *prefix) int cmd_rerere(int argc, const char **argv, const char *prefix)
{ {
struct path_list merge_rr = { NULL, 0, 0, 1 }; struct path_list merge_rr = { NULL, 0, 0, 1 };
int i, fd = -1; int i, fd = -1;
struct stat st;
if (stat(git_path("rr-cache"), &st) || !S_ISDIR(st.st_mode))
return 0;
git_config(git_rerere_config); git_config(git_rerere_config);
if (!is_rerere_enabled())
return 0;
merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR")); merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1); fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
@ -411,6 +434,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
return do_plain_rerere(&merge_rr, fd); return do_plain_rerere(&merge_rr, fd);
else if (!strcmp(argv[1], "clear")) { else if (!strcmp(argv[1], "clear")) {
for (i = 0; i < merge_rr.nr; i++) { for (i = 0; i < merge_rr.nr; i++) {
struct stat st;
const char *name = (const char *)merge_rr.items[i].util; const char *name = (const char *)merge_rr.items[i].util;
if (!stat(git_path("rr-cache/%s", name), &st) && if (!stat(git_path("rr-cache/%s", name), &st) &&
S_ISDIR(st.st_mode) && S_ISDIR(st.st_mode) &&

View File

@ -681,8 +681,7 @@ and returns the process output as a string."
(condition-case nil (delete-file ".git/MERGE_MSG") (error nil)) (condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
(with-current-buffer buffer (erase-buffer)) (with-current-buffer buffer (erase-buffer))
(git-set-files-state files 'uptodate) (git-set-files-state files 'uptodate)
(when (file-directory-p ".git/rr-cache") (git-run-command nil nil "rerere")
(git-run-command nil nil "rerere"))
(git-refresh-files) (git-refresh-files)
(git-refresh-ewoc-hf git-status) (git-refresh-ewoc-hf git-status)
(message "Committed %s." commit) (message "Committed %s." commit)

View File

@ -95,10 +95,7 @@ It does not apply to blobs recorded in its index."
eval GITHEAD_$his_tree='"$SUBJECT"' eval GITHEAD_$his_tree='"$SUBJECT"'
export GITHEAD_$his_tree export GITHEAD_$his_tree
git-merge-recursive $orig_tree -- HEAD $his_tree || { git-merge-recursive $orig_tree -- HEAD $his_tree || {
if test -d "$GIT_DIR/rr-cache" git rerere
then
git rerere
fi
echo Failed to merge in the changes. echo Failed to merge in the changes.
exit 1 exit 1
} }
@ -252,10 +249,7 @@ last=`cat "$dotest/last"`
this=`cat "$dotest/next"` this=`cat "$dotest/next"`
if test "$skip" = t if test "$skip" = t
then then
if test -d "$GIT_DIR/rr-cache" git rerere clear
then
git rerere clear
fi
this=`expr "$this" + 1` this=`expr "$this" + 1`
resume= resume=
fi fi
@ -420,10 +414,7 @@ do
stop_here_user_resolve $this stop_here_user_resolve $this
fi fi
apply_status=0 apply_status=0
if test -d "$GIT_DIR/rr-cache" git rerere
then
git rerere
fi
;; ;;
esac esac

View File

@ -610,10 +610,7 @@ rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
cd_to_toplevel cd_to_toplevel
if test -d "$GIT_DIR/rr-cache" git rerere
then
git rerere
fi
if test "$ret" = 0 if test "$ret" = 0
then then

View File

@ -496,9 +496,6 @@ Conflicts:
sed -e 's/^[^ ]* / /' | sed -e 's/^[^ ]* / /' |
uniq uniq
} >>"$GIT_DIR/MERGE_MSG" } >>"$GIT_DIR/MERGE_MSG"
if test -d "$GIT_DIR/rr-cache" git rerere
then
git rerere
fi
die "Automatic merge failed; fix conflicts and then commit the result." die "Automatic merge failed; fix conflicts and then commit the result."
fi fi

View File

@ -101,7 +101,7 @@ call_merge () {
return return
;; ;;
1) 1)
test -d "$GIT_DIR/rr-cache" && git rerere git rerere
die "$RESOLVEMSG" die "$RESOLVEMSG"
;; ;;
2) 2)
@ -160,10 +160,7 @@ do
--skip) --skip)
if test -d "$dotest" if test -d "$dotest"
then then
if test -d "$GIT_DIR/rr-cache" git rerere clear
then
git rerere clear
fi
prev_head="`cat $dotest/prev_head`" prev_head="`cat $dotest/prev_head`"
end="`cat $dotest/end`" end="`cat $dotest/end`"
msgnum="`cat $dotest/msgnum`" msgnum="`cat $dotest/msgnum`"
@ -181,10 +178,7 @@ do
exit exit
;; ;;
--abort) --abort)
if test -d "$GIT_DIR/rr-cache" git rerere clear
then
git rerere clear
fi
if test -d "$dotest" if test -d "$dotest"
then then
rm -r "$dotest" rm -r "$dotest"

View File

@ -39,15 +39,32 @@ sed -e 's/To die, t/To die! T/' > a1
echo "* END *" >>a1 echo "* END *" >>a1
git commit -q -a -m second git commit -q -a -m second
# activate rerere test_expect_success 'nothing recorded without rerere' '
mkdir .git/rr-cache (rm -rf .git/rr-cache; git config rerere.enabled false) &&
! git merge first &&
! test -d .git/rr-cache
'
test_expect_failure 'conflicting merge' 'git pull . first' # activate rerere, old style
test_expect_success 'conflicting merge' '
git reset --hard &&
mkdir .git/rr-cache &&
git config --unset rerere.enabled &&
! git merge first
'
sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR) sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR)
rr=.git/rr-cache/$sha1 rr=.git/rr-cache/$sha1
test_expect_success 'recorded preimage' "grep ======= $rr/preimage" test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
test_expect_success 'rerere.enabled works, too' '
rm -rf .git/rr-cache &&
git config rerere.enabled true &&
git reset --hard &&
! git merge first &&
grep ======= $rr/preimage
'
test_expect_success 'no postimage or thisimage yet' \ test_expect_success 'no postimage or thisimage yet' \
"test ! -f $rr/postimage -a ! -f $rr/thisimage" "test ! -f $rr/postimage -a ! -f $rr/thisimage"