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

Junio C Hamano committed Jul 17, 2015 at 13:28 UTC 05dd9f139d6a7e4c7cd22d8d3b57faf5be88a571
2 files changed +41 -18
rerere.c
+25 -17
@@ -117,7 +117,9 @@ static struct rerere_dir *find_rerere_dir(const char *hex)
117
118 static int has_rerere_resolution(const struct rerere_id *id)
119 {
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);
123 }
124
125 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)
808 string_list_insert(rr, path)->util = id;
809
810 /*
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.
814 */
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? */
818
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 + }
835 }
836
837 for (i = 0; i < rr->nr; i++)
t/t4200-rerere.sh
+16 -1
@@ -184,12 +184,27 @@ test_expect_success 'rerere updates postimage timestamp' '
184 '
185
186 test_expect_success 'rerere clear' '
187 - rm $rr/postimage &&
187 + mv $rr/postimage .git/post-saved &&
188 echo "$sha1 a1" | perl -pe "y/\012/\000/" >.git/MERGE_RR &&
189 git rerere clear &&
190 ! test -d $rr
191 '
192
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 +
208 test_expect_success 'set up for garbage collection tests' '
209 mkdir -p $rr &&
210 echo Hello >$rr/preimage &&