~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ftp.py

Merge from bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
import random
38
38
from warnings import warn
39
39
 
 
40
from bzrlib import (
 
41
    errors,
 
42
    urlutils,
 
43
    )
 
44
from bzrlib.trace import mutter, warning
40
45
from bzrlib.transport import (
41
 
    Transport,
42
46
    Server,
43
47
    split_url,
 
48
    Transport,
44
49
    )
45
 
import bzrlib.errors as errors
46
 
from bzrlib.trace import mutter, warning
47
50
import bzrlib.ui
48
51
 
49
52
_have_medusa = False
122
125
            netloc = '%s@%s' % (urllib.quote(self._username), netloc)
123
126
        if self._port is not None:
124
127
            netloc = '%s:%d' % (netloc, self._port)
125
 
        return urlparse.urlunparse(('ftp', netloc, path, '', '', ''))
 
128
        proto = 'ftp'
 
129
        if self.is_active:
 
130
            proto = 'aftp'
 
131
        return urlparse.urlunparse((proto, netloc, path, '', '', ''))
126
132
 
127
133
    def _get_FTP(self):
128
134
        """Return the ftplib.FTP instance for this object."""
189
195
 
190
196
    def _abspath(self, relpath):
191
197
        assert isinstance(relpath, basestring)
192
 
        relpath = urllib.unquote(relpath)
 
198
        relpath = urlutils.unescape(relpath)
193
199
        relpath_parts = relpath.split('/')
194
200
        if len(relpath_parts) > 1:
195
201
            if relpath_parts[0] == '':
212
218
        # Possibly, we could use urlparse.urljoin() here, but
213
219
        # I'm concerned about when it chooses to strip the last
214
220
        # portion of the path, and when it doesn't.
215
 
        return '/'.join(basepath) or '/'
 
221
 
 
222
        # XXX: It seems that ftplib does not handle Unicode paths
 
223
        # at the same time, medusa won't handle utf8 paths
 
224
        # So if we .encode(utf8) here, then we get a Server failure.
 
225
        # while if we use str(), we get a UnicodeError, and the test suite
 
226
        # just skips testing UnicodePaths.
 
227
        return str('/'.join(basepath) or '/')
216
228
    
217
229
    def abspath(self, relpath):
218
230
        """Return the full url to the given relative path.
453
465
 
454
466
    def list_dir(self, relpath):
455
467
        """See Transport.list_dir."""
 
468
        basepath = self._abspath(relpath)
 
469
        mutter("FTP nlst: %s", basepath)
 
470
        f = self._get_FTP()
456
471
        try:
457
 
            mutter("FTP nlst: %s", self._abspath(relpath))
458
 
            f = self._get_FTP()
459
 
            basepath = self._abspath(relpath)
460
472
            paths = f.nlst(basepath)
461
 
            # If FTP.nlst returns paths prefixed by relpath, strip 'em
462
 
            if paths and paths[0].startswith(basepath):
463
 
                paths = [path[len(basepath)+1:] for path in paths]
464
 
            # Remove . and .. if present, and return
465
 
            return [path for path in paths if path not in (".", "..")]
466
473
        except ftplib.error_perm, e:
467
474
            self._translate_perm_error(e, relpath, extra='error with list_dir')
 
475
        # If FTP.nlst returns paths prefixed by relpath, strip 'em
 
476
        if paths and paths[0].startswith(basepath):
 
477
            entries = [path[len(basepath)+1:] for path in paths]
 
478
        else:
 
479
            entries = paths
 
480
        # Remove . and .. if present
 
481
        return [urlutils.escape(entry) for entry in entries
 
482
                if entry not in ('.', '..')]
468
483
 
469
484
    def iter_files_recursive(self):
470
485
        """See Transport.iter_files_recursive.
473
488
        mutter("FTP iter_files_recursive")
474
489
        queue = list(self.list_dir("."))
475
490
        while queue:
476
 
            relpath = urllib.quote(queue.pop(0))
 
491
            relpath = queue.pop(0)
477
492
            st = self.stat(relpath)
478
493
            if stat.S_ISDIR(st.st_mode):
479
494
                for i, basename in enumerate(self.list_dir(relpath)):