20
20
from bzrlib.trace import mutter
22
Represent and apply a changeset
22
# XXX: mbp: I'm not totally convinced that we should handle conflicts
23
# as part of changeset application, rather than only in the merge
26
"""Represent and apply a changeset
28
Conflicts in applying a changeset are represented as exceptions.
24
31
__docformat__ = "restructuredtext"
1030
1037
class ExceptionConflictHandler(object):
1038
"""Default handler for merge exceptions.
1040
This throws an error on any kind of conflict. Conflict handlers can
1041
descend from this class if they have a better way to handle some or
1042
all types of conflict.
1031
1044
def __init__(self, dir):
1382
1395
parent = inventory[dirname]
1383
1396
return parent.id
1385
def get_paths(self, entry, tree):
1398
def get_path(self, entry, tree):
1386
1399
if entry is None:
1387
1400
return (None, None)
1388
full_path = tree.readonly_path(entry.id)
1389
1401
if entry.path == ".":
1390
return ("", full_path)
1391
return (entry.path, full_path)
1393
1405
def make_basic_entry(self, id, only_interesting):
1394
1406
entry_a = self.r_inventory_a.get(id)
1395
1407
entry_b = self.r_inventory_b.get(id)
1396
1408
if only_interesting and not self.is_interesting(entry_a, entry_b):
1397
return (None, None, None)
1398
1410
parent = self.get_entry_parent(entry_a, self.inventory_a)
1399
(path, full_path_a) = self.get_paths(entry_a, self.tree_a)
1411
path = self.get_path(entry_a, self.tree_a)
1400
1412
cs_entry = ChangesetEntry(id, parent, path)
1401
1413
new_parent = self.get_entry_parent(entry_b, self.inventory_b)
1404
(new_path, full_path_b) = self.get_paths(entry_b, self.tree_b)
1416
new_path = self.get_path(entry_b, self.tree_b)
1406
1418
cs_entry.new_path = new_path
1407
1419
cs_entry.new_parent = new_parent
1408
return (cs_entry, full_path_a, full_path_b)
1410
1422
def is_interesting(self, entry_a, entry_b):
1411
1423
if entry_a is not None:
1419
1431
def make_boring_entry(self, id):
1420
(cs_entry, full_path_a, full_path_b) = \
1421
self.make_basic_entry(id, only_interesting=False)
1432
cs_entry = self.make_basic_entry(id, only_interesting=False)
1422
1433
if cs_entry.is_creation_or_deletion():
1423
1434
return self.make_entry(id, only_interesting=False)
1428
1439
def make_entry(self, id, only_interesting=True):
1429
(cs_entry, full_path_a, full_path_b) = \
1430
self.make_basic_entry(id, only_interesting)
1440
cs_entry = self.make_basic_entry(id, only_interesting)
1432
1442
if cs_entry is None:
1444
if id in self.tree_a and id in self.tree_b:
1445
a_sha1 = self.tree_a.get_file_sha1(id)
1446
b_sha1 = self.tree_b.get_file_sha1(id)
1447
if None not in (a_sha1, b_sha1) and a_sha1 == b_sha1:
1450
full_path_a = self.tree_a.readonly_path(id)
1451
full_path_b = self.tree_b.readonly_path(id)
1435
1452
stat_a = self.lstat(full_path_a)
1436
1453
stat_b = self.lstat(full_path_b)
1437
1454
if stat_b is None: