Rev 2865: Merge bzr.dev. in http://people.ubuntu.com/~robertc/baz2.0/repository

Robert Collins robertc at robertcollins.net
Fri Nov 2 00:21:21 GMT 2007


At http://people.ubuntu.com/~robertc/baz2.0/repository

------------------------------------------------------------
revno: 2865
revision-id:robertc at robertcollins.net-20071102002057-ox02yp5uish1a1xe
parent: robertc at robertcollins.net-20071030204117-odbfrt5u28k8ur4l
parent: pqm at pqm.ubuntu.com-20071031141102-b5664t8izotfnc6h
committer: Robert Collins <robertc at robertcollins.net>
branch nick: repository
timestamp: Fri 2007-11-02 11:20:57 +1100
message:
  Merge bzr.dev.
added:
  bzrlib/tests/ftp_server.py     ftpserver.py-20071019102346-61jbvdkrr70igauv-1
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
  bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
  bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
  bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.6
    revision-id:pqm at pqm.ubuntu.com-20071031141102-b5664t8izotfnc6h
    parent: pqm at pqm.ubuntu.com-20071031123737-3srdl8uoj1o9vb69
    parent: v.ladeuil+lp at free.fr-20071031124019-ir0as6cxx5tjpayy
    committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
    branch nick: +trunk
    timestamp: Wed 2007-10-31 14:11:02 +0000
    message:
      Fix typo (is_permament => is_permanent) reported on IRC
    modified:
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
      bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.5.1.1
        revision-id:v.ladeuil+lp at free.fr-20071031124019-ir0as6cxx5tjpayy
        parent: pqm at pqm.ubuntu.com-20071031123737-3srdl8uoj1o9vb69
        parent: v.ladeuil+lp at free.fr-20071031123811-ya0py5cpwhh6rabl
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: trunk
        timestamp: Wed 2007-10-31 13:40:19 +0100
        message:
          Fix typo (is_permament => is_permanent) reported on IRC
        modified:
          bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
          bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
          bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.4.1
        revision-id:v.ladeuil+lp at free.fr-20071031123811-ya0py5cpwhh6rabl
        parent: pqm at pqm.ubuntu.com-20071029221703-zy7q7a0ehfvpybtn
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: http
        timestamp: Wed 2007-10-31 13:38:11 +0100
        message:
          Fix typo (is_permament => is_permanent) reported on IRC
          
          * bzrlib/errors.py:
          (RedirectRequested.__init__): Fix typo and delete useless
          attribute.
          
          * bzrlib/transport/http/_urllib.py:
          (HttpTransport_urllib._perform): Fix typo.
          
          * bzrlib/transport/http/_pycurl.py:
          (PyCurlTransport._curl_perform): Fix typo.
        modified:
          bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
          bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
          bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
    ------------------------------------------------------------
    revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.5
    revision-id:pqm at pqm.ubuntu.com-20071031123737-3srdl8uoj1o9vb69
    parent: pqm at pqm.ubuntu.com-20071031104053-fj7i7m8037qjgce4
    parent: v.ladeuil+lp at free.fr-20071031114844-4aiho9kp87gzzngk
    committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
    branch nick: +trunk
    timestamp: Wed 2007-10-31 12:37:37 +0000
    message:
      Fix reference to FTPServer, forgotten in the previous renaming
    modified:
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.4.1.1
        revision-id:v.ladeuil+lp at free.fr-20071031114844-4aiho9kp87gzzngk
        parent: pqm at pqm.ubuntu.com-20071031104053-fj7i7m8037qjgce4
        parent: v.ladeuil+lp at free.fr-20071031114545-4sovxko8bk8nq115
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: trunk
        timestamp: Wed 2007-10-31 12:48:44 +0100
        message:
          Fix reference to FTPServer, forgotten in the previous renaming
        modified:
          bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.3.3
        revision-id:v.ladeuil+lp at free.fr-20071031114545-4sovxko8bk8nq115
        parent: v.ladeuil+lp at free.fr-20071031093150-jampe95fzzgls1ny
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: 157752
        timestamp: Wed 2007-10-31 12:45:45 +0100
        message:
          Fix reference to FTPServer, forgotten in the previous renaming.
          
          * bzrlib/tests/__init__.py:
          (_FTPServerFeature._probe): Test the right module import.
        modified:
          bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
    ------------------------------------------------------------
    revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.4
    revision-id:pqm at pqm.ubuntu.com-20071031104053-fj7i7m8037qjgce4
    parent: pqm at pqm.ubuntu.com-20071030223954-0ussb5qn1dy2fg8v
    parent: v.ladeuil+lp at free.fr-20071031094642-pi0ce5o2etkjqoix
    committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
    branch nick: +trunk
    timestamp: Wed 2007-10-31 10:40:53 +0000
    message:
      Fix #157752 by wrapping medusa test ftp server behind FTPServerFeature
    added:
      bzrlib/tests/ftp_server.py     ftpserver.py-20071019102346-61jbvdkrr70igauv-1
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
      bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.3.1.1
        revision-id:v.ladeuil+lp at free.fr-20071031094642-pi0ce5o2etkjqoix
        parent: pqm at pqm.ubuntu.com-20071030223954-0ussb5qn1dy2fg8v
        parent: v.ladeuil+lp at free.fr-20071031093150-jampe95fzzgls1ny
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: trunk
        timestamp: Wed 2007-10-31 10:46:42 +0100
        message:
          Fix #157752 by wrapping medusa test ftp server behind FTPServerFeature
        added:
          bzrlib/tests/ftp_server.py     ftpserver.py-20071019102346-61jbvdkrr70igauv-1
        modified:
          NEWS                           NEWS-20050323055033-4e00b5db738777ff
          bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
          bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
          bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.3.2
        revision-id:v.ladeuil+lp at free.fr-20071031093150-jampe95fzzgls1ny
        parent: v.ladeuil+lp at free.fr-20071030175409-yvkwn2d5t1paslvh
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: 157752
        timestamp: Wed 2007-10-31 10:31:50 +0100
        message:
          Rename FTPServer.py to ftp_server.py.
          
          * bzrlib/transport/ftp.py:
          Rename FTPServer.py to ftp_server.py.
          (get_test_permutations): Rename the fake FTPServer to
          UnavailableFTPServer.
          
          * bzrlib/tests/test_ftp_transport.py: 
          Rename FTPServer.py to ftp_server.py.
        renamed:
          bzrlib/tests/FTPServer.py => bzrlib/tests/ftp_server.py ftpserver.py-20071019102346-61jbvdkrr70igauv-1
        modified:
          bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
          bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.3.1
        revision-id:v.ladeuil+lp at free.fr-20071030175409-yvkwn2d5t1paslvh
        parent: pqm at pqm.ubuntu.com-20071029221703-zy7q7a0ehfvpybtn
        parent: v.ladeuil+lp at free.fr-20071029173634-yxcis9vbrv60t3z9
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: 157752
        timestamp: Tue 2007-10-30 18:54:09 +0100
        message:
          Fix #157752 by wrapping medusa test ftp server behind FTPServerFeature
        added:
          bzrlib/tests/FTPServer.py      ftpserver.py-20071019102346-61jbvdkrr70igauv-1
        modified:
          NEWS                           NEWS-20050323055033-4e00b5db738777ff
          bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
          bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
          bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.6.3.2
        revision-id:v.ladeuil+lp at free.fr-20071029173634-yxcis9vbrv60t3z9
        parent: v.ladeuil+lp at free.fr-20071019131948-g5793d6onl5ik5sm
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: 127164
        timestamp: Mon 2007-10-29 18:36:34 +0100
        message:
          Prepare for fixing bug #157752 (so close to a palindrome...)
          
          * bzrlib/transport/ftp.py:
          (get_test_permutations): Add a dummy FPTServer so that the test
          suite reports the skipped tests.
        modified:
          bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.6.3.1
        revision-id:v.ladeuil+lp at free.fr-20071019131948-g5793d6onl5ik5sm
        parent: pqm at pqm.ubuntu.com-20071019042839-xwvsz0loa77yokxm
        committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
        branch nick: 127164
        timestamp: Fri 2007-10-19 15:19:48 +0200
        message:
          Separate transport from test server.
          
          * bzrlib/transport/ftp.py:
          Move ftp test server to its own file.
          (get_test_permutations): Reworked around FTPServerFeature.
          
          * bzrlib/tests/test_ftp_transport.py:
          (TestCaseWithFTPServer.setUp): Use FTPServerFeature instead of
          MedusaFeature.
          
          * bzrlib/tests/__init__.py:
          (_FTPServerFeature): New feature allowing a cleaner separation
          between ftp.py and FTPServer.py.
          
          * bzrlib/tests/FTPServer.py: 
          New file. Extracted from bzrlib/transport/ftp.py (use case for
          tracking moving lines).
        added:
          bzrlib/tests/FTPServer.py      ftpserver.py-20071019102346-61jbvdkrr70igauv-1
        modified:
          bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
          bzrlib/tests/test_ftp_transport.py test_aftp_transport.-20060823221619-98mwjzxtwtkt527k-1
          bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
    ------------------------------------------------------------
    revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.3
    revision-id:pqm at pqm.ubuntu.com-20071030223954-0ussb5qn1dy2fg8v
    parent: pqm at pqm.ubuntu.com-20071030214613-c0ojrpmnm21da068
    parent: robertc at robertcollins.net-20071030210601-poh10rzw97d51vxq
    committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
    branch nick: +trunk
    timestamp: Tue 2007-10-30 22:39:54 +0000
    message:
      (robertc) Avoid resetting dirstate parent data during revert if the parents list has not changed. (Robert Collins)
    modified:
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
        ------------------------------------------------------------
        revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.2.2
        revision-id:robertc at robertcollins.net-20071030210601-poh10rzw97d51vxq
        parent: robertc at robertcollins.net-20071030200323-2iyytqgqcltpngta
        committer: Robert Collins <robertc at robertcollins.net>
        branch nick: revert
        timestamp: Wed 2007-10-31 08:06:01 +1100
        message:
          Avoid dirstate parent resetting when it is not needed during revert.
        modified:
          bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
    ------------------------------------------------------------
    revno: 2592.1.25.2.7.1.28.1.6.1.3.1.9.2.1.3.74.1.31.3.18.1.9.1.2.1.12.1.8.1.46.1.18.1.1.2.21.2.10.3.8.2.9.1.9.2.2.1.2
    revision-id:pqm at pqm.ubuntu.com-20071030214613-c0ojrpmnm21da068
    parent: pqm at pqm.ubuntu.com-20071030203434-6ffpvdncd12ncx3d
    parent: robertc at robertcollins.net-20071030200323-2iyytqgqcltpngta
    committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
    branch nick: +trunk
    timestamp: Tue 2007-10-30 21:46:13 +0000
    message:
      (robertc) Stop reading the basis inventory from the repository twice during revert and manage basis tree locks better. (Robert Collins)
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
=== added file 'bzrlib/tests/ftp_server.py'
--- a/bzrlib/tests/ftp_server.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/ftp_server.py	2007-10-31 09:31:50 +0000
@@ -0,0 +1,249 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+"""
+FTP test server.
+
+Based on medusa: http://www.amk.ca/python/code/medusa.html
+"""
+
+import asyncore
+import os
+import select
+import stat
+import threading
+
+import medusa
+import medusa.filesys
+import medusa.ftp_server
+
+from bzrlib import (
+    tests,
+    trace,
+    transport,
+    )
+
+
+class test_authorizer(object):
+    """A custom Authorizer object for running the test suite.
+
+    The reason we cannot use dummy_authorizer, is because it sets the
+    channel to readonly, which we don't always want to do.
+    """
+
+    def __init__(self, root):
+        self.root = root
+        # If secured_user is set secured_password will be checked
+        self.secured_user = None
+        self.secured_password = None
+
+    def authorize(self, channel, username, password):
+        """Return (success, reply_string, filesystem)"""
+        channel.persona = -1, -1
+        if username == 'anonymous':
+            channel.read_only = 1
+        else:
+            channel.read_only = 0
+
+        # Check secured_user if set
+        if (self.secured_user is not None
+            and username == self.secured_user
+            and password != self.secured_password):
+            return 0, 'Password invalid.', None
+        else:
+            return 1, 'OK.', medusa.filesys.os_filesystem(self.root)
+
+
+class ftp_channel(medusa.ftp_server.ftp_channel):
+    """Customized ftp channel"""
+
+    def log(self, message):
+        """Redirect logging requests."""
+        trace.mutter('ftp_channel: %s', message)
+
+    def log_info(self, message, type='info'):
+        """Redirect logging requests."""
+        trace.mutter('ftp_channel %s: %s', type, message)
+
+    def cmd_rnfr(self, line):
+        """Prepare for renaming a file."""
+        self._renaming = line[1]
+        self.respond('350 Ready for RNTO')
+        # TODO: jam 20060516 in testing, the ftp server seems to
+        #       check that the file already exists, or it sends
+        #       550 RNFR command failed
+
+    def cmd_rnto(self, line):
+        """Rename a file based on the target given.
+
+        rnto must be called after calling rnfr.
+        """
+        if not self._renaming:
+            self.respond('503 RNFR required first.')
+        pfrom = self.filesystem.translate(self._renaming)
+        self._renaming = None
+        pto = self.filesystem.translate(line[1])
+        if os.path.exists(pto):
+            self.respond('550 RNTO failed: file exists')
+            return
+        try:
+            os.rename(pfrom, pto)
+        except (IOError, OSError), e:
+            # TODO: jam 20060516 return custom responses based on
+            #       why the command failed
+            # (bialix 20070418) str(e) on Python 2.5 @ Windows
+            # sometimes don't provide expected error message;
+            # so we obtain such message via os.strerror()
+            self.respond('550 RNTO failed: %s' % os.strerror(e.errno))
+        except:
+            self.respond('550 RNTO failed')
+            # For a test server, we will go ahead and just die
+            raise
+        else:
+            self.respond('250 Rename successful.')
+
+    def cmd_size(self, line):
+        """Return the size of a file
+
+        This is overloaded to help the test suite determine if the 
+        target is a directory.
+        """
+        filename = line[1]
+        if not self.filesystem.isfile(filename):
+            if self.filesystem.isdir(filename):
+                self.respond('550 "%s" is a directory' % (filename,))
+            else:
+                self.respond('550 "%s" is not a file' % (filename,))
+        else:
+            self.respond('213 %d' 
+                % (self.filesystem.stat(filename)[stat.ST_SIZE]),)
+
+    def cmd_mkd(self, line):
+        """Create a directory.
+
+        Overloaded because default implementation does not distinguish
+        *why* it cannot make a directory.
+        """
+        if len (line) != 2:
+            self.command_not_understood(''.join(line))
+        else:
+            path = line[1]
+            try:
+                self.filesystem.mkdir (path)
+                self.respond ('257 MKD command successful.')
+            except (IOError, OSError), e:
+                # (bialix 20070418) str(e) on Python 2.5 @ Windows
+                # sometimes don't provide expected error message;
+                # so we obtain such message via os.strerror()
+                self.respond ('550 error creating directory: %s' %
+                              os.strerror(e.errno))
+            except:
+                self.respond ('550 error creating directory.')
+
+
+class ftp_server(medusa.ftp_server.ftp_server):
+    """Customize the behavior of the Medusa ftp_server.
+
+    There are a few warts on the ftp_server, based on how it expects
+    to be used.
+    """
+    _renaming = None
+    ftp_channel_class = ftp_channel
+
+    def __init__(self, *args, **kwargs):
+        trace.mutter('Initializing ftp_server: %r, %r', args, kwargs)
+        medusa.ftp_server.ftp_server.__init__(self, *args, **kwargs)
+
+    def log(self, message):
+        """Redirect logging requests."""
+        trace.mutter('ftp_server: %s', message)
+
+    def log_info(self, message, type='info'):
+        """Override the asyncore.log_info so we don't stipple the screen."""
+        trace.mutter('ftp_server %s: %s', type, message)
+
+
+class FTPServer(transport.Server):
+    """Common code for FTP server facilities."""
+
+    def __init__(self):
+        self._root = None
+        self._ftp_server = None
+        self._port = None
+        self._async_thread = None
+        # ftp server logs
+        self.logs = []
+
+    def get_url(self):
+        """Calculate an ftp url to this server."""
+        return 'ftp://foo:bar@localhost:%d/' % (self._port)
+
+#    def get_bogus_url(self):
+#        """Return a URL which cannot be connected to."""
+#        return 'ftp://127.0.0.1:1'
+
+    def log(self, message):
+        """This is used by medusa.ftp_server to log connections, etc."""
+        self.logs.append(message)
+
+    def setUp(self, vfs_server=None):
+        from bzrlib.transport.local import LocalURLServer
+        assert vfs_server is None or isinstance(vfs_server, LocalURLServer), \
+            "FTPServer currently assumes local transport, got %s" % vfs_server
+
+        self._root = os.getcwdu()
+        self._ftp_server = ftp_server(
+            authorizer=test_authorizer(root=self._root),
+            ip='localhost',
+            port=0, # bind to a random port
+            resolver=None,
+            logger_object=self # Use FTPServer.log() for messages
+            )
+        self._port = self._ftp_server.getsockname()[1]
+        # Don't let it loop forever, or handle an infinite number of requests.
+        # In this case it will run for 1000s, or 10000 requests
+        self._async_thread = threading.Thread(
+                target=FTPServer._asyncore_loop_ignore_EBADF,
+                kwargs={'timeout':0.1, 'count':10000})
+        self._async_thread.setDaemon(True)
+        self._async_thread.start()
+
+    def tearDown(self):
+        """See bzrlib.transport.Server.tearDown."""
+        self._ftp_server.close()
+        asyncore.close_all()
+        self._async_thread.join()
+
+    @staticmethod
+    def _asyncore_loop_ignore_EBADF(*args, **kwargs):
+        """Ignore EBADF during server shutdown.
+
+        We close the socket to get the server to shutdown, but this causes
+        select.select() to raise EBADF.
+        """
+        try:
+            asyncore.loop(*args, **kwargs)
+            # FIXME: If we reach that point, we should raise an exception
+            # explaining that the 'count' parameter in setUp is too low or
+            # testers may wonder why their test just sits there waiting for a
+            # server that is already dead. Note that if the tester waits too
+            # long under pdb the server will also die.
+        except select.error, e:
+            if e.args[0] != errno.EBADF:
+                raise
+
+
+
+

=== modified file 'NEWS'
--- a/NEWS	2007-10-30 20:41:17 +0000
+++ b/NEWS	2007-11-02 00:20:57 +0000
@@ -208,6 +208,9 @@
    * ``WorkingTree.rename_one`` will now raise an error if normalisation of the
      new path causes bzr to be unable to access the file. (Robert Collins)
 
+   * Wrap medusa ftp test server as an FTPServer feature.
+     (Vincent Ladeuil, #157752)
+
    * Correctly detect a NoSuchFile when using a filezilla server. (Gary van der
      Merwe)
 

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2007-10-30 17:39:11 +0000
+++ b/bzrlib/errors.py	2007-10-31 12:40:19 +0000
@@ -1482,14 +1482,13 @@
 
     _fmt = '%(source)s is%(permanently)s redirected to %(target)s'
 
-    def __init__(self, source, target, is_permament=False, qual_proto=None):
+    def __init__(self, source, target, is_permanent=False, qual_proto=None):
         self.source = source
         self.target = target
-        if is_permament:
+        if is_permanent:
             self.permanently = ' permanently'
         else:
             self.permanently = ''
-        self.is_permament = is_permament
         self._qualified_proto = qual_proto
         TransportError.__init__(self)
 

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2007-10-27 16:33:27 +0000
+++ b/bzrlib/tests/__init__.py	2007-10-31 11:45:45 +0000
@@ -2723,3 +2723,23 @@
         except UnicodeDecodeError:
             return char
     return None
+
+
+class _FTPServerFeature(Feature):
+    """Some tests want an FTP Server, check if one is available.
+
+    Right now, the only way this is available is if 'medusa' is installed.
+    http://www.amk.ca/python/code/medusa.html
+    """
+
+    def _probe(self):
+        try:
+            import bzrlib.tests.ftp_server
+            return True
+        except ImportError:
+            return False
+
+    def feature_name(self):
+        return 'FTPServer'
+
+FTPServerFeature = _FTPServerFeature()

=== modified file 'bzrlib/tests/test_ftp_transport.py'
--- a/bzrlib/tests/test_ftp_transport.py	2007-10-19 17:55:07 +0000
+++ b/bzrlib/tests/test_ftp_transport.py	2007-10-31 09:31:50 +0000
@@ -23,38 +23,16 @@
     )
 
 
-class _MedusaFeature(tests.Feature):
-    """Some tests want an FTP Server, check if one is available.
-
-    Right now, the only way this is available is if 'medusa' is installed.
-    """
-
-    def _probe(self):
-        try:
-            import medusa
-            import medusa.filesys
-            import medusa.ftp_server
-            return True
-        except ImportError:
-            return False
-
-    def feature_name(self):
-        return 'medusa'
-
-MedusaFeature = _MedusaFeature()
-
-
 class TestCaseWithFTPServer(tests.TestCaseWithTransport):
 
-    _test_needs_features = [MedusaFeature]
+    _test_needs_features = [tests.FTPServerFeature]
 
     def setUp(self):
-        from bzrlib.transport.ftp import FtpServer
-        self.transport_server = FtpServer
+        from bzrlib.tests import ftp_server
+        self.transport_server = ftp_server.FTPServer
         super(TestCaseWithFTPServer, self).setUp()
 
 
-
 class TestCaseAFTP(tests.TestCaseWithTransport):
     """Test aftp transport."""
 

=== modified file 'bzrlib/transport/ftp.py'
--- a/bzrlib/transport/ftp.py	2007-10-22 01:23:51 +0000
+++ b/bzrlib/transport/ftp.py	2007-10-31 09:31:50 +0000
@@ -25,16 +25,12 @@
 """
 
 from cStringIO import StringIO
-import asyncore
 import errno
 import ftplib
 import os
 import os.path
-import urllib
 import urlparse
-import select
 import stat
-import threading
 import time
 import random
 from warnings import warn
@@ -557,246 +553,17 @@
         return self.lock_read(relpath)
 
 
-class FtpServer(Server):
-    """Common code for FTP server facilities."""
-
-    def __init__(self):
-        self._root = None
-        self._ftp_server = None
-        self._port = None
-        self._async_thread = None
-        # ftp server logs
-        self.logs = []
-
-    def get_url(self):
-        """Calculate an ftp url to this server."""
-        return 'ftp://foo:bar@localhost:%d/' % (self._port)
-
-#    def get_bogus_url(self):
-#        """Return a URL which cannot be connected to."""
-#        return 'ftp://127.0.0.1:1'
-
-    def log(self, message):
-        """This is used by medusa.ftp_server to log connections, etc."""
-        self.logs.append(message)
-
-    def setUp(self, vfs_server=None):
-        if not _have_medusa:
-            raise RuntimeError('Must have medusa to run the FtpServer')
-
-        assert vfs_server is None or isinstance(vfs_server, LocalURLServer), \
-            "FtpServer currently assumes local transport, got %s" % vfs_server
-
-        self._root = os.getcwdu()
-        self._ftp_server = _ftp_server(
-            authorizer=_test_authorizer(root=self._root),
-            ip='localhost',
-            port=0, # bind to a random port
-            resolver=None,
-            logger_object=self # Use FtpServer.log() for messages
-            )
-        self._port = self._ftp_server.getsockname()[1]
-        # Don't let it loop forever, or handle an infinite number of requests.
-        # In this case it will run for 1000s, or 10000 requests
-        self._async_thread = threading.Thread(
-                target=FtpServer._asyncore_loop_ignore_EBADF,
-                kwargs={'timeout':0.1, 'count':10000})
-        self._async_thread.setDaemon(True)
-        self._async_thread.start()
-
-    def tearDown(self):
-        """See bzrlib.transport.Server.tearDown."""
-        self._ftp_server.close()
-        asyncore.close_all()
-        self._async_thread.join()
-
-    @staticmethod
-    def _asyncore_loop_ignore_EBADF(*args, **kwargs):
-        """Ignore EBADF during server shutdown.
-
-        We close the socket to get the server to shutdown, but this causes
-        select.select() to raise EBADF.
-        """
-        try:
-            asyncore.loop(*args, **kwargs)
-            # FIXME: If we reach that point, we should raise an exception
-            # explaining that the 'count' parameter in setUp is too low or
-            # testers may wonder why their test just sits there waiting for a
-            # server that is already dead. Note that if the tester waits too
-            # long under pdb the server will also die.
-        except select.error, e:
-            if e.args[0] != errno.EBADF:
-                raise
-
-
-_ftp_channel = None
-_ftp_server = None
-_test_authorizer = None
-
-
-def _setup_medusa():
-    global _have_medusa, _ftp_channel, _ftp_server, _test_authorizer
-    try:
-        import medusa
-        import medusa.filesys
-        import medusa.ftp_server
-    except ImportError:
-        return False
-
-    _have_medusa = True
-
-    class test_authorizer(object):
-        """A custom Authorizer object for running the test suite.
-
-        The reason we cannot use dummy_authorizer, is because it sets the
-        channel to readonly, which we don't always want to do.
-        """
-
-        def __init__(self, root):
-            self.root = root
-            # If secured_user is set secured_password will be checked
-            self.secured_user = None
-            self.secured_password = None
-
-        def authorize(self, channel, username, password):
-            """Return (success, reply_string, filesystem)"""
-            if not _have_medusa:
-                return 0, 'No Medusa.', None
-
-            channel.persona = -1, -1
-            if username == 'anonymous':
-                channel.read_only = 1
-            else:
-                channel.read_only = 0
-
-            # Check secured_user if set
-            if (self.secured_user is not None
-                and username == self.secured_user
-                and password != self.secured_password):
-                return 0, 'Password invalid.', None
-            else:
-                return 1, 'OK.', medusa.filesys.os_filesystem(self.root)
-
-
-    class ftp_channel(medusa.ftp_server.ftp_channel):
-        """Customized ftp channel"""
-
-        def log(self, message):
-            """Redirect logging requests."""
-            mutter('_ftp_channel: %s', message)
-
-        def log_info(self, message, type='info'):
-            """Redirect logging requests."""
-            mutter('_ftp_channel %s: %s', type, message)
-
-        def cmd_rnfr(self, line):
-            """Prepare for renaming a file."""
-            self._renaming = line[1]
-            self.respond('350 Ready for RNTO')
-            # TODO: jam 20060516 in testing, the ftp server seems to
-            #       check that the file already exists, or it sends
-            #       550 RNFR command failed
-
-        def cmd_rnto(self, line):
-            """Rename a file based on the target given.
-
-            rnto must be called after calling rnfr.
-            """
-            if not self._renaming:
-                self.respond('503 RNFR required first.')
-            pfrom = self.filesystem.translate(self._renaming)
-            self._renaming = None
-            pto = self.filesystem.translate(line[1])
-            if os.path.exists(pto):
-                self.respond('550 RNTO failed: file exists')
-                return
-            try:
-                os.rename(pfrom, pto)
-            except (IOError, OSError), e:
-                # TODO: jam 20060516 return custom responses based on
-                #       why the command failed
-                # (bialix 20070418) str(e) on Python 2.5 @ Windows
-                # sometimes don't provide expected error message;
-                # so we obtain such message via os.strerror()
-                self.respond('550 RNTO failed: %s' % os.strerror(e.errno))
-            except:
-                self.respond('550 RNTO failed')
-                # For a test server, we will go ahead and just die
-                raise
-            else:
-                self.respond('250 Rename successful.')
-
-        def cmd_size(self, line):
-            """Return the size of a file
-
-            This is overloaded to help the test suite determine if the 
-            target is a directory.
-            """
-            filename = line[1]
-            if not self.filesystem.isfile(filename):
-                if self.filesystem.isdir(filename):
-                    self.respond('550 "%s" is a directory' % (filename,))
-                else:
-                    self.respond('550 "%s" is not a file' % (filename,))
-            else:
-                self.respond('213 %d' 
-                    % (self.filesystem.stat(filename)[stat.ST_SIZE]),)
-
-        def cmd_mkd(self, line):
-            """Create a directory.
-
-            Overloaded because default implementation does not distinguish
-            *why* it cannot make a directory.
-            """
-            if len (line) != 2:
-                self.command_not_understood(''.join(line))
-            else:
-                path = line[1]
-                try:
-                    self.filesystem.mkdir (path)
-                    self.respond ('257 MKD command successful.')
-                except (IOError, OSError), e:
-                    # (bialix 20070418) str(e) on Python 2.5 @ Windows
-                    # sometimes don't provide expected error message;
-                    # so we obtain such message via os.strerror()
-                    self.respond ('550 error creating directory: %s' %
-                                  os.strerror(e.errno))
-                except:
-                    self.respond ('550 error creating directory.')
-
-
-    class ftp_server(medusa.ftp_server.ftp_server):
-        """Customize the behavior of the Medusa ftp_server.
-
-        There are a few warts on the ftp_server, based on how it expects
-        to be used.
-        """
-        _renaming = None
-        ftp_channel_class = ftp_channel
-
-        def __init__(self, *args, **kwargs):
-            mutter('Initializing _ftp_server: %r, %r', args, kwargs)
-            medusa.ftp_server.ftp_server.__init__(self, *args, **kwargs)
-
-        def log(self, message):
-            """Redirect logging requests."""
-            mutter('_ftp_server: %s', message)
-
-        def log_info(self, message, type='info'):
-            """Override the asyncore.log_info so we don't stipple the screen."""
-            mutter('_ftp_server %s: %s', type, message)
-
-    _test_authorizer = test_authorizer
-    _ftp_channel = ftp_channel
-    _ftp_server = ftp_server
-
-    return True
-
-
 def get_test_permutations():
     """Return the permutations to be used in testing."""
-    if not _setup_medusa():
-        warn("You must install medusa (http://www.amk.ca/python/code/medusa.html) for FTP tests")
-        return []
+    from bzrlib import tests
+    if tests.FTPServerFeature.available():
+        from bzrlib.tests import ftp_server
+        return [(FtpTransport, ftp_server.FTPServer)]
     else:
-        return [(FtpTransport, FtpServer)]
+        # Dummy server to have the test suite report the number of tests
+        # needing that feature.
+        class UnavailableFTPServer(object):
+            def setUp(self):
+                raise tests.UnavailableFeature(tests.FTPServerFeature)
+
+        return [(FtpTransport, UnavailableFTPServer)]

=== modified file 'bzrlib/transport/http/_pycurl.py'
--- a/bzrlib/transport/http/_pycurl.py	2007-10-19 19:56:06 +0000
+++ b/bzrlib/transport/http/_pycurl.py	2007-10-31 12:38:11 +0000
@@ -312,7 +312,7 @@
             redirected_to = headers['Location']
             raise errors.RedirectRequested(url,
                                            redirected_to,
-                                           is_permament=(code == 301),
+                                           is_permanent=(code == 301),
                                            qual_proto=self._scheme)
 
 

=== modified file 'bzrlib/transport/http/_urllib.py'
--- a/bzrlib/transport/http/_urllib.py	2007-10-19 19:56:06 +0000
+++ b/bzrlib/transport/http/_urllib.py	2007-10-31 12:38:11 +0000
@@ -106,7 +106,7 @@
                 and code in (301, 302, 303, 307):
             raise errors.RedirectRequested(request.get_full_url(),
                                            request.redirected_to,
-                                           is_permament=(code == 301),
+                                           is_permanent=(code == 301),
                                            qual_proto=self._scheme)
 
         if request.redirected_to is not None:

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2007-10-30 20:03:23 +0000
+++ b/bzrlib/workingtree.py	2007-10-30 21:06:01 +0000
@@ -1968,7 +1968,7 @@
         try:
             conflicts = transform.revert(self, old_tree, filenames, backups, pb,
                                          report_changes)
-            if filenames is None:
+            if filenames is None and len(self.get_parent_ids()) > 1:
                 parent_trees = []
                 last_revision = self.last_revision()
                 if last_revision != NULL_REVISION:




More information about the bazaar-commits mailing list