/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.169.2 by Vincent Ladeuil
Fix deprecation warning about tree.inventory usage
1
# Copyright (C) 2011, 2012 Canonical Ltd
0.165.1 by Jelmer Vernooij
Support lazily loading.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""bzr-upload command implementations."""
18
6645.2.2 by Jelmer Vernooij
Merge lp:brz.
19
from __future__ import absolute_import
20
6645.2.1 by Jelmer Vernooij
Bundle the upload plugin.
21
from ... import (
0.165.1 by Jelmer Vernooij
Support lazily loading.
22
    commands,
0.152.93 by Vincent Ladeuil
Migrate to config stacks
23
    config,
0.165.1 by Jelmer Vernooij
Support lazily loading.
24
    lazy_import,
25
    option,
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
26
    osutils,
0.165.1 by Jelmer Vernooij
Support lazily loading.
27
    )
28
lazy_import.lazy_import(globals(), """
29
import stat
30
6645.2.1 by Jelmer Vernooij
Bundle the upload plugin.
31
from breezy import (
6667.2.1 by Jelmer Vernooij
Some cleanup; s/BzrDir/ControlDir/, remove some unused imports.
32
    controldir,
0.165.1 by Jelmer Vernooij
Support lazily loading.
33
    errors,
34
    globbing,
35
    ignores,
36
    revision,
37
    transport,
38
    urlutils,
39
    )
40
""")
41
6754.5.1 by Jelmer Vernooij
Fix some python3 compatibility issues that break 'make check-nodocs3' for me.
42
from ...sixish import (
43
    text_type,
44
    )
45
0.152.93 by Vincent Ladeuil
Migrate to config stacks
46
auto_option = config.Option(
47
    'upload_auto', default=False, from_unicode=config.bool_from_store,
48
    help="""\
49
Whether upload should occur when the tip of the branch changes.
50
""")
51
auto_quiet_option = config.Option(
52
    'upload_auto_quiet', default=False, from_unicode=config.bool_from_store,
53
    help="""\
54
Whether upload should occur quietly.
55
""")
56
location_option = config.Option(
57
    'upload_location', default=None,
58
    help="""\
59
The url to upload the working tree to.
60
""")
61
revid_location_option = config.Option(
62
    'upload_revid_location', default=u'.bzr-upload.revid',
63
    help="""\
64
The relative path to be used to store the uploaded revid.
65
66
The only bzr-related info uploaded with the working tree is the corresponding
67
revision id. The uploaded working tree is not linked to any other bzr data.
68
69
If the layout of your remote server is such that you can't write in the
70
root directory but only in the directories inside that root, you will need
71
to use the 'upload_revid_location' configuration variable to specify the
72
relative path to be used. That configuration variable can be specified in
73
locations.conf or branch.conf.
74
75
For example, given the following layout:
76
77
  Project/
78
    private/
79
    public/
80
81
you may have write access in 'private' and 'public' but in 'Project'
82
itself. In that case, you can add the following in your locations.conf or
83
branch.conf file:
84
85
  upload_revid_location = private/.bzr-upload.revid
86
""")
87
88
89
# FIXME: Add more tests around invalid paths or relative paths that doesn't
90
# exist on remote (if only to get proper error messages) for
91
# 'upload_revid_location'
0.165.1 by Jelmer Vernooij
Support lazily loading.
92
93
94
class BzrUploader(object):
95
96
    def __init__(self, branch, to_transport, outf, tree, rev_id,
97
                 quiet=False):
98
        self.branch = branch
99
        self.to_transport = to_transport
100
        self.outf = outf
101
        self.tree = tree
102
        self.rev_id = rev_id
103
        self.quiet = quiet
104
        self._pending_deletions = []
105
        self._pending_renames = []
106
        self._uploaded_revid = None
107
        self._ignored = None
108
109
    def _up_stat(self, relpath):
110
        return self.to_transport.stat(urlutils.escape(relpath))
111
112
    def _up_rename(self, old_path, new_path):
113
        return self.to_transport.rename(urlutils.escape(old_path),
114
                                        urlutils.escape(new_path))
115
116
    def _up_delete(self, relpath):
117
        return self.to_transport.delete(urlutils.escape(relpath))
118
119
    def _up_delete_tree(self, relpath):
120
        return self.to_transport.delete_tree(urlutils.escape(relpath))
121
122
    def _up_mkdir(self, relpath, mode):
123
        return self.to_transport.mkdir(urlutils.escape(relpath), mode)
124
125
    def _up_rmdir(self, relpath):
126
        return self.to_transport.rmdir(urlutils.escape(relpath))
127
128
    def _up_put_bytes(self, relpath, bytes, mode):
129
        self.to_transport.put_bytes(urlutils.escape(relpath), bytes, mode)
130
131
    def _up_get_bytes(self, relpath):
132
        return self.to_transport.get_bytes(urlutils.escape(relpath))
133
134
    def set_uploaded_revid(self, rev_id):
135
        # XXX: Add tests for concurrent updates, etc.
0.152.93 by Vincent Ladeuil
Migrate to config stacks
136
        revid_path = self.branch.get_config_stack().get('upload_revid_location')
0.165.1 by Jelmer Vernooij
Support lazily loading.
137
        self.to_transport.put_bytes(urlutils.escape(revid_path), rev_id)
138
        self._uploaded_revid = rev_id
139
140
    def get_uploaded_revid(self):
141
        if self._uploaded_revid is None:
0.152.93 by Vincent Ladeuil
Migrate to config stacks
142
            revid_path = self.branch.get_config_stack(
143
                ).get('upload_revid_location')
0.165.1 by Jelmer Vernooij
Support lazily loading.
144
            try:
145
                self._uploaded_revid = self._up_get_bytes(revid_path)
146
            except errors.NoSuchFile:
0.152.93 by Vincent Ladeuil
Migrate to config stacks
147
                # We have not uploaded to here.
0.165.1 by Jelmer Vernooij
Support lazily loading.
148
                self._uploaded_revid = revision.NULL_REVISION
149
        return self._uploaded_revid
150
151
    def _get_ignored(self):
152
        if self._ignored is None:
153
            try:
0.152.89 by Vincent Ladeuil
Cope with bzr.dev changes
154
                ignore_file_path = '.bzrignore-upload'
6809.4.7 by Jelmer Vernooij
Swap arguments for get_symlink_target and kind/stored_kind.
155
                ignore_file = self.tree.get_file(ignore_file_path)
156
            except errors.NoSuchFile:
157
                ignored_patterns = []
158
            else:
0.165.1 by Jelmer Vernooij
Support lazily loading.
159
                ignored_patterns = ignores.parse_ignore_file(ignore_file)
160
            self._ignored = globbing.Globster(ignored_patterns)
161
        return self._ignored
162
163
    def is_ignored(self, relpath):
164
        glob = self._get_ignored()
165
        ignored = glob.match(relpath)
166
        import os
167
        if not ignored:
168
            # We still need to check that all parents are not ignored
169
            dir = os.path.dirname(relpath)
170
            while dir and not ignored:
171
                ignored = glob.match(dir)
172
                if not ignored:
173
                    dir = os.path.dirname(dir)
174
        return ignored
175
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
176
    def upload_file(self, old_relpath, new_relpath, id, mode=None):
0.165.1 by Jelmer Vernooij
Support lazily loading.
177
        if mode is None:
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
178
            if self.tree.is_executable(new_relpath, id):
6754.5.1 by Jelmer Vernooij
Fix some python3 compatibility issues that break 'make check-nodocs3' for me.
179
                mode = 0o775
0.165.1 by Jelmer Vernooij
Support lazily loading.
180
            else:
6754.5.1 by Jelmer Vernooij
Fix some python3 compatibility issues that break 'make check-nodocs3' for me.
181
                mode = 0o664
0.165.1 by Jelmer Vernooij
Support lazily loading.
182
        if not self.quiet:
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
183
            self.outf.write('Uploading %s\n' % old_relpath)
184
        self._up_put_bytes(old_relpath, self.tree.get_file_text(new_relpath, id), mode)
0.165.1 by Jelmer Vernooij
Support lazily loading.
185
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
186
    def _force_clear(self, relpath):
187
        try:
188
            st = self._up_stat(relpath)
189
            if stat.S_ISDIR(st.st_mode):
190
                # A simple rmdir may not be enough
191
                if not self.quiet:
192
                    self.outf.write('Clearing %s/%s\n' % (
193
                            self.to_transport.external_url(), relpath))
194
                self._up_delete_tree(relpath)
195
            elif stat.S_ISLNK(st.st_mode):
196
                if not self.quiet:
197
                    self.outf.write('Clearing %s/%s\n' % (
198
                        self.to_transport.external_url(), relpath))
199
                self._up_delete(relpath)
200
        except errors.PathError:
201
            pass
202
0.165.1 by Jelmer Vernooij
Support lazily loading.
203
    def upload_file_robustly(self, relpath, id, mode=None):
204
        """Upload a file, clearing the way on the remote side.
205
206
        When doing a full upload, it may happen that a directory exists where
207
        we want to put our file.
208
        """
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
209
        self._force_clear(relpath)
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
210
        self.upload_file(relpath, relpath, id, mode)
0.165.1 by Jelmer Vernooij
Support lazily loading.
211
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
212
    def upload_symlink(self, relpath, target):
213
        self.to_transport.symlink(target, relpath)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
214
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
215
    def upload_symlink_robustly(self, relpath, target):
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
216
        """Handle uploading symlinks.
217
        """
218
        self._force_clear(relpath)
219
        # Target might not be there at this time; dummy file should be
220
        # overwritten at some point, possibly by another upload.
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
221
        target = osutils.normpath(osutils.pathjoin(
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
222
            osutils.dirname(relpath),
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
223
            target)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
224
        )
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
225
        self.upload_symlink(relpath, target)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
226
0.165.1 by Jelmer Vernooij
Support lazily loading.
227
    def make_remote_dir(self, relpath, mode=None):
228
        if mode is None:
6754.5.1 by Jelmer Vernooij
Fix some python3 compatibility issues that break 'make check-nodocs3' for me.
229
            mode = 0o775
0.165.1 by Jelmer Vernooij
Support lazily loading.
230
        self._up_mkdir(relpath, mode)
231
232
    def make_remote_dir_robustly(self, relpath, mode=None):
233
        """Create a remote directory, clearing the way on the remote side.
234
235
        When doing a full upload, it may happen that a file exists where we
236
        want to create our directory.
237
        """
238
        try:
239
            st = self._up_stat(relpath)
240
            if not stat.S_ISDIR(st.st_mode):
241
                if not self.quiet:
242
                    self.outf.write('Deleting %s/%s\n' % (
243
                            self.to_transport.external_url(), relpath))
244
                self._up_delete(relpath)
245
            else:
246
                # Ok the remote dir already exists, nothing to do
247
                return
248
        except errors.PathError:
249
            pass
250
        self.make_remote_dir(relpath, mode)
251
252
    def delete_remote_file(self, relpath):
253
        if not self.quiet:
254
            self.outf.write('Deleting %s\n' % relpath)
255
        self._up_delete(relpath)
256
257
    def delete_remote_dir(self, relpath):
258
        if not self.quiet:
259
            self.outf.write('Deleting %s\n' % relpath)
260
        self._up_rmdir(relpath)
261
        # XXX: Add a test where a subdir is ignored but we still want to
262
        # delete the dir -- vila 100106
263
264
    def delete_remote_dir_maybe(self, relpath):
265
        """Try to delete relpath, keeping failures to retry later."""
266
        try:
267
            self._up_rmdir(relpath)
268
        # any kind of PathError would be OK, though we normally expect
269
        # DirectoryNotEmpty
270
        except errors.PathError:
271
            self._pending_deletions.append(relpath)
272
273
    def finish_deletions(self):
274
        if self._pending_deletions:
275
            # Process the previously failed deletions in reverse order to
276
            # delete children before parents
277
            for relpath in reversed(self._pending_deletions):
278
                self._up_rmdir(relpath)
279
            # The following shouldn't be needed since we use it once per
280
            # upload, but better safe than sorry ;-)
281
            self._pending_deletions = []
282
283
    def rename_remote(self, old_relpath, new_relpath):
284
        """Rename a remote file or directory taking care of collisions.
285
286
        To avoid collisions during bulk renames, each renamed target is
287
        temporarily assigned a unique name. When all renames have been done,
288
        each target get its proper name.
289
        """
290
        # We generate a sufficiently random name to *assume* that
291
        # no collisions will occur and don't worry about it (nor
292
        # handle it).
293
        import os
294
        import random
295
        import time
296
297
        stamp = '.tmp.%.9f.%d.%d' % (time.time(),
298
                                     os.getpid(),
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
299
                                     random.randint(0, 0x7FFFFFFF))
0.165.1 by Jelmer Vernooij
Support lazily loading.
300
        if not self.quiet:
301
            self.outf.write('Renaming %s to %s\n' % (old_relpath, new_relpath))
302
        self._up_rename(old_relpath, stamp)
303
        self._pending_renames.append((stamp, new_relpath))
304
305
    def finish_renames(self):
306
        for (stamp, new_path) in self._pending_renames:
307
            self._up_rename(stamp, new_path)
308
        # The following shouldn't be needed since we use it once per upload,
309
        # but better safe than sorry ;-)
310
        self._pending_renames = []
311
312
    def upload_full_tree(self):
313
        self.to_transport.ensure_base() # XXX: Handle errors (add
314
                                        # --create-prefix option ?)
6754.8.4 by Jelmer Vernooij
Use new context stuff.
315
        with self.tree.lock_read():
0.169.2 by Vincent Ladeuil
Fix deprecation warning about tree.inventory usage
316
            for relpath, ie in self.tree.iter_entries_by_dir():
0.165.1 by Jelmer Vernooij
Support lazily loading.
317
                if relpath in ('', '.bzrignore', '.bzrignore-upload'):
318
                    # skip root ('')
319
                    # .bzrignore and .bzrignore-upload have no meaning outside
320
                    # a working tree so do not upload them
321
                    continue
322
                if self.is_ignored(relpath):
323
                    if not self.quiet:
324
                        self.outf.write('Ignoring %s\n' % relpath)
325
                    continue
326
                if ie.kind == 'file':
327
                    self.upload_file_robustly(relpath, ie.file_id)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
328
                elif ie.kind == 'symlink':
329
                    try:
330
                        self.upload_symlink_robustly(relpath, ie.symlink_target)
331
                    except errors.TransportNotPossible:
332
                        if not self.quiet:
333
                            target = self.tree.path_content_summary(relpath)[3]
334
                            self.outf.write('Not uploading symlink %s -> %s\n'
335
                                            % (relpath, target))
0.165.1 by Jelmer Vernooij
Support lazily loading.
336
                elif ie.kind == 'directory':
337
                    self.make_remote_dir_robustly(relpath)
338
                else:
339
                    raise NotImplementedError
340
            self.set_uploaded_revid(self.rev_id)
341
342
    def upload_tree(self):
343
        # If we can't find the revid file on the remote location, upload the
344
        # full tree instead
345
        rev_id = self.get_uploaded_revid()
346
347
        if rev_id == revision.NULL_REVISION:
348
            if not self.quiet:
349
                self.outf.write('No uploaded revision id found,'
350
                                ' switching to full upload\n')
351
            self.upload_full_tree()
352
            # We're done
353
            return
354
355
        # Check if the revision hasn't already been uploaded
356
        if rev_id == self.rev_id:
357
            if not self.quiet:
358
                self.outf.write('Remote location already up to date\n')
359
360
        from_tree = self.branch.repository.revision_tree(rev_id)
361
        self.to_transport.ensure_base() # XXX: Handle errors (add
362
                                        # --create-prefix option ?)
363
        changes = self.tree.changes_from(from_tree)
6754.8.4 by Jelmer Vernooij
Use new context stuff.
364
        with self.tree.lock_read():
0.165.1 by Jelmer Vernooij
Support lazily loading.
365
            for (path, id, kind) in changes.removed:
366
                if self.is_ignored(path):
367
                    if not self.quiet:
368
                        self.outf.write('Ignoring %s\n' % path)
369
                    continue
370
                if kind is 'file':
371
                    self.delete_remote_file(path)
372
                elif kind is  'directory':
373
                    self.delete_remote_dir_maybe(path)
374
                elif kind == 'symlink':
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
375
                    self.delete_remote_file(path)
0.165.1 by Jelmer Vernooij
Support lazily loading.
376
                else:
377
                    raise NotImplementedError
378
379
            for (old_path, new_path, id, kind,
380
                 content_change, exec_change) in changes.renamed:
381
                if self.is_ignored(old_path) and self.is_ignored(new_path):
382
                    if not self.quiet:
383
                        self.outf.write('Ignoring %s\n' % old_path)
384
                        self.outf.write('Ignoring %s\n' % new_path)
385
                    continue
386
                if content_change:
387
                    # We update the old_path content because renames and
388
                    # deletions are differed.
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
389
                    self.upload_file(old_path, new_path, id)
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
390
                self.rename_remote(old_path, new_path)
0.165.1 by Jelmer Vernooij
Support lazily loading.
391
            self.finish_renames()
392
            self.finish_deletions()
393
394
            for (path, id, old_kind, new_kind) in changes.kind_changed:
395
                if self.is_ignored(path):
396
                    if not self.quiet:
397
                        self.outf.write('Ignoring %s\n' % path)
398
                    continue
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
399
                if old_kind in ('file', 'symlink'):
0.165.1 by Jelmer Vernooij
Support lazily loading.
400
                    self.delete_remote_file(path)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
401
                elif old_kind == 'directory':
0.165.1 by Jelmer Vernooij
Support lazily loading.
402
                    self.delete_remote_dir(path)
403
                else:
404
                    raise NotImplementedError
405
406
                if new_kind == 'file':
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
407
                    self.upload_file(path, path, id)
7058.5.1 by Neil Santos, Jelmer Vernooij
Add support for uploading symlinks.
408
                elif new_kind == 'symlink':
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
409
                    target = self.tree.get_symlink_target(path)
410
                    self.upload_symlink(path, target)
0.165.1 by Jelmer Vernooij
Support lazily loading.
411
                elif new_kind is 'directory':
412
                    self.make_remote_dir(path)
413
                else:
414
                    raise NotImplementedError
415
416
            for (path, id, kind) in changes.added:
417
                if self.is_ignored(path):
418
                    if not self.quiet:
419
                        self.outf.write('Ignoring %s\n' % path)
420
                    continue
421
                if kind == 'file':
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
422
                    self.upload_file(path, path, id)
0.165.1 by Jelmer Vernooij
Support lazily loading.
423
                elif kind == 'directory':
424
                    self.make_remote_dir(path)
425
                elif kind == 'symlink':
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
426
                    target = self.tree.get_symlink_target(path)
427
                    try:
428
                        self.upload_symlink(path, target)
429
                    except errors.TransportNotPossible:
430
                        if not self.quiet:
431
                            self.outf.write('Not uploading symlink %s -> %s\n'
432
                                            % (path, target))
0.165.1 by Jelmer Vernooij
Support lazily loading.
433
                else:
434
                    raise NotImplementedError
435
436
            # XXX: Add a test for exec_change
437
            for (path, id, kind,
438
                 content_change, exec_change) in changes.modified:
439
                if self.is_ignored(path):
440
                    if not self.quiet:
441
                        self.outf.write('Ignoring %s\n' % path)
442
                    continue
6874.2.1 by Jelmer Vernooij
Make Tree.iter_files_bytes() take paths rather than file_ids.
443
                if kind == 'file':
444
                    self.upload_file(path, path, id)
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
445
                elif kind == 'symlink':
446
                    target = self.tree.get_symlink_target(path)
447
                    self.upload_symlink(path, target)
0.165.1 by Jelmer Vernooij
Support lazily loading.
448
                else:
449
                    raise NotImplementedError
450
451
            self.set_uploaded_revid(self.rev_id)
452
453
454
class CannotUploadToWorkingTree(errors.BzrCommandError):
455
456
    _fmt = 'Cannot upload to a bzr managed working tree: %(url)s".'
457
458
459
class DivergedUploadedTree(errors.BzrCommandError):
460
461
    _fmt = ("Your branch (%(revid)s)"
462
            " and the uploaded tree (%(uploaded_revid)s) have diverged: ")
463
464
465
class cmd_upload(commands.Command):
466
    """Upload a working tree, as a whole or incrementally.
467
468
    If no destination is specified use the last one used.
469
    If no revision is specified upload the changes since the last upload.
470
471
    Changes include files added, renamed, modified or removed.
472
    """
473
    _see_also = ['plugins/upload']
474
    takes_args = ['location?']
475
    takes_options = [
476
        'revision',
477
        'remember',
478
        'overwrite',
479
        option.Option('full', 'Upload the full working tree.'),
480
        option.Option('quiet', 'Do not output what is being done.',
481
                       short_name='q'),
482
        option.Option('directory',
483
                      help='Branch to upload from, '
484
                      'rather than the one containing the working directory.',
485
                      short_name='d',
6754.5.1 by Jelmer Vernooij
Fix some python3 compatibility issues that break 'make check-nodocs3' for me.
486
                      type=text_type,
0.165.1 by Jelmer Vernooij
Support lazily loading.
487
                      ),
488
        option.Option('auto',
489
                      'Trigger an upload from this branch whenever the tip '
490
                      'revision changes.')
491
       ]
492
493
    def run(self, location=None, full=False, revision=None, remember=None,
494
            directory=None, quiet=False, auto=None, overwrite=False
495
            ):
496
        if directory is None:
497
            directory = u'.'
498
499
        (wt, branch,
6667.2.1 by Jelmer Vernooij
Some cleanup; s/BzrDir/ControlDir/, remove some unused imports.
500
         relpath) = controldir.ControlDir.open_containing_tree_or_branch(
501
             directory)
0.165.1 by Jelmer Vernooij
Support lazily loading.
502
503
        if wt:
504
            wt.lock_read()
505
            locked = wt
506
        else:
507
            branch.lock_read()
508
            locked = branch
509
        try:
510
            if wt:
511
                changes = wt.changes_from(wt.basis_tree())
512
513
                if revision is None and  changes.has_changed():
514
                    raise errors.UncommittedChanges(wt)
515
0.152.93 by Vincent Ladeuil
Migrate to config stacks
516
            conf = branch.get_config_stack()
0.165.1 by Jelmer Vernooij
Support lazily loading.
517
            if location is None:
0.152.93 by Vincent Ladeuil
Migrate to config stacks
518
                stored_loc = conf.get('upload_location')
0.165.1 by Jelmer Vernooij
Support lazily loading.
519
                if stored_loc is None:
520
                    raise errors.BzrCommandError(
521
                        'No upload location known or specified.')
522
                else:
523
                    # FIXME: Not currently tested
524
                    display_url = urlutils.unescape_for_display(stored_loc,
525
                            self.outf.encoding)
526
                    self.outf.write("Using saved location: %s\n" % display_url)
527
                    location = stored_loc
528
529
            to_transport = transport.get_transport(location)
530
531
            # Check that we are not uploading to a existing working tree.
532
            try:
6667.2.1 by Jelmer Vernooij
Some cleanup; s/BzrDir/ControlDir/, remove some unused imports.
533
                to_bzr_dir = controldir.ControlDir.open_from_transport(
534
                        to_transport)
0.165.1 by Jelmer Vernooij
Support lazily loading.
535
                has_wt = to_bzr_dir.has_workingtree()
536
            except errors.NotBranchError:
537
                has_wt = False
538
            except errors.NotLocalUrl:
539
                # The exception raised is a bit weird... but that's life.
540
                has_wt = True
541
542
            if has_wt:
543
                raise CannotUploadToWorkingTree(url=location)
544
            if revision is None:
545
                rev_id = branch.last_revision()
546
            else:
547
                if len(revision) != 1:
548
                    raise errors.BzrCommandError(
549
                        'bzr upload --revision takes exactly 1 argument')
550
                rev_id = revision[0].in_history(branch).rev_id
551
552
            tree = branch.repository.revision_tree(rev_id)
553
554
            uploader = BzrUploader(branch, to_transport, self.outf, tree,
555
                                   rev_id, quiet=quiet)
556
557
            if not overwrite:
558
                prev_uploaded_rev_id = uploader.get_uploaded_revid()
559
                graph = branch.repository.get_graph()
560
                if not graph.is_ancestor(prev_uploaded_rev_id, rev_id):
561
                    raise DivergedUploadedTree(
562
                        revid=rev_id, uploaded_revid=prev_uploaded_rev_id)
563
            if full:
564
                uploader.upload_full_tree()
565
            else:
566
                uploader.upload_tree()
567
        finally:
568
            locked.unlock()
569
570
        # We uploaded successfully, remember it
7058.5.4 by Jelmer Vernooij
Add upload support for symlinks.
571
        with branch.lock_write():
0.152.93 by Vincent Ladeuil
Migrate to config stacks
572
            upload_location = conf.get('upload_location')
573
            if upload_location is None or remember:
574
                conf.set('upload_location',
575
                         urlutils.unescape(to_transport.base))
576
            if auto is not None:
577
                conf.set('upload_auto', auto)
578