Merge 0.3.4 release.
authorJelmer Vernooij <jelmer@samba.org>
Sun, 24 Jun 2007 18:14:04 +0000 (20:14 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Sun, 24 Jun 2007 18:14:04 +0000 (20:14 +0200)
1  2 
NEWS
README
__init__.py
checkout.py
tests/test_workingtree.py

diff --combined NEWS
index d2b530389c7cdea0bf5c2e90b76db121ac0a677e,0dfc5769613ae35339e2c1a6e3307282f5f3edb1..76802bb7606e77172c3805d9b62bb8f1b75be11b
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,55 -1,17 +1,57 @@@
- bzr-svn 0.3.4 UNRELEASED
 +bzr-svn 0.4   UNRELEASED
 +  
 +  BUG FIXES
 +
 +   * Non-ascii characters in file ids are now supported (fixes imports 
 +     of the Python repository).
 +
 +   * Fixed error raised during version incompatibility. (Wouter van Heyst, 
 +                                                         #80467)
 +
 +   * Implemented Repository.get_revision_graph(None)
 +
 +   * svn-import will no longer spin using CPU if the target directory 
 +     did not exist (#80223).
 +
 +   * Remove branches when they are being replaced. Fixes DivergedBranches 
 +     error when using svn-import (#81908).
 +
 +   * Support true push (#80612).
 +
 +   * Support commits in heavy checkouts (#79330).
 +   
 +   * Use shared repositories by default in svn-import command.
 +
 +   * Put branching schemes in revision ids.
 +
 +   * Support using custom branching schemes.
 +
 +  PERFORMANCE
 +
 +   * do_update() is now used to find the contents of a directory recursively. 
 +     This should reduce the number of roundtrips significantly when 
 +       finding file id mappings.
 +
 +  INTERNALS
 +
 +   * Implement SvnRaTransport.local_abspath(). (#117090)
 +
 +   * Implement SvnRemoteAccess.create_branch().
 +
+ bzr-svn 0.3.4 2007-06-15
  
    BUG FIXES
  
    * Check for a working pysqlite, rather than checking that the 
      first one found works. (#115026)
  
+   * Fix compatibility with Bazaar 0.17.
  bzr-svn 0.3.3 2007-04-29
  
    IMPROVEMENTS
  
-   * Fix compatibility with 0.16 (#110164)
+   * Fix compatibility with Bazaar 0.16 (#110164)
  
    * Don't do extra checkout before push if possible. (#91885)
  
diff --combined README
index 26405274852ff6b3f584af6c714c8f4264d9778c,9107f6c545d489b89a8ff0dfde22f12d20615cba..47bee4f5f404119aad2e227bfe8659c69e9954c3
--- 1/README
--- 2/README
+++ b/README
@@@ -14,12 -14,12 +14,12 @@@ to and view logs of Subversion branche
  Dependencies
  ============
  
 -You will need at least version 0.14 of Bazaar or higher.
 +You will need at least version 0.15 of Bazaar or higher.
  
  You also need a fairly recent version of the Python bindings to the 
  Subversion libraries. At the moment, the svn plugin only works with 
 -Subversion 1.5 (trunk). The python-subversion package in Ubuntu Edgy and 
 -Debian Sid also contains the required changes.
 +Subversion 1.5 (trunk). The python-subversion package in Ubuntu Feisty 
 +and Debian Etch and Sid also contain the required changes. 
  
  If you are running an older version of Python (under 2.5), you will also 
  need to have the pysqlite package installed.
@@@ -79,14 -79,28 +79,14 @@@ In the future, I also hope to support
    but the number of corner cases is wide, so support for this 
    has not been enabled by default yet.
  
 -- "True" push. This requires storing the Bazaar 
 -  inventory and revision in Subversion revision properties.
 -
 -  Ideally, revision id aliases would have to be used so the 
 -  revision id that is being 'overriden' can still exist.
 -
 -  Once this is implemented, it would also be possible and 
 -  make sense to store GPG signatures for commits in 
 -  Subversion branches.
 -
 -  This might require also storing 'bzr:inventory' and 'bzr:revision' 
 -  properties in order to make sure the sha1's for a revision keep matching.
 -
 -- Proper read locking, which has basically been ignored for now. 
 -
 -- Performance. Network-wise (both bandwidth and roundtrips), the plugin is in
 -  good shape. However, it is currently quite CPU-intensive for no good reason 
 -  and I hope to make a couple of improvements in that area.
 +- Better performance. Network-wise (both bandwidth and roundtrips), the plugin 
 +  is in good shape. However, it is currently quite CPU-intensive for no good 
 +  reason and I hope to make a couple of improvements in that area.
  
  - Override implementation of get_revision_delta(). Will speed up 'bzr log -v'
        
 -- use svn_ra_replay() on systems that have Subversion 1.4. Saves a couple of roundtrips when fetching history.
 +- use svn_ra_replay() on systems that have Subversion 1.4. Saves a couple of 
 +  roundtrips when fetching history.
  
  - implement svn_ra_get_dir_revs() in Subversion to fetch the properties set on 
    a specific directory all at once.
@@@ -148,4 -162,5 +148,5 @@@ Installatio
  ============
  
  Simply place this directory in ~/.bazaar/plugins and you should be able 
- to check out branches from Subversion using bzr.
+ to check out branches from Subversion using bzr. Make sure the directory 
+ name is 'svn'.
diff --combined __init__.py
index bb08b41edd5ce1005358004a5c1a18ffbb62d1c3,0aaa6ec8023eab0142ca9aef6f12f5bfa3c5499b..52bc01906245f04667b681eb3577e566cbf3ced4
@@@ -24,8 -24,8 +24,8 @@@ import bzrli
  
  from bzrlib.trace import warning
  
 -__version__ = '0.3.5'
 +__version__ = '0.4.0'
- COMPATIBLE_BZR_VERSIONS = [(0, 15), (0, 16), (0, 17)]
+ COMPATIBLE_BZR_VERSIONS = [(0, 15), (0, 16), (0, 17), (0, 18)]
  
  def check_bzrlib_version(desired):
      """Check that bzrlib is compatible.
@@@ -76,18 -76,19 +76,18 @@@ from bzrlib.bzrdir import BzrDirForma
  
  from bzrlib.repository import InterRepository
  
 -from fetch import InterSvnRepository
 +from fetch import InterFromSvnRepository
 +from commit import InterToSvnRepository
  
  BzrDirFormat.register_control_format(format.SvnFormat)
  
  import svn.core
  _subr_version = svn.core.svn_subr_version()
  
 -if _subr_version.major == 1 and _subr_version.minor < 4:
 -    warning('Subversion version too old for working tree support.')
 -else:
 -    BzrDirFormat.register_control_format(checkout.SvnWorkingTreeDirFormat)
 +BzrDirFormat.register_control_format(checkout.SvnWorkingTreeDirFormat)
  
 -InterRepository.register_optimiser(InterSvnRepository)
 +InterRepository.register_optimiser(InterFromSvnRepository)
 +InterRepository.register_optimiser(InterToSvnRepository)
  
  from bzrlib.branch import Branch
  from bzrlib.commands import Command, register_command, display_command, Option
@@@ -112,16 -113,16 +112,16 @@@ class cmd_svn_import(Command)
      """
      takes_args = ['from_location', 'to_location?']
      takes_options = [Option('trees', help='Create working trees'),
 -                     Option('shared', help='Create shared repository'),
 +                     Option('standalone', help='Create standalone branches'),
                       Option('all', 
                           help='Convert all revisions, even those not in '
 -                              'current branch history (implies --shared)'),
 +                              'current branch history (forbids --standalone)'),
                       Option('scheme', type=get_scheme,
                           help='Branching scheme (none, trunk, or trunk-INT)')]
  
      @display_command
      def run(self, from_location, to_location=None, trees=False, 
 -            shared=False, scheme=None, all=False):
 +            standalone=False, scheme=None, all=False):
          from convert import convert_repository
          from scheme import TrunkBranchingScheme
  
              to_location = os.path.basename(from_location.rstrip("/\\"))
  
          if all:
 -            shared = True
 -        convert_repository(from_location, to_location, scheme, shared, trees,
 -                           all)
 +            standalone = False
 +        convert_repository(from_location, to_location, scheme, not standalone, 
 +                trees, all)
  
  
  register_command(cmd_svn_import)
  
  class cmd_svn_upgrade(Command):
 -    """Upgrade the revisions mapped from Subversion in a Bazaar branch.
 +    """Upgrade revisions mapped from Subversion in a Bazaar branch.
      
      This will change the revision ids of revisions whose parents 
      were mapped from svn revisions.
@@@ -174,14 -175,16 +174,14 @@@ register_command(cmd_svn_upgrade
  def test_suite():
      from unittest import TestSuite
      import tests
 -
      suite = TestSuite()
 -
      suite.addTest(tests.test_suite())
 -
      return suite
  
  if __name__ == '__main__':
      print ("This is a Bazaar plugin. Copy this directory to ~/.bazaar/plugins "
            "to use it.\n")
 +    runner = unittest.TextTestRunner()
 +    runner.run(test_suite())
  else:
 -    sys.path.append(os.path.dirname(__file__))
 -
 +    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
diff --combined checkout.py
index e93466525049d3d4cff1a64f4d9170eb8456e68a,81c8b66eae8e268f68bddd9655afaf57929932e7..4b079a72227701f946445ca9c114fdf86e5453b2
@@@ -19,7 -19,8 +19,7 @@@ from bzrlib.branch import PullResul
  from bzrlib.bzrdir import BzrDirFormat, BzrDir
  from bzrlib.errors import (InvalidRevisionId, NotBranchError, NoSuchFile,
                             NoRepositoryPresent, BzrError)
 -from bzrlib.inventory import (Inventory, InventoryDirectory, InventoryFile,
 -                              InventoryLink, ROOT_ID)
 +from bzrlib.inventory import Inventory, InventoryFile, InventoryLink
  from bzrlib.lockable_files import TransportLock, LockableFiles
  from bzrlib.lockdir import LockDir
  from bzrlib.osutils import fingerprint_file
@@@ -31,12 -32,9 +31,12 @@@ from bzrlib.workingtree import WorkingT
  
  from branch import SvnBranch
  from convert import SvnConverter
 -from repository import (SvnRepository, escape_svn_path, SVN_PROP_BZR_MERGE,
 +from errors import LocalCommitsUnsupported
 +from repository import (SvnRepository, SVN_PROP_BZR_MERGE,
                          SVN_PROP_SVK_MERGE, SVN_PROP_BZR_FILEIDS, 
 -                        revision_id_to_svk_feature) 
 +                        SVN_PROP_BZR_REVISION_ID, SVN_PROP_BZR_REVISION_INFO,
 +                        revision_id_to_svk_feature, generate_revision_metadata) 
 +from revids import escape_svn_path
  from scheme import BranchingScheme
  from transport import (SvnRaTransport, svn_config, bzr_to_svn_url, 
                         _create_auth_baton) 
@@@ -49,9 -47,6 +49,9 @@@ import urlli
  import svn.core, svn.wc
  from svn.core import SubversionException, Pool
  
 +from errors import NoCheckoutSupport
 +from format import get_rich_root_format
 +
  class WorkingTreeInconsistent(BzrError):
      _fmt = """Working copy is in inconsistent state (%(min_revnum)d:%(max_revnum)d)"""
  
@@@ -88,7 -83,7 +88,7 @@@ class SvnWorkingTree(WorkingTree)
          self.base_revnum = status.max_rev
          self.base_tree = SvnBasisTree(self)
          self.base_revid = branch.repository.generate_revision_id(
 -                    self.base_revnum, branch.branch_path)
 +                    self.base_revnum, branch.branch_path, bzrdir.scheme)
  
          self.read_working_inventory()
  
          pass
  
      def get_ignore_list(self):
-         ignores = [svn.wc.get_adm_dir()] + \
-                    svn.wc.get_default_ignores(svn_config)
+         ignores = set([svn.wc.get_adm_dir()])
+         ignores.update(svn.wc.get_default_ignores(svn_config))
  
          def dir_add(wc, prefix):
              ignorestr = svn.wc.prop_get(svn.core.SVN_PROP_IGNORE, 
                                          self.abspath(prefix).rstrip("/"), wc)
              if ignorestr is not None:
                  for pat in ignorestr.splitlines():
-                     ignores.append("./"+os.path.join(prefix, pat))
+                     ignores.add("./"+os.path.join(prefix, pat))
  
              entries = svn.wc.entries_read(wc, False)
              for entry in entries:
  
      def move(self, from_paths, to_dir=None, after=False, **kwargs):
          # FIXME: Use after argument
 +        assert after != True
          revt = svn.core.svn_opt_revision_t()
          revt.kind = svn.core.svn_opt_revision_working
          for entry in from_paths:
  
      def rename_one(self, from_rel, to_rel, after=False):
          # FIXME: Use after
 +        assert after != True
          revt = svn.core.svn_opt_revision_t()
          revt.kind = svn.core.svn_opt_revision_unspecified
          (to_wc, to_file) = self._get_rel_wc(to_rel, write_lock=True)
          assert isinstance(revnum, int) and revnum >= 0
          assert isinstance(path, basestring)
  
 -        (_, rp) = self.branch.repository.scheme.unprefix(path)
 +        (_, rp) = self.branch.scheme.unprefix(path)
          entry = self.base_tree.id_map[rp]
          assert entry[0] is not None
 +        assert isinstance(entry[0], str), "fileid %r for %r is not a string" % (entry[0], path)
          return entry
  
      def read_working_inventory(self):
              if id is None:
                  mutter('no id for %r' % entry.url)
                  return
 +            assert revid is None or isinstance(revid, str), "%r is not a string" % revid
              assert isinstance(id, str), "%r is not a string" % id
  
              # First handle directory itself
 +            inv.add_path(relpath, 'directory', id, parent_id).revision = revid
              if relpath == "":
 -                inv.add_path("", 'directory', ROOT_ID)
                  inv.revision_id = revid
 -            else:
 -                inventry = InventoryDirectory(id, os.path.basename(relpath), 
 -                                              parent_id)
 -                inventry.revision = revid
 -                inv.add(inventry)
  
              for name in entries:
                  if name == "":
              self.base_tree = RevisionTree(self, Inventory(), revid)
              return
  
 -        (bp, rev) = self.branch.repository.parse_revision_id(revid)
 -        assert bp == self.branch.branch_path
 +        rev = self.branch.lookup_revision_id(revid)
          self.base_revnum = rev
          self.base_revid = revid
          self.base_tree = SvnBasisTree(self)
          def update_settings(wc, path):
              id = newrevtree.inventory.path2id(path)
              mutter("Updating settings for %r" % id)
 -            (_, revnum) = self.branch.repository.parse_revision_id(
 +            revnum = self.branch.lookup_revision_id(
                      newrevtree.inventory[id].revision)
  
              svn.wc.process_committed2(self.abspath(path).rstrip("/"), wc, 
                 allow_pointless=True, strict=False, verbose=False, local=False, 
                 reporter=None, config=None, specific_files=None):
          # FIXME: Use allow_pointless
 -        # FIXME: Use committer
          # FIXME: Use verbose
          # FIXME: Use reporter
 -        # FIXME: Use revprops
 -        # FIXME: Raise exception when local is True
 -        # FIXME: Use strct
 -        assert timestamp is None
 -        assert timezone is None
 -        assert rev_id is None
 +        # FIXME: Use strict
 +        if local:
 +            raise LocalCommitsUnsupported()
  
          if specific_files:
              specific_files = [self.abspath(x).encode('utf8') for x in specific_files]
                  return message.encode("utf-8")
  
          self.client_ctx.log_msg_baton2 = log_message_func
 -        commit_info = svn.client.commit3(specific_files, True, False, 
 +        if rev_id is not None:
 +            extra = "%d %s\n" % (self.branch.revno()+1, rev_id)
 +        else:
 +            extra = ""
 +        wc = self._get_wc(write_lock=True)
 +        try:
 +            svn.wc.prop_set(SVN_PROP_BZR_REVISION_ID+str(self.branch.scheme), 
 +                             self._get_bzr_revids() + extra,
 +                             self.basedir, wc)
 +            svn.wc.prop_set(SVN_PROP_BZR_REVISION_INFO, 
 +                             generate_revision_metadata(timestamp, 
 +                                                        timezone, 
 +                                                        committer,
 +                                                        revprops),
 +                             self.basedir, wc)
 +        finally:
 +            svn.wc.adm_close(wc)
 +
 +        try:
 +            commit_info = svn.client.commit3(specific_files, True, False, 
                                           self.client_ctx)
 +        except:
 +            # Reset properties so the next subversion commit won't 
 +            # accidently set these properties.
 +            wc = self._get_wc(write_lock=True)
 +            svn.wc.prop_set(SVN_PROP_BZR_REVISION_ID+str(self.branch.scheme), 
 +                             self._get_bzr_revids(), self.basedir, wc)
 +            svn.wc.prop_set(SVN_PROP_BZR_REVISION_INFO, 
 +                self.branch.repository.branchprop_list.get_property(
 +                self.branch.branch_path, self.base_revnum, 
 +                SVN_PROP_BZR_REVISION_INFO, ""), 
 +                self.basedir, wc)
 +            svn.wc.adm_close(wc)
 +            raise
 +
          self.client_ctx.log_msg_baton2 = None
  
 -        revid = self.branch.repository.generate_revision_id(
 -                commit_info.revision, self.branch.branch_path)
 +        revid = self.branch.generate_revision_id(commit_info.revision)
  
          self.base_revid = revid
          self.base_revnum = commit_info.revision
          self.base_tree = SvnBasisTree(self)
  
 +        self.branch.repository._latest_revnum = commit_info.revision
 +
          #FIXME: Use public API:
 -        self.branch.revision_history()
 -        self.branch._revision_history.append(revid)
 +        if self.branch._revision_history is not None:
 +            self.branch._revision_history.append(revid)
  
          return revid
  
              stop_revision = self.branch.last_revision()
          rev = svn.core.svn_opt_revision_t()
          rev.kind = svn.core.svn_opt_revision_number
 -        rev.value.number = self.branch.repository.parse_revision_id(stop_revision)[1]
 +        rev.value.number = self.branch.lookup_revision_id(stop_revision)
          fetched = svn.client.update(self.basedir, rev, True, self.client_ctx)
          self.base_revid = self.branch.repository.generate_revision_id(fetched, self.branch.branch_path)
          result.new_revid = self.branch.generate_revision_id(fetched)
              if new_entries.has_key(path):
                  del new_entries[path]
          else:
 +            assert isinstance(id, str)
              new_entries[path] = id
          committed = self.branch.repository.branchprop_list.get_property(
                  self.branch.branch_path, 
  
      def _get_new_file_ids(self, wc):
          committed = self.branch.repository.branchprop_list.get_property(
 -                self.branch.branch_path, 
 -                self.base_revnum, 
 +                self.branch.branch_path, self.base_revnum, 
                  SVN_PROP_BZR_FILEIDS, "")
          existing = svn.wc.prop_get(SVN_PROP_BZR_FILEIDS, self.basedir, wc)
          if existing is None:
              return {}
          else:
 -            return dict(map(lambda x: x.split("\t"), existing[len(committed):].splitlines()))
 +            return dict(map(lambda x: str(x).split("\t"), 
 +                existing[len(committed):].splitlines()))
 +
 +    def _get_bzr_revids(self):
 +        return self.branch.repository.branchprop_list.get_property(
 +                self.branch.branch_path, self.base_revnum, 
 +                SVN_PROP_BZR_REVISION_ID+str(self.branch.scheme), "")
  
      def _get_bzr_merges(self):
          return self.branch.repository.branchprop_list.get_property(
 -                self.branch.branch_path, 
 -                self.base_revnum, 
 +                self.branch.branch_path, self.base_revnum, 
                  SVN_PROP_BZR_MERGE, "")
  
      def _get_svk_merges(self):
          return self.branch.repository.branchprop_list.get_property(
 -                self.branch.branch_path, 
 -                self.base_revnum, 
 +                self.branch.branch_path, self.base_revnum, 
                  SVN_PROP_SVK_MERGE, "")
  
      def set_pending_merges(self, merges):
@@@ -671,7 -634,7 +671,7 @@@ class SvnCheckout(BzrDir)
          self.branch_path = svn_url[len(bzr_to_svn_url(self.svn_root_transport.base)):]
          self.scheme = BranchingScheme.guess_scheme(self.branch_path)
          mutter('scheme for %r is %r' % (self.branch_path, self.scheme))
 -        if not self.scheme.is_branch(self.branch_path):
 +        if not self.scheme.is_branch(self.branch_path) and not self.scheme.is_tag(self.branch_path):
              raise NotBranchError(path=self.transport.base)
  
      def clone(self, path, revision_id=None, force_new_repo=False):
                 recurse='down'):
          # FIXME: honor force_new_repo
          # FIXME: Use recurse
 -        result = BzrDirFormat.get_default_format().initialize(url)
 +        result = get_rich_root_format().initialize(url)
          repo = self.find_repository()
          repo.clone(result, revision_id)
          branch = self.open_branch()
@@@ -735,9 -698,6 +735,9 @@@ class SvnWorkingTreeDirFormat(BzrDirFor
  
          if isinstance(transport, LocalTransport) and \
              transport.has(svn.wc.get_adm_dir()):
 +            subr_version = svn.core.svn_subr_version()
 +            if subr_version.major == 1 and subr_version.minor < 4:
 +                raise NoCheckoutSupport()
              return format
  
          raise NotBranchError(path=transport.base)
      def get_converter(self, format=None):
          """See BzrDirFormat.get_converter()."""
          if format is None:
 -            format = BzrDirFormat.get_default_format()
 +            format = get_rich_root_format()
          return SvnConverter(format)
index 06292c86c967070aff091b8db8fff76cbb1d4c19,f91291d6b92c2db8f4b26ada80c38001843effb2..fcb6a15ce74afbfca4676499560f138e83cb625f
@@@ -18,7 -18,8 +18,7 @@@
  
  from bzrlib.bzrdir import BzrDir
  from bzrlib.errors import NoSuchFile
 -from bzrlib.inventory import Inventory, ROOT_ID
 -from bzrlib.revision import NULL_REVISION
 +from bzrlib.inventory import Inventory
  from bzrlib.trace import mutter
  from bzrlib.workingtree import WorkingTree
  
@@@ -27,9 -28,7 +27,9 @@@ import svn.w
  
  import os
  
 +from fileids import generate_svn_file_id
  from repository import MAPPING_VERSION
 +from transport import svn_config
  from tests import TestCaseWithSubversionRepository, RENAMES
  
  class TestWorkingTree(TestCaseWithSubversionRepository):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
  
      def test_add_unexisting(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertRaises(NoSuchFile, tree.add, ["bl"])
  
      def test_add(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
  
          inv = tree.read_working_inventory()
@@@ -59,7 -58,7 +59,7 @@@
      def test_add_nolist(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add("bl")
  
          inv = tree.read_working_inventory()
@@@ -70,7 -69,7 +70,7 @@@
      def test_add_nolist_withid(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add("bl", "bloe")
  
          inv = tree.read_working_inventory()
@@@ -82,7 -81,7 +82,7 @@@
      def test_add_not_recursive(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl/file": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
  
          tree = WorkingTree.open("dc")
@@@ -92,7 -91,7 +92,7 @@@
      def test_add_nested(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl/file": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl", "bl/file"])
  
          tree = WorkingTree.open("dc")
  
      def test_lock_write(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.lock_write()
  
      def test_lock_read(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.lock_read()
  
      def test_unlock(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.unlock()
  
      def test_get_ignore_list_empty(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 -        self.assertEqual(set([".svn"] + svn.core.SVN_CONFIG_DEFAULT_GLOBAL_IGNORES.split(" ")), tree.get_ignore_list())
 +        tree = self.open_checkout("dc")
-         self.assertEqual([".svn"] + svn.wc.get_default_ignores(svn_config), tree.get_ignore_list())
++        self.assertEqual(set([".svn"] + svn.wc.get_default_ignores(svn_config)), tree.get_ignore_list())
  
      def test_get_ignore_list_onelevel(self):
          self.make_client('a', 'dc')
          self.client_set_prop("dc", "svn:ignore", "*.d\n*.c\n")
 -        tree = WorkingTree.open("dc")
 -        self.assertEqual(set([".svn"] + svn.core.SVN_CONFIG_DEFAULT_GLOBAL_IGNORES.split(" ") + ["./*.d", "./*.c"]), tree.get_ignore_list())
 +        tree = self.open_checkout("dc")
-         self.assertEqual([".svn"] + svn.wc.get_default_ignores(svn_config) + ["./*.d", "./*.c"], tree.get_ignore_list())
++        self.assertEqual(set([".svn"] + svn.wc.get_default_ignores(svn_config) + ["./*.d", "./*.c"]), tree.get_ignore_list())
  
      def test_get_ignore_list_morelevel(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/x': None})
          self.client_add("dc/x")
          self.client_set_prop("dc/x", "svn:ignore", "*.e\n")
 -        tree = WorkingTree.open("dc")
 -        self.assertEqual(set([".svn"] + svn.core.SVN_CONFIG_DEFAULT_GLOBAL_IGNORES.split(" ") + ["./*.d", "./*.c", "./x/*.e"]), tree.get_ignore_list())
 +        tree = self.open_checkout("dc")
-         self.assertEqual([".svn"] + svn.wc.get_default_ignores(svn_config) + ["./*.d", "./*.c", "./x/*.e"], tree.get_ignore_list())
++        self.assertEqual(set([".svn"] + svn.wc.get_default_ignores(svn_config) + ["./*.d", "./*.c", "./x/*.e"]), tree.get_ignore_list())
  
      def test_add_reopen(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
  
          inv = WorkingTree.open("dc").read_working_inventory()
      def test_remove(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
          tree.remove(["bl"])
          inv = tree.read_working_inventory()
      def test_remove_dup(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["bl"])
          os.remove("dc/bl")
          inv = tree.read_working_inventory()
  
      def test_is_control_file(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertTrue(tree.is_control_filename(".svn"))
          self.assertFalse(tree.is_control_filename(".bzr"))
  
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
          self.client_commit("dc", "Bla")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.rename_one("bl", "bloe")
          
          basis_inv = tree.basis_tree().inventory
  
      def test_empty_basis_tree(self):
          self.make_client('a', 'dc')
 -        wt = WorkingTree.open("dc")
 -        self.assertEqual(NULL_REVISION, wt.basis_tree().inventory.revision_id)
 -        self.assertEqual(Inventory(), wt.basis_tree().inventory)
 +        wt = self.open_checkout("dc")
 +        self.assertEqual(wt.branch.generate_revision_id(0), 
 +                         wt.basis_tree().inventory.revision_id)
 +        inv = Inventory()
 +        root_id = generate_svn_file_id(wt.branch.repository.uuid, 0, "", "")
 +        inv.revision_id = wt.branch.generate_revision_id(0)
 +        inv.add_path('', 'directory', root_id).revision = inv.revision_id
 +                              
 +        self.assertEqual(inv, wt.basis_tree().inventory)
  
      def test_basis_tree(self):
          self.make_client('a', 'dc')
          self.client_add("dc/bl")
          self.client_commit("dc", "Bla")
          self.client_update("dc")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertEqual(
              tree.branch.generate_revision_id(1),
              tree.basis_tree().get_revision_id())
          self.client_add("dc/a")
          self.client_add("dc/dir")
          self.client_commit("dc", "Bla")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.move(["bl", "a"], "dir")
          
          basis_inv = tree.basis_tree().inventory
      def test_pending_merges_empty(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertEqual([], tree.pending_merges())
   
      def test_delta(self):
          self.build_tree({"dc/bl": "data"})
          self.client_commit("dc", "Bla")
          self.build_tree({"dc/bl": "data2"})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.basis_tree()
          delta = tree.changes_from(tree.basis_tree())
          self.assertEqual("bl", delta.modified[0][0])
          self.client_commit("dc", "bla")
          self.build_tree({"dc/test": "data"})
          self.client_add("dc/test")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          inv = tree.read_working_inventory()
 -        self.assertEqual(ROOT_ID, inv.path2id(""))
 +        self.assertEqual(inv.path2id(""), inv.root.file_id)
          self.assertTrue(inv.path2id("foo") != "")
          self.assertTrue(inv.has_filename("bl"))
          self.assertTrue(inv.has_filename("foo"))
          self.client_commit("dc", "bla")
          self.client_set_prop("dc", "svn:ignore", "foo\nbar\n")
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          ignorelist = tree.get_ignore_list()
          self.assertTrue("./bl/test.*" in ignorelist)
          self.assertTrue("./foo" in ignorelist)
          self.client_commit("dc", "bla")
          self.client_set_prop("dc", "svn:ignore", "foo\nbar\n")
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertTrue(tree.is_ignored("bl/test.foo"))
          self.assertFalse(tree.is_ignored("bl/notignored"))
          self.assertTrue(tree.is_ignored("foo"))
  
      def test_ignore_controldir(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertEqual([], list(tree.unknowns()))
  
      def test_unknowns(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": None})
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertEqual(['bl'], list(tree.unknowns()))
  
      def test_unknown_not_added(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": None})
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertFalse(tree.inventory.has_filename("bl"))
  
      def test_extras(self):
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": None})
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertEqual(['.svn', 'bl'], list(tree.extras()))
  
      def test_executable(self):
          self.build_tree({"dc/bla": "data"})
          self.client_add("dc/bla")
          self.client_set_prop("dc/bla", "svn:executable", "*")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          inv = tree.read_working_inventory()
          self.assertTrue(inv[inv.path2id("bla")].executable)
  
          self.make_client('a', 'dc')
          os.symlink("target", "dc/bla")
          self.client_add("dc/bla")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          inv = tree.read_working_inventory()
          self.assertEqual('symlink', inv[inv.path2id("bla")].kind)
          self.assertEqual("target", inv[inv.path2id("bla")].symlink_target)
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": None})
  
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.set_pending_merges(["a", "c"])
          self.assertEqual(["a", "c"], tree.pending_merges())
          tree.set_pending_merges([])
          self.build_tree({"dc/bl": None})
          self.client_add("dc/bl")
          
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.set_pending_merges([
              "svn-v%d:1@a-uuid-foo-branch%%2fpath" % MAPPING_VERSION, "c"])
          self.assertEqual(
          self.build_tree({"dc/bl": None})
          self.client_add("dc/bl")
          
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.set_pending_merges([
 -            "svn-v%d:1@a-uuid-foo-branch%%2fpath" % MAPPING_VERSION, "c"])
 +            "svn-v%d-undefined:a-uuid-foo:branch%%2fpath:1" % MAPPING_VERSION, "c"])
          self.assertEqual("a-uuid-foo:/branch/path:1\n", 
                           self.client_get_prop("dc", "svk:merge"))
  
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.basis_tree()
          tree.commit(message_callback=lambda x: "data")
  
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.basis_tree()
          tree.commit(message_callback=lambda x: u"data")
  
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          orig_tree = tree.basis_tree()
          tree.commit(message=u"data")
  
          self.client_add("dc/branches")
          self.client_commit("dc", "initial changes")
          self.make_checkout(repos_url + "/branches/foobranch", "de")
 -        tree = WorkingTree.open("de")
 +        tree = self.open_checkout("de")
          self.build_tree({'de/file': "foo"})
          tree.basis_tree()
          tree.commit(message="data")
          self.make_client('a', 'dc')
          self.build_tree({"dc/bl": "data"})
          self.client_add("dc/bl")
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          orig_tree = tree.basis_tree()
          tree.commit(message="data")
          self.assertEqual(
  
      def test_status(self):
          self.make_client('a', 'dc')
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          self.assertTrue(os.path.exists("dc/.svn"))
          self.assertFalse(os.path.exists("dc/.bzr"))
          tree.read_working_inventory()
  
      def test_status_bzrdir(self):
          self.make_client('a', 'dc')
 -        bzrdir = BzrDir.open("dc")
 +        bzrdir = self.open_checkout_bzrdir("dc")
          self.assertTrue(os.path.exists("dc/.svn"))
          self.assertTrue(not os.path.exists("dc/.bzr"))
          bzrdir.open_workingtree()
      def test_file_id_consistent(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file"])
          oldid = tree.inventory.path2id("file")
          tree = WorkingTree.open("dc")
      def test_file_id_kept(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file"], ["fooid"])
          self.assertEqual("fooid", tree.inventory.path2id("file"))
          tree = WorkingTree.open("dc")
      def test_file_rename_id(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file"], ["fooid"])
          tree.commit("msg")
          tree.rename_one("file", "file2")
      def test_file_id_kept_2(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data', 'dc/other': 'blaid'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file", "other"], ["fooid", "blaid"])
          self.assertEqual("fooid", tree.inventory.path2id("file"))
          self.assertEqual("blaid", tree.inventory.path2id("other"))
      def test_file_remove_id(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file"], ["fooid"])
          tree.commit("msg")
          tree.remove(["file"])
      def test_file_move_id(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file': 'data', 'dc/dir': None})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file", "dir"], ["fooid", "blaid"])
          tree.commit("msg")
          tree.move(["file"], "dir")
      def test_escaped_char_filename(self):
          self.make_client('a', 'dc')
          self.build_tree({'dc/file with spaces': 'data'})
 -        tree = WorkingTree.open("dc")
 +        tree = self.open_checkout("dc")
          tree.add(["file with spaces"], ["fooid"])
          tree.commit("msg")
          self.assertEqual("fooid", tree.inventory.path2id("file with spaces"))
  
 +    def test_get_branch_nick(self):
 +        self.make_client('a', 'dc')
 +        self.build_tree({'dc/some strange file': 'data'})
 +        tree = self.open_checkout("dc")
 +        tree.add(["some strange file"])
 +        tree.commit("message")
 +        self.assertEqual(None, tree.branch.nick)