137
137
# A counter of how many files have been renamed
138
138
self.rename_count = 0
141
"""Support Context Manager API."""
144
def __exit__(self, exc_type, exc_val, exc_tb):
145
"""Support Context Manager API."""
140
148
def finalize(self):
141
149
"""Release the working tree lock, if held.
244
252
if (self.tree_file_id(self._new_root) is not None and
245
253
self._new_root not in self._removed_id):
246
254
self.unversion_file(self._new_root)
247
self.version_file(file_id, self._new_root)
255
if file_id is not None:
256
self.version_file(file_id, self._new_root)
249
258
# Now move children of new root into old root directory.
250
259
# Ensure all children are registered with the transaction, but don't
384
393
return sorted(FinalPaths(self).get_paths(new_ids))
386
395
def _inventory_altered(self):
387
"""Get the trans_ids and paths of files needing new inv entries."""
389
for id_set in [self._new_name, self._new_parent, self._new_id,
396
"""Determine which trans_ids need new Inventory entries.
398
An new entry is needed when anything that would be reflected by an
399
inventory entry changes, including file name, file_id, parent file_id,
400
file kind, and the execute bit.
402
Some care is taken to return entries with real changes, not cases
403
where the value is deleted and then restored to its original value,
404
but some actually unchanged values may be returned.
406
:returns: A list of (path, trans_id) for all items requiring an
407
inventory change. Ordered by path.
410
# Find entries whose file_ids are new (or changed).
411
new_file_id = set(t for t in self._new_id
412
if self._new_id[t] != self.tree_file_id(t))
413
for id_set in [self._new_name, self._new_parent, new_file_id,
390
414
self._new_executability]:
391
new_ids.update(id_set)
415
changed_ids.update(id_set)
416
# removing implies a kind change
392
417
changed_kind = set(self._removed_contents)
393
419
changed_kind.intersection_update(self._new_contents)
394
changed_kind.difference_update(new_ids)
420
# Ignore entries that are already known to have changed.
421
changed_kind.difference_update(changed_ids)
422
# to keep only the truly changed ones
395
423
changed_kind = (t for t in changed_kind
396
424
if self.tree_kind(t) != self.final_kind(t))
397
new_ids.update(changed_kind)
398
return sorted(FinalPaths(self).get_paths(new_ids))
425
# all kind changes will alter the inventory
426
changed_ids.update(changed_kind)
427
# To find entries with changed parent_ids, find parents which existed,
428
# but changed file_id.
429
changed_file_id = set(t for t in new_file_id if t in self._removed_id)
430
# Now add all their children to the set.
431
for parent_trans_id in new_file_id:
432
changed_ids.update(self.iter_tree_children(parent_trans_id))
433
return sorted(FinalPaths(self).get_paths(changed_ids))
400
435
def final_kind(self, trans_id):
401
436
"""Determine the final file kind, after any changes applied.
1172
1208
if self._tree is None:
1175
entries = [(self._limbo_name(t), t, k) for t, k in
1176
self._new_contents.iteritems()]
1177
entries.sort(reverse=True)
1178
for path, trans_id, kind in entries:
1211
limbo_paths = self._limbo_files.values() + list(
1212
self._possibly_stale_limbo_files)
1213
limbo_paths = sorted(limbo_paths, reverse=True)
1214
for path in limbo_paths:
1218
if e.errno != errno.ENOENT:
1220
# XXX: warn? perhaps we just got interrupted at an
1221
# inconvenient moment, but perhaps files are disappearing
1181
1224
delete_any(self._limbodir)
1182
1225
except OSError:
1231
1274
entries from _limbo_files, because they are now stale.
1233
1276
for trans_id in trans_ids:
1234
old_path = self._limbo_files.pop(trans_id)
1277
old_path = self._limbo_files[trans_id]
1278
self._possibly_stale_limbo_files.add(old_path)
1279
del self._limbo_files[trans_id]
1235
1280
if trans_id not in self._new_contents:
1237
1282
new_path = self._limbo_name(trans_id)
1238
1283
os.rename(old_path, new_path)
1284
self._possibly_stale_limbo_files.remove(old_path)
1239
1285
for descendant in self._limbo_descendants(trans_id):
1240
1286
desc_path = self._limbo_files[descendant]
1241
1287
desc_path = new_path + desc_path[len(old_path):]
1265
1311
name = self._limbo_name(trans_id)
1266
1312
f = open(name, 'wb')
1269
unique_add(self._new_contents, trans_id, 'file')
1271
# Clean up the file, it never got registered so
1272
# TreeTransform.finalize() won't clean it up.
1314
unique_add(self._new_contents, trans_id, 'file')
1276
1315
f.writelines(contents)
1788
1827
tree_paths.sort(reverse=True)
1789
1828
child_pb = ui.ui_factory.nested_progress_bar()
1791
for num, data in enumerate(tree_paths):
1792
path, trans_id = data
1830
for num, (path, trans_id) in enumerate(tree_paths):
1831
# do not attempt to move root into a subdirectory of itself.
1793
1834
child_pb.update('removing file', num, len(tree_paths))
1794
1835
full_path = self._tree.abspath(path)
1795
1836
if trans_id in self._removed_contents:
1851
1892
self._observed_sha1s[trans_id] = (o_sha1, st)
1853
1894
child_pb.finished()
1895
for path, trans_id in new_paths:
1896
# new_paths includes stuff like workingtree conflicts. Only the
1897
# stuff in new_contents actually comes from limbo.
1898
if trans_id in self._limbo_files:
1899
del self._limbo_files[trans_id]
1854
1900
self._new_contents.clear()
1855
1901
return modified_paths