##// END OF EJS Templates
copy: add flag for disabling copy tracing...
copy: add flag for disabling copy tracing Copy tracing can be up to 80% of rebase time when rebasing stacks of commits in large repos (hundreds of thousands of files). This provides the option of turning off the majority of copy tracing. It does not turn off _forwardcopies() since that is used to carry copy information inside a commit across a rebase. This will affect the situation where a user edits a file, then rebases on top of commits that have moved that file. The move will not be detected and the user will have to manually resolve the issue (possibly by redoing the rebase with this flag off). The reason to have a flag instead of trying to fix the actual copy tracing performance is that copy tracing is fundamentally an O(number of files in the repo) operation. In order to know if file X in the rebase source was copied anywhere, we have to walk the filelog for every new file that exists in the rebase destination (i.e. a file in the destination that is not in the common ancestor). Without an index that lets us trace forward (i.e. from file Y in the common ancestor forward to the rebase destination), it will never be an O(number of changes in my branch) operation. In mozilla-central, rebasing a 3 commit stack across 20,000 revs goes from 39s to 11s.

File last commit:

r15530:eeac5e17 default
r26013:38f92d12 default
Show More
bdiff.py
87 lines | 2.3 KiB | text/x-python | PythonLexer
Martin Geisler
pure Python implementation of bdiff.c
r7703 # bdiff.py - Python implementation of bdiff.c
#
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Martin Geisler
pure Python implementation of bdiff.c
r7703
Patrick Mezard
mdiff: replace wscleanup() regexps with C loops...
r15530 import struct, difflib, re
Matt Mackall
pure/bdiff: fix circular import
r7944
def splitnewlines(text):
'''like str.splitlines, but only split on newlines.'''
lines = [l + '\n' for l in text.split('\n')]
if lines:
if lines[-1] == '\n':
lines.pop()
else:
lines[-1] = lines[-1][:-1]
return lines
Martin Geisler
pure Python implementation of bdiff.c
r7703
def _normalizeblocks(a, b, blocks):
prev = None
Dan Villiom Podlaski Christiansen
pure bdiff: don't use a generator...
r14066 r = []
Martin Geisler
pure Python implementation of bdiff.c
r7703 for curr in blocks:
if prev is None:
prev = curr
continue
shift = 0
a1, b1, l1 = prev
a1end = a1 + l1
b1end = b1 + l1
a2, b2, l2 = curr
a2end = a2 + l2
b2end = b2 + l2
if a1end == a2:
Matt Mackall
many, many trivial check-code fixups
r10282 while (a1end + shift < a2end and
a[a1end + shift] == b[b1end + shift]):
Martin Geisler
pure Python implementation of bdiff.c
r7703 shift += 1
elif b1end == b2:
Matt Mackall
many, many trivial check-code fixups
r10282 while (b1end + shift < b2end and
a[a1end + shift] == b[b1end + shift]):
Martin Geisler
pure Python implementation of bdiff.c
r7703 shift += 1
Dan Villiom Podlaski Christiansen
pure bdiff: don't use a generator...
r14066 r.append((a1, b1, l1 + shift))
Matt Mackall
many, many trivial check-code fixups
r10282 prev = a2 + shift, b2 + shift, l2 - shift
Dan Villiom Podlaski Christiansen
pure bdiff: don't use a generator...
r14066 r.append(prev)
return r
Martin Geisler
pure Python implementation of bdiff.c
r7703
def bdiff(a, b):
a = str(a).splitlines(True)
b = str(b).splitlines(True)
if not a:
s = "".join(b)
return s and (struct.pack(">lll", 0, 0, len(s)) + s)
bin = []
p = [0]
for i in a: p.append(p[-1] + len(i))
d = difflib.SequenceMatcher(None, a, b).get_matching_blocks()
d = _normalizeblocks(a, b, d)
la = 0
lb = 0
for am, bm, size in d:
s = "".join(b[lb:bm])
if am > la or s:
bin.append(struct.pack(">lll", p[la], p[am], len(s)) + s)
la = am + size
lb = bm + size
return "".join(bin)
def blocks(a, b):
Matt Mackall
pure/bdiff: fix circular import
r7944 an = splitnewlines(a)
bn = splitnewlines(b)
Martin Geisler
pure Python implementation of bdiff.c
r7703 d = difflib.SequenceMatcher(None, an, bn).get_matching_blocks()
d = _normalizeblocks(an, bn, d)
return [(i, i + n, j, j + n) for (i, j, n) in d]
Patrick Mezard
mdiff: replace wscleanup() regexps with C loops...
r15530 def fixws(text, allws):
if allws:
text = re.sub('[ \t\r]+', '', text)
else:
text = re.sub('[ \t\r]+', ' ', text)
text = text.replace(' \n', '\n')
return text