48
48
for entry in cset.entries.itervalues():
49
49
if entry.is_boring():
50
50
new_cset.add_entry(entry)
51
elif entry.is_creation(False):
52
if inventory.this.get_path(entry.id) is None:
53
new_cset.add_entry(entry)
55
this_contents = get_this_contents(entry.id)
56
other_contents = entry.contents_change.new_contents
57
if other_contents == this_contents:
58
boring_entry = changeset.ChangesetEntry(entry.id,
61
new_cset.add_entry(boring_entry)
63
conflict_handler.contents_conflict(this_contents,
66
elif entry.is_deletion(False):
67
if inventory.this.get_path(entry.id) is None:
68
boring_entry = changeset.ChangesetEntry(entry.id, entry.parent,
70
new_cset.add_entry(boring_entry)
71
elif entry.contents_change is not None:
72
this_contents = get_this_contents(entry.id)
73
base_contents = entry.contents_change.old_contents
74
if base_contents == this_contents:
75
new_cset.add_entry(entry)
77
entry_path = inventory.this.get_path(entry.id)
78
conflict_handler.rem_contents_conflict(entry_path,
83
new_cset.add_entry(entry)
85
entry = get_merge_entry(entry, inventory, base, other,
88
new_cset.add_entry(entry)
52
new_entry = make_merged_entry(entry, inventory, conflict_handler)
53
new_contents = make_merged_contents(entry, this, base, other,
55
new_entry.contents_change = new_contents
56
new_entry.metadata_change = make_merged_metadata(entry, base, other)
57
new_cset.add_entry(new_entry)
92
def get_merge_entry(entry, inventory, base, other, conflict_handler):
61
def make_merged_entry(entry, inventory, conflict_handler):
93
62
this_name = inventory.this.get_name(entry.id)
94
63
this_parent = inventory.this.get_parent(entry.id)
95
64
this_dir = inventory.this.get_dir(entry.id)
96
65
if this_dir is None:
99
return conflict_handler.merge_missing(entry.id, inventory)
101
68
base_name = inventory.base.get_name(entry.id)
102
69
base_parent = inventory.base.get_parent(entry.id)
133
100
old_dir = this_dir
134
101
new_parent = other_parent
135
102
new_dir = other_dir
136
old_path = os.path.join(old_dir, old_name)
103
if old_name is not None and old_parent is not None:
104
old_path = os.path.join(old_dir, old_name)
137
107
new_entry = changeset.ChangesetEntry(entry.id, old_parent, old_name)
138
if new_name is not None or new_parent is not None:
108
if new_name is not None and new_parent is not None:
139
109
new_entry.new_path = os.path.join(new_dir, new_name)
141
111
new_entry.new_path = None
142
112
new_entry.new_parent = new_parent
144
base_path = base.readonly_path(entry.id)
145
other_path = other.readonly_path(entry.id)
116
def make_merged_contents(entry, this, base, other, conflict_handler):
117
contents = entry.contents_change
120
this_path = this.readonly_path(entry.id)
122
if this_path is None:
123
return conflict_handler.missing_for_merge(entry.id, inventory)
124
base_path = base.readonly_path(entry.id)
125
other_path = other.readonly_path(entry.id)
126
return changeset.Diff3Merge(base_path, other_path)
128
if isinstance(contents, changeset.PatchApply):
130
if isinstance(contents, changeset.ReplaceContents):
131
if contents.old_contents is None and contents.new_contents is None:
133
if contents.new_contents is None:
134
if this_path is not None and os.path.exists(this_path):
138
elif contents.old_contents is None:
139
if this_path is None or not os.path.exists(this_path):
142
this_contents = file(this_path, "rb").read()
143
if this_contents == contents.new_contents:
146
other_path = other.readonly_path(entry.id)
147
conflict_handler.new_contents_conflict(this_path,
149
elif isinstance(contents.old_contents, changeset.FileCreate) and \
150
isinstance(contents.new_contents, changeset.FileCreate):
153
raise Exception("Unhandled merge scenario")
155
def make_merged_metadata(entry, base, other):
156
if entry.metadata_change is not None:
157
base_path = base.readonly_path(entry.id)
158
other_path = other.readonly_path(entry.id)
159
return PermissionsMerge(base_path, other_path)
161
def get_merge_entry(entry, inventory, base, other, conflict_handler):
147
162
if entry.contents_change is not None:
148
163
new_entry.contents_change = changeset.Diff3Merge(base_path, other_path)
149
164
if entry.metadata_change is not None:
210
225
def full_path(self, id):
211
226
return self.abs_path(self.inventory[id])
228
def readonly_path(self, id):
229
return self.full_path(id)
213
231
def change_path(self, id, path):
214
232
new = os.path.join(self.dir, self.inventory[id])
215
233
os.rename(self.abs_path(self.inventory[id]), self.abs_path(path))
329
347
Inventory(self.base.inventory),
330
348
Inventory(self.other.inventory))
331
349
conflict_handler = changeset.ExceptionConflictHandler(self.this.dir)
332
return make_merge_changeset(self.cset, all_inventory, self.this.dir,
333
self.base.dir, self.other.dir,
350
return make_merge_changeset(self.cset, all_inventory, self.this,
351
self.base, self.other, conflict_handler)
353
def apply_inv_change(self, inventory_change, orig_inventory):
354
orig_inventory_by_path = {}
355
for file_id, path in orig_inventory.iteritems():
356
orig_inventory_by_path[path] = file_id
358
def parent_id(file_id):
360
parent_dir = os.path.dirname(orig_inventory[file_id])
366
return orig_inventory_by_path[parent_dir]
368
def new_path(file_id):
369
if inventory_change.has_key(file_id):
370
return inventory_change[file_id]
372
parent = parent_id(file_id)
374
return orig_inventory[file_id]
375
dirname = new_path(parent)
376
return os.path.join(dirname, orig_inventory[file_id])
379
for file_id in orig_inventory.iterkeys():
380
path = new_path(file_id)
383
new_inventory[file_id] = path
385
for file_id, path in inventory_change.iteritems():
386
if orig_inventory.has_key(file_id):
388
new_inventory[file_id] = path
335
393
def apply_changeset(self, cset, conflict_handler=None, reverse=False):
336
self.this.inventory = \
337
changeset.apply_changeset(cset, self.this.inventory,
338
self.this.dir, conflict_handler,
394
inventory_change = changeset.apply_changeset(cset,
397
conflict_handler, reverse)
398
self.this.inventory = self.apply_inv_change(inventory_change,
341
405
def cleanup(self):
342
406
shutil.rmtree(self.dir)