]>
Commit | Line | Data |
---|---|---|
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 |
9 | static 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 | 15 | int 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 | 40 | static 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 | 63 | int 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 | ||
74 | int 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 |
80 | static 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 | 94 | struct 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 |
109 | struct 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 | ||
115 | int 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 |
121 | struct 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 | } |