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:
1325
1337
tree_paths = list(self._tree_path_ids.iteritems())
1326
1338
tree_paths.sort(reverse=True)
1327
kind_changes = set()
1328
1339
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1330
1341
for num, data in enumerate(tree_paths):
1357
1367
If inventory_delta is None, no inventory delta is calculated, and
1358
1368
no list of modified paths is returned.
1360
kind_changes is a set of trans ids where the entry has changed
1361
kind, and so an inventory delta entry should be created for them.
1363
1370
new_paths = self.new_paths(filesystem_only=True)
1364
1371
modified_paths = []
1526
1533
for (file_id, paths, changed, versioned, parent, name, kind,
1527
1534
executable) in self._transform.iter_changes():
1528
1535
if paths[1] in to_find:
1529
result.append(file_id)
1530
1537
to_find.remove(paths[1])
1531
1538
result.update(self._transform._tree.paths2ids(to_find,
1532
1539
trees=[], require_versioned=require_versioned))
1579
1586
parent_file_id, file_id)
1580
1587
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
1589
def _list_files_by_dir(self):
1588
1590
todo = [ROOT_PARENT]
1589
1591
ordered_ids = []
1590
1592
while len(todo) > 0:
1596
1598
todo.extend(reversed(children))
1597
1599
for trans_id in children:
1598
1600
ordered_ids.append((trans_id, parent_file_id))
1603
def iter_entries_by_dir(self, specific_file_ids=None):
1604
# This may not be a maximally efficient implementation, but it is
1605
# reasonably straightforward. An implementation that grafts the
1606
# TreeTransform changes onto the tree's iter_entries_by_dir results
1607
# might be more efficient, but requires tricky inferences about stack
1609
ordered_ids = self._list_files_by_dir()
1599
1610
for entry, trans_id in self._make_inv_entries(ordered_ids,
1600
1611
specific_file_ids):
1601
1612
yield unicode(self._final_paths.get_path(trans_id)), entry
1614
def list_files(self, include_root=False):
1615
"""See Tree.list_files."""
1616
# XXX This should behave like WorkingTree.list_files, but is really
1617
# more like RevisionTree.list_files.
1618
for path, entry in self.iter_entries_by_dir():
1619
if entry.name == '' and not include_root:
1621
yield path, 'V', entry.kind, entry.file_id, entry
1603
1623
def kind(self, file_id):
1604
1624
trans_id = self._transform.trans_id_file_id(file_id)
1605
1625
return self._transform.final_kind(trans_id)
1731
1751
name = self._transform._limbo_name(trans_id)
1732
1752
return os.readlink(name)
1734
def list_files(self, include_root=False):
1735
return self._transform._tree.list_files(include_root)
1737
def walkdirs(self, prefix=""):
1738
return self._transform._tree.walkdirs(prefix)
1754
def walkdirs(self, prefix=''):
1755
pending = [self._transform.root]
1756
while len(pending) > 0:
1757
parent_id = pending.pop()
1760
prefix = prefix.rstrip('/')
1761
parent_path = self._final_paths.get_path(parent_id)
1762
parent_file_id = self._transform.final_file_id(parent_id)
1763
for child_id in self._all_children(parent_id):
1764
path_from_root = self._final_paths.get_path(child_id)
1765
basename = self._transform.final_name(child_id)
1766
file_id = self._transform.final_file_id(child_id)
1768
kind = self._transform.final_kind(child_id)
1769
versioned_kind = kind
1772
versioned_kind = self._transform._tree.stored_kind(file_id)
1773
if versioned_kind == 'directory':
1774
subdirs.append(child_id)
1775
children.append((path_from_root, basename, kind, None,
1776
file_id, versioned_kind))
1778
if parent_path.startswith(prefix):
1779
yield (parent_path, parent_file_id), children
1780
pending.extend(sorted(subdirs, key=self._final_paths.get_path,
1740
1783
def get_parent_ids(self):
1741
1784
return self._parent_ids
2121
2164
tt = TreeTransform(working_tree, pb)
2123
2166
pp = ProgressPhase("Revert phase", 3, pb)
2125
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2127
merge_modified = _alter_files(working_tree, target_tree, tt,
2128
child_pb, filenames, backups)
2132
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2134
raw_conflicts = resolve_conflicts(tt, child_pb,
2135
lambda t, c: conflict_pass(t, c, target_tree))
2138
conflicts = cook_conflicts(raw_conflicts, tt)
2167
conflicts, merge_modified = _prepare_revert_transform(
2168
working_tree, target_tree, tt, filenames, backups, pp)
2139
2169
if change_reporter:
2140
2170
change_reporter = delta._ChangeReporter(
2141
2171
unversioned_filter=working_tree.is_ignored)
2152
2182
return conflicts
2185
def _prepare_revert_transform(working_tree, target_tree, tt, filenames,
2186
backups, pp, basis_tree=None,
2187
merge_modified=None):
2189
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2191
if merge_modified is None:
2192
merge_modified = working_tree.merge_modified()
2193
merge_modified = _alter_files(working_tree, target_tree, tt,
2194
child_pb, filenames, backups,
2195
merge_modified, basis_tree)
2199
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2201
raw_conflicts = resolve_conflicts(tt, child_pb,
2202
lambda t, c: conflict_pass(t, c, target_tree))
2205
conflicts = cook_conflicts(raw_conflicts, tt)
2206
return conflicts, merge_modified
2155
2209
def _alter_files(working_tree, target_tree, tt, pb, specific_files,
2157
merge_modified = working_tree.merge_modified()
2210
backups, merge_modified, basis_tree=None):
2211
if basis_tree is not None:
2212
basis_tree.lock_read()
2158
2213
change_list = target_tree.iter_changes(working_tree,
2159
2214
specific_files=specific_files, pb=pb)
2160
if target_tree.inventory.root is None:
2215
if target_tree.get_root_id() is None:
2161
2216
skip_root = True
2163
2218
skip_root = False
2166
2220
deferred_files = []
2167
2221
for id_num, (file_id, path, changed_content, versioned, parent, name,
2204
2258
mode_id = trans_id
2205
2259
trans_id = new_trans_id
2206
if kind[1] == 'directory':
2260
if kind[1] in ('directory', 'tree-reference'):
2207
2261
tt.create_directory(trans_id)
2262
if kind[1] == 'tree-reference':
2263
revision = target_tree.get_reference_revision(file_id,
2265
tt.set_tree_reference(revision, trans_id)
2208
2266
elif kind[1] == 'symlink':
2209
2267
tt.create_symlink(target_tree.get_symlink_target(file_id),
2230
2288
tt.version_file(file_id, trans_id)
2231
2289
if versioned == (True, False):
2232
2290
tt.unversion_file(trans_id)
2233
if (name[1] is not None and
2291
if (name[1] is not None and
2234
2292
(name[0] != name[1] or parent[0] != parent[1])):
2236
name[1], tt.trans_id_file_id(parent[1]), trans_id)
2293
if name[1] == '' and parent[1] is None:
2294
parent_trans = ROOT_PARENT
2296
parent_trans = tt.trans_id_file_id(parent[1])
2297
tt.adjust_path(name[1], parent_trans, trans_id)
2237
2298
if executable[0] != executable[1] and kind[1] == "file":
2238
2299
tt.set_executability(executable[1], trans_id)
2239
2300
for (trans_id, mode_id), bytes in target_tree.iter_files_bytes(
2347
2408
if parent_file_id is not None:
2348
2409
tt.unversion_file(parent_id)
2349
2410
new_conflicts.add((c_type, 'Created directory', new_parent_id))
2411
elif c_type == 'versioning no contents':
2412
tt.cancel_versioning(conflict[1])
2350
2413
return new_conflicts