replay: allow callers to control what happens with empty commits
When replaying commits it may happen that some of the commits become empty relative to their parent. Such commits are for now automatically dropped by the replay subsystem without much control from the user. Introduce a new enum that allows the caller to drop, keep or abort in this case. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
94f057755b
commit
0cf4ad7cf5
29
replay.c
29
replay.c
|
|
@ -269,7 +269,8 @@ static struct commit *pick_regular_commit(struct repository *repo,
|
|||
struct commit *onto,
|
||||
struct merge_options *merge_opt,
|
||||
struct merge_result *result,
|
||||
enum replay_mode mode)
|
||||
enum replay_mode mode,
|
||||
enum replay_empty_commit_action empty)
|
||||
{
|
||||
struct commit *base, *replayed_base;
|
||||
struct tree *pickme_tree, *base_tree, *replayed_base_tree;
|
||||
|
|
@ -321,12 +322,25 @@ static struct commit *pick_regular_commit(struct repository *repo,
|
|||
}
|
||||
merge_opt->ancestor = NULL;
|
||||
merge_opt->branch2 = NULL;
|
||||
|
||||
if (!result->clean)
|
||||
return NULL;
|
||||
/* Drop commits that become empty */
|
||||
|
||||
/* Handle commits that become empty */
|
||||
if (oideq(&replayed_base_tree->object.oid, &result->tree->object.oid) &&
|
||||
!oideq(&pickme_tree->object.oid, &base_tree->object.oid))
|
||||
return replayed_base;
|
||||
!oideq(&pickme_tree->object.oid, &base_tree->object.oid)) {
|
||||
switch (empty) {
|
||||
case REPLAY_EMPTY_COMMIT_DROP:
|
||||
return replayed_base;
|
||||
case REPLAY_EMPTY_COMMIT_KEEP:
|
||||
break;
|
||||
case REPLAY_EMPTY_COMMIT_ABORT:
|
||||
result->clean = error(_("commit %s became empty after replay"),
|
||||
oid_to_hex(&pickme->object.oid));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return create_commit(repo, result->tree, pickme, replayed_base, mode);
|
||||
}
|
||||
|
||||
|
|
@ -417,7 +431,7 @@ int replay_revisions(struct rev_info *revs,
|
|||
|
||||
last_commit = pick_regular_commit(revs->repo, commit, replayed_commits,
|
||||
mode == REPLAY_MODE_REVERT ? last_commit : onto,
|
||||
&merge_opt, &result, mode);
|
||||
&merge_opt, &result, mode, opts->empty);
|
||||
if (!last_commit)
|
||||
break;
|
||||
|
||||
|
|
@ -458,6 +472,11 @@ int replay_revisions(struct rev_info *revs,
|
|||
}
|
||||
}
|
||||
|
||||
if (result.clean < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!result.clean) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
|
|
|
|||
19
replay.h
19
replay.h
|
|
@ -6,6 +6,19 @@
|
|||
struct repository;
|
||||
struct rev_info;
|
||||
|
||||
/*
|
||||
* Controls what happens when a replayed commit becomes empty (i.e. its tree
|
||||
* is identical to its parent's tree after the replay).
|
||||
*/
|
||||
enum replay_empty_commit_action {
|
||||
/* Silently discard the empty commit. */
|
||||
REPLAY_EMPTY_COMMIT_DROP,
|
||||
/* Keep the empty commit as-is. */
|
||||
REPLAY_EMPTY_COMMIT_KEEP,
|
||||
/* Abort with an error. */
|
||||
REPLAY_EMPTY_COMMIT_ABORT,
|
||||
};
|
||||
|
||||
/*
|
||||
* A set of options that can be passed to `replay_revisions()`.
|
||||
*/
|
||||
|
|
@ -43,6 +56,12 @@ struct replay_revisions_options {
|
|||
* Requires `onto` to be set.
|
||||
*/
|
||||
int contained;
|
||||
|
||||
/*
|
||||
* Controls what to do when a replayed commit becomes empty.
|
||||
* Defaults to REPLAY_EMPTY_COMMIT_DROP.
|
||||
*/
|
||||
enum replay_empty_commit_action empty;
|
||||
};
|
||||
|
||||
/* This struct is used as an out-parameter by `replay_revisions()`. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue