Skip to content

Commit 05dd9f1

Browse files
committed
rerere: handle leftover rr-cache/$ID directory and postimage files
If by some accident there is only $GIT_DIR/rr-cache/$ID directory existed, we wouldn't have recorded a preimage for a conflict that is newly encountered, which would mean after a manual resolution, we wouldn't have recorded it by storing the postimage, because the logic used to be "if there is no rr-cache/$ID directory, then we are the first so record the preimage". Instead, record preimage if we do not have one. In addition, if there is only $GIT_DIR/rr-cache/$ID/postimage without corresponding preimage, we would have tried to call into merge() and punted. These would have been a situation frustratingly hard to recover from. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2c7929b commit 05dd9f1

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

rerere.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
117117

118118
static int has_rerere_resolution(const struct rerere_id *id)
119119
{
120-
return (id->collection->status & RR_HAS_POSTIMAGE);
120+
const int both = RR_HAS_POSTIMAGE|RR_HAS_PREIMAGE;
121+
122+
return ((id->collection->status & both) == both);
121123
}
122124

123125
static struct rerere_id *new_rerere_id_hex(char *hex)
@@ -806,24 +808,30 @@ static int do_plain_rerere(struct string_list *rr, int fd)
806808
string_list_insert(rr, path)->util = id;
807809

808810
/*
809-
* If the directory does not exist, create
810-
* it. mkdir_in_gitdir() will fail with
811-
* EEXIST if there already is one.
812-
*
813-
* NEEDSWORK: make sure "gc" does not remove
814-
* preimage without removing the directory.
811+
* Ensure that the directory exists.
812+
* mkdir_in_gitdir() will fail with EEXIST if there
813+
* already is one.
815814
*/
816-
if (mkdir_in_gitdir(rerere_path(id, NULL)))
817-
continue;
815+
if (mkdir_in_gitdir(rerere_path(id, NULL)) &&
816+
errno != EEXIST)
817+
continue; /* NEEDSWORK: perhaps we should die? */
818818

819-
/*
820-
* We are the first to encounter this
821-
* conflict. Ask handle_file() to write the
822-
* normalized contents to the "preimage" file.
823-
*/
824-
handle_file(path, NULL, rerere_path(id, "preimage"));
825-
id->collection->status |= RR_HAS_PREIMAGE;
826-
fprintf(stderr, "Recorded preimage for '%s'\n", path);
819+
if (id->collection->status & RR_HAS_PREIMAGE) {
820+
;
821+
} else {
822+
/*
823+
* We are the first to encounter this
824+
* conflict. Ask handle_file() to write the
825+
* normalized contents to the "preimage" file.
826+
*
827+
* NEEDSWORK: what should happen if we had a
828+
* leftover postimage that is totally
829+
* unrelated? Perhaps we should unlink it?
830+
*/
831+
handle_file(path, NULL, rerere_path(id, "preimage"));
832+
id->collection->status |= RR_HAS_PREIMAGE;
833+
fprintf(stderr, "Recorded preimage for '%s'\n", path);
834+
}
827835
}
828836

829837
for (i = 0; i < rr->nr; i++)

t/t4200-rerere.sh

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,27 @@ test_expect_success 'rerere updates postimage timestamp' '
184184
'
185185

186186
test_expect_success 'rerere clear' '
187-
rm $rr/postimage &&
187+
mv $rr/postimage .git/post-saved &&
188188
echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR &&
189189
git rerere clear &&
190190
! test -d $rr
191191
'
192192

193+
test_expect_success 'leftover directory' '
194+
git reset --hard &&
195+
mkdir -p $rr &&
196+
test_must_fail git merge first &&
197+
test -f $rr/preimage
198+
'
199+
200+
test_expect_success 'missing preimage' '
201+
git reset --hard &&
202+
mkdir -p $rr &&
203+
cp .git/post-saved $rr/postimage &&
204+
test_must_fail git merge first &&
205+
test -f $rr/preimage
206+
'
207+
193208
test_expect_success 'set up for garbage collection tests' '
194209
mkdir -p $rr &&
195210
echo Hello >$rr/preimage &&

0 commit comments

Comments
 (0)