]> git.ipfire.org Git - thirdparty/git.git/blame - patch-ids.c
Merge branch 'so/diff-doc-for-patch-update' into maint-2.42
[thirdparty/git.git] / patch-ids.c
CommitLineData
4f6728d5 1#include "git-compat-util.h"
5d23e133
JH
2#include "diff.h"
3#include "commit.h"
df6e8744 4#include "hash.h"
bc626927 5#include "hash-lookup.h"
41771fa4 6#include "hex.h"
5d23e133
JH
7#include "patch-ids.h"
8
7c810407
JK
9static int patch_id_defined(struct commit *commit)
10{
11 /* must be 0 or 1 parents */
12 return !commit->parents || !commit->parents->next;
13}
14
ded2c097 15int commit_patch_id(struct commit *commit, struct diff_options *options,
51276c18 16 struct object_id *oid, int diff_header_only)
5d23e133 17{
7c810407
JK
18 if (!patch_id_defined(commit))
19 return -1;
20
5d23e133 21 if (commit->parents)
66f414f8
BW
22 diff_tree_oid(&commit->parents->item->object.oid,
23 &commit->object.oid, "", options);
5d23e133 24 else
7b8dea0c 25 diff_root_tree_oid(&commit->object.oid, "", options);
5d23e133 26 diffcore_std(options);
51276c18 27 return diff_flush_patch_id(options, oid, diff_header_only);
5d23e133
JH
28}
29
b3dfeebb
KW
30/*
31 * When we cannot load the full patch-id for both commits for whatever
32 * reason, the function returns -1 (i.e. return error(...)). Despite
cc00e5ce 33 * the "neq" in the name of this function, the caller only cares about
b3dfeebb
KW
34 * the return value being zero (a and b are equivalent) or non-zero (a
35 * and b are different), and returning non-zero would keep both in the
36 * result, even if they actually were equivalent, in order to err on
37 * the side of safety. The actual value being negative does not have
38 * any significance; only that it is non-zero matters.
39 */
cc00e5ce 40static int patch_id_neq(const void *cmpfn_data,
939af16e
EW
41 const struct hashmap_entry *eptr,
42 const struct hashmap_entry *entry_or_key,
5cf88fd8 43 const void *keydata UNUSED)
5d23e133 44{
8d0017da
SB
45 /* NEEDSWORK: const correctness? */
46 struct diff_options *opt = (void *)cmpfn_data;
939af16e
EW
47 struct patch_id *a, *b;
48
49 a = container_of(eptr, struct patch_id, ent);
50 b = container_of(entry_or_key, struct patch_id, ent);
8d0017da 51
34f3c0eb 52 if (is_null_oid(&a->patch_id) &&
51276c18 53 commit_patch_id(a->commit, opt, &a->patch_id, 0))
b3dfeebb
KW
54 return error("Could not get patch ID for %s",
55 oid_to_hex(&a->commit->object.oid));
34f3c0eb 56 if (is_null_oid(&b->patch_id) &&
51276c18 57 commit_patch_id(b->commit, opt, &b->patch_id, 0))
b3dfeebb
KW
58 return error("Could not get patch ID for %s",
59 oid_to_hex(&b->commit->object.oid));
cc00e5ce 60 return !oideq(&a->patch_id, &b->patch_id);
5d23e133
JH
61}
62
a7edadda 63int init_patch_ids(struct repository *r, struct patch_ids *ids)
5d23e133
JH
64{
65 memset(ids, 0, sizeof(*ids));
a7edadda 66 repo_diff_setup(r, &ids->diffopts);
5a29cbc6 67 ids->diffopts.detect_rename = 0;
0d1e0e78 68 ids->diffopts.flags.recursive = 1;
28452655 69 diff_setup_done(&ids->diffopts);
cc00e5ce 70 hashmap_init(&ids->patches, patch_id_neq, &ids->diffopts, 256);
5d23e133
JH
71 return 0;
72}
73
74int free_patch_ids(struct patch_ids *ids)
75{
6da1a258 76 hashmap_clear_and_free(&ids->patches, struct patch_id, ent);
5d23e133
JH
77 return 0;
78}
79
dfb7a1b4
KW
80static int init_patch_id_entry(struct patch_id *patch,
81 struct commit *commit,
82 struct patch_ids *ids)
5d23e133 83{
34f3c0eb 84 struct object_id header_only_patch_id;
b3dfeebb 85
683f17ec 86 patch->commit = commit;
51276c18 87 if (commit_patch_id(commit, &ids->diffopts, &header_only_patch_id, 1))
dfb7a1b4 88 return -1;
5d23e133 89
d22245a2 90 hashmap_entry_init(&patch->ent, oidhash(&header_only_patch_id));
dfb7a1b4 91 return 0;
5d23e133
JH
92}
93
c9e3a4e7 94struct patch_id *patch_id_iter_first(struct commit *commit,
5d23e133
JH
95 struct patch_ids *ids)
96{
dfb7a1b4
KW
97 struct patch_id patch;
98
7c810407
JK
99 if (!patch_id_defined(commit))
100 return NULL;
101
dfb7a1b4
KW
102 memset(&patch, 0, sizeof(patch));
103 if (init_patch_id_entry(&patch, commit, ids))
104 return NULL;
105
404ab78e 106 return hashmap_get_entry(&ids->patches, &patch, ent, NULL);
5d23e133
JH
107}
108
c9e3a4e7
JK
109struct patch_id *patch_id_iter_next(struct patch_id *cur,
110 struct patch_ids *ids)
111{
112 return hashmap_get_next_entry(&ids->patches, cur, ent);
113}
114
115int has_commit_patch_id(struct commit *commit,
116 struct patch_ids *ids)
117{
118 return !!patch_id_iter_first(commit, ids);
119}
120
5d23e133
JH
121struct patch_id *add_commit_patch_id(struct commit *commit,
122 struct patch_ids *ids)
123{
5748693b 124 struct patch_id *key;
dfb7a1b4 125
7c810407
JK
126 if (!patch_id_defined(commit))
127 return NULL;
128
ca56dadb 129 CALLOC_ARRAY(key, 1);
dfb7a1b4
KW
130 if (init_patch_id_entry(key, commit, ids)) {
131 free(key);
132 return NULL;
133 }
134
b94e5c1d 135 hashmap_add(&ids->patches, &key->ent);
dfb7a1b4 136 return key;
5d23e133 137}