Skip to content

Commit 629716d

Browse files
committed
rerere: do use multiple variants
This enables the multiple-variant support for real. Multiple conflicts of the same shape can have differences in contexts where they appear, interfering the replaying of recorded resolution of one conflict to another, and in such a case, their resolutions are recorded as different variants under the same conflict ID. We still need to adjust garbage collection codepaths for this change, but the basic "replay" functionality is functional with this change. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 82efa6e commit 629716d

File tree

2 files changed

+61
-39
lines changed

2 files changed

+61
-39
lines changed

rerere.c

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ static void assign_variant(struct rerere_id *id)
7474

7575
variant = id->variant;
7676
if (variant < 0) {
77-
variant = 0; /* for now */
77+
for (variant = 0; variant < rr_dir->status_nr; variant++)
78+
if (!rr_dir->status[variant])
79+
break;
7880
}
7981
fit_variant(rr_dir, variant);
8082
id->variant = variant;
@@ -177,15 +179,6 @@ static int has_rerere_resolution(const struct rerere_id *id)
177179
return ((id->collection->status[variant] & both) == both);
178180
}
179181

180-
static int has_rerere_preimage(const struct rerere_id *id)
181-
{
182-
int variant = id->variant;
183-
184-
if (variant < 0)
185-
return 0;
186-
return (id->collection->status[variant] & RR_HAS_PREIMAGE);
187-
}
188-
189182
static struct rerere_id *new_rerere_id_hex(char *hex)
190183
{
191184
struct rerere_id *id = xmalloc(sizeof(*id));
@@ -818,6 +811,13 @@ static void update_paths(struct string_list *update)
818811
rollback_lock_file(&index_lock);
819812
}
820813

814+
static void remove_variant(struct rerere_id *id)
815+
{
816+
unlink_or_warn(rerere_path(id, "postimage"));
817+
unlink_or_warn(rerere_path(id, "preimage"));
818+
id->collection->status[id->variant] = 0;
819+
}
820+
821821
/*
822822
* The path indicated by rr_item may still have conflict for which we
823823
* have a recorded resolution, in which case replay it and optionally
@@ -830,49 +830,71 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
830830
{
831831
const char *path = rr_item->string;
832832
struct rerere_id *id = rr_item->util;
833+
struct rerere_dir *rr_dir = id->collection;
833834
int variant;
834835

835-
if (id->variant < 0)
836-
assign_variant(id);
837836
variant = id->variant;
838837

839-
if (!has_rerere_preimage(id)) {
838+
/* Has the user resolved it already? */
839+
if (variant >= 0) {
840+
if (!handle_file(path, NULL, NULL)) {
841+
copy_file(rerere_path(id, "postimage"), path, 0666);
842+
id->collection->status[variant] |= RR_HAS_POSTIMAGE;
843+
fprintf(stderr, "Recorded resolution for '%s'.\n", path);
844+
free_rerere_id(rr_item);
845+
rr_item->util = NULL;
846+
return;
847+
}
840848
/*
841-
* We are the first to encounter this conflict. Ask
842-
* handle_file() to write the normalized contents to
843-
* the "preimage" file.
849+
* There may be other variants that can cleanly
850+
* replay. Try them and update the variant number for
851+
* this one.
844852
*/
845-
handle_file(path, NULL, rerere_path(id, "preimage"));
846-
if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
847-
const char *path = rerere_path(id, "postimage");
848-
if (unlink(path))
849-
die_errno("cannot unlink stray '%s'", path);
850-
id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;
851-
}
852-
id->collection->status[variant] |= RR_HAS_PREIMAGE;
853-
fprintf(stderr, "Recorded preimage for '%s'\n", path);
854-
return;
855-
} else if (has_rerere_resolution(id)) {
856-
/* Is there a recorded resolution we could attempt to apply? */
857-
if (merge(id, path))
858-
return; /* failed to replay */
853+
}
854+
855+
/* Does any existing resolution apply cleanly? */
856+
for (variant = 0; variant < rr_dir->status_nr; variant++) {
857+
const int both = RR_HAS_PREIMAGE | RR_HAS_POSTIMAGE;
858+
struct rerere_id vid = *id;
859+
860+
if ((rr_dir->status[variant] & both) != both)
861+
continue;
862+
863+
vid.variant = variant;
864+
if (merge(&vid, path))
865+
continue; /* failed to replay */
866+
867+
/*
868+
* If there already is a different variant that applies
869+
* cleanly, there is no point maintaining our own variant.
870+
*/
871+
if (0 <= id->variant && id->variant != variant)
872+
remove_variant(id);
859873

860874
if (rerere_autoupdate)
861875
string_list_insert(update, path);
862876
else
863877
fprintf(stderr,
864878
"Resolved '%s' using previous resolution.\n",
865879
path);
866-
} else if (!handle_file(path, NULL, NULL)) {
867-
/* The user has resolved it. */
868-
copy_file(rerere_path(id, "postimage"), path, 0666);
869-
id->collection->status[variant] |= RR_HAS_POSTIMAGE;
870-
fprintf(stderr, "Recorded resolution for '%s'.\n", path);
871-
} else {
880+
free_rerere_id(rr_item);
881+
rr_item->util = NULL;
872882
return;
873883
}
874-
free_rerere_id(rr_item);
875-
rr_item->util = NULL;
884+
885+
/* None of the existing one applies; we need a new variant */
886+
assign_variant(id);
887+
888+
variant = id->variant;
889+
handle_file(path, NULL, rerere_path(id, "preimage"));
890+
if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
891+
const char *path = rerere_path(id, "postimage");
892+
if (unlink(path))
893+
die_errno("cannot unlink stray '%s'", path);
894+
id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;
895+
}
896+
id->collection->status[variant] |= RR_HAS_PREIMAGE;
897+
fprintf(stderr, "Recorded preimage for '%s'\n", path);
876898
}
877899

878900
static int do_plain_rerere(struct string_list *rr, int fd)

t/t4200-rerere.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ concat_insert () {
412412
cat early && printf "%s\n" "$@" && cat late "$last"
413413
}
414414

415-
test_expect_failure 'multiple identical conflicts' '
415+
test_expect_success 'multiple identical conflicts' '
416416
git reset --hard &&
417417
418418
test_seq 1 6 >early &&

0 commit comments

Comments
 (0)