644
645
if (self._new_name, self._new_parent) == ({}, {}):
646
647
for children in by_parent.itervalues():
647
name_ids = [(self.final_name(t), t) for t in children]
648
if not self._case_sensitive_target:
649
name_ids = [(n.lower(), t) for n, t in name_ids]
649
for child_tid in children:
650
name = self.final_name(child_tid)
652
# Keep children only if they still exist in the end
653
if not self._case_sensitive_target:
655
name_ids.append((name, child_tid))
652
658
last_trans_id = None
928
934
return _PreviewTree(self)
930
def commit(self, branch, message, merge_parents=None, strict=False):
936
def commit(self, branch, message, merge_parents=None, strict=False,
937
timestamp=None, timezone=None, committer=None, authors=None,
938
revprops=None, revision_id=None):
931
939
"""Commit the result of this TreeTransform to a branch.
933
941
:param branch: The branch to commit to.
934
942
:param message: The message to attach to the commit.
935
:param merge_parents: Additional parents specified by pending merges.
943
:param merge_parents: Additional parent revision-ids specified by
945
:param strict: If True, abort the commit if there are unversioned
947
:param timestamp: if not None, seconds-since-epoch for the time and
948
date. (May be a float.)
949
:param timezone: Optional timezone for timestamp, as an offset in
951
:param committer: Optional committer in email-id format.
952
(e.g. "J Random Hacker <jrandom@example.com>")
953
:param authors: Optional list of authors in email-id format.
954
:param revprops: Optional dictionary of revision properties.
955
:param revision_id: Optional revision id. (Specifying a revision-id
956
may reduce performance for some non-native formats.)
936
957
:return: The revision_id of the revision committed.
938
959
self._check_malformed()
955
976
if self._tree.get_revision_id() != last_rev_id:
956
977
raise ValueError('TreeTransform not based on branch basis: %s' %
957
978
self._tree.get_revision_id())
958
builder = branch.get_commit_builder(parent_ids)
979
revprops = commit.Commit.update_revprops(revprops, branch, authors)
980
builder = branch.get_commit_builder(parent_ids,
985
revision_id=revision_id)
959
986
preview = self.get_preview_tree()
960
987
list(builder.record_iter_changes(preview, last_rev_id,
961
988
self.iter_changes()))
1160
1187
if trans_id not in self._new_contents:
1162
1189
new_path = self._limbo_name(trans_id)
1163
osutils.rename(old_path, new_path)
1190
os.rename(old_path, new_path)
1164
1191
for descendant in self._limbo_descendants(trans_id):
1165
1192
desc_path = self._limbo_files[descendant]
1166
1193
desc_path = new_path + desc_path[len(old_path):]
1635
1662
or trans_id in self._new_parent):
1637
1664
mover.rename(full_path, self._limbo_name(trans_id))
1665
except errors.TransformRenameFailed, e:
1639
1666
if e.errno != errno.ENOENT:
1666
1693
if trans_id in self._needs_rename:
1668
1695
mover.rename(self._limbo_name(trans_id), full_path)
1696
except errors.TransformRenameFailed, e:
1670
1697
# We may be renaming a dangling inventory id
1671
1698
if e.errno != errno.ENOENT:
1770
1797
parent_keys = [(file_id, self._file_revision(t, file_id)) for t in
1771
1798
self._iter_parent_trees()]
1772
1799
vf.add_lines((file_id, tree_revision), parent_keys,
1773
self.get_file(file_id).readlines())
1800
self.get_file_lines(file_id))
1774
1801
repo = self._get_repository()
1775
1802
base_vf = repo.texts
1776
1803
if base_vf not in vf.fallback_versionedfiles:
1798
1825
executable = self.is_executable(file_id, path)
1799
1826
return kind, executable, None
1828
def is_locked(self):
1801
1831
def lock_read(self):
1802
1832
# Perhaps in theory, this should lock the TreeTransform?
1805
1835
def unlock(self):
2266
2296
for num, _unused in enumerate(wt.all_file_ids()):
2267
2297
if num > 0: # more than just a root
2268
2298
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
2269
existing_files = set()
2270
for dir, files in wt.walkdirs():
2271
existing_files.update(f[0] for f in files)
2272
2299
file_trans_id = {}
2273
2300
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2274
2301
pp = ProgressPhase("Build phase", 2, top_pb)
2298
2325
precomputed_delta = []
2300
2327
precomputed_delta = None
2328
# Check if tree inventory has content. If so, we populate
2329
# existing_files with the directory content. If there are no
2330
# entries we skip populating existing_files as its not used.
2331
# This improves performance and unncessary work on large
2332
# directory trees. (#501307)
2334
existing_files = set()
2335
for dir, files in wt.walkdirs():
2336
existing_files.update(f[0] for f in files)
2301
2337
for num, (tree_path, entry) in \
2302
2338
enumerate(tree.inventory.iter_entries_by_dir()):
2303
2339
pb.update("Building tree", num - len(deferred_contents), total)
2435
2471
if entry.kind == "directory":
2437
2473
if entry.kind == "file":
2438
if tree.get_file(file_id).read() == file(target_path, 'rb').read():
2474
f = file(target_path, 'rb')
2476
if tree.get_file_text(file_id) == f.read():
2440
2480
elif entry.kind == "symlink":
2441
2481
if tree.get_symlink_target(file_id) == os.readlink(target_path):
2900
2940
def rename(self, from_, to):
2901
2941
"""Rename a file from one path to another."""
2903
osutils.rename(from_, to)
2943
os.rename(from_, to)
2904
2944
except OSError, e:
2905
2945
if e.errno in (errno.EEXIST, errno.ENOTEMPTY):
2906
2946
raise errors.FileExists(to, str(e))
2947
# normal OSError doesn't include filenames so it's hard to see where
2948
# the problem is, see https://bugs.launchpad.net/bzr/+bug/491763
2949
raise errors.TransformRenameFailed(from_, to, str(e), e.errno)
2908
2950
self.past_renames.append((from_, to))
2910
2952
def pre_delete(self, from_, to):
2920
2962
def rollback(self):
2921
2963
"""Reverse all renames that have been performed"""
2922
2964
for from_, to in reversed(self.past_renames):
2923
osutils.rename(to, from_)
2966
os.rename(to, from_)
2968
raise errors.TransformRenameFailed(to, from_, str(e), e.errno)
2924
2969
# after rollback, don't reuse _FileMover
2925
2970
past_renames = None
2926
2971
pending_deletions = None