Rev 4538: Implement commit for tree transforms (abentley) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Jul 15 21:13:40 BST 2009
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 4538 [merge]
revision-id: pqm at pqm.ubuntu.com-20090715201337-pujob8s96drd11p3
parent: pqm at pqm.ubuntu.com-20090715083553-ssotnv68cr0x5yxr
parent: aaron at aaronbentley.com-20090715190639-muemosrtdhqseaiw
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2009-07-15 21:13:37 +0100
message:
Implement commit for tree transforms (abentley)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
bzrlib/transform.py transform.py-20060105172343-dd99e54394d91687
=== modified file 'NEWS'
--- a/NEWS 2009-07-14 16:27:40 +0000
+++ b/NEWS 2009-07-15 19:06:39 +0000
@@ -36,6 +36,9 @@
API Changes
***********
+* New TransformPreview.commit() allows committing without a working tree.
+ (Aaron Bentley)
+
Internals
*********
=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py 2009-06-10 03:56:49 +0000
+++ b/bzrlib/tests/test_transform.py 2009-07-15 13:45:28 +0000
@@ -1873,6 +1873,106 @@
self.assertEqual('FILE', target.id2path('upper-id'))
+class TestCommitTransform(tests.TestCaseWithTransport):
+
+ def get_branch(self):
+ tree = self.make_branch_and_tree('tree')
+ tree.lock_write()
+ self.addCleanup(tree.unlock)
+ tree.commit('empty commit')
+ return tree.branch
+
+ def get_branch_and_transform(self):
+ branch = self.get_branch()
+ tt = TransformPreview(branch.basis_tree())
+ self.addCleanup(tt.finalize)
+ return branch, tt
+
+ def test_commit_wrong_basis(self):
+ branch = self.get_branch()
+ basis = branch.repository.revision_tree(
+ _mod_revision.NULL_REVISION)
+ tt = TransformPreview(basis)
+ self.addCleanup(tt.finalize)
+ e = self.assertRaises(ValueError, tt.commit, branch, '')
+ self.assertEqual('TreeTransform not based on branch basis: null:',
+ str(e))
+
+ def test_empy_commit(self):
+ branch, tt = self.get_branch_and_transform()
+ rev = tt.commit(branch, 'my message')
+ self.assertEqual(2, branch.revno())
+ repo = branch.repository
+ self.assertEqual('my message', repo.get_revision(rev).message)
+
+ def test_merge_parents(self):
+ branch, tt = self.get_branch_and_transform()
+ rev = tt.commit(branch, 'my message', ['rev1b', 'rev1c'])
+ self.assertEqual(['rev1b', 'rev1c'],
+ branch.basis_tree().get_parent_ids()[1:])
+
+ def test_first_commit(self):
+ branch = self.make_branch('branch')
+ branch.lock_write()
+ self.addCleanup(branch.unlock)
+ tt = TransformPreview(branch.basis_tree())
+ rev = tt.commit(branch, 'my message')
+ self.assertEqual([], branch.basis_tree().get_parent_ids())
+ self.assertNotEqual(_mod_revision.NULL_REVISION,
+ branch.last_revision())
+
+ def test_first_commit_with_merge_parents(self):
+ branch = self.make_branch('branch')
+ branch.lock_write()
+ self.addCleanup(branch.unlock)
+ tt = TransformPreview(branch.basis_tree())
+ e = self.assertRaises(ValueError, tt.commit, branch,
+ 'my message', ['rev1b-id'])
+ self.assertEqual('Cannot supply merge parents for first commit.',
+ str(e))
+ self.assertEqual(_mod_revision.NULL_REVISION, branch.last_revision())
+
+ def test_add_files(self):
+ branch, tt = self.get_branch_and_transform()
+ tt.new_file('file', tt.root, 'contents', 'file-id')
+ trans_id = tt.new_directory('dir', tt.root, 'dir-id')
+ tt.new_symlink('symlink', trans_id, 'target', 'symlink-id')
+ rev = tt.commit(branch, 'message')
+ tree = branch.basis_tree()
+ self.assertEqual('file', tree.id2path('file-id'))
+ self.assertEqual('contents', tree.get_file_text('file-id'))
+ self.assertEqual('dir', tree.id2path('dir-id'))
+ self.assertEqual('dir/symlink', tree.id2path('symlink-id'))
+ self.assertEqual('target', tree.get_symlink_target('symlink-id'))
+
+ def test_add_unversioned(self):
+ branch, tt = self.get_branch_and_transform()
+ tt.new_file('file', tt.root, 'contents')
+ self.assertRaises(errors.StrictCommitFailed, tt.commit, branch,
+ 'message', strict=True)
+
+ def test_modify_strict(self):
+ branch, tt = self.get_branch_and_transform()
+ tt.new_file('file', tt.root, 'contents', 'file-id')
+ tt.commit(branch, 'message', strict=True)
+ tt = TransformPreview(branch.basis_tree())
+ trans_id = tt.trans_id_file_id('file-id')
+ tt.delete_contents(trans_id)
+ tt.create_file('contents', trans_id)
+ tt.commit(branch, 'message', strict=True)
+
+ def test_commit_malformed(self):
+ """Committing a malformed transform should raise an exception.
+
+ In this case, we are adding a file without adding its parent.
+ """
+ branch, tt = self.get_branch_and_transform()
+ parent_id = tt.trans_id_file_id('parent-id')
+ tt.new_file('file', parent_id, 'contents', 'file-id')
+ self.assertRaises(errors.MalformedTransform, tt.commit, branch,
+ 'message')
+
+
class MockTransform(object):
def has_named_child(self, by_parent, parent_id, name):
=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py 2009-07-06 21:22:45 +0000
+++ b/bzrlib/transform.py 2009-07-15 13:45:28 +0000
@@ -442,6 +442,11 @@
conflicts.extend(self._overwrite_conflicts())
return conflicts
+ def _check_malformed(self):
+ conflicts = self.find_conflicts()
+ if len(conflicts) != 0:
+ raise MalformedTransform(conflicts=conflicts)
+
def _add_tree_children(self):
"""Add all the children of all active parents to the known paths.
@@ -859,6 +864,43 @@
"""
return _PreviewTree(self)
+ def commit(self, branch, message, merge_parents=None, strict=False):
+ """Commit the result of this TreeTransform to a branch.
+
+ :param branch: The branch to commit to.
+ :param message: The message to attach to the commit.
+ :param merge_parents: Additional parents specified by pending merges.
+ :return: The revision_id of the revision committed.
+ """
+ self._check_malformed()
+ if strict:
+ unversioned = set(self._new_contents).difference(set(self._new_id))
+ for trans_id in unversioned:
+ if self.final_file_id(trans_id) is None:
+ raise errors.StrictCommitFailed()
+
+ revno, last_rev_id = branch.last_revision_info()
+ if last_rev_id == _mod_revision.NULL_REVISION:
+ if merge_parents is not None:
+ raise ValueError('Cannot supply merge parents for first'
+ ' commit.')
+ parent_ids = []
+ else:
+ parent_ids = [last_rev_id]
+ if merge_parents is not None:
+ parent_ids.extend(merge_parents)
+ if self._tree.get_revision_id() != last_rev_id:
+ raise ValueError('TreeTransform not based on branch basis: %s' %
+ self._tree.get_revision_id())
+ builder = branch.get_commit_builder(parent_ids)
+ preview = self.get_preview_tree()
+ list(builder.record_iter_changes(preview, last_rev_id,
+ self.iter_changes()))
+ builder.finish_inventory()
+ revision_id = builder.commit(message)
+ branch.set_last_revision_info(revno + 1, revision_id)
+ return revision_id
+
def _text_parent(self, trans_id):
file_id = self.tree_file_id(trans_id)
try:
@@ -1354,7 +1396,6 @@
continue
yield self.trans_id_tree_path(childpath)
-
def apply(self, no_conflicts=False, precomputed_delta=None, _mover=None):
"""Apply all changes to the inventory and filesystem.
@@ -1370,9 +1411,7 @@
:param _mover: Supply an alternate FileMover, for testing
"""
if not no_conflicts:
- conflicts = self.find_conflicts()
- if len(conflicts) != 0:
- raise MalformedTransform(conflicts=conflicts)
+ self._check_malformed()
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
try:
if precomputed_delta is None:
More information about the bazaar-commits
mailing list