rerere: do not record failed conflict resolution data
`rerere` can mark a conflict variant as resolved even when writing its
preimage or postimage fails. A later invocation may then replay
incomplete data from the cache, turning a local filesystem failure into
an incorrect working-tree change.
629716d256 (rerere: do use multiple variants, 2015-07-30) introduced
the code paths without checks for those I/O results. Treat such failures
as failures, report them, and leave the rerere status unchanged unless
the corresponding data was recorded successfully.
The defect has been latent since 2015. Git for Windows' Coverity run
only reported it after merging v2.56.0-rc0, for reasons that could not
be figured out in a reasonable amount of time.
Assisted-by: GPT-5.6 Luna
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
jch
parent
c3a6be2333
commit
742d8eb897
30
rerere.c
30
rerere.c
|
|
@ -476,8 +476,11 @@ static int handle_file(struct index_state *istate,
|
|||
unlink_or_warn(output);
|
||||
return error(_("could not parse conflict hunks in '%s'"), path);
|
||||
}
|
||||
if (io.io.wrerror)
|
||||
if (io.io.wrerror) {
|
||||
if (output)
|
||||
unlink_or_warn(output);
|
||||
return -1;
|
||||
}
|
||||
return has_conflicts;
|
||||
}
|
||||
|
||||
|
|
@ -729,8 +732,25 @@ static void do_rerere_one_path(struct index_state *istate,
|
|||
|
||||
/* Has the user resolved it already? */
|
||||
if (variant >= 0) {
|
||||
if (!handle_file(istate, path, NULL, NULL)) {
|
||||
copy_file(the_repository, rerere_path(&buf, id, "postimage"), path, 0666);
|
||||
int ret = handle_file(istate, path, NULL, NULL);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (!ret) {
|
||||
const int had_postimage =
|
||||
id->collection->status[variant] & RR_HAS_POSTIMAGE;
|
||||
const char *postimage =
|
||||
rerere_path(&buf, id, "postimage");
|
||||
|
||||
if (copy_file(the_repository,
|
||||
postimage,
|
||||
path, 0666)) {
|
||||
if (!had_postimage)
|
||||
unlink_or_warn(postimage);
|
||||
error_errno(_("could not copy resolution for '%s'"),
|
||||
path);
|
||||
goto out;
|
||||
}
|
||||
id->collection->status[variant] |= RR_HAS_POSTIMAGE;
|
||||
fprintf_ln(stderr, _("Recorded resolution for '%s'."), path);
|
||||
free_rerere_id(rr_item);
|
||||
|
|
@ -778,7 +798,9 @@ static void do_rerere_one_path(struct index_state *istate,
|
|||
assign_variant(id);
|
||||
|
||||
variant = id->variant;
|
||||
handle_file(istate, path, NULL, rerere_path(&buf, id, "preimage"));
|
||||
if (handle_file(istate, path, NULL,
|
||||
rerere_path(&buf, id, "preimage")) < 0)
|
||||
goto out;
|
||||
if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
|
||||
const char *path = rerere_path(&buf, id, "postimage");
|
||||
if (unlink(path))
|
||||
|
|
|
|||
Loading…
Reference in New Issue