129
129
# Cache of relpath results, to speed up canonical_path
130
130
self._relpaths = {}
131
131
# The trans_id that will be used as the tree root
132
self._new_root = self.trans_id_tree_file_id(tree.get_root_id())
132
root_id = tree.get_root_id()
133
if root_id is not None:
134
self._new_root = self.trans_id_tree_file_id(root_id)
136
self._new_root = None
133
137
# Indictor of whether the transform has been applied
134
138
self._done = False
196
200
previous_name = self._new_name.get(trans_id)
197
201
self._new_name[trans_id] = name
198
202
self._new_parent[trans_id] = parent
203
if parent == ROOT_PARENT:
204
if self._new_root is not None:
205
raise ValueError("Cannot have multiple roots.")
206
self._new_root = trans_id
199
207
if (trans_id in self._limbo_files and
200
208
trans_id not in self._needs_rename):
201
209
self._rename_in_limbo([trans_id])
258
266
This reflects only files that already exist, not ones that will be
259
267
added by transactions.
269
if inventory_id is None:
270
raise ValueError('None is not a valid file id')
261
271
path = self._tree.id2path(inventory_id)
262
272
return self.trans_id_tree_path(path)
267
277
a transaction has been unversioned, it is deliberately still returned.
268
278
(this will likely lead to an unversioned parent conflict.)
281
raise ValueError('None is not a valid file id')
270
282
if file_id in self._r_new_id and self._r_new_id[file_id] is not None:
271
283
return self._r_new_id[file_id]
272
284
elif file_id in self._tree.inventory:
1526
1538
for (file_id, paths, changed, versioned, parent, name, kind,
1527
1539
executable) in self._transform.iter_changes():
1528
1540
if paths[1] in to_find:
1529
result.append(file_id)
1530
1542
to_find.remove(paths[1])
1531
1543
result.update(self._transform._tree.paths2ids(to_find,
1532
1544
trees=[], require_versioned=require_versioned))
1579
1591
parent_file_id, file_id)
1580
1592
yield new_entry, trans_id
1582
def iter_entries_by_dir(self, specific_file_ids=None):
1583
# This may not be a maximally efficient implementation, but it is
1584
# reasonably straightforward. An implementation that grafts the
1585
# TreeTransform changes onto the tree's iter_entries_by_dir results
1586
# might be more efficient, but requires tricky inferences about stack
1594
def _list_files_by_dir(self):
1588
1595
todo = [ROOT_PARENT]
1589
1596
ordered_ids = []
1590
1597
while len(todo) > 0:
1596
1603
todo.extend(reversed(children))
1597
1604
for trans_id in children:
1598
1605
ordered_ids.append((trans_id, parent_file_id))
1608
def iter_entries_by_dir(self, specific_file_ids=None):
1609
# This may not be a maximally efficient implementation, but it is
1610
# reasonably straightforward. An implementation that grafts the
1611
# TreeTransform changes onto the tree's iter_entries_by_dir results
1612
# might be more efficient, but requires tricky inferences about stack
1614
ordered_ids = self._list_files_by_dir()
1599
1615
for entry, trans_id in self._make_inv_entries(ordered_ids,
1600
1616
specific_file_ids):
1601
1617
yield unicode(self._final_paths.get_path(trans_id)), entry
1619
def list_files(self, include_root=False):
1620
"""See Tree.list_files."""
1621
# XXX This should behave like WorkingTree.list_files, but is really
1622
# more like RevisionTree.list_files.
1623
for path, entry in self.iter_entries_by_dir():
1624
if entry.name == '' and not include_root:
1626
yield path, 'V', entry.kind, entry.file_id, entry
1603
1628
def kind(self, file_id):
1604
1629
trans_id = self._transform.trans_id_file_id(file_id)
1605
1630
return self._transform.final_kind(trans_id)
1731
1756
name = self._transform._limbo_name(trans_id)
1732
1757
return os.readlink(name)
1734
def list_files(self, include_root=False):
1735
return self._transform._tree.list_files(include_root)
1737
1759
def walkdirs(self, prefix=''):
1738
1760
pending = [self._transform.root]
1739
1761
while len(pending) > 0:
2147
2169
tt = TreeTransform(working_tree, pb)
2149
2171
pp = ProgressPhase("Revert phase", 3, pb)
2151
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2153
merge_modified = _alter_files(working_tree, target_tree, tt,
2154
child_pb, filenames, backups)
2158
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2160
raw_conflicts = resolve_conflicts(tt, child_pb,
2161
lambda t, c: conflict_pass(t, c, target_tree))
2164
conflicts = cook_conflicts(raw_conflicts, tt)
2172
conflicts, merge_modified = _prepare_revert_transform(
2173
working_tree, target_tree, tt, filenames, backups, pp)
2165
2174
if change_reporter:
2166
2175
change_reporter = delta._ChangeReporter(
2167
2176
unversioned_filter=working_tree.is_ignored)
2178
2187
return conflicts
2190
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2191
backups, pp, basis_tree=None,
2192
merge_modified=None):
2194
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2196
if merge_modified is None:
2197
merge_modified = working_tree.merge_modified()
2198
merge_modified = _alter_files(working_tree, target_tree, tt,
2199
child_pb, filenames, backups,
2200
merge_modified, basis_tree)
2204
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2206
raw_conflicts = resolve_conflicts(tt, child_pb,
2207
lambda t, c: conflict_pass(t, c, target_tree))
2210
conflicts = cook_conflicts(raw_conflicts, tt)
2211
return conflicts, merge_modified
2181
2214
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
2183
merge_modified = working_tree.merge_modified()
2215
backups, merge_modified, basis_tree=None):
2216
if basis_tree is not None:
2217
basis_tree.lock_read()
2184
2218
change_list = target_tree.iter_changes(working_tree,
2185
2219
specific_files=specific_files, pb=pb)
2186
if target_tree.inventory.root is None:
2220
if target_tree.get_root_id() is None:
2187
2221
skip_root = True
2189
2223
skip_root = False
2192
2225
deferred_files = []
2193
2226
for id_num, (file_id, path, changed_content, versioned, parent, name,
2230
2263
mode_id = trans_id
2231
2264
trans_id = new_trans_id
2232
if kind[1] == 'directory':
2265
if kind[1] in ('directory', 'tree-reference'):
2233
2266
tt.create_directory(trans_id)
2267
if kind[1] == 'tree-reference':
2268
revision = target_tree.get_reference_revision(file_id,
2270
tt.set_tree_reference(revision, trans_id)
2234
2271
elif kind[1] == 'symlink':
2235
2272
tt.create_symlink(target_tree.get_symlink_target(file_id),
2256
2293
tt.version_file(file_id, trans_id)
2257
2294
if versioned == (True, False):
2258
2295
tt.unversion_file(trans_id)
2259
if (name[1] is not None and
2296
if (name[1] is not None and
2260
2297
(name[0] != name[1] or parent[0] != parent[1])):
2262
name[1], tt.trans_id_file_id(parent[1]), trans_id)
2298
if name[1] == '' and parent[1] is None:
2299
parent_trans = ROOT_PARENT
2301
parent_trans = tt.trans_id_file_id(parent[1])
2302
tt.adjust_path(name[1], parent_trans, trans_id)
2263
2303
if executable[0] != executable[1] and kind[1] == "file":
2264
2304
tt.set_executability(executable[1], trans_id)
2265
2305
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
2373
2413
if parent_file_id is not None:
2374
2414
tt.unversion_file(parent_id)
2375
2415
new_conflicts.add((c_type, 'Created directory', new_parent_id))
2416
elif c_type == 'versioning no contents':
2417
tt.cancel_versioning(conflict[1])
2376
2418
return new_conflicts