[Pkg-bazaar-commits] ./bzr/unstable r918: - start doing new weave-merge algorithm
Martin Pool
mbp at sourcefrog.net
Fri Apr 10 08:21:27 UTC 2009
------------------------------------------------------------
revno: 918
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Thu 2005-07-14 01:03:52 -0700
message:
- start doing new weave-merge algorithm
modified:
bzrlib/weave.py
-------------- next part --------------
=== modified file 'bzrlib/weave.py'
--- a/bzrlib/weave.py 2005-07-11 23:09:49 +0000
+++ b/bzrlib/weave.py 2005-07-14 08:03:52 +0000
@@ -44,6 +44,17 @@
# properly nested, that there is no text outside of an insertion, that
# insertions or deletions are not repeated, etc.
+# TODO: Make the info command just show info, not extract everything:
+# it can be much faster.
+
+# TODO: Perhaps use long integers as sets instead of set objects; may
+# be faster.
+
+# TODO: Parallel-extract that passes back each line along with a
+# description of which revisions include it. Nice for checking all
+# shas in parallel.
+
+
try:
@@ -178,6 +189,10 @@
sha1 = s.hexdigest()
del s
+ # TODO: It'd probably be faster to append things on to a new
+ # list rather than modifying the existing one, which is likely
+ # to cause a lot of copying.
+
if parents:
ancestors = self.inclusions(parents)
delta = self._delta(ancestors, text)
@@ -225,6 +240,20 @@
return idx
+ def inclusions_bitset(self, versions):
+ i = 0
+ for v in versions:
+ i |= (1L << v)
+ v = max(versions)
+ while v >= 0:
+ if i & (1L << v):
+ # if v is included, include all its parents
+ for pv in self._v[v]:
+ i |= (1L << pv)
+ v -= 1
+ return i
+
+
def inclusions(self, versions):
"""Return set of all ancestors of given version(s)."""
i = set(versions)
@@ -301,6 +330,46 @@
yield origin, text
+ def _walk(self):
+ """Walk the weave.
+
+ Yields sequence of
+ (lineno, insert, deletes, text)
+ for each literal line.
+ """
+
+ istack = []
+ dset = 0L
+
+ lineno = 0 # line of weave, 0-based
+
+ for l in self._l:
+ if isinstance(l, tuple):
+ c, v = l
+ isactive = None
+ if c == '{':
+ istack.append(v)
+ elif c == '}':
+ oldv = istack.pop()
+ elif c == '[':
+ vs = (1L << v)
+ assert not (dset & vs)
+ dset |= vs
+ elif c == ']':
+ vs = (1L << v)
+ assert dset & vs
+ dset ^= vs
+ else:
+ raise WeaveFormatError('unexpected instruction %r'
+ % v)
+ else:
+ assert isinstance(l, basestring)
+ assert istack
+ yield lineno, istack[-1], dset, l
+ lineno += 1
+
+
+
def _extract(self, versions):
"""Yield annotation of lines in included set.
@@ -494,6 +563,55 @@
yield real_i1, real_i2, lines[j1:j2]
+
+ def plan_merge(self, ver_a, ver_b):
+ """Return pseudo-annotation indicating how the two versions merge.
+
+ This is computed between versions a and b and their common
+ base.
+
+ Weave lines present in none of them are skipped entirely.
+ """
+ inc_a = self.inclusions_bitset([ver_a])
+ inc_b = self.inclusions_bitset([ver_b])
+ inc_c = inc_a & inc_b
+
+ for lineno, insert, deleteset, line in self._walk():
+ insertset = (1L << insert)
+ if deleteset & inc_c:
+ # killed in parent; can't be in either a or b
+ # not relevant to our work
+ yield 'killed-base', line
+ elif insertset & inc_c:
+ # was inserted in base
+ killed_a = bool(deleteset & inc_a)
+ killed_b = bool(deleteset & inc_b)
+ if killed_a and killed_b:
+ # killed in both
+ yield 'killed-both', line
+ elif killed_a:
+ yield 'killed-a', line
+ elif killed_b:
+ yield 'killed-b', line
+ else:
+ yield 'unchanged', line
+ elif insertset & inc_a:
+ if deleteset & inc_a:
+ yield 'ghost-a', line
+ else:
+ # new in A; not in B
+ yield 'new-a', line
+ elif insertset & inc_b:
+ if deleteset & inc_b:
+ yield 'ghost-b', line
+ else:
+ yield 'new-b', line
+ else:
+ # not in either revision
+ yield 'irrelevant', line
+
+
+
def weave_info(filename, out):
"""Show some text information about the weave."""
@@ -642,6 +760,11 @@
w = readit()
print ' '.join(map(str, w._v[int(argv[3])]))
+ elif cmd == 'plan-merge':
+ w = readit()
+ for state, line in w.plan_merge(int(argv[3]), int(argv[4])):
+ print '%14s | %s' % (state, line),
+
elif cmd == 'merge':
if len(argv) != 5:
usage()
More information about the Pkg-bazaar-commits
mailing list