diff -r ab798d1a230f -r 1cbf144fd8a1 mercurial/manifest.py --- a/mercurial/manifest.py Wed Nov 04 23:44:51 2015 -0800 +++ b/mercurial/manifest.py Thu Nov 05 18:56:40 2015 -0800 @@ -334,36 +334,44 @@ # zero copy representation of base as a buffer addbuf = util.buffer(base) - # start with a readonly loop that finds the offset of - # each line and creates the deltas - for f, todelete in changes: - # bs will either be the index of the item or the insert point - start, end = _msearch(addbuf, f, start) - if not todelete: - h, fl = self._lm[f] - l = "%s\0%s%s\n" % (f, revlog.hex(h), fl) - else: - if start == end: - # item we want to delete was not found, error out - raise AssertionError( - _("failed to remove %s from manifest") % f) - l = "" - if dstart is not None and dstart <= start and dend >= start: - if dend < end: + changes = list(changes) + if len(changes) < 1000: + # start with a readonly loop that finds the offset of + # each line and creates the deltas + for f, todelete in changes: + # bs will either be the index of the item or the insert point + start, end = _msearch(addbuf, f, start) + if not todelete: + h, fl = self._lm[f] + l = "%s\0%s%s\n" % (f, revlog.hex(h), fl) + else: + if start == end: + # item we want to delete was not found, error out + raise AssertionError( + _("failed to remove %s from manifest") % f) + l = "" + if dstart is not None and dstart <= start and dend >= start: + if dend < end: + dend = end + if l: + dline.append(l) + else: + if dstart is not None: + delta.append([dstart, dend, "".join(dline)]) + dstart = start dend = end - if l: - dline.append(l) - else: - if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) - dstart = start - dend = end - dline = [l] + dline = [l] - if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) - # apply the delta to the base, and get a delta for addrevision - deltatext, arraytext = _addlistdelta(base, delta) + if dstart is not None: + delta.append([dstart, dend, "".join(dline)]) + # apply the delta to the base, and get a delta for addrevision + deltatext, arraytext = _addlistdelta(base, delta) + else: + # For large changes, it's much cheaper to just build the text and + # diff it. + arraytext = array.array('c', self.text()) + deltatext = mdiff.textdiff(base, arraytext) + return arraytext, deltatext def _msearch(m, s, lo=0, hi=None):