[Pkg-bazaar-commits] ./bzr-loom/unstable r90: Merge new upstream snapshot.

Jelmer Vernooij jelmer at samba.org
Fri Apr 10 07:14:43 UTC 2009


------------------------------------------------------------
revno: 90
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: experimental
timestamp: Tue 2009-01-13 17:06:51 +0100
message:
  Merge new upstream snapshot.
modified:
  NEWS
  branch.py
  commands.py
  debian/changelog
  debian/control
  tests/blackbox.py
  tests/test_branch.py
  tests/test_tree.py
  tree.py
    ------------------------------------------------------------
    revno: 84.3.1
    committer: Gary Wilson Jr. <gary.wilson at gmail.com>
    branch nick: bzr-loom-trunk
    timestamp: Sun 2008-07-20 22:08:00 -0500
    message:
      Corrected typo in revert-loom command docstring.
    modified:
      commands.py
    ------------------------------------------------------------
    revno: 84.4.1
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: trunk
    timestamp: Mon 2008-11-17 11:47:46 +1100
    message:
      Merge doc typo fix. (Gary Wilson)
    modified:
      commands.py
    ------------------------------------------------------------
    revno: 84.4.2
    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
      branch.py
      commands.py
      tests/blackbox.py
      tests/test_branch.py
      tests/test_tree.py
      tree.py
        ------------------------------------------------------------
        revno: 84.5.1
        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
          tests/blackbox.py
        ------------------------------------------------------------
        revno: 84.5.2
        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
        ------------------------------------------------------------
        revno: 84.5.3
        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
          tests/test_branch.py
        ------------------------------------------------------------
        revno: 84.5.4
        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
        ------------------------------------------------------------
        revno: 84.5.5
        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
        ------------------------------------------------------------
        revno: 84.5.6
        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
        ------------------------------------------------------------
        revno: 84.5.7
        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
        ------------------------------------------------------------
        revno: 84.5.8
        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
        ------------------------------------------------------------
        revno: 84.5.9
        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
        ------------------------------------------------------------
        revno: 84.5.10
        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
        ------------------------------------------------------------
        revno: 84.5.11
        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
          tests/test_tree.py
        ------------------------------------------------------------
        revno: 84.5.12
        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
        ------------------------------------------------------------
        revno: 84.5.13
        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
        ------------------------------------------------------------
        revno: 84.5.14
        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
          tests/blackbox.py
          tests/test_tree.py
          tree.py
        ------------------------------------------------------------
        revno: 84.5.15
        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
        ------------------------------------------------------------
        revno: 84.5.16
        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
          tests/test_branch.py
        ------------------------------------------------------------
        revno: 84.5.17
        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
          tests/test_branch.py
        ------------------------------------------------------------
        revno: 84.5.18
        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
    ------------------------------------------------------------
    revno: 84.4.3
    committer: Jonathan Lange <jml at canonical.com>
    branch nick: trunk
    timestamp: Mon 2008-12-01 15:21:17 +1100
    message:
      Add aliases for up-thread and down-thread.
    modified:
      NEWS
      commands.py
        ------------------------------------------------------------
        revno: 84.6.1
        committer: Jonathan Lange <jml at canonical.com>
        branch nick: up-down-alias
        timestamp: Wed 2008-11-19 18:18:17 +1100
        message:
          Add aliases for up-thread and down-thread, and make them refer to each other in help.
        modified:
          NEWS
          commands.py
    ------------------------------------------------------------
    revno: 84.4.4
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: loom
    timestamp: Fri 2008-12-19 14:04:57 +0100
    message:
      Fix selftest failure.
      
      * commands.py:
      (cmd_up_thread): 'up' alias is already used by 'bzr update'.
    modified:
      commands.py
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2008-07-25 05:24:06 +0000
+++ b/NEWS	2008-11-19 07:18:17 +0000
@@ -24,6 +24,9 @@
     * ``bzr push`` now pushes the last-loom rather than creating an empty loom.
       (Robert Collins, #201613)
 
+    * ``up`` and ``down`` are now aliases for ``up-thread`` and
+      ``down-thread`` respectively.
+
   BUGFIXES:
 
   API BREAKS:

=== 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-17 09:36:54 +0000
+++ b/commands.py	2008-12-19 13:04:57 +0000
@@ -120,7 +120,7 @@
         finally:
             loom.unlock()
 
-            
+
 class cmd_show_loom(bzrlib.commands.Command):
     """Show the threads in this loom.
 
@@ -223,7 +223,7 @@
         """Parse command line and run.
         
         If the command requests it, run the decorated version.
-        """ 
+        """
         try:
             super(cmd_switch, self).run_argv_aliases(list(argv), alias_argv)
         except (errors.MustUseDecorated, errors.BzrOptionError):
@@ -245,7 +245,7 @@
 
 
 class cmd_revert_loom(bzrlib.commands.Command):
-    """Revert part of all of a loom.
+    """Revert part or all of a loom.
     
     This will update the current loom to be the same as the basis when --all
     is supplied. If no parameters or options are supplied then nothing will
@@ -254,7 +254,7 @@
     """
 
     takes_args = ['thread?']
-    takes_options = [Option('all', 
+    takes_options = [Option('all',
                         help='Revert all threads.'),
                      ]
 
@@ -275,18 +275,35 @@
 
 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?']
+    aliases = ['down']
+    _see_also = ['switch', 'up-thread']
 
     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 +314,19 @@
     that thread.
     """
 
-    takes_options = ['merge-type']
-
-    def run(self, merge_type=None):
+    takes_options = ['merge-type', Option('auto',
+        help='Automatically commit and merge repeatedly.')]
+
+    _see_also = ['down-thread', 'switch']
+
+    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 'debian/changelog'
--- a/debian/changelog	2008-11-07 15:12:02 +0000
+++ b/debian/changelog	2009-01-13 16:06:51 +0000
@@ -1,3 +1,9 @@
+bzr-loom (1.4.0~bzr90-1) experimental; urgency=low
+
+  * New upstream snapshot.
+
+ -- Jelmer Vernooij <jelmer at debian.org>  Tue, 13 Jan 2009 17:06:01 +0100
+
 bzr-loom (1.4.0~bzr87-1) unstable; urgency=low
 
   * New upstream snapshot.

=== modified file 'debian/control'
--- a/debian/control	2008-06-14 15:47:29 +0000
+++ b/debian/control	2009-01-13 16:06:51 +0000
@@ -2,13 +2,13 @@
 Section: devel
 Priority: optional
 Maintainer: Debian Bazaar Maintainers <pkg-bazaar-maint at lists.alioth.debian.org>
-Uploaders: Jelmer Vernooij <jelmer at samba.org>
+Uploaders: Jelmer Vernooij <jelmer at debian.org>
 Homepage: https://launchpad.net/bzr-loom
 Build-Depends-Indep: bzr (>= 1.5)
 Build-Depends: python-central (>= 0.5), cdbs (>= 0.4.43), debhelper (>= 5.0.37.2), python-dev
 Standards-Version: 3.8.0
 XS-Python-Version: >= 2.4
-Vcs-Bzr: http://bzr.debian.org/pkg-bazaar/bzr-loom/unstable/
+Vcs-Bzr: http://bzr.debian.org/pkg-bazaar/bzr-loom/experimental
 DM-Upload-Allowed: yes
 
 Package: bzr-loom

=== 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 Pkg-bazaar-commits mailing list