37
38
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
38
ReusingTransform, NotVersionedError, CantMoveRoot,
39
ReusingTransform, CantMoveRoot,
39
40
ExistingLimbo, ImmortalLimbo, NoFinalPath,
40
41
UnableCreateSymlink)
41
42
from bzrlib.filters import filtered_output_bytes, ContentFilterContext
916
917
return _PreviewTree(self)
918
def commit(self, branch, message, merge_parents=None, strict=False):
919
def commit(self, branch, message, merge_parents=None, strict=False,
920
timestamp=None, timezone=None, committer=None, authors=None,
921
revprops=None, revision_id=None):
919
922
"""Commit the result of this TreeTransform to a branch.
921
924
:param branch: The branch to commit to.
922
925
:param message: The message to attach to the commit.
923
:param merge_parents: Additional parents specified by pending merges.
926
:param merge_parents: Additional parent revision-ids specified by
928
:param strict: If True, abort the commit if there are unversioned
930
:param timestamp: if not None, seconds-since-epoch for the time and
931
date. (May be a float.)
932
:param timezone: Optional timezone for timestamp, as an offset in
934
:param committer: Optional committer in email-id format.
935
(e.g. "J Random Hacker <jrandom@example.com>")
936
:param authors: Optional list of authors in email-id format.
937
:param revprops: Optional dictionary of revision properties.
938
:param revision_id: Optional revision id. (Specifying a revision-id
939
may reduce performance for some non-native formats.)
924
940
:return: The revision_id of the revision committed.
926
942
self._check_malformed()
943
959
if self._tree.get_revision_id() != last_rev_id:
944
960
raise ValueError('TreeTransform not based on branch basis: %s' %
945
961
self._tree.get_revision_id())
946
builder = branch.get_commit_builder(parent_ids)
962
revprops = commit.Commit.update_revprops(revprops, branch, authors)
963
builder = branch.get_commit_builder(parent_ids,
968
revision_id=revision_id)
947
969
preview = self.get_preview_tree()
948
970
list(builder.record_iter_changes(preview, last_rev_id,
949
971
self.iter_changes()))
1622
1644
or trans_id in self._new_parent):
1624
1646
mover.rename(full_path, self._limbo_name(trans_id))
1647
except errors.TransformRenameFailed, e:
1626
1648
if e.errno != errno.ENOENT:
1653
1675
if trans_id in self._needs_rename:
1655
1677
mover.rename(self._limbo_name(trans_id), full_path)
1678
except errors.TransformRenameFailed, e:
1657
1679
# We may be renaming a dangling inventory id
1658
1680
if e.errno != errno.ENOENT:
1757
1779
parent_keys = [(file_id, self._file_revision(t, file_id)) for t in
1758
1780
self._iter_parent_trees()]
1759
1781
vf.add_lines((file_id, tree_revision), parent_keys,
1760
self.get_file(file_id).readlines())
1782
self.get_file_lines(file_id))
1761
1783
repo = self._get_repository()
1762
1784
base_vf = repo.texts
1763
1785
if base_vf not in vf.fallback_versionedfiles:
1785
1807
executable = self.is_executable(file_id, path)
1786
1808
return kind, executable, None
1810
def is_locked(self):
1788
1813
def lock_read(self):
1789
1814
# Perhaps in theory, this should lock the TreeTransform?
1792
1817
def unlock(self):
2252
2277
for num, _unused in enumerate(wt.all_file_ids()):
2253
2278
if num > 0: # more than just a root
2254
2279
raise errors.WorkingTreeAlreadyPopulated(base=wt.basedir)
2255
existing_files = set()
2256
for dir, files in wt.walkdirs():
2257
existing_files.update(f[0] for f in files)
2258
2280
file_trans_id = {}
2259
2281
top_pb = bzrlib.ui.ui_factory.nested_progress_bar()
2260
2282
pp = ProgressPhase("Build phase", 2, top_pb)
2284
2306
precomputed_delta = []
2286
2308
precomputed_delta = None
2309
# Check if tree inventory has content. If so, we populate
2310
# existing_files with the directory content. If there are no
2311
# entries we skip populating existing_files as its not used.
2312
# This improves performance and unncessary work on large
2313
# directory trees. (#501307)
2315
existing_files = set()
2316
for dir, files in wt.walkdirs():
2317
existing_files.update(f[0] for f in files)
2287
2318
for num, (tree_path, entry) in \
2288
2319
enumerate(tree.inventory.iter_entries_by_dir()):
2289
2320
pb.update("Building tree", num - len(deferred_contents), total)
2421
2452
if entry.kind == "directory":
2423
2454
if entry.kind == "file":
2424
if tree.get_file(file_id).read() == file(target_path, 'rb').read():
2455
f = file(target_path, 'rb')
2457
if tree.get_file_text(file_id) == f.read():
2426
2461
elif entry.kind == "symlink":
2427
2462
if tree.get_symlink_target(file_id) == os.readlink(target_path):
2480
2515
raise errors.BadFileKindError(name, kind)
2483
@deprecated_function(deprecated_in((1, 9, 0)))
2484
def create_by_entry(tt, entry, tree, trans_id, lines=None, mode_id=None):
2485
"""Create new file contents according to an inventory entry.
2487
DEPRECATED. Use create_from_tree instead.
2489
if entry.kind == "file":
2491
lines = tree.get_file(entry.file_id).readlines()
2492
tt.create_file(lines, trans_id, mode_id=mode_id)
2493
elif entry.kind == "symlink":
2494
tt.create_symlink(tree.get_symlink_target(entry.file_id), trans_id)
2495
elif entry.kind == "directory":
2496
tt.create_directory(trans_id)
2499
2518
def create_from_tree(tt, trans_id, tree, file_id, bytes=None,
2500
2519
filter_tree_path=None):
2501
2520
"""Create new file contents according to tree contents.
2884
2903
self.pending_deletions = []
2886
2905
def rename(self, from_, to):
2887
"""Rename a file from one path to another. Functions like os.rename"""
2906
"""Rename a file from one path to another."""
2889
2908
os.rename(from_, to)
2890
2909
except OSError, e:
2891
2910
if e.errno in (errno.EEXIST, errno.ENOTEMPTY):
2892
2911
raise errors.FileExists(to, str(e))
2912
# normal OSError doesn't include filenames so it's hard to see where
2913
# the problem is, see https://bugs.launchpad.net/bzr/+bug/491763
2914
raise errors.TransformRenameFailed(from_, to, str(e), e.errno)
2894
2915
self.past_renames.append((from_, to))
2896
2917
def pre_delete(self, from_, to):
2906
2927
def rollback(self):
2907
2928
"""Reverse all renames that have been performed"""
2908
2929
for from_, to in reversed(self.past_renames):
2909
os.rename(to, from_)
2931
os.rename(to, from_)
2933
raise errors.TransformRenameFailed(to, from_, str(e), e.errno)
2910
2934
# after rollback, don't reuse _FileMover
2911
2935
past_renames = None
2912
2936
pending_deletions = None