diff options
author | Junio C Hamano <gitster@pobox.com> | 2009-04-04 23:04:50 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2009-04-04 23:04:50 -0700 |
commit | 5aaa507b067ca22324c34308cb56bcb64392a5db (patch) | |
tree | 7c06044a90a7eb892a1f28694460e3beb96275be /patch-ids.c | |
parent | 7428d754e2dec9e82253d1e02b4df20fab3f3384 (diff) | |
parent | 5289bae17f24805cc8507129e21d794b0b56264c (diff) | |
download | git-5aaa507b067ca22324c34308cb56bcb64392a5db.tar.gz |
Merge branch 'cc/sha1-bsearch' into HEAD
* cc/sha1-bsearch: (95 commits)
patch-ids: use the new generic "sha1_pos" function to lookup sha1
sha1-lookup: add new "sha1_pos" function to efficiently lookup sha1
Update draft release notes to 1.6.3
GIT 1.6.2.2
send-email: ensure quoted addresses are rfc2047 encoded
send-email: correct two tests which were going interactive
Documentation: git-svn: fix trunk/fetch svn-remote key typo
Mailmap: Allow empty email addresses to be mapped
Cleanup warning about known issues in cvsimport documentation
Documentation: Remove an odd "instead"
send-email: ask_default should apply to all emails, not just the first
send-email: don't attempt to prompt if tty is closed
fix portability problem with IS_RUN_COMMAND_ERR
Documentation: use "spurious .sp" XSLT if DOCBOOK_SUPPRESS_SP is set
mailmap: resurrect lower-casing of email addresses
builtin-clone.c: no need to strdup for setenv
builtin-clone.c: make junk_pid static
git-svn: add a double quiet option to hide git commits
Update draft release notes to 1.6.2.2
Documentation: push.default applies to all remotes
...
Diffstat (limited to 'patch-ids.c')
-rw-r--r-- | patch-ids.c | 93 |
1 files changed, 5 insertions, 88 deletions
diff --git a/patch-ids.c b/patch-ids.c index 3be5d3165e..5717257051 100644 --- a/patch-ids.c +++ b/patch-ids.c @@ -1,6 +1,7 @@ #include "cache.h" #include "diff.h" #include "commit.h" +#include "sha1-lookup.h" #include "patch-ids.h" static int commit_patch_id(struct commit *commit, struct diff_options *options, @@ -15,99 +16,15 @@ static int commit_patch_id(struct commit *commit, struct diff_options *options, return diff_flush_patch_id(options, sha1); } -static uint32_t take2(const unsigned char *id) +static const unsigned char *patch_id_access(size_t index, void *table) { - return ((id[0] << 8) | id[1]); + struct patch_id **id_table = table; + return id_table[index]->patch_id; } -/* - * Conventional binary search loop looks like this: - * - * do { - * int mi = (lo + hi) / 2; - * int cmp = "entry pointed at by mi" minus "target"; - * if (!cmp) - * return (mi is the wanted one) - * if (cmp > 0) - * hi = mi; "mi is larger than target" - * else - * lo = mi+1; "mi is smaller than target" - * } while (lo < hi); - * - * The invariants are: - * - * - When entering the loop, lo points at a slot that is never - * above the target (it could be at the target), hi points at a - * slot that is guaranteed to be above the target (it can never - * be at the target). - * - * - We find a point 'mi' between lo and hi (mi could be the same - * as lo, but never can be the same as hi), and check if it hits - * the target. There are three cases: - * - * - if it is a hit, we are happy. - * - * - if it is strictly higher than the target, we update hi with - * it. - * - * - if it is strictly lower than the target, we update lo to be - * one slot after it, because we allow lo to be at the target. - * - * When choosing 'mi', we do not have to take the "middle" but - * anywhere in between lo and hi, as long as lo <= mi < hi is - * satisfied. When we somehow know that the distance between the - * target and lo is much shorter than the target and hi, we could - * pick mi that is much closer to lo than the midway. - */ static int patch_pos(struct patch_id **table, int nr, const unsigned char *id) { - int hi = nr; - int lo = 0; - int mi = 0; - - if (!nr) - return -1; - - if (nr != 1) { - unsigned lov, hiv, miv, ofs; - - for (ofs = 0; ofs < 18; ofs += 2) { - lov = take2(table[0]->patch_id + ofs); - hiv = take2(table[nr-1]->patch_id + ofs); - miv = take2(id + ofs); - if (miv < lov) - return -1; - if (hiv < miv) - return -1 - nr; - if (lov != hiv) { - /* - * At this point miv could be equal - * to hiv (but id could still be higher); - * the invariant of (mi < hi) should be - * kept. - */ - mi = (nr-1) * (miv - lov) / (hiv - lov); - if (lo <= mi && mi < hi) - break; - die("oops"); - } - } - if (18 <= ofs) - die("cannot happen -- lo and hi are identical"); - } - - do { - int cmp; - cmp = hashcmp(table[mi]->patch_id, id); - if (!cmp) - return mi; - if (cmp > 0) - hi = mi; - else - lo = mi + 1; - mi = (hi + lo) / 2; - } while (lo < hi); - return -lo-1; + return sha1_pos(id, table, nr, patch_id_access); } #define BUCKET_SIZE 190 /* 190 * 21 = 3990, with slop close enough to 4K */ |