6 static int commit_patch_id(struct commit
*commit
, struct diff_options
*options
,
10 diff_tree_sha1(commit
->parents
->item
->object
.sha1
,
11 commit
->object
.sha1
, "", options
);
13 diff_root_tree_sha1(commit
->object
.sha1
, "", options
);
14 diffcore_std(options
);
15 return diff_flush_patch_id(options
, sha1
);
18 static uint32_t take2(const unsigned char *id
)
20 return ((id
[0] << 8) | id
[1]);
24 * Conventional binary search loop looks like this:
27 * int mi = (lo + hi) / 2;
28 * int cmp = "entry pointed at by mi" minus "target";
30 * return (mi is the wanted one)
32 * hi = mi; "mi is larger than target"
34 * lo = mi+1; "mi is smaller than target"
39 * - When entering the loop, lo points at a slot that is never
40 * above the target (it could be at the target), hi points at a
41 * slot that is guaranteed to be above the target (it can never
44 * - We find a point 'mi' between lo and hi (mi could be the same
45 * as lo, but never can be the same as hi), and check if it hits
46 * the target. There are three cases:
48 * - if it is a hit, we are happy.
50 * - if it is strictly higher than the target, we update hi with
53 * - if it is strictly lower than the target, we update lo to be
54 * one slot after it, because we allow lo to be at the target.
56 * When choosing 'mi', we do not have to take the "middle" but
57 * anywhere in between lo and hi, as long as lo <= mi < hi is
58 * satisfied. When we somehow know that the distance between the
59 * target and lo is much shorter than the target and hi, we could
60 * pick mi that is much closer to lo than the midway.
62 static int patch_pos(struct patch_id
**table
, int nr
, const unsigned char *id
)
72 unsigned lov
, hiv
, miv
, ofs
;
74 for (ofs
= 0; ofs
< 18; ofs
+= 2) {
75 lov
= take2(table
[0]->patch_id
+ ofs
);
76 hiv
= take2(table
[nr
-1]->patch_id
+ ofs
);
77 miv
= take2(id
+ ofs
);
84 * At this point miv could be equal
85 * to hiv (but id could still be higher);
86 * the invariant of (mi < hi) should be
89 mi
= (nr
-1) * (miv
- lov
) / (hiv
- lov
);
90 if (lo
<= mi
&& mi
< hi
)
96 die("cannot happen -- lo and hi are identical");
101 cmp
= hashcmp(table
[mi
]->patch_id
, id
);
113 #define BUCKET_SIZE 190 /* 190 * 21 = 3990, with slop close enough to 4K */
114 struct patch_id_bucket
{
115 struct patch_id_bucket
*next
;
117 struct patch_id bucket
[BUCKET_SIZE
];
120 int init_patch_ids(struct patch_ids
*ids
)
122 memset(ids
, 0, sizeof(*ids
));
123 diff_setup(&ids
->diffopts
);
124 ids
->diffopts
.recursive
= 1;
125 if (diff_setup_done(&ids
->diffopts
) < 0)
126 return error("diff_setup_done failed");
130 int free_patch_ids(struct patch_ids
*ids
)
132 struct patch_id_bucket
*next
, *patches
;
135 for (patches
= ids
->patches
; patches
; patches
= next
) {
136 next
= patches
->next
;
142 static struct patch_id
*add_commit(struct commit
*commit
,
143 struct patch_ids
*ids
,
146 struct patch_id_bucket
*bucket
;
147 struct patch_id
*ent
;
148 unsigned char sha1
[20];
151 if (commit_patch_id(commit
, &ids
->diffopts
, sha1
))
153 pos
= patch_pos(ids
->table
, ids
->nr
, sha1
);
155 return ids
->table
[pos
];
161 bucket
= ids
->patches
;
162 if (!bucket
|| (BUCKET_SIZE
<= bucket
->nr
)) {
163 bucket
= xcalloc(1, sizeof(*bucket
));
164 bucket
->next
= ids
->patches
;
165 ids
->patches
= bucket
;
167 ent
= &bucket
->bucket
[bucket
->nr
++];
168 hashcpy(ent
->patch_id
, sha1
);
170 if (ids
->alloc
<= ids
->nr
) {
171 ids
->alloc
= alloc_nr(ids
->nr
);
172 ids
->table
= xrealloc(ids
->table
, sizeof(ent
) * ids
->alloc
);
175 memmove(ids
->table
+ pos
+ 1, ids
->table
+ pos
,
176 sizeof(ent
) * (ids
->nr
- pos
));
178 ids
->table
[pos
] = ent
;
179 return ids
->table
[pos
];
182 struct patch_id
*has_commit_patch_id(struct commit
*commit
,
183 struct patch_ids
*ids
)
185 return add_commit(commit
, ids
, 1);
188 struct patch_id
*add_commit_patch_id(struct commit
*commit
,
189 struct patch_ids
*ids
)
191 return add_commit(commit
, ids
, 0);