Rev 4800: (jam) Lots of win32 test-suite fixes. in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Nov 16 22:42:56 GMT 2009


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 4800 [merge]
revision-id: pqm at pqm.ubuntu.com-20091116224254-fgspnq9xz29z662j
parent: pqm at pqm.ubuntu.com-20091116215927-rula71sotgtosnc4
parent: john at arbash-meinel.com-20091116213652-74njzf1y3hvp9ojb
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2009-11-16 22:42:54 +0000
message:
  (jam) Lots of win32 test-suite fixes.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/dirstate.py             dirstate.py-20060728012006-d6mvoihjb3je9peu-1
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/blackbox/test_add.py test_add.py-20060518072250-857e4f86f54a30b2
  bzrlib/tests/blackbox/test_commit.py test_commit.py-20060212094538-ae88fc861d969db0
  bzrlib/tests/blackbox/test_init.py test_init.py-20060309032856-a292116204d86eb7
  bzrlib/tests/blackbox/test_serve.py test_serve.py-20060913064329-8t2pvmsikl4s3xhl-1
  bzrlib/tests/http_server.py    httpserver.py-20061012142527-m1yxdj1xazsf8d7s-1
  bzrlib/tests/per_branch/test_parent.py test_parent.py-20050830052751-5e62766623c32222
  bzrlib/tests/per_bzrdir/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
  bzrlib/tests/per_tree/test_path_content_summary.py test_path_content_su-20070904100855-3vrwedz6akn34kl5-1
  bzrlib/tests/per_workingtree/test_smart_add.py test_smart_add.py-20070215175752-9s5mxoz8aqpd80fm-1
  bzrlib/tests/per_workingtree/test_workingtree.py test_workingtree.py-20060203003124-817757d3e31444fb
  bzrlib/tests/script.py         script.py-20090901081155-yk3tiy1nunxg16ne-1
  bzrlib/tests/test_directory_service.py test_directory_servi-20080305221044-vr2mkvlsk8jypa2y-2
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
  bzrlib/tests/test_script.py    test_script.py-20090901081156-y90z4w2t62fv7e7b-1
  bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
  bzrlib/tests/test_win32utils.py test_win32utils.py-20070713181630-8xsrjymd3e8mgw23-108
  bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
  bzrlib/transport/sftp.py       sftp.py-20051019050329-ab48ce71b7e32dfe
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
=== modified file 'NEWS'
--- a/NEWS	2009-11-16 19:45:47 +0000
+++ b/NEWS	2009-11-16 20:50:41 +0000
@@ -8,7 +8,7 @@
 bzr 2.1.0b4 (not released yet)
 ##############################
 
-:Codename: san franscisco airport
+:Codename: san francisco airport
 :2.1.0b4: ???
 
 Compatibility Breaks
@@ -19,6 +19,13 @@
 
 Bug Fixes
 *********
+* After renaming a file, the dirstate could accidentally reference
+  ``source\\path`` rather than ``source/path`` on Windows. This might be a
+  source of some dirstate-related failures. (John Arbash Meinel)
+
+* Lots of bugfixes for the test suite on Windows. We should once again
+  have a test suite with no failures on Windows. (Once all the patches
+  have landed, remove this line.) (John Arbash Meinel)
 
 Improvements
 ************

=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py	2009-10-02 05:43:41 +0000
+++ b/bzrlib/dirstate.py	2009-11-08 19:29:02 +0000
@@ -1339,14 +1339,14 @@
                     minikind = child[1][0][0]
                     fingerprint = child[1][0][4]
                     executable = child[1][0][3]
-                    old_child_path = osutils.pathjoin(child[0][0],
-                                                      child[0][1])
+                    old_child_path = osutils.pathjoin(child_dirname,
+                                                      child_basename)
                     removals[child[0][2]] = old_child_path
                     child_suffix = child_dirname[len(old_path):]
                     new_child_dirname = (new_path + child_suffix)
                     key = (new_child_dirname, child_basename, child[0][2])
-                    new_child_path = os.path.join(new_child_dirname,
-                                                  child_basename)
+                    new_child_path = osutils.pathjoin(new_child_dirname,
+                                                      child_basename)
                     insertions[child[0][2]] = (key, minikind, executable,
                                                fingerprint, new_child_path)
         self._check_delta_ids_absent(new_ids, delta, 0)

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-10-23 16:31:03 +0000
+++ b/bzrlib/osutils.py	2009-11-10 07:01:56 +0000
@@ -224,6 +224,7 @@
     else:
         file_existed = True
 
+    failure_exc = None
     success = False
     try:
         try:
@@ -235,8 +236,12 @@
             # source and target may be aliases of each other (e.g. on a
             # case-insensitive filesystem), so we may have accidentally renamed
             # source by when we tried to rename target
-            if not (file_existed and e.errno in (None, errno.ENOENT)):
-                raise
+            failure_exc = sys.exc_info()
+            if (file_existed and e.errno in (None, errno.ENOENT)
+                and old.lower() == new.lower()):
+                # source and target are the same file on a case-insensitive
+                # filesystem, so we don't generate an exception
+                failure_exc = None
     finally:
         if file_existed:
             # If the file used to exist, rename it back into place
@@ -245,6 +250,8 @@
                 unlink_func(tmp_name)
             else:
                 rename_func(tmp_name, new)
+    if failure_exc is not None:
+        raise failure_exc[0], failure_exc[1], failure_exc[2]
 
 
 # In Python 2.4.2 and older, os.path.abspath and os.path.realpath

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2009-11-04 11:59:35 +0000
+++ b/bzrlib/tests/__init__.py	2009-11-16 19:56:24 +0000
@@ -4321,7 +4321,9 @@
             # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
             # We trigger SIGBREAK via a Console api so we need ctypes to
             # access the function
-            if not have_ctypes:
+            try:
+                import ctypes
+            except OSError:
                 return False
         return True
 

=== modified file 'bzrlib/tests/blackbox/test_add.py'
--- a/bzrlib/tests/blackbox/test_add.py	2009-08-10 08:25:05 +0000
+++ b/bzrlib/tests/blackbox/test_add.py	2009-11-08 00:05:26 +0000
@@ -27,7 +27,6 @@
     SymlinkFeature
     )
 from bzrlib.tests.blackbox import ExternalBase
-from bzrlib.tests.test_win32utils import NeedsGlobExpansionFeature
 
 
 def load_tests(standard_tests, module, loader):
@@ -211,20 +210,6 @@
         err = self.run_bzr('add .bzr/crescent', retcode=3)[1]
         self.assertContainsRe(err, r'ERROR:.*\.bzr.*control file')
 
-    def test_add_with_wildcards(self):
-        self.requireFeature(NeedsGlobExpansionFeature)
-        self.make_branch_and_tree('.')
-        self.build_tree(['a1', 'a2', 'b', 'c33'])
-        self.run_bzr(['add', 'a?', 'c*'])
-        self.assertEquals(self.run_bzr('unknowns')[0], 'b\n')
-
-    def test_add_with_wildcards_unicode(self):
-        self.requireFeature(NeedsGlobExpansionFeature)
-        self.make_branch_and_tree('.')
-        self.build_tree([u'\u1234A', u'\u1235A', u'\u1235AA', 'cc'])
-        self.run_bzr(['add', u'\u1234?', u'\u1235*'])
-        self.assertEquals(self.run_bzr('unknowns')[0], 'cc\n')
-
     def test_add_via_symlink(self):
         self.requireFeature(SymlinkFeature)
         self.make_branch_and_tree('source')

=== modified file 'bzrlib/tests/blackbox/test_commit.py'
--- a/bzrlib/tests/blackbox/test_commit.py	2009-11-03 20:24:25 +0000
+++ b/bzrlib/tests/blackbox/test_commit.py	2009-11-08 01:09:14 +0000
@@ -25,6 +25,7 @@
     ignores,
     msgeditor,
     osutils,
+    tests,
     )
 from bzrlib.bzrdir import BzrDir
 from bzrlib.tests import (
@@ -263,6 +264,9 @@
         self.run_bzr('commit -m ""', retcode=3)
 
     def test_unsupported_encoding_commit_message(self):
+        if sys.platform == 'win32':
+            raise tests.TestNotApplicable('Win32 parses arguments directly'
+                ' as Unicode, so we can\'t pass invalid non-ascii')
         tree = self.make_branch_and_tree('.')
         self.build_tree_contents([('foo.c', 'int main() {}')])
         tree.add('foo.c')
@@ -273,10 +277,6 @@
         if char is None:
             raise TestSkipped('Cannot find suitable non-ascii character'
                 'for user_encoding (%s)' % osutils.get_user_encoding())
-        # TODO: jam 2009-07-23 This test seems to fail on Windows now. My best
-        #       guess is that the change to use Unicode command lines means
-        #       that we no longer pay any attention to LANG=C when decoding the
-        #       commandline arguments.
         out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
                                           retcode=1,
                                           env_changes={'LANG': 'C'})

=== modified file 'bzrlib/tests/blackbox/test_init.py'
--- a/bzrlib/tests/blackbox/test_init.py	2009-08-12 22:16:29 +0000
+++ b/bzrlib/tests/blackbox/test_init.py	2009-11-08 02:23:13 +0000
@@ -22,6 +22,7 @@
 
 from bzrlib import (
     branch as _mod_branch,
+    osutils,
     urlutils,
     )
 from bzrlib.bzrdir import BzrDirMetaFormat1
@@ -74,8 +75,8 @@
 Using shared repository: %s
 """ % (self._default_label, urlutils.local_path_from_url(
             repo.bzrdir.root_transport.external_url())), out)
-        self.assertEndsWith(out, "bzrlib.tests.blackbox.test_init.TestInit."
-            "test_init_at_repository_root/work/repo/\n")
+        cwd = osutils.getcwd()
+        self.assertEndsWith(out, cwd + '/repo/\n')
         self.assertEqual('', err)
         newdir.open_branch()
         newdir.open_workingtree()

=== modified file 'bzrlib/tests/blackbox/test_serve.py'
--- a/bzrlib/tests/blackbox/test_serve.py	2009-09-22 04:25:05 +0000
+++ b/bzrlib/tests/blackbox/test_serve.py	2009-11-16 21:36:52 +0000
@@ -30,6 +30,7 @@
     errors,
     osutils,
     revision as _mod_revision,
+    urlutils,
     )
 from bzrlib.branch import Branch
 from bzrlib.bzrdir import BzrDir
@@ -278,23 +279,26 @@
         (optionally decorated with 'readonly+').  BzrServerFactory can
         determine the original --directory from that transport.
         """
+        # URLs always include the trailing slash, and get_base_path returns it
+        base_dir = osutils.abspath('/a/b/c') + '/'
+        base_url = urlutils.local_path_to_url(base_dir) + '/'
         # Define a fake 'protocol' to capture the transport that cmd_serve
         # passes to serve_bzr.
         def capture_transport(transport, host, port, inet):
             self.bzr_serve_transport = transport
         cmd = builtins.cmd_serve()
         # Read-only
-        cmd.run(directory='/a/b/c', protocol=capture_transport)
+        cmd.run(directory=base_dir, protocol=capture_transport)
         server_maker = BzrServerFactory()
         self.assertEqual(
-            'readonly+file:///a/b/c/', self.bzr_serve_transport.base)
+            'readonly+%s' % base_url, self.bzr_serve_transport.base)
         self.assertEqual(
-            u'/a/b/c/', server_maker.get_base_path(self.bzr_serve_transport))
+            base_dir, server_maker.get_base_path(self.bzr_serve_transport))
         # Read-write
-        cmd.run(directory='/a/b/c', protocol=capture_transport,
+        cmd.run(directory=base_dir, protocol=capture_transport,
             allow_writes=True)
         server_maker = BzrServerFactory()
-        self.assertEqual('file:///a/b/c/', self.bzr_serve_transport.base)
-        self.assertEqual(
-            u'/a/b/c/', server_maker.get_base_path(self.bzr_serve_transport))
+        self.assertEqual(base_url, self.bzr_serve_transport.base)
+        self.assertEqual(base_dir,
+            server_maker.get_base_path(self.bzr_serve_transport))
 

=== modified file 'bzrlib/tests/http_server.py'
--- a/bzrlib/tests/http_server.py	2009-07-08 15:24:31 +0000
+++ b/bzrlib/tests/http_server.py	2009-11-11 07:23:59 +0000
@@ -462,7 +462,7 @@
                 raise httplib.UnknownProtocol(proto_vers)
             else:
                 self._httpd = self.create_httpd(serv_cls, rhandler)
-            host, self.port = self._httpd.socket.getsockname()
+            self.host, self.port = self._httpd.socket.getsockname()
         return self._httpd
 
     def _http_start(self):

=== modified file 'bzrlib/tests/per_branch/test_parent.py'
--- a/bzrlib/tests/per_branch/test_parent.py	2009-04-15 03:45:24 +0000
+++ b/bzrlib/tests/per_branch/test_parent.py	2009-11-08 03:00:33 +0000
@@ -96,11 +96,11 @@
         if sys.platform != 'win32':
             raise TestSkipped('windows-specific test')
         b = self.make_branch('.')
-        base_url = b.abspath('.')
+        base_url = b.bzrdir.transport.abspath('.')
         if not base_url.startswith('file:///'):
             raise TestNotApplicable('this test should be run with local base')
         base = urlutils.local_path_from_url(base_url)
-        other = 'file:///B:/path'
+        other = 'file:///D:/path'
         if base[0] != 'C':
             other = 'file:///C:/path'
         b.set_parent(other)

=== modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py'
--- a/bzrlib/tests/per_bzrdir/test_bzrdir.py	2009-09-18 17:19:15 +0000
+++ b/bzrlib/tests/per_bzrdir/test_bzrdir.py	2009-11-16 20:05:44 +0000
@@ -778,13 +778,16 @@
                                      './.bzr/repository/inventory.knit',
                                      ])
         try:
+            local_inventory = dir.transport.local_abspath('inventory')
+        except errors.NotLocalUrl:
+            return
+        try:
             # If we happen to have a tree, we'll guarantee everything
             # except for the tree root is the same.
-            inventory_f = file(dir.transport.base+'inventory', 'rb')
+            inventory_f = file(local_inventory, 'rb')
+            self.addCleanup(inventory_f.close)
             self.assertContainsRe(inventory_f.read(),
-                                  '<inventory file_id="TREE_ROOT[^"]*"'
-                                  ' format="5">\n</inventory>\n')
-            inventory_f.close()
+                                  '<inventory format="5">\n</inventory>\n')
         except IOError, e:
             if e.errno != errno.ENOENT:
                 raise

=== modified file 'bzrlib/tests/per_tree/test_path_content_summary.py'
--- a/bzrlib/tests/per_tree/test_path_content_summary.py	2009-08-26 05:34:10 +0000
+++ b/bzrlib/tests/per_tree/test_path_content_summary.py	2009-11-10 19:38:37 +0000
@@ -21,6 +21,7 @@
 from bzrlib import (
     osutils,
     tests,
+    transform,
     )
 
 from bzrlib.tests import per_tree
@@ -78,13 +79,13 @@
         self.assertEqual(('missing', None, None, None), summary)
 
     def test_file_content_summary_executable(self):
-        if not osutils.supports_executable():
-            raise tests.TestNotApplicable()
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/path'])
         tree.add(['path'])
-        current_mode = os.stat('tree/path').st_mode
-        os.chmod('tree/path', current_mode | 0100)
+        tt = transform.TreeTransform(tree)
+        self.addCleanup(tt.finalize)
+        tt.set_executability(True, tt.trans_id_tree_path('path'))
+        tt.apply()
         summary = self._convert_tree(tree).path_content_summary('path')
         self.assertEqual(4, len(summary))
         self.assertEqual('file', summary[0])
@@ -95,6 +96,28 @@
         self.assertSubset((summary[3],),
             (None, '0c352290ae1c26ca7f97d5b2906c4624784abd60'))
 
+    def test_file_content_summary_not_versioned(self):
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree(['tree/path'])
+        tree = self._convert_tree(tree)
+        summary = tree.path_content_summary('path')
+        self.assertEqual(4, len(summary))
+        if isinstance(tree, (per_tree.DirStateRevisionTree,
+                             per_tree.RevisionTree)):
+            self.assertEqual('missing', summary[0])
+            self.assertIs(None, summary[2])
+            self.assertIs(None, summary[3])
+        elif isinstance(tree, transform._PreviewTree):
+            self.expectFailure('PreviewTree returns "missing" for unversioned'
+                'files', self.assertEqual, 'file', summary[0])
+            self.assertEqual('file', summary[0])
+        else:
+            self.assertEqual('file', summary[0])
+            self.check_content_summary_size(tree, summary, 22)
+            self.assertEqual(False, summary[2])
+        self.assertSubset((summary[3],),
+            (None, '0c352290ae1c26ca7f97d5b2906c4624784abd60'))
+
     def test_file_content_summary_non_exec(self):
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/path'])

=== modified file 'bzrlib/tests/per_workingtree/test_smart_add.py'
--- a/bzrlib/tests/per_workingtree/test_smart_add.py	2009-09-28 02:02:30 +0000
+++ b/bzrlib/tests/per_workingtree/test_smart_add.py	2009-11-08 04:49:06 +0000
@@ -17,6 +17,7 @@
 """Test that we can use smart_add on all Tree implementations."""
 
 from cStringIO import StringIO
+import sys
 
 from bzrlib import (
     add,
@@ -53,7 +54,12 @@
 
     def assertFilenameSkipped(self, filename):
         tree = self.make_branch_and_tree('tree')
-        self.build_tree(['tree/'+filename])
+        try:
+            self.build_tree(['tree/'+filename])
+        except errors.NoSuchFile:
+            if sys.platform == 'win32':
+                raise tests.TestNotApplicable('Cannot create files named %r on'
+                    ' win32' % (filename,))
         tree.smart_add(['tree'])
         self.assertEqual(None, tree.path2id(filename))
 

=== modified file 'bzrlib/tests/per_workingtree/test_workingtree.py'
--- a/bzrlib/tests/per_workingtree/test_workingtree.py	2009-08-20 04:09:58 +0000
+++ b/bzrlib/tests/per_workingtree/test_workingtree.py	2009-11-08 05:28:57 +0000
@@ -513,30 +513,37 @@
 
     def test_merge_revert(self):
         from bzrlib.merge import merge_inner
-        self.thisFailsStrictLockCheck()
         this = self.make_branch_and_tree('b1')
-        open('b1/a', 'wb').write('a test\n')
-        this.add('a')
-        open('b1/b', 'wb').write('b test\n')
-        this.add('b')
+        self.build_tree_contents([('b1/a', 'a test\n'), ('b1/b', 'b test\n')])
+        this.add(['a', 'b'])
         this.commit(message='')
         base = this.bzrdir.clone('b2').open_workingtree()
-        open('b2/a', 'wb').write('b test\n')
+        self.build_tree_contents([('b2/a', 'b test\n')])
         other = this.bzrdir.clone('b3').open_workingtree()
-        open('b3/a', 'wb').write('c test\n')
-        open('b3/c', 'wb').write('c test\n')
+        self.build_tree_contents([('b3/a', 'c test\n'), ('b3/c', 'c test\n')])
         other.add('c')
 
-        open('b1/b', 'wb').write('q test\n')
-        open('b1/d', 'wb').write('d test\n')
+        self.build_tree_contents([('b1/b', 'q test\n'), ('b1/d', 'd test\n')])
+        # Note: If we don't lock this before calling merge_inner, then we get a
+        #       lock-contention failure. This probably indicates something
+        #       weird going on inside merge_inner. Probably something about
+        #       calling bt = this_tree.basis_tree() in one lock, and then
+        #       locking both this_tree and bt separately, causing a dirstate
+        #       locking race.
+        this.lock_write()
+        self.addCleanup(this.unlock)
         merge_inner(this.branch, other, base, this_tree=this)
-        self.assertNotEqual(open('b1/a', 'rb').read(), 'a test\n')
+        a = open('b1/a', 'rb')
+        try:
+            self.assertNotEqual(a.read(), 'a test\n')
+        finally:
+            a.close()
         this.revert()
-        self.assertEqual(open('b1/a', 'rb').read(), 'a test\n')
-        self.assertIs(os.path.exists('b1/b.~1~'), True)
-        self.assertIs(os.path.exists('b1/c'), False)
-        self.assertIs(os.path.exists('b1/a.~1~'), False)
-        self.assertIs(os.path.exists('b1/d'), True)
+        self.assertFileEqual('a test\n', 'b1/a')
+        self.failUnlessExists('b1/b.~1~')
+        self.failIfExists('b1/c')
+        self.failIfExists('b1/a.~1~')
+        self.failUnlessExists('b1/d')
 
     def test_update_updates_bound_branch_no_local_commits(self):
         # doing an update in a tree updates the branch its bound to too.

=== modified file 'bzrlib/tests/script.py'
--- a/bzrlib/tests/script.py	2009-09-24 06:53:43 +0000
+++ b/bzrlib/tests/script.py	2009-11-08 20:28:36 +0000
@@ -217,7 +217,8 @@
             # Specifying None means: any output is accepted
             return
         if actual is None:
-            test_case.fail('Unexpected: %s' % actual)
+            test_case.fail('We expected output: %r, but found None'
+                           % (expected,))
         matching = self.output_checker.check_output(
             expected, actual, self.check_options)
         if not matching:
@@ -289,30 +290,31 @@
             try:
                 inputs.append(self._read_input(None, in_name))
             except IOError, e:
-                if e.errno == errno.ENOENT:
+                # Some filenames are illegal on Windows and generate EINVAL
+                # rather than just saying the filename doesn't exist
+                if e.errno in (errno.ENOENT, errno.EINVAL):
                     return (1, None,
                             '%s: No such file or directory\n' % (in_name,))
+                raise
         # Basically cat copy input to output
         output = ''.join(inputs)
         # Handle output redirections
         try:
             output = self._write_output(output, out_name, out_mode)
         except IOError, e:
-            if e.errno == errno.ENOENT:
+            # If out_name cannot be created, we may get 'ENOENT', however if
+            # out_name is something like '', we can get EINVAL
+            if e.errno in (errno.ENOENT, errno.EINVAL):
                 return 1, None, '%s: No such file or directory\n' % (out_name,)
+            raise
         return 0, output, None
 
     def do_echo(self, test_case, input, args):
         (in_name, out_name, out_mode, args) = _scan_redirection_options(args)
-        if input and args:
-                raise SyntaxError('Specify parameters OR use redirection')
+        if input or in_name:
+            raise SyntaxError('echo doesn\'t read from stdin')
         if args:
             input = ' '.join(args)
-        try:
-            input = self._read_input(input, in_name)
-        except IOError, e:
-            if e.errno == errno.ENOENT:
-                return 1, None, '%s: No such file or directory\n' % (in_name,)
         # Always append a \n'
         input += '\n'
         # Process output
@@ -321,8 +323,9 @@
         try:
             output = self._write_output(output, out_name, out_mode)
         except IOError, e:
-            if e.errno == errno.ENOENT:
+            if e.errno in (errno.ENOENT, errno.EINVAL):
                 return 1, None, '%s: No such file or directory\n' % (out_name,)
+            raise
         return 0, output, None
 
     def _get_jail_root(self, test_case):

=== modified file 'bzrlib/tests/test_directory_service.py'
--- a/bzrlib/tests/test_directory_service.py	2009-03-23 14:59:43 +0000
+++ b/bzrlib/tests/test_directory_service.py	2009-11-10 04:58:31 +0000
@@ -16,18 +16,23 @@
 
 """Test directory service implementation"""
 
-from bzrlib import errors
+from bzrlib import (
+    errors,
+    urlutils,
+    )
 from bzrlib.directory_service import DirectoryServiceRegistry, directories
 from bzrlib.tests import TestCase, TestCaseWithTransport
 from bzrlib.transport import get_transport
-from bzrlib import urlutils
 
 
 class FooService(object):
     """A directory service that maps the name to a FILE url"""
 
+    # eg 'file:///foo' on Linux, or 'file:///C:/foo' on Windows
+    base = urlutils.local_path_to_url('/foo')
+
     def look_up(self, name, url):
-        return 'file:///foo' + name
+        return self.base + name
 
 
 class TestDirectoryLookup(TestCase):
@@ -43,14 +48,15 @@
         self.assertEqual('bar', suffix)
 
     def test_dereference(self):
-        self.assertEqual('file:///foobar',
+        self.assertEqual(FooService.base + 'bar',
                          self.registry.dereference('foo:bar'))
         self.assertEqual('baz:qux', self.registry.dereference('baz:qux'))
 
     def test_get_transport(self):
         directories.register('foo:', FooService, 'Map foo URLs to http urls')
         self.addCleanup(lambda: directories.remove('foo:'))
-        self.assertEqual('file:///foobar/', get_transport('foo:bar').base)
+        self.assertEqual(FooService.base + 'bar/',
+                         get_transport('foo:bar').base)
 
 
 class TestAliasDirectory(TestCaseWithTransport):

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-10-15 04:01:26 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-11-10 07:01:56 +0000
@@ -126,33 +126,51 @@
 
 class TestRename(tests.TestCaseInTempDir):
 
+    def create_file(self, filename, content):
+        f = open(filename, 'wb')
+        try:
+            f.write(content)
+        finally:
+            f.close()
+
+    def _fancy_rename(self, a, b):
+        osutils.fancy_rename(a, b, rename_func=os.rename,
+                             unlink_func=os.unlink)
+
     def test_fancy_rename(self):
         # This should work everywhere
-        def rename(a, b):
-            osutils.fancy_rename(a, b,
-                    rename_func=os.rename,
-                    unlink_func=os.unlink)
-
-        open('a', 'wb').write('something in a\n')
-        rename('a', 'b')
+        self.create_file('a', 'something in a\n')
+        self._fancy_rename('a', 'b')
         self.failIfExists('a')
         self.failUnlessExists('b')
         self.check_file_contents('b', 'something in a\n')
 
-        open('a', 'wb').write('new something in a\n')
-        rename('b', 'a')
+        self.create_file('a', 'new something in a\n')
+        self._fancy_rename('b', 'a')
 
         self.check_file_contents('a', 'something in a\n')
 
+    def test_fancy_rename_fails_source_missing(self):
+        # An exception should be raised, and the target should be left in place
+        self.create_file('target', 'data in target\n')
+        self.assertRaises((IOError, OSError), self._fancy_rename,
+                          'missingsource', 'target')
+        self.failUnlessExists('target')
+        self.check_file_contents('target', 'data in target\n')
+
+    def test_fancy_rename_fails_if_source_and_target_missing(self):
+        self.assertRaises((IOError, OSError), self._fancy_rename,
+                          'missingsource', 'missingtarget')
+
     def test_rename(self):
         # Rename should be semi-atomic on all platforms
-        open('a', 'wb').write('something in a\n')
+        self.create_file('a', 'something in a\n')
         osutils.rename('a', 'b')
         self.failIfExists('a')
         self.failUnlessExists('b')
         self.check_file_contents('b', 'something in a\n')
 
-        open('a', 'wb').write('new something in a\n')
+        self.create_file('a', 'new something in a\n')
         osutils.rename('b', 'a')
 
         self.check_file_contents('a', 'something in a\n')

=== modified file 'bzrlib/tests/test_script.py'
--- a/bzrlib/tests/test_script.py	2009-09-17 14:15:15 +0000
+++ b/bzrlib/tests/test_script.py	2009-11-08 20:28:36 +0000
@@ -262,14 +262,6 @@
 2>: No such file or directory
 """)
 
-    def test_echo_bogus_input_file(self):
-        # We need a backing file sysytem for that test so it can't be in
-        # TestEcho
-        self.run_script("""
-$ echo <file
-2>file: No such file or directory
-""")
-
     def test_echo_bogus_output_file(self):
         # We need a backing file sysytem for that test so it can't be in
         # TestEcho
@@ -338,6 +330,11 @@
 """
         self.assertRaises(SyntaxError, self.run_script, story)
 
+    def test_echo_input(self):
+        self.assertRaises(SyntaxError, self.run_script, """
+            $ echo <foo
+            """)
+
     def test_echo_to_output(self):
         retcode, out, err = self.run_command(['echo'], None, '\n', None)
         self.assertEquals('\n', out)

=== modified file 'bzrlib/tests/test_transform.py'
--- a/bzrlib/tests/test_transform.py	2009-10-26 06:44:40 +0000
+++ b/bzrlib/tests/test_transform.py	2009-11-10 19:40:13 +0000
@@ -2470,8 +2470,6 @@
         self.assertIs(None, summary[3])
 
     def test_change_executability(self):
-        if not osutils.supports_executable():
-            raise TestNotApplicable()
         tree = self.make_branch_and_tree('tree')
         self.build_tree(['tree/path'])
         tree.add('path')
@@ -2491,10 +2489,7 @@
         # size must be known
         self.assertEqual(len('contents'), summary[1])
         # not executable
-        if osutils.supports_executable():
-            self.assertEqual(False, summary[2])
-        else:
-            self.assertEqual(None, summary[2])
+        self.assertEqual(False, summary[2])
         # will not have hash (not cheap to determine)
         self.assertIs(None, summary[3])
 

=== modified file 'bzrlib/tests/test_win32utils.py'
--- a/bzrlib/tests/test_win32utils.py	2009-11-11 04:03:33 +0000
+++ b/bzrlib/tests/test_win32utils.py	2009-11-16 20:52:38 +0000
@@ -32,18 +32,20 @@
 from bzrlib.win32utils import glob_expand, get_app_path
 
 
-# Features
-# --------
-
-class _NeedsGlobExpansionFeature(Feature):
+class _BackslashDirSeparatorFeature(tests.Feature):
 
     def _probe(self):
-        return sys.platform == 'win32'
+        try:
+            os.lstat(os.getcwd() + '\\')
+        except OSError:
+            return False
+        else:
+            return True
 
     def feature_name(self):
-        return 'Internally performed glob expansion'
+        return "Filesystem treats '\\' as a directory separator."
 
-NeedsGlobExpansionFeature = _NeedsGlobExpansionFeature()
+BackslashDirSeparatorFeature = _BackslashDirSeparatorFeature()
 
 
 class _RequiredModuleFeature(Feature):
@@ -70,19 +72,9 @@
 # Tests
 # -----
 
-class TestNeedsGlobExpansionFeature(TestCase):
-
-    def test_available(self):
-        self.assertEqual(sys.platform == 'win32',
-                         NeedsGlobExpansionFeature.available())
-
-    def test_str(self):
-        self.assertTrue("performed" in str(NeedsGlobExpansionFeature))
-
-
 class TestWin32UtilsGlobExpand(TestCaseInTempDir):
 
-    _test_needs_features = [NeedsGlobExpansionFeature]
+    _test_needs_features = []
 
     def test_empty_tree(self):
         self.build_tree([])
@@ -92,22 +84,28 @@
             [['*'], ['*']],
             [['a', 'a'], ['a', 'a']]])
 
-    def test_tree_ascii(self):
-        """Checks the glob expansion and path separation char
-        normalization"""
+    def build_ascii_tree(self):
         self.build_tree(['a', 'a1', 'a2', 'a11', 'a.1',
                          'b', 'b1', 'b2', 'b3',
                          'c/', 'c/c1', 'c/c2',
                          'd/', 'd/d1', 'd/d2', 'd/e/', 'd/e/e1'])
+
+    def build_unicode_tree(self):
+        self.requireFeature(UnicodeFilenameFeature)
+        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/',
+                         u'\u1235/\u1235'])
+
+    def test_tree_ascii(self):
+        """Checks the glob expansion and path separation char
+        normalization"""
+        self.build_ascii_tree()
         self._run_testset([
             # no wildcards
             [[u'a'], [u'a']],
             [[u'a', u'a' ], [u'a', u'a']],
-            [[u'A'], [u'A']],
 
             [[u'd'], [u'd']],
             [[u'd/'], [u'd/']],
-            [[u'd\\'], [u'd/']],
 
             # wildcards
             [[u'a*'], [u'a', u'a1', u'a2', u'a11', u'a.1']],
@@ -115,18 +113,35 @@
             [[u'a?'], [u'a1', u'a2']],
             [[u'a??'], [u'a11', u'a.1']],
             [[u'b[1-2]'], [u'b1', u'b2']],
-            [[u'A?'], [u'a1', u'a2']],
 
             [[u'd/*'], [u'd/d1', u'd/d2', u'd/e']],
+            [[u'?/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
+            [[u'*/*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
+            [[u'*/'], [u'c/', u'd/']],
+            ])
+
+    def test_backslash_globbing(self):
+        self.requireFeature(BackslashDirSeparatorFeature)
+        self.build_ascii_tree()
+        self._run_testset([
+            [[u'd\\'], [u'd/']],
             [[u'd\\*'], [u'd/d1', u'd/d2', u'd/e']],
             [[u'?\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
             [[u'*\\*'], [u'c/c1', u'c/c2', u'd/d1', u'd/d2', u'd/e']],
-            [[u'*/'], [u'c/', u'd/']],
-            [[u'*\\'], [u'c/', u'd/']]])
+            [[u'*\\'], [u'c/', u'd/']],
+            ])
+
+    def test_case_insensitive_globbing(self):
+        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
+        self.build_ascii_tree()
+        self._run_testset([
+            [[u'A'], [u'A']],
+            [[u'A?'], [u'a1', u'a2']],
+            ])
 
     def test_tree_unicode(self):
         """Checks behaviour with non-ascii filenames"""
-        self.build_tree([u'\u1234', u'\u1234\u1234', u'\u1235/', u'\u1235/\u1235'])
+        self.build_unicode_tree()
         self._run_testset([
             # no wildcards
             [[u'\u1234'], [u'\u1234']],
@@ -142,16 +157,26 @@
 
             [[u'\u1235/?'], [u'\u1235/\u1235']],
             [[u'\u1235/*'], [u'\u1235/\u1235']],
+            [[u'?/'], [u'\u1235/']],
+            [[u'*/'], [u'\u1235/']],
+            [[u'?/?'], [u'\u1235/\u1235']],
+            [[u'*/*'], [u'\u1235/\u1235']],
+            ])
+
+    def test_unicode_backslashes(self):
+        self.requireFeature(BackslashDirSeparatorFeature)
+        self.build_unicode_tree()
+        self._run_testset([
+            # no wildcards
+            [[u'\u1235\\'], [u'\u1235/']],
+            [[u'\u1235\\\u1235'], [u'\u1235/\u1235']],
             [[u'\u1235\\?'], [u'\u1235/\u1235']],
             [[u'\u1235\\*'], [u'\u1235/\u1235']],
-            [[u'?/'], [u'\u1235/']],
-            [[u'*/'], [u'\u1235/']],
             [[u'?\\'], [u'\u1235/']],
             [[u'*\\'], [u'\u1235/']],
-            [[u'?/?'], [u'\u1235/\u1235']],
-            [[u'*/*'], [u'\u1235/\u1235']],
             [[u'?\\?'], [u'\u1235/\u1235']],
-            [[u'*\\*'], [u'\u1235/\u1235']]])
+            [[u'*\\*'], [u'\u1235/\u1235']],
+            ])
 
     def _run_testset(self, testset):
         for pattern, expected in testset:
@@ -356,3 +381,13 @@
     def test_no_single_quote_supported(self):
         self.assertCommandLine(["add", "let's-do-it.txt"],
             "add let's-do-it.txt")
+
+    def test_case_insensitive_globs(self):
+        self.requireFeature(tests.CaseInsCasePresFilenameFeature)
+        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
+        self.assertCommandLine([u'A/b.c'], 'A/B*')
+
+    def test_backslashes(self):
+        self.requireFeature(BackslashDirSeparatorFeature)
+        self.build_tree(['a/', 'a/b.c', 'a/c.c', 'a/c.h'])
+        self.assertCommandLine([u'a/b.c'], 'a\\b*')

=== modified file 'bzrlib/transform.py'
--- a/bzrlib/transform.py	2009-10-29 21:13:16 +0000
+++ b/bzrlib/transform.py	2009-11-10 05:26:00 +0000
@@ -1973,7 +1973,7 @@
                 statval = os.lstat(limbo_name)
                 size = statval.st_size
                 if not supports_executable():
-                    executable = None
+                    executable = False
                 else:
                     executable = statval.st_mode & S_IEXEC
             else:
@@ -1981,8 +1981,7 @@
                 executable = None
             if kind == 'symlink':
                 link_or_sha1 = os.readlink(limbo_name).decode(osutils._fs_enc)
-        if supports_executable():
-            executable = tt._new_executability.get(trans_id, executable)
+        executable = tt._new_executability.get(trans_id, executable)
         return kind, size, executable, link_or_sha1
 
     def iter_changes(self, from_tree, include_unchanged=False,

=== modified file 'bzrlib/transport/sftp.py'
--- a/bzrlib/transport/sftp.py	2009-06-10 03:56:49 +0000
+++ b/bzrlib/transport/sftp.py	2009-11-11 07:35:08 +0000
@@ -917,7 +917,7 @@
         self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         self._socket.bind(('localhost', 0))
         self._socket.listen(1)
-        self.port = self._socket.getsockname()[1]
+        self.host, self.port = self._socket.getsockname()[:2]
         self._stop_event = threading.Event()
 
     def stop(self):
@@ -1045,7 +1045,8 @@
 
     def _get_sftp_url(self, path):
         """Calculate an sftp url to this server for path."""
-        return 'sftp://foo:bar@localhost:%d/%s' % (self._listener.port, path)
+        return 'sftp://foo:bar@%s:%d/%s' % (self._listener.host,
+                                            self._listener.port, path)
 
     def log(self, message):
         """StubServer uses this to log when a new server is created."""

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2009-10-06 14:40:37 +0000
+++ b/bzrlib/workingtree.py	2009-11-10 09:14:34 +0000
@@ -636,6 +636,10 @@
 
     def _is_executable_from_path_and_stat_from_basis(self, path, stat_result):
         file_id = self.path2id(path)
+        if file_id is None:
+            # For unversioned files on win32, we just assume they are not
+            # executable
+            return False
         return self._inventory[file_id].executable
 
     def _is_executable_from_path_and_stat_from_stat(self, path, stat_result):




More information about the bazaar-commits mailing list