69
69
self.contents_change.apply(filename, conflict_handler, reverse)
72
class ThreewayInventory(object):
73
def __init__(self, this_inventory, base_inventory, other_inventory):
74
self.this = this_inventory
75
self.base = base_inventory
76
self.other = other_inventory
77
72
def invert_invent(inventory):
79
74
for file_id in inventory:
85
80
invert_invent[file_id] = path
86
81
return invert_invent
88
def make_inv(inventory):
89
return Inventory(invert_invent(inventory))
92
84
def merge_flex(this, base, other, changeset_function, inventory_function,
93
85
conflict_handler, merge_factory, interesting_ids):
94
this_inventory = inventory_function(this)
95
base_inventory = inventory_function(base)
96
other_inventory = inventory_function(other)
97
inventory = ThreewayInventory(make_inv(this_inventory),
98
make_inv(base_inventory),
99
make_inv(other_inventory))
100
86
cset = changeset_function(base, other, interesting_ids)
101
new_cset = make_merge_changeset(cset, inventory, this, base, other,
87
new_cset = make_merge_changeset(cset, this, base, other,
102
88
conflict_handler, merge_factory)
103
result = apply_changeset(new_cset, invert_invent(this_inventory),
89
result = apply_changeset(new_cset, invert_invent(this.tree.inventory),
104
90
this.root, conflict_handler, False)
105
91
conflict_handler.finalize()
110
def make_merge_changeset(cset, inventory, this, base, other,
96
def make_merge_changeset(cset, this, base, other,
111
97
conflict_handler, merge_factory):
112
98
new_cset = changeset.Changeset()
113
99
def get_this_contents(id):
114
path = os.path.join(this.root, inventory.this.get_path(id))
100
path = this.readonly_path(id)
115
101
if os.path.isdir(path):
116
102
return changeset.dir_create
121
107
if entry.is_boring():
122
108
new_cset.add_entry(entry)
124
new_entry = make_merged_entry(entry, inventory, conflict_handler)
110
new_entry = make_merged_entry(entry, this, base, other,
125
112
new_contents = make_merged_contents(entry, this, base, other,
126
inventory, conflict_handler,
128
115
new_entry.contents_change = new_contents
129
116
new_entry.metadata_change = make_merged_metadata(entry, base, other)
134
def make_merged_entry(entry, inventory, conflict_handler):
121
def make_merged_entry(entry, this, base, other, conflict_handler):
135
122
from bzrlib.trace import mutter
136
this_name = inventory.this.get_name(entry.id)
137
this_parent = inventory.this.get_parent(entry.id)
138
this_dir = inventory.this.get_dir(entry.id)
142
base_name = inventory.base.get_name(entry.id)
143
base_parent = inventory.base.get_parent(entry.id)
144
base_dir = inventory.base.get_dir(entry.id)
147
other_name = inventory.other.get_name(entry.id)
148
other_parent = inventory.other.get_parent(entry.id)
149
other_dir = inventory.base.get_dir(entry.id)
150
if other_dir is None:
123
def entry_data(file_id, tree):
124
assert hasattr(tree, "__contains__"), "%s" % tree
125
if file_id not in tree:
126
return (None, None, "")
127
entry = tree.tree.inventory[file_id]
128
my_dir = tree.id2path(entry.parent_id)
131
return entry.name, entry.parent_id, my_dir
132
this_name, this_parent, this_dir = entry_data(entry.id, this)
133
base_name, base_parent, base_dir = entry_data(entry.id, base)
134
other_name, other_parent, other_dir = entry_data(entry.id, other)
152
135
mutter("Dirs: this, base, other %r %r %r" % (this_dir, base_dir, other_dir))
153
136
mutter("Names: this, base, other %r %r %r" % (this_name, base_name, other_name))
154
137
if base_name == other_name:
192
def make_merged_contents(entry, this, base, other, inventory, conflict_handler,
176
def make_merged_contents(entry, this, base, other, conflict_handler,
194
178
contents = entry.contents_change
195
179
if contents is None:
197
181
this_path = this.readonly_path(entry.id)
198
182
def make_merge():
199
183
if this_path is None:
200
return conflict_handler.missing_for_merge(entry.id, inventory)
184
return conflict_handler.missing_for_merge(entry.id,
185
other.id2path(entry.id))
201
186
base_path = base.readonly_path(entry.id)
202
187
other_path = other.readonly_path(entry.id)
203
188
return merge_factory(base_path, other_path)
250
from bzrlib.inventory import InventoryEntry, RootEntry
251
from osutils import file_kind
252
class FalseTree(object):
253
def __init__(self, realtree):
254
self._realtree = realtree
255
self.inventory = self
257
def __getitem__(self, file_id):
258
entry = self.make_inventory_entry(file_id)
260
raise KeyError(file_id)
263
def make_inventory_entry(self, file_id):
264
path = self._realtree.inventory.get(file_id)
268
return RootEntry(file_id)
269
dir, name = os.path.split(path)
270
kind = file_kind(self._realtree.abs_path(path))
271
for parent_id, path in self._realtree.inventory.iteritems():
275
raise Exception("Can't find parent for %s" % name)
276
return InventoryEntry(file_id, name, kind, parent_id)
265
279
class MergeTree(object):
266
280
def __init__(self, dir):
269
283
self.inventory = {'0': ""}
284
self.tree = FalseTree(self)
271
286
def child_path(self, parent, name):
272
287
return os.path.join(self.inventory[parent], name)
304
319
def readonly_path(self, id):
305
320
return self.full_path(id)
322
def __contains__(self, file_id):
323
return file_id in self.inventory
325
def id2path(self, file_id):
326
return self.inventory[file_id]
307
328
def change_path(self, id, path):
308
329
new = os.path.join(self.dir, self.inventory[id])
309
330
os.rename(self.abs_path(self.inventory[id]), self.abs_path(path))
435
456
os.chmod(tree.full_path(id), mode)
437
458
def merge_changeset(self, merge_factory):
438
all_inventory = ThreewayInventory(Inventory(self.this.inventory),
439
Inventory(self.base.inventory),
440
Inventory(self.other.inventory))
441
459
conflict_handler = changeset.ExceptionConflictHandler(self.this.dir)
442
return make_merge_changeset(self.cset, all_inventory, self.this,
443
self.base, self.other, conflict_handler,
460
return make_merge_changeset(self.cset, self.this, self.base,
461
self.other, conflict_handler,
446
464
def apply_inv_change(self, inventory_change, orig_inventory):