~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport/ftp.py

  • Committer: Vincent Ladeuil
  • Date: 2007-06-03 13:01:58 UTC
  • mto: (2485.8.44 bzr.connection.sharing)
  • mto: This revision was merged to the branch mainline in revision 2646.
  • Revision ID: v.ladeuil+lp@free.fr-20070603130158-kfeitm6gxuxt0b1j
ftp connection sharing refactored. Tests passing.

* bzrlib/transport/ftp.py:
(FtpTransport._create_connection): New method. Refactored from
_get_FTP and implementing the new connection sharing mechanism.
(FtpTransport._reconnect): New method. Helper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
            self.is_active = True
89
89
        else:
90
90
            self.is_active = False
91
 
        if from_transport is None:
92
 
            self._FTP_instance = None
93
 
        else:
94
 
            self._FTP_instance = from_transport._FTP_instance
95
91
 
96
92
    def _get_FTP(self):
97
93
        """Return the ftplib.FTP instance for this object."""
98
 
        if self._FTP_instance is None:
99
 
            mutter("Constructing FTP instance against %r" %
100
 
                   ((self._host, self._port, self._user, '********',
101
 
                    self.is_active),))
102
 
            try:
103
 
                connection = ftplib.FTP()
104
 
                connection.connect(host=self._host, port=self._port)
105
 
                if self._user and self._user != 'anonymous' and \
106
 
                        not self._password:
107
 
                    self._password = bzrlib.ui.ui_factory.get_password(
108
 
                        prompt='FTP %(user)s@%(host)s password',
109
 
                        user=self._user, host=self._host)
110
 
                connection.login(user=self._user, passwd=self._password)
111
 
                connection.set_pasv(not self.is_active)
112
 
            except ftplib.error_perm, e:
113
 
                raise errors.TransportError(msg="Error setting up connection:"
114
 
                                            " %s" % str(e), orig_error=e)
115
 
            self._FTP_instance = connection
116
 
        return self._FTP_instance
117
 
 
118
 
    def _translate_perm_error(self, err, path, extra=None, unknown_exc=FtpPathError):
 
94
        # Ensures that a connection is established
 
95
        connection = self._get_connection()
 
96
        if connection is None:
 
97
            # First connection ever
 
98
            connection, credentials = self._create_connection()
 
99
            self._set_connection(connection, credentials)
 
100
        return connection
 
101
 
 
102
    def _create_connection(self, credentials=None):
 
103
        """Create a new connection with the provided credentials.
 
104
 
 
105
        :param credentials: The credentials needed to establish the connection.
 
106
 
 
107
        :return: The created connection and its associated credentials.
 
108
 
 
109
        The credentials are only the password as it may have been entered
 
110
        interactively by the user and may be different from the one provided
 
111
        in base url at transport creation time.
 
112
        """
 
113
        if credentials is None:
 
114
            password = self._password
 
115
        else:
 
116
            password = credentials
 
117
 
 
118
        mutter("Constructing FTP instance against %r" %
 
119
               ((self._host, self._port, self._user, '********',
 
120
                self.is_active),))
 
121
        try:
 
122
            connection = ftplib.FTP()
 
123
            connection.connect(host=self._host, port=self._port)
 
124
            if self._user and self._user != 'anonymous' and \
 
125
                    password is not None: # '' is a valid password
 
126
                get_password = bzrlib.ui.ui_factory.get_password
 
127
                password = get_password(prompt='FTP %(user)s@%(host)s password',
 
128
                                        user=self._user, host=self._host)
 
129
            connection.login(user=self._user, passwd=password)
 
130
            connection.set_pasv(not self.is_active)
 
131
        except ftplib.error_perm, e:
 
132
            raise errors.TransportError(msg="Error setting up connection:"
 
133
                                        " %s" % str(e), orig_error=e)
 
134
        return connection, password
 
135
 
 
136
    def _reconnect(self):
 
137
        """Create a new connection with the previously used credentials"""
 
138
        credentials = self.get_credentials()
 
139
        connection, credentials = self._create_connection(credentials)
 
140
        self._set_connection(connection, credentials)
 
141
 
 
142
    def _translate_perm_error(self, err, path, extra=None,
 
143
                              unknown_exc=FtpPathError):
119
144
        """Try to translate an ftplib.error_perm exception.
120
145
 
121
146
        :param err: The error to translate into a bzr error
215
240
                                     orig_error=e)
216
241
            else:
217
242
                warning("FTP temporary error: %s. Retrying.", str(e))
218
 
                self._FTP_instance = None
 
243
                self._reconnect()
219
244
                return self.get(relpath, decode, retries+1)
220
245
        except EOFError, e:
221
246
            if retries > _number_of_retries:
225
250
            else:
226
251
                warning("FTP control connection closed. Trying to reopen.")
227
252
                time.sleep(_sleep_between_retries)
228
 
                self._FTP_instance = None
 
253
                self._reconnect()
229
254
                return self.get(relpath, decode, retries+1)
230
255
 
231
256
    def put_file(self, relpath, fp, mode=None, retries=0):
267
292
                                     % self.abspath(relpath), orig_error=e)
268
293
            else:
269
294
                warning("FTP temporary error: %s. Retrying.", str(e))
270
 
                self._FTP_instance = None
 
295
                self._reconnect()
271
296
                self.put_file(relpath, fp, mode, retries+1)
272
297
        except EOFError:
273
298
            if retries > _number_of_retries:
276
301
            else:
277
302
                warning("FTP control connection closed. Trying to reopen.")
278
303
                time.sleep(_sleep_between_retries)
279
 
                self._FTP_instance = None
 
304
                self._reconnect()
280
305
                self.put_file(relpath, fp, mode, retries+1)
281
306
 
282
307
    def mkdir(self, relpath, mode=None):
343
368
                        "Aborting." % abspath, orig_error=e)
344
369
            else:
345
370
                warning("FTP temporary error: %s. Retrying.", str(e))
346
 
                self._FTP_instance = None
 
371
                self._reconnect()
347
372
                self._try_append(relpath, text, mode, retries+1)
348
373
 
349
374
    def _setmode(self, relpath, mode):