Skip to content

Commit

Permalink
Merge branch 'jk/log-cherry-pick-duplicate-patches'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed Jan 25, 2021
2 parents 27d7c85 + c9e3a4e commit b69bed2
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
14 changes: 13 additions & 1 deletion patch-ids.c
Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down
20 changes: 19 additions & 1 deletion patch-ids.h
Expand Up @@ -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 */
6 changes: 4 additions & 2 deletions revision.c
Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions t/t6007-rev-list-cherry-pick-file.sh
Expand Up @@ -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 () {
Expand Down

0 comments on commit b69bed2

Please sign in to comment.