Rev 88: Merge Aaron test fixes, support for stacking, and disabling of down-thread-with-changes. in http://bazaar.launchpad.net/~bzr-loom-devs/bzr-loom/trunk/
Robert Collins
robertc at robertcollins.net
Mon Nov 17 00:58:01 GMT 2008
At http://bazaar.launchpad.net/~bzr-loom-devs/bzr-loom/trunk/
------------------------------------------------------------
revno: 88
revision-id: robertc at robertcollins.net-20081117005800-284m5e4d2hunwpxd
parent: robertc at robertcollins.net-20081117004746-k9uygzdp9y2xsh1d
parent: aaron at aaronbentley.com-20081017192404-b0biybmo0q40rvcm
committer: Robert Collins <robertc at robertcollins.net>
branch nick: trunk
timestamp: Mon 2008-11-17 11:58:00 +1100
message:
Merge Aaron test fixes, support for stacking, and disabling of down-thread-with-changes.
modified:
CONTRIBUTORS CONTRIBUTORS-20060620084702-jnrwijq76kg45klj-2
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
commands.py commands.py-20060620084702-jnrwijq76kg45klj-6
tests/blackbox.py blackbox.py-20060620084702-jnrwijq76kg45klj-7
tests/test_branch.py test_branch.py-20060620084702-jnrwijq76kg45klj-9
tests/test_tree.py test_tree.py-20060701081608-boqb8o8yz1a2bil2-1
tree.py tree.py-20060701085538-3ajq87mglfa5ryqa-1
------------------------------------------------------------
revno: 86.1.18
revision-id: aaron at aaronbentley.com-20081017192404-b0biybmo0q40rvcm
parent: aaron at aaronbentley.com-20081016162441-yavoowvwh7ggrc8j
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Fri 2008-10-17 15:24:04 -0400
message:
Prevent pre-stacking exception by using _synchronize_history.
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.17
revision-id: aaron at aaronbentley.com-20081016162441-yavoowvwh7ggrc8j
parent: aaron at aaronbentley.com-20081010195541-3eteqrbkjvnsitj7
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Thu 2008-10-16 12:24:41 -0400
message:
Ensure require_loom_branc accepts branch7
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
tests/test_branch.py test_branch.py-20060620084702-jnrwijq76kg45klj-9
------------------------------------------------------------
revno: 86.1.16
revision-id: aaron at aaronbentley.com-20081010195541-3eteqrbkjvnsitj7
parent: aaron at aaronbentley.com-20081007003428-0doh0jafbhw3baq0
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Fri 2008-10-10 15:55:41 -0400
message:
Add loom format 7, for compatibility with Branch format 7.
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
tests/test_branch.py test_branch.py-20060620084702-jnrwijq76kg45klj-9
------------------------------------------------------------
revno: 86.1.15
revision-id: aaron at aaronbentley.com-20081007003428-0doh0jafbhw3baq0
parent: aaron at aaronbentley.com-20081002012428-z88nhc4hqwv3et7x
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-10-06 20:34:28 -0400
message:
Fix transport reuse
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.14
revision-id: aaron at aaronbentley.com-20081002012428-z88nhc4hqwv3et7x
parent: aaron at aaronbentley.com-20081001135629-dcngj75q4o5qwdec
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Wed 2008-10-01 21:24:28 -0400
message:
Move up_many onto LoomTreeDecorator, add tests
modified:
commands.py commands.py-20060620084702-jnrwijq76kg45klj-6
tests/blackbox.py blackbox.py-20060620084702-jnrwijq76kg45klj-7
tests/test_tree.py test_tree.py-20060701081608-boqb8o8yz1a2bil2-1
tree.py tree.py-20060701085538-3ajq87mglfa5ryqa-1
------------------------------------------------------------
revno: 86.1.13
revision-id: aaron at aaronbentley.com-20081001135629-dcngj75q4o5qwdec
parent: aaron at aaronbentley.com-20080930125115-ylw0d200m4nj1ww2
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Wed 2008-10-01 09:56:29 -0400
message:
Implement up-thread --auto
modified:
commands.py commands.py-20060620084702-jnrwijq76kg45klj-6
------------------------------------------------------------
revno: 86.1.12
revision-id: aaron at aaronbentley.com-20080930125115-ylw0d200m4nj1ww2
parent: aaron at aaronbentley.com-20080930035310-zrxdxbl7ikg5yj4m
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Tue 2008-09-30 08:51:15 -0400
message:
fix NULL_REVISION handling
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.11
revision-id: aaron at aaronbentley.com-20080930035310-zrxdxbl7ikg5yj4m
parent: aaron at aaronbentley.com-20080930034427-bcnu1gofbiw5kma6
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 23:53:10 -0400
message:
All tests matching loom pass
modified:
tests/blackbox.py blackbox.py-20060620084702-jnrwijq76kg45klj-7
tests/test_tree.py test_tree.py-20060701081608-boqb8o8yz1a2bil2-1
------------------------------------------------------------
revno: 86.1.10
revision-id: aaron at aaronbentley.com-20080930034427-bcnu1gofbiw5kma6
parent: aaron at aaronbentley.com-20080930032650-55izsid6lcaozz44
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 23:44:27 -0400
message:
Handle NULL_REVISION
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.9
revision-id: aaron at aaronbentley.com-20080930032650-55izsid6lcaozz44
parent: aaron at aaronbentley.com-20080930032157-0ds53wiuycl9vdqf
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 23:26:50 -0400
message:
Add get_file_with_stat
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.8
revision-id: aaron at aaronbentley.com-20080930032157-0ds53wiuycl9vdqf
parent: aaron at aaronbentley.com-20080930030721-sylbu6agrhijl4ir
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 23:21:57 -0400
message:
Fix failing tests
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.7
revision-id: aaron at aaronbentley.com-20080930030721-sylbu6agrhijl4ir
parent: aaron at aaronbentley.com-20080929195112-9yqt8kuq4zh3fdvx
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 23:07:21 -0400
message:
Get all but two Branch tests passing
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.6
revision-id: aaron at aaronbentley.com-20080929195112-9yqt8kuq4zh3fdvx
parent: aaron at aaronbentley.com-20080929194207-7fqh0f54oyz5lsjv
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 15:51:12 -0400
message:
Do not error when copy_content_into destination is not a loom
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.5
revision-id: aaron at aaronbentley.com-20080929194207-7fqh0f54oyz5lsjv
parent: aaron at aaronbentley.com-20080929193851-237ik1km7xek09wz
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 15:42:07 -0400
message:
Handle NULL_REVISION in copy_content_into
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.4
revision-id: aaron at aaronbentley.com-20080929193851-237ik1km7xek09wz
parent: aaron at aaronbentley.com-20080922173529-vwosyfd5e4qrw2wx
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-29 15:38:51 -0400
message:
Honour new _override_hook_target param
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
------------------------------------------------------------
revno: 86.1.3
revision-id: aaron at aaronbentley.com-20080922173529-vwosyfd5e4qrw2wx
parent: aaron at aaronbentley.com-20080920160119-i35ovqtxbd4v9wcb
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Mon 2008-09-22 13:35:29 -0400
message:
Correctly populate trees produced by export-loom
modified:
branch.py branch.py-20060620084702-jnrwijq76kg45klj-5
tests/test_branch.py test_branch.py-20060620084702-jnrwijq76kg45klj-9
------------------------------------------------------------
revno: 86.1.2
revision-id: aaron at aaronbentley.com-20080920160119-i35ovqtxbd4v9wcb
parent: aaron at aaronbentley.com-20080905140031-nyf5u3u2a30wu81e
parent: jml at canonical.com-20080912014618-u132uws19xj9uamv
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Sat 2008-09-20 12:01:19 -0400
message:
Merge with trunk
modified:
CONTRIBUTORS CONTRIBUTORS-20060620084702-jnrwijq76kg45klj-2
------------------------------------------------------------
revno: 86.3.1
revision-id: jml at canonical.com-20080912014618-u132uws19xj9uamv
parent: jml at canonical.com-20080725052406-r9rplrdtu8c3gyhm
parent: jml at canonical.com-20080912014434-lw68tqey2k6vevzp
committer: Jonathan Lange <jml at canonical.com>
branch nick: trunk
timestamp: Fri 2008-09-12 11:46:18 +1000
message:
Add myself to contributors.
modified:
CONTRIBUTORS CONTRIBUTORS-20060620084702-jnrwijq76kg45klj-2
------------------------------------------------------------
revno: 86.2.1
revision-id: jml at canonical.com-20080912014434-lw68tqey2k6vevzp
parent: jml at canonical.com-20080725052406-r9rplrdtu8c3gyhm
committer: Jonathan Lange <jml at canonical.com>
branch nick: jml-contributed
timestamp: Fri 2008-09-12 11:44:34 +1000
message:
Add myself to contributors.
modified:
CONTRIBUTORS CONTRIBUTORS-20060620084702-jnrwijq76kg45klj-2
------------------------------------------------------------
revno: 86.1.1
revision-id: aaron at aaronbentley.com-20080905140031-nyf5u3u2a30wu81e
parent: jml at canonical.com-20080725052406-r9rplrdtu8c3gyhm
committer: Aaron Bentley <aaron at aaronbentley.com>
branch nick: loom
timestamp: Fri 2008-09-05 10:00:31 -0400
message:
Make down-thread error on uncommitted changes
modified:
commands.py commands.py-20060620084702-jnrwijq76kg45klj-6
tests/blackbox.py blackbox.py-20060620084702-jnrwijq76kg45klj-7
=== modified file 'CONTRIBUTORS'
--- a/CONTRIBUTORS 2008-02-28 11:15:18 +0000
+++ b/CONTRIBUTORS 2008-09-12 01:44:34 +0000
@@ -2,3 +2,4 @@
Scott James Remnant <scott at canonical.com>
Aaron Bentley <aaron.bentley at canonical.com>
Rob Weir <rweir at ertius.org>
+Jonathan Lange <jml at mumak.net>
=== modified file 'branch.py'
--- a/branch.py 2008-05-23 03:04:33 +0000
+++ b/branch.py 2008-10-17 19:24:04 +0000
@@ -52,24 +52,22 @@
"""
try:
branch.lock_write()
- if branch._format.__class__ == bzrlib.branch.BzrBranchFormat5:
- format = BzrBranchLoomFormat1()
- format.take_over(branch)
- elif branch._format.__class__ == bzrlib.branch.BzrBranchFormat6:
- format = BzrBranchLoomFormat6()
- format.take_over(branch)
- else:
+ try:
+ format = {
+ bzrlib.branch.BzrBranchFormat5: BzrBranchLoomFormat1,
+ bzrlib.branch.BzrBranchFormat6: BzrBranchLoomFormat6,
+ bzrlib.branch.BzrBranchFormat7: BzrBranchLoomFormat7,
+ }[branch._format.__class__]()
+ except KeyError:
raise UnsupportedBranchFormat(branch._format)
+ format.take_over(branch)
finally:
branch.unlock()
def require_loom_branch(branch):
"""Return None if branch is already loomified, or raise NotALoom."""
- if not branch._format.__class__ in (
- BzrBranchLoomFormat1,
- BzrBranchLoomFormat6,
- ):
+ if not branch._format.__class__ in LOOM_FORMATS:
raise NotALoom(branch)
@@ -155,7 +153,10 @@
As usual this must be for the single existing file 'loom'.
"""
return self._loom_stream
-
+
+ def get_file_with_stat(self, file_id, path=None):
+ return (self.get_file(file_id, path), None)
+
def get_file_sha1(self, file_id, path):
"""Get the sha1 for a file.
@@ -249,8 +250,7 @@
else:
loom_tip = None
threads = self.get_threads(state.get_basis_revision_id())
- new_history = self.revision_history()
- if revision_id is not None:
+ if revision_id not in (None, NULL_REVISION):
if threads:
# revision_id should be in the loom, or its an error
found_threads = [thread for thread, rev in threads
@@ -260,14 +260,7 @@
# side has not been recorded yet, so its data is not
# present at this point.
raise UnrecordedRevision(self, revision_id)
- else:
- # no threads yet, be a normal branch
- try:
- new_history = new_history[:new_history.index(revision_id) + 1]
- except ValueError:
- rev = self.repository.get_revision(revision_id)
- new_history = rev.get_history(self.repository)[1:]
-
+
# pull in the warp, which was skipped during the initial pull
# because the front end does not know what to pull.
# nb: this is mega huge hacky. THINK. RBC 2006062
@@ -284,19 +277,23 @@
finally:
nested.finished()
state = loom_state.LoomState()
- if threads:
- last_rev = threads[-1][1]
- if last_rev == EMPTY_REVISION:
- last_rev = bzrlib.revision.NULL_REVISION
- destination.generate_revision_history(last_rev)
- state.set_parents([loom_tip])
- state.set_threads(
- (thread + ([thread[1]],) for thread in threads)
- )
- else:
- # no threads yet, be a normal branch.
- destination.set_revision_history(new_history)
- destination._set_last_loom(state)
+ try:
+ require_loom_branch(destination)
+ if threads:
+ last_rev = threads[-1][1]
+ if last_rev == EMPTY_REVISION:
+ last_rev = bzrlib.revision.NULL_REVISION
+ destination.generate_revision_history(last_rev)
+ state.set_parents([loom_tip])
+ state.set_threads(
+ (thread + ([thread[1]],) for thread in threads)
+ )
+ else:
+ # no threads yet, be a normal branch.
+ self._synchronize_history(destination, revision_id)
+ destination._set_last_loom(state)
+ except NotALoom:
+ self._synchronize_history(destination, revision_id)
try:
parent = self.get_parent()
except bzrlib.errors.InaccessibleParent, e:
@@ -358,13 +355,16 @@
user_location = bzrlib.urlutils.unescape_for_display(
thread_transport.base, 'utf-8')
try:
- branch = bzrlib.branch.Branch.open_from_transport(
- thread_transport)
+ control_dir = bzrdir.BzrDir.open(thread_transport.base,
+ possible_transports=[thread_transport])
+ tree, branch = control_dir._get_tree_branch()
except bzrlib.errors.NotBranchError:
bzrlib.trace.note('Creating branch at %s' % user_location)
branch = bzrdir.BzrDir.create_branch_convenience(
thread_transport.base,
possible_transports=[thread_transport])
+ tree, branch = branch.bzrdir.open_tree_or_branch(
+ thread_transport.base)
else:
if thread_revision == branch.last_revision():
bzrlib.trace.note('Skipping up-to-date branch at %s'
@@ -372,7 +372,10 @@
continue
else:
bzrlib.trace.note('Updating branch at %s' % user_location)
- branch.pull(self, stop_revision=thread_revision)
+ if tree is not None:
+ tree.pull(self, stop_revision=thread_revision)
+ else:
+ branch.pull(self, stop_revision=thread_revision)
def _loom_content(self, rev_id):
"""Return the raw formatted content of a loom as a series of lines.
@@ -432,7 +435,7 @@
@needs_write_lock
def pull(self, source, overwrite=False, stop_revision=None,
- run_hooks=True, possible_transports=None):
+ run_hooks=True, possible_transports=None, _override_hook_target=None):
"""Pull from a branch into this loom.
If the remote branch is a non-loom branch, the pull is done against the
@@ -442,110 +445,21 @@
if not isinstance(source, LoomSupport):
return super(LoomSupport, self).pull(source,
overwrite=overwrite, stop_revision=stop_revision,
- possible_transports=possible_transports)
- # pull the loom, and position our
- pb = bzrlib.ui.ui_factory.nested_progress_bar()
- result = bzrlib.branch.PullResult()
- result.source_branch = source
- result.target_branch = self
- # cannot bind currently
- result.local_branch = None
- result.master_branch = self
- try:
- result.old_revno, result.old_revid = self.last_revision_info()
- source.lock_read()
- try:
- source_state = source.get_loom_state()
- source_parents = source_state.get_parents()
- if not source_parents:
- # no thread commits ever
- # just pull the main branch.
- new_rev = source.last_revision()
- self.repository.fetch(source.repository,
- revision_id=new_rev)
- if not overwrite:
- new_rev_ancestry = source.repository.get_ancestry(
- new_rev)
- last_rev = self.last_revision()
- # get_ancestry returns None for NULL_REVISION currently.
- if last_rev == NULL_REVISION:
- last_rev = None
- if last_rev not in new_rev_ancestry:
- raise bzrlib.errors.DivergedBranches(self, source)
- old_count = len(self.revision_history())
- if new_rev == EMPTY_REVISION:
- new_rev = bzrlib.revision.NULL_REVISION
- self.generate_revision_history(new_rev)
- # get the final result object details
- result.tag_conflicts = None
- result.new_revno, result.new_revid = self.last_revision_info()
- if run_hooks:
- for hook in bzrlib.branch.Branch.hooks['post_pull']:
- hook(result)
- return result
- # pulling a loom
- # the first parent is the 'tip' revision.
- my_state = self.get_loom_state()
- source_loom_rev = source_state.get_parents()[0]
- if not overwrite:
- # is the loom compatible?
- if len(my_state.get_parents()) > 0:
- source_ancestry = source.repository.get_ancestry(
- source_loom_rev)
- if my_state.get_parents()[0] not in source_ancestry:
- raise bzrlib.errors.DivergedBranches(self, source)
- # fetch the loom content
- self.repository.fetch(source.repository,
- revision_id=source_loom_rev)
- # get the threads for the new basis
- threads = self.get_threads(source_state.get_basis_revision_id())
- # stopping at from our repository.
- revisions = [rev for name,rev in threads]
- # for each thread from top to bottom, retrieve its referenced
- # content. XXX FIXME: a revision_ids parameter to fetch would be
- # nice here.
- # the order is reversed because the common case is for the top
- # thread to include all content.
- for rev_id in reversed(revisions):
- if rev_id not in (EMPTY_REVISION,
- bzrlib.revision.NULL_REVISION):
- # fetch the loom content for this revision
- self.repository.fetch(source.repository,
- revision_id=rev_id)
- # set our work threads to match (this is where we lose data if
- # there are local mods)
- my_state.set_threads(
- (thread + ([thread[1]],) for thread in threads)
- )
- # and the new parent data
- my_state.set_parents([source_loom_rev])
- # and save the state.
- self._set_last_loom(my_state)
- # set the branch nick.
- self.nick = threads[-1][0]
- # and position the branch on the top loom
- new_rev = threads[-1][1]
- if new_rev == EMPTY_REVISION:
- new_rev = bzrlib.revision.NULL_REVISION
- self.generate_revision_history(new_rev)
- # get the final result object details
- result.tag_conflicts = None
- result.new_revno, result.new_revid = self.last_revision_info()
- if run_hooks:
- for hook in bzrlib.branch.Branch.hooks['post_pull']:
- hook(result)
- return result
- finally:
- source.unlock()
- finally:
- pb.finished()
+ possible_transports=possible_transports,
+ _override_hook_target=_override_hook_target)
+ return _Puller(source, self).transfer(overwrite, stop_revision,
+ run_hooks, possible_transports, _override_hook_target)
@needs_read_lock
def push(self, target, overwrite=False, stop_revision=None,
_override_hook_source_branch=None):
# Not ideal, but see the issues raised on bazaar at lists.canonical.com
# about the push api needing work.
- return target.pull(self, overwrite=overwrite, stop_revision=stop_revision)
+ if not isinstance(target, LoomSupport):
+ return super(LoomSupport, self).push(target, overwrite,
+ stop_revision, _override_hook_source_branch=None)
+ return _Pusher(self, target).transfer(overwrite, stop_revision,
+ run_hooks=True)
@needs_write_lock
def record_loom(self, commit_message):
@@ -689,6 +603,151 @@
super(LoomSupport, self).unlock()
+class _Puller(object):
+
+ def __init__(self, source, target):
+ self.target = target
+ self.source = source
+
+ def prepare_result(self, _override_hook_target):
+ result = self.make_result()
+ result.source_branch = self.source
+ result.target_branch = _override_hook_target
+ if result.target_branch is None:
+ result.target_branch = self.target
+ # cannot bind currently
+ result.local_branch = None
+ result.master_branch = self.target
+ result.old_revno, result.old_revid = self.target.last_revision_info()
+ return result
+
+ def finish_result(self, result):
+ result.tag_conflicts = None
+ result.new_revno, result.new_revid = self.target.last_revision_info()
+
+ def do_hooks(self, result, run_hooks):
+ self.finish_result(result)
+ # get the final result object details
+ if run_hooks:
+ for hook in self.post_hooks():
+ hook(result)
+ return result
+
+ @staticmethod
+ def make_result():
+ return bzrlib.branch.PullResult()
+
+ @staticmethod
+ def post_hooks():
+ return bzrlib.branch.Branch.hooks['post_pull']
+
+ def plain_transfer(self, result, run_hooks, stop_revision, overwrite):
+ # no thread commits ever
+ # just pull the main branch.
+ new_rev = stop_revision
+ if new_rev is None:
+ new_rev = self.source.last_revision()
+ if new_rev == EMPTY_REVISION:
+ new_rev = bzrlib.revision.NULL_REVISION
+ self.target.repository.fetch(self.source.repository,
+ revision_id=new_rev)
+ if not overwrite:
+ new_rev_ancestry = self.source.repository.get_ancestry(
+ new_rev)
+ last_rev = self.target.last_revision()
+ # get_ancestry returns None for NULL_REVISION currently.
+ if last_rev == NULL_REVISION:
+ last_rev = None
+ if last_rev not in new_rev_ancestry:
+ raise bzrlib.errors.DivergedBranches(
+ self.target, self.source)
+ self.target.generate_revision_history(new_rev)
+ # get the final result object details
+ self.do_hooks(result, run_hooks)
+ return result
+
+ def transfer(self, overwrite, stop_revision, run_hooks=True,
+ possible_transports=None, _override_hook_target=None):
+ """Implementation of push and pull"""
+ # pull the loom, and position our
+ pb = bzrlib.ui.ui_factory.nested_progress_bar()
+ try:
+ result = self.prepare_result(_override_hook_target)
+ self.target.lock_write()
+ self.source.lock_read()
+ try:
+ source_state = self.source.get_loom_state()
+ source_parents = source_state.get_parents()
+ if not source_parents:
+ return self.plain_transfer(result, run_hooks,
+ stop_revision, overwrite)
+ # pulling a loom
+ # the first parent is the 'tip' revision.
+ my_state = self.target.get_loom_state()
+ source_loom_rev = source_state.get_parents()[0]
+ if not overwrite:
+ # is the loom compatible?
+ if len(my_state.get_parents()) > 0:
+ source_ancestry = self.source.repository.get_ancestry(
+ source_loom_rev)
+ if my_state.get_parents()[0] not in source_ancestry:
+ raise bzrlib.errors.DivergedBranches(
+ self.target, self.source)
+ # fetch the loom content
+ self.target.repository.fetch(self.source.repository,
+ revision_id=source_loom_rev)
+ # get the threads for the new basis
+ threads = self.target.get_threads(
+ source_state.get_basis_revision_id())
+ # stopping at from our repository.
+ revisions = [rev for name,rev in threads]
+ # for each thread from top to bottom, retrieve its referenced
+ # content. XXX FIXME: a revision_ids parameter to fetch would be
+ # nice here.
+ # the order is reversed because the common case is for the top
+ # thread to include all content.
+ for rev_id in reversed(revisions):
+ if rev_id not in (EMPTY_REVISION,
+ bzrlib.revision.NULL_REVISION):
+ # fetch the loom content for this revision
+ self.target.repository.fetch(self.source.repository,
+ revision_id=rev_id)
+ # set our work threads to match (this is where we lose data if
+ # there are local mods)
+ my_state.set_threads(
+ (thread + ([thread[1]],) for thread in threads)
+ )
+ # and the new parent data
+ my_state.set_parents([source_loom_rev])
+ # and save the state.
+ self.target._set_last_loom(my_state)
+ # set the branch nick.
+ self.target.nick = threads[-1][0]
+ # and position the branch on the top loom
+ new_rev = threads[-1][1]
+ if new_rev == EMPTY_REVISION:
+ new_rev = bzrlib.revision.NULL_REVISION
+ self.target.generate_revision_history(new_rev)
+ self.do_hooks(result, run_hooks)
+ return result
+ finally:
+ self.source.unlock()
+ self.target.unlock()
+ finally:
+ pb.finished()
+
+
+class _Pusher(_Puller):
+
+ @staticmethod
+ def make_result():
+ return bzrlib.branch.PushResult()
+
+ @staticmethod
+ def post_hooks():
+ return bzrlib.branch.Branch.hooks['post_push']
+
+
class LoomBranch(LoomSupport, bzrlib.branch.BzrBranch5):
"""The Loom branch.
@@ -705,6 +764,15 @@
"""
+class LoomBranch7(LoomSupport, bzrlib.branch.BzrBranch7):
+ """Branch6 Loom branch.
+
+ A mixin is used as the easiest migration path to support branch7.
+ A rewrite would be preferable, but a stackable loom format is needed
+ quickly.
+ """
+
+
class LoomFormatMixin(object):
"""Support code for Loom formats."""
# A mixin is not ideal because it is tricky to test, but it seems to be the
@@ -821,5 +889,40 @@
return "bzr loom format 6 (based on bzr branch format 6)\n"
+class BzrBranchLoomFormat7(LoomFormatMixin, bzrlib.branch.BzrBranchFormat7):
+ """Loom's second edition - based on bzr's Branch7.
+
+ This format is an extension to BzrBranchFormat7 with the following changes:
+ - a last-loom file.
+
+ The last-loom file has a revision id in it which points into the loom
+ data branch in the repository.
+
+ This format is new in the loom plugin.
+ """
+
+ _branch_class = LoomBranch7
+ _parent_classs = bzrlib.branch.BzrBranchFormat7
+
+ def get_format_string(self):
+ """See BranchFormat.get_format_string()."""
+ return "Bazaar-NG Loom branch format 7\n"
+
+ def get_format_description(self):
+ """See BranchFormat.get_format_description()."""
+ return "Loom branch format 7"
+
+ def __str__(self):
+ return "bzr loom format 7 (based on bzr branch format 7)\n"
+
+
bzrlib.branch.BranchFormat.register_format(BzrBranchLoomFormat1())
bzrlib.branch.BranchFormat.register_format(BzrBranchLoomFormat6())
+bzrlib.branch.BranchFormat.register_format(BzrBranchLoomFormat7())
+
+
+LOOM_FORMATS = [
+ BzrBranchLoomFormat1,
+ BzrBranchLoomFormat6,
+ BzrBranchLoomFormat7,
+]
=== modified file 'commands.py'
--- a/commands.py 2008-07-21 03:08:00 +0000
+++ b/commands.py 2008-11-17 00:58:00 +0000
@@ -275,18 +275,34 @@
class cmd_down_thread(bzrlib.commands.Command):
"""Move the branch down a thread in the loom.
-
+
This removes the changes introduced by the current thread from the branch
and sets the branch to be the next thread down.
+
+ Down-thread refuses to operate if there are uncommitted changes, since
+ this is typically a mistake. Switch can be used for this purpose, instead.
"""
takes_args = ['thread?']
+ _see_also = ['switch']
def run(self, thread=None):
- (tree, path) = workingtree.WorkingTree.open_containing('.')
- branch.require_loom_branch(tree.branch)
- tree = LoomTreeDecorator(tree)
- return tree.down_thread(thread)
+ (wt, path) = workingtree.WorkingTree.open_containing('.')
+ branch.require_loom_branch(wt.branch)
+ tree = LoomTreeDecorator(wt)
+ tree.lock_write()
+ try:
+ basis = wt.basis_tree()
+ basis.lock_read()
+ try:
+ for change in wt.iter_changes(basis):
+ raise errors.BzrCommandError(
+ 'Working tree has uncommitted changes.')
+ finally:
+ basis.unlock()
+ return tree.down_thread(thread)
+ finally:
+ tree.unlock()
class cmd_up_thread(bzrlib.commands.Command):
@@ -297,13 +313,17 @@
that thread.
"""
- takes_options = ['merge-type']
+ takes_options = ['merge-type', Option('auto',
+ help='Automatically commit and merge repeatedly.')]
- def run(self, merge_type=None):
+ def run(self, merge_type=None, auto=False):
(tree, path) = workingtree.WorkingTree.open_containing('.')
branch.require_loom_branch(tree.branch)
tree = LoomTreeDecorator(tree)
- return tree.up_thread(merge_type)
+ if not auto:
+ return tree.up_thread(merge_type)
+ else:
+ return tree.up_many(merge_type)
class cmd_export_loom(bzrlib.commands.Command):
=== modified file 'tests/blackbox.py'
--- a/tests/blackbox.py 2008-07-17 09:36:54 +0000
+++ b/tests/blackbox.py 2008-10-02 01:24:28 +0000
@@ -21,6 +21,7 @@
import os
import bzrlib
+from bzrlib import branch as _mod_branch
from bzrlib import workingtree
from bzrlib.plugins.loom.branch import EMPTY_REVISION
from bzrlib.plugins.loom.tree import LoomTreeDecorator
@@ -384,6 +385,17 @@
"""We should raise a user-friendly exception if the branch isn't loomed yet."""
self.assert_exception_raised_on_non_loom_branch(['down-thread'])
+ def test_down_thread_with_changes(self):
+ """Trying to down-thread with changes causes an error."""
+ tree = self.get_vendor_loom()
+ tree.branch.new_thread('upper-thread')
+ tree.branch.nick = 'upper-thread'
+ self.build_tree(['new-file'])
+ tree.add('new-file')
+ out, err = self.run_bzr('down-thread', retcode=3)
+ self.assertEqual('bzr: ERROR: Working tree has uncommitted changes.\n',
+ err)
+
class TestUp(TestsWithLooms):
@@ -471,6 +483,14 @@
self.run_bzr(['down-thread'])
self.run_bzr(['up-thread', '--lca'])
+ def test_up_thread_auto(self):
+ tree = self.get_vendor_loom()
+ tree.branch.new_thread('middle')
+ tree.branch.new_thread('top')
+ self.run_bzr('up-thread --auto')
+ branch = _mod_branch.Branch.open('.')
+ self.assertEqual('top', branch.nick)
+
class TestPush(TestsWithLooms):
@@ -522,7 +542,7 @@
out, err = self.run_bzr(['pull'])
finally:
os.chdir('..')
- self.assertStartsWith(out, 'Using saved location:')
+ self.assertStartsWith(out, 'Using saved parent location:')
self.assertEndsWith(out, 'Now on revision 2.\n')
self.assertEqual(
'All changes applied successfully.\n',
=== modified file 'tests/test_branch.py'
--- a/tests/test_branch.py 2008-04-10 00:38:37 +0000
+++ b/tests/test_branch.py 2008-10-16 16:24:41 +0000
@@ -34,6 +34,8 @@
import bzrlib.revision
from bzrlib.revision import NULL_REVISION
from bzrlib.tests import TestCaseWithTransport
+from bzrlib.transport import get_transport
+from bzrlib.workingtree import WorkingTree
class TestFormat(TestCaseWithTransport):
@@ -65,13 +67,23 @@
branch = self.make_branch('.')
self.assertRaises(NotALoom, require_loom_branch, branch)
- def test_on_loom(self):
- branch = self.make_branch('.')
+
+ def works_on_loom(self, format):
+ branch = self.make_branch('.', format)
loomify(branch)
# reopen it
branch = branch.bzrdir.open_branch()
self.assertEqual(None, require_loom_branch(branch))
+ def test_works_on_loom1(self):
+ self.works_on_loom('knit')
+
+ def test_works_on_loom6(self):
+ self.works_on_loom('pack-0.92')
+
+ def test_works_on_loom7(self):
+ self.works_on_loom('1.6')
+
class TestLoomify(TestCaseWithTransport):
@@ -113,6 +125,12 @@
bzrlib.plugins.loom.branch.LoomBranch6,
bzrlib.plugins.loom.branch.BzrBranchLoomFormat6)
+ def test_loomify_branch_format_7(self):
+ branch = self.make_branch('.', format='1.6')
+ loomify(branch)
+ self.assertConvertedBranchFormat(branch,
+ bzrlib.plugins.loom.branch.LoomBranch7,
+ bzrlib.plugins.loom.branch.BzrBranchLoomFormat7)
class TestLoom(TestCaseWithLoom):
@@ -595,3 +613,25 @@
self.assertEqual('thread1-id', thread1.last_revision())
thread2 = Branch.open_from_transport(root_transport.clone('thread2'))
self.assertEqual('thread2-id', thread2.last_revision())
+
+ def test_export_loom_as_tree(self):
+ tree = self.get_multi_threaded()
+ tree.branch.bzrdir.root_transport.mkdir('root')
+ root_transport = tree.branch.bzrdir.root_transport.clone('root')
+ tree.branch.export_threads(root_transport)
+ export_tree = WorkingTree.open(root_transport.local_abspath('thread1'))
+ self.assertEqual('thread1-id', export_tree.last_revision())
+
+ def test_export_loom_as_branch(self):
+ tree = self.get_multi_threaded()
+ tree.branch.bzrdir.root_transport.mkdir('root')
+ root_path = tree.branch.bzrdir.root_transport.local_abspath('root')
+ repo = self.make_repository('root', shared=True)
+ repo.set_make_working_trees(False)
+ root_transport = get_transport('root')
+ tree.branch.export_threads(root_transport)
+ self.assertRaises(errors.NoWorkingTree, WorkingTree.open,
+ root_transport.local_abspath('thread1'))
+ export_branch = Branch.open_from_transport(
+ root_transport.clone('thread1'))
+ self.assertEqual('thread1-id', export_branch.last_revision())
=== modified file 'tests/test_tree.py'
--- a/tests/test_tree.py 2008-03-20 06:02:24 +0000
+++ b/tests/test_tree.py 2008-10-02 01:24:28 +0000
@@ -98,7 +98,7 @@
tree_loom_tree.down_thread()
# check the test will be valid
self.assertEqual([None, bottom_rev1, top_rev1],
- tree.branch.repository.get_ancestry([top_rev1]))
+ tree.branch.repository.get_ancestry(top_rev1))
self.assertEqual([bottom_rev1], tree.get_parent_ids())
tree_loom_tree.up_thread()
self.assertEqual('top', tree.branch.nick)
@@ -117,7 +117,7 @@
tree_loom_tree.down_thread()
# check the test will be valid
self.assertEqual([None, bottom_rev1, top_rev1],
- tree.branch.repository.get_ancestry([top_rev1]))
+ tree.branch.repository.get_ancestry(top_rev1))
self.assertEqual([bottom_rev1], tree.get_parent_ids())
bottom_rev2 = tree.commit('bottom_two', allow_pointless=True)
tree_loom_tree.up_thread()
@@ -146,6 +146,51 @@
loom_tree.up_thread(_mod_merge.WeaveMerger)
self.failIfExists('source/a.BASE')
+ def get_loom_with_three_threads(self):
+ tree = self.get_tree_with_loom('source')
+ tree.branch.new_thread('bottom')
+ tree.branch.new_thread('middle')
+ tree.branch.new_thread('top')
+ tree.branch.nick = 'bottom'
+ return bzrlib.plugins.loom.tree.LoomTreeDecorator(tree)
+
+ def test_up_many(self):
+ loom_tree = self.get_loom_with_three_threads()
+ loom_tree.up_many()
+ self.assertEqual('top', loom_tree.tree.branch.nick)
+ self.assertEqual([], loom_tree.tree.get_parent_ids())
+
+ def test_up_many_commits(self):
+ loom_tree = self.get_loom_with_two_threads()
+ loom_tree.tree.commit('bottom', rev_id='bottom-1')
+ loom_tree.up_thread()
+ loom_tree.tree.commit('top', rev_id='top-1')
+ loom_tree.down_thread()
+ loom_tree.tree.commit('bottom', rev_id='bottom-2')
+ loom_tree.up_many()
+ last_revision = loom_tree.tree.last_revision()
+ self.assertNotEqual(last_revision, 'top-1')
+ rev = loom_tree.tree.branch.repository.get_revision(last_revision)
+ self.assertEqual(['top-1', 'bottom-2'], rev.parent_ids)
+ self.assertEqual('Merge bottom into top', rev.message)
+
+ def test_up_many_halts_on_conflicts(self):
+ loom_tree = self.get_loom_with_three_threads()
+ tree = loom_tree.tree
+ self.build_tree_contents([('source/file', 'contents-a')])
+ tree.add('file')
+ tree.commit('bottom', rev_id='bottom-1')
+ loom_tree.up_thread()
+ self.build_tree_contents([('source/file', 'contents-b')])
+ tree.commit('middle', rev_id='middle-1')
+ loom_tree.down_thread()
+ self.build_tree_contents([('source/file', 'contents-c')])
+ tree.commit('bottom', rev_id='bottom-2')
+ loom_tree.up_many()
+ self.assertEqual('middle', tree.branch.nick)
+ self.assertEqual(['middle-1', 'bottom-2'], tree.get_parent_ids())
+ self.assertEqual(1, len(tree.conflicts()))
+
def test_revert_loom(self):
tree = self.get_tree_with_loom(',')
# ensure we have some stuff to revert
=== modified file 'tree.py'
--- a/tree.py 2008-04-24 16:13:06 +0000
+++ b/tree.py 2008-10-02 01:24:28 +0000
@@ -133,6 +133,17 @@
else:
return 0
+ def up_many(self, merge_type=None):
+ threads = self.branch.get_loom_state().get_threads()
+ top_thread_name = threads[-1][0]
+ while self.branch.nick != top_thread_name:
+ old_nick = self.branch.nick
+ if self.up_thread(merge_type) != 0:
+ break
+ if len(self.tree.get_parent_ids()) > 1:
+ self.tree.commit('Merge %s into %s' % (old_nick,
+ self.branch.nick))
+
@needs_write_lock
def down_thread(self, name=None):
"""Move to a thread down in the loom.
More information about the bazaar-commits
mailing list