~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transport.py

  • Committer: John Arbash Meinel
  • Date: 2005-07-11 18:53:10 UTC
  • mto: (1185.11.1)
  • mto: This revision was merged to the branch mainline in revision 1396.
  • Revision ID: john@arbash-meinel.com-20050711185310-3ed8748ad27e9baf
Working on making Branch() do all of it's work over a Transport.

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
    multiple requests. They generally have a dumb base implementation 
74
74
    which just iterates over the arguments, but smart Transport
75
75
    implementations can do pipelining.
 
76
    In general implementations should support having a generator or a list
 
77
    as an argument (ie always iterate, never index)
 
78
 
 
79
    TODO: Worry about file encodings. For instance bzr control files should
 
80
          all be encoded in utf-8, but read as local encoding.
76
81
    """
77
82
 
78
83
    def __init__(self, base):
79
84
        self.base = base
80
85
 
 
86
    def clone(self, offset=None):
 
87
        """Return a new Transport object, cloned from the current location,
 
88
        using a subdirectory. This allows connections to be pooled,
 
89
        rather than a new one needed for each subdir.
 
90
        """
 
91
        raise NotImplementedError
 
92
 
81
93
    def _pump(self, from_file, to_file):
82
94
        """Most children will need to copy from one file-like 
83
95
        object or string to another one.
89
101
            from bzrlib.osutils import pumpfile
90
102
            pumpfile(from_file, to_file)
91
103
 
 
104
    def _get_total(self, multi):
 
105
        """Try to figure out how many entries are in multi,
 
106
        but if not possible, return None.
 
107
        """
 
108
        try:
 
109
            return len(multi)
 
110
        except TypeError: # We can't tell how many, because relpaths is a generator
 
111
            return None
 
112
 
 
113
    def _update_pb(self, pb, msg, count, total):
 
114
        """Update the progress bar based on the current count
 
115
        and total available, total may be None if it was
 
116
        not possible to determine.
 
117
        """
 
118
        if total is None:
 
119
            pb.update(msg, count, count+1)
 
120
        else:
 
121
            pb.update(msg, count, total)
 
122
 
 
123
    def _iterate_over(self, multi, func, pb, msg):
 
124
        """Iterate over all entries in multi, passing them to func,
 
125
        and update the progress bar as you go along.
 
126
        """
 
127
        total = self._get_total(multi)
 
128
        count = 0
 
129
        for entry in multi:
 
130
            self._update_pb(pb, msg, count, total)
 
131
            func(*entry)
 
132
            count += 1
 
133
        return count
 
134
 
92
135
    def has(self, relpath):
93
136
        """Does the target location exist?"""
94
137
        raise NotImplementedError
98
141
        """
99
142
        raise NotImplementedError
100
143
 
101
 
    def get_multi(self, relpaths):
 
144
    def abspath(self, *args):
 
145
        """Return the full url to the given relative path.
 
146
        This can be supplied with multiple arguments
 
147
        """
 
148
        raise NotImplementedError
 
149
 
 
150
    def get_multi(self, relpaths, pb=None):
102
151
        """Get a list of file-like objects, one for each entry in relpaths.
103
152
 
104
153
        :param relpaths: A list of relative paths.
105
 
        :return: A list of file-like objects.
 
154
        :param pb:  An optional ProgressBar for indicating percent done.
 
155
        :return: A list or generator of file-like objects
106
156
        """
107
 
        files = []
 
157
        # TODO: Consider having this actually buffer the requests,
 
158
        # in the default mode, it probably won't give worse performance,
 
159
        # and all children wouldn't have to implement buffering
 
160
        total = self._get_total(multi)
 
161
        count = 0
108
162
        for relpath in relpaths:
109
 
            files.append(self.get(relpath))
 
163
            self._update_pb(pb, msg, count, total)
 
164
            yield self.get(relpath)
 
165
            count += 1
110
166
        return files
111
167
 
112
168
    def put(self, relpath, f):
114
170
        """
115
171
        raise NotImplementedError
116
172
 
117
 
    def put_multi(self, files):
 
173
    def put_multi(self, files, pb=None):
118
174
        """Put a set of files or strings into the location.
119
175
 
120
176
        :param files: A list of tuples of relpath, file object [(path1, file1), (path2, file2),...]
121
 
        """
122
 
        for path, f in files:
123
 
            self.put(path, f)
 
177
        :param pb:  An optional ProgressBar for indicating percent done.
 
178
        :return: The number of files copied.
 
179
        """
 
180
        return self._iterate_over(files, self.put, pb, 'put')
 
181
 
 
182
    def mkdir(self, relpath):
 
183
        """Create a directory at the given path."""
 
184
        raise NotImplementedError
 
185
 
 
186
    def open(self, relpath, mode='wb'):
 
187
        """Open a remote file for writing.
 
188
        This may return a proxy object, which is written to locally, and
 
189
        then when the file is closed, it is uploaded using put()
 
190
        """
 
191
        raise NotImplementedError
124
192
 
125
193
    def append(self, relpath, f):
126
194
        """Append the text in the file-like or string object to 
131
199
    def append_multi(self, files):
132
200
        """Append the text in each file-like or string object to
133
201
        the supplied location.
 
202
 
 
203
        :param files: A set of (path, f) entries
 
204
        :param pb:  An optional ProgressBar for indicating percent done.
134
205
        """
135
 
        for path, f in files:
136
 
            self.append(path, f)
 
206
        return self._iterate_over(files, self.append, pb, 'append')
137
207
 
138
208
    def copy(self, rel_from, rel_to):
139
209
        """Copy the item at rel_from to the location at rel_to"""
146
216
        """
147
217
        # This is the non-pipelined implementation, so that
148
218
        # implementors don't have to implement everything.
149
 
        for rel_from, rel_to in relpaths:
150
 
            self.copy(rel_from, rel_to)
 
219
        return self._iterate_over(relpaths, self.copy, pb, 'copy')
151
220
 
152
221
    def move(self, rel_from, rel_to):
153
222
        """Move the item at rel_from to the location at rel_to"""
158
227
        
159
228
        :param relpaths: A list of tuples of the form [(from1, to1), (from2, to2),...]
160
229
        """
161
 
        for rel_from, rel_to in relpaths:
162
 
            self.move(rel_from, rel_to)
 
230
        return self._iterate_over(relpaths, self.move, pb, 'move')
163
231
 
164
232
    def move_multi_to(self, relpaths, rel_to):
165
233
        """Move a bunch of entries to a single location.
180
248
    def delete_multi(self, relpaths):
181
249
        """Queue up a bunch of deletes to be done.
182
250
        """
183
 
        for relpath in relpaths:
184
 
            self.delete(relpath)
 
251
        return self._iterate_over(relpaths, self.delete, pb, 'delete')
 
252
 
 
253
    def stat(self, relpath):
 
254
        """Return the stat information for a file.
 
255
        WARNING: This may not be implementable for all protocols, so use
 
256
        sparingly.
 
257
        """
 
258
        raise NotImplementedError
 
259
 
 
260
    def stat_multi(self, relpaths, pb=None):
 
261
        """Stat multiple files and return the information.
 
262
        """
 
263
        #TODO:  Is it worth making this a generator instead of a
 
264
        #       returning a list?
 
265
        stats = []
 
266
        def gather(path):
 
267
            stats.append(self.stat(path))
 
268
 
 
269
        count = self._iterate_over(relpaths, gather, pb, 'stat')
 
270
        return stats
 
271
 
185
272
 
186
273
    def async_get(self, relpath):
187
274
        """Make a request for an file at the given location, but