diff --git a/mercurial/thirdparty/xdiff/xprepare.c b/mercurial/thirdparty/xdiff/xprepare.c --- a/mercurial/thirdparty/xdiff/xprepare.c +++ b/mercurial/thirdparty/xdiff/xprepare.c @@ -62,6 +62,7 @@ static int xdl_clean_mmatch(char const *dis, long i, long s, long e); static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2); static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2); +static long xdl_trim_reserved_lines(xdfile_t *xdf1, xdfile_t *xdf2); @@ -234,13 +235,24 @@ * unique. This makes future calculation faster - they can just compare "ha" * instead of comparing line content. */ -static int xdl_prepare_hashtable(unsigned int pass, mmfile_t *mf, - xpparam_t const *xpp, xdlclassifier_t *cf, xdfile_t *xdf) { +static int xdl_prepare_hashtable(unsigned int pass, long reserved, mmfile_t + *mf, xpparam_t const *xpp, xdlclassifier_t *cf, xdfile_t *xdf) +{ xrecord_t **rhash = NULL; - long nrec = xdf->nrec; + long nrec; + unsigned int hbits; long hsize; long i; + long start = xdf->dstart - reserved; + long end = xdf->dend + reserved; + + if (start < 0) + start = 0; + if (end >= xdf->nrec) + end = xdf->nrec - 1; + + nrec = end - start; hbits = xdl_hashbits((unsigned int) nrec); hsize = 1 << hbits; @@ -248,7 +260,7 @@ goto abort; memset(rhash, 0, hsize * sizeof(xrecord_t *)); - for (i = 0; i < nrec; ++i) { + for (i = start; i <= end; i++) { if (xdl_classify_record(pass, cf, rhash, hbits, xdf->recs[i]) < 0) goto abort; } @@ -275,7 +287,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdfenv_t *xe) { - long enl1, enl2, sample; + long enl1, enl2, sample, reserved; xdlclassifier_t cf; memset(&cf, 0, sizeof(cf)); @@ -307,13 +319,14 @@ return -1; } - if (xdl_prepare_hashtable(1, mf1, xpp, &cf, &xe->xdf1) < 0) { + reserved = xdl_trim_reserved_lines(&xe->xdf1, &xe->xdf2); + if (xdl_prepare_hashtable(1, reserved, mf1, xpp, &cf, &xe->xdf1) < 0) { xdl_free_ctx(&xe->xdf1); xdl_free_ctx(&xe->xdf2); xdl_free_classifier(&cf); return -1; } - if (xdl_prepare_hashtable(2, mf2, xpp, &cf, &xe->xdf2) < 0) { + if (xdl_prepare_hashtable(2, reserved, mf2, xpp, &cf, &xe->xdf2) < 0) { xdl_free_ctx(&xe->xdf1); xdl_free_ctx(&xe->xdf2); xdl_free_classifier(&cf); @@ -462,7 +475,6 @@ return 0; } - /* * Early trim initial and terminal matching records. */ @@ -500,3 +512,22 @@ return 0; } + + +/* + * Return "reserved lines" for possible hunk shifting. Normally, only look at + * lines in dstart..dend range. But hunk shifting also needs accurate line + * hashes. Estimated hunk size and reserve lines for shifting purpose. + * + * This would be used by xdl_prepare_hashtable, to build accurate hash values. + */ +static long xdl_trim_reserved_lines(xdfile_t *xdf1, xdfile_t *xdf2) { + long lines = 0; + if (xdf1->dend > xdf1->dstart) + lines += xdf1->dend - xdf1->dstart; + if (xdf2->dend > xdf2->dstart) + lines += xdf2->dend - xdf2->dstart; + return lines; +} + +