810
810
It is illegal for the two weaves to contain different values
811
811
or different parents for any version. See also reweave().
813
:param other: The other weave to pull into this one
814
:param pb: An optional progress bar
815
:param msg: An optional message to display for progress
813
817
if other.numversions() == 0:
814
818
return # nothing to update, easy
815
819
# two loops so that we do not change ourselves before verifying it
817
821
# work through in index order to make sure we get all dependencies
818
824
for other_idx, name in enumerate(other._names):
819
825
self._check_version_consistent(other, other_idx, name)
826
sha1 = other._sha1s[other_idx]
830
if name in self._name_map:
831
idx = self.lookup(name)
832
n1 = set(map(other.idx_to_name, other._parents[other_idx]))
833
n2 = set(map(self.idx_to_name, self._parents[idx]))
834
if sha1 == self._sha1s[idx] and n1 == n2:
837
names_to_join.append((other_idx, name))
823
843
time0 = time.time( )
824
for other_idx, name in enumerate(other._names):
844
for other_idx, name in names_to_join:
825
845
# TODO: If all the parents of the other version are already
826
846
# present then we can avoid some work by just taking the delta
827
847
# and adjusting the offsets.
828
848
new_parents = self._imported_parents(other, other_idx)
829
849
sha1 = other._sha1s[other_idx]
854
pb.update(msg, merged, len(names_to_join))
833
if name in self._names:
834
idx = self.lookup(name)
835
n1 = map(other.idx_to_name, other._parents[other_idx] )
836
n2 = map(self.idx_to_name, self._parents[other_idx] )
837
if sha1 == self._sha1s[idx] and n1 == n2:
841
856
lines = other.get_lines(other_idx)
842
857
self.add(name, new_parents, lines, sha1)
844
859
mutter("merged = %d, processed = %d, file_id=%s; deltat=%d"%(
845
merged,processed,self._weave_name, time.time( )-time0))
860
merged, processed, self._weave_name, time.time( )-time0))
850
862
def _imported_parents(self, other, other_idx):
851
863
"""Return list of parents in self corresponding to indexes in other."""
880
892
self_parents = self._parents[this_idx]
881
893
other_parents = other._parents[other_idx]
882
n1 = [self._names[i] for i in self_parents]
883
n2 = [other._names[i] for i in other_parents]
894
n1 = set([self._names[i] for i in self_parents])
895
n2 = set([other._names[i] for i in other_parents])
887
897
raise WeaveParentMismatch("inconsistent parents "
888
898
"for version {%s}: %s vs %s" % (name, n1, n2))
894
def reweave(self, other):
895
"""Reweave self with other."""
896
new_weave = reweave(self, other)
904
def reweave(self, other, pb=None, msg=None):
905
"""Reweave self with other.
907
:param other: The other weave to merge
908
:param pb: An optional progress bar, indicating how far done we are
909
:param msg: An optional message for the progress
911
new_weave = reweave(self, other, pb=pb, msg=msg)
897
912
for attr in self.__slots__:
898
913
setattr(self, attr, getattr(new_weave, attr))
916
def reweave(wa, wb, pb=None, msg=None):
902
917
"""Combine two weaves and return the result.
904
919
This works even if a revision R has different parents in
920
938
mutter("combined parents: %r", combined_parents)
921
939
order = topo_sort(combined_parents.iteritems())
922
940
mutter("order to reweave: %r", order)
945
for idx, name in enumerate(order):
947
pb.update(msg, idx, len(order))
924
948
if name in wa._name_map:
925
949
lines = wa.get_lines(name)
926
950
if name in wb._name_map:
927
assert lines == wb.get_lines(name)
951
lines_b = wb.get_lines(name)
953
mutter('Weaves differ on content. rev_id {%s}', name)
954
mutter('weaves: %s, %s', wa._weave_name, wb._weave_name)
956
lines = list(difflib.unified_diff(lines, lines_b,
957
wa._weave_name, wb._weave_name))
958
mutter('lines:\n%s', ''.join(lines))
959
raise errors.WeaveTextDiffers(name, wa, wb)
929
961
lines = wb.get_lines(name)
930
962
wr.add(name, combined_parents[name], lines)