1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-03-28 10:59:57 +01:00

Merge branch 'jk/log-cherry-pick-duplicate-patches' into next

When more than one commit with the same patch ID appears on one
side, "git log --cherry-pick A...B" did not exclude them all when a
commit with the same patch ID appears on the other side.  Now it
does.

* jk/log-cherry-pick-duplicate-patches:
  patch-ids: handle duplicate hashmap entries
This commit is contained in:
Junio C Hamano 2021-01-13 00:51:39 -08:00
commit abcfbf8603
4 changed files with 48 additions and 4 deletions

View File

@ -89,7 +89,7 @@ static int init_patch_id_entry(struct patch_id *patch,
return 0;
}
struct patch_id *has_commit_patch_id(struct commit *commit,
struct patch_id *patch_id_iter_first(struct commit *commit,
struct patch_ids *ids)
{
struct patch_id patch;
@ -104,6 +104,18 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
return hashmap_get_entry(&ids->patches, &patch, ent, NULL);
}
struct patch_id *patch_id_iter_next(struct patch_id *cur,
struct patch_ids *ids)
{
return hashmap_get_next_entry(&ids->patches, cur, ent);
}
int has_commit_patch_id(struct commit *commit,
struct patch_ids *ids)
{
return !!patch_id_iter_first(commit, ids);
}
struct patch_id *add_commit_patch_id(struct commit *commit,
struct patch_ids *ids)
{

View File

@ -23,7 +23,25 @@ int commit_patch_id(struct commit *commit, struct diff_options *options,
struct object_id *oid, int, int);
int init_patch_ids(struct repository *, struct patch_ids *);
int free_patch_ids(struct patch_ids *);
/* Add a patch_id for a single commit to the set. */
struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *);
struct patch_id *has_commit_patch_id(struct commit *, struct patch_ids *);
/* Returns true if the patch-id of "commit" is present in the set. */
int has_commit_patch_id(struct commit *commit, struct patch_ids *);
/*
* Iterate over all commits in the set whose patch id matches that of
* "commit", like:
*
* struct patch_id *cur;
* for (cur = patch_id_iter_first(commit, ids);
* cur;
* cur = patch_id_iter_next(cur, ids) {
* ... look at cur->commit
* }
*/
struct patch_id *patch_id_iter_first(struct commit *commit, struct patch_ids *);
struct patch_id *patch_id_iter_next(struct patch_id *cur, struct patch_ids *);
#endif /* PATCH_IDS_H */

View File

@ -1241,12 +1241,14 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
/*
* Have we seen the same patch id?
*/
id = has_commit_patch_id(commit, &ids);
id = patch_id_iter_first(commit, &ids);
if (!id)
continue;
commit->object.flags |= cherry_flag;
id->commit->object.flags |= cherry_flag;
do {
id->commit->object.flags |= cherry_flag;
} while ((id = patch_id_iter_next(id, &ids)));
}
free_patch_ids(&ids);

View File

@ -248,6 +248,18 @@ test_expect_success '--count --left-right' '
test_cmp expect actual
'
test_expect_success '--cherry-pick with duplicates on each side' '
git checkout -b dup-orig &&
test_commit dup-base &&
git revert dup-base &&
git cherry-pick dup-base &&
git checkout -b dup-side HEAD~3 &&
test_tick &&
git cherry-pick -3 dup-orig &&
git rev-list --cherry-pick dup-orig...dup-side >actual &&
test_must_be_empty actual
'
# Corrupt the object store deliberately to make sure
# the object is not even checked for its existence.
remove_loose_object () {