/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/plugins/upload/cmds.py

  • Committer: Jelmer Vernooij
  • Date: 2018-02-18 21:42:57 UTC
  • mto: This revision was merged to the branch mainline in revision 6859.
  • Revision ID: jelmer@jelmer.uk-20180218214257-jpevutp1wa30tz3v
Update TODO to reference Breezy, not Bazaar.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""bzr-upload command implementations."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
from ... import (
 
22
    branch,
20
23
    commands,
21
24
    config,
22
 
    errors,
23
25
    lazy_import,
24
26
    option,
25
 
    osutils,
26
27
    )
27
28
lazy_import.lazy_import(globals(), """
28
29
import stat
 
30
import sys
29
31
 
30
32
from breezy import (
31
33
    controldir,
 
34
    errors,
32
35
    globbing,
33
36
    ignores,
34
37
    revision,
37
40
    )
38
41
""")
39
42
 
 
43
from ...sixish import (
 
44
    text_type,
 
45
    )
40
46
 
41
47
auto_option = config.Option(
42
48
    'upload_auto', default=False, from_unicode=config.bool_from_store,
168
174
                    dir = os.path.dirname(dir)
169
175
        return ignored
170
176
 
171
 
    def upload_file(self, old_relpath, new_relpath, mode=None):
 
177
    def upload_file(self, relpath, id, mode=None):
172
178
        if mode is None:
173
 
            if self.tree.is_executable(new_relpath):
 
179
            if self.tree.is_executable(relpath, id):
174
180
                mode = 0o775
175
181
            else:
176
182
                mode = 0o664
177
183
        if not self.quiet:
178
 
            self.outf.write('Uploading %s\n' % old_relpath)
179
 
        self._up_put_bytes(
180
 
            old_relpath, self.tree.get_file_text(new_relpath), mode)
181
 
 
182
 
    def _force_clear(self, relpath):
 
184
            self.outf.write('Uploading %s\n' % relpath)
 
185
        self._up_put_bytes(relpath, self.tree.get_file_text(relpath, id), mode)
 
186
 
 
187
    def upload_file_robustly(self, relpath, id, mode=None):
 
188
        """Upload a file, clearing the way on the remote side.
 
189
 
 
190
        When doing a full upload, it may happen that a directory exists where
 
191
        we want to put our file.
 
192
        """
183
193
        try:
184
194
            st = self._up_stat(relpath)
185
195
            if stat.S_ISDIR(st.st_mode):
186
196
                # A simple rmdir may not be enough
187
197
                if not self.quiet:
188
198
                    self.outf.write('Clearing %s/%s\n' % (
189
 
                        self.to_transport.external_url(), relpath))
 
199
                            self.to_transport.external_url(), relpath))
190
200
                self._up_delete_tree(relpath)
191
 
            elif stat.S_ISLNK(st.st_mode):
192
 
                if not self.quiet:
193
 
                    self.outf.write('Clearing %s/%s\n' % (
194
 
                        self.to_transport.external_url(), relpath))
195
 
                self._up_delete(relpath)
196
201
        except errors.PathError:
197
202
            pass
198
 
 
199
 
    def upload_file_robustly(self, relpath, mode=None):
200
 
        """Upload a file, clearing the way on the remote side.
201
 
 
202
 
        When doing a full upload, it may happen that a directory exists where
203
 
        we want to put our file.
204
 
        """
205
 
        self._force_clear(relpath)
206
 
        self.upload_file(relpath, relpath, mode)
207
 
 
208
 
    def upload_symlink(self, relpath, target):
209
 
        self.to_transport.symlink(target, relpath)
210
 
 
211
 
    def upload_symlink_robustly(self, relpath, target):
212
 
        """Handle uploading symlinks.
213
 
        """
214
 
        self._force_clear(relpath)
215
 
        # Target might not be there at this time; dummy file should be
216
 
        # overwritten at some point, possibly by another upload.
217
 
        target = osutils.normpath(osutils.pathjoin(
218
 
            osutils.dirname(relpath),
219
 
            target)
220
 
        )
221
 
        self.upload_symlink(relpath, target)
 
203
        self.upload_file(relpath, id, mode)
222
204
 
223
205
    def make_remote_dir(self, relpath, mode=None):
224
206
        if mode is None:
236
218
            if not stat.S_ISDIR(st.st_mode):
237
219
                if not self.quiet:
238
220
                    self.outf.write('Deleting %s/%s\n' % (
239
 
                        self.to_transport.external_url(), relpath))
 
221
                            self.to_transport.external_url(), relpath))
240
222
                self._up_delete(relpath)
241
223
            else:
242
224
                # Ok the remote dir already exists, nothing to do
306
288
        self._pending_renames = []
307
289
 
308
290
    def upload_full_tree(self):
309
 
        self.to_transport.ensure_base()  # XXX: Handle errors (add
310
 
        # --create-prefix option ?)
 
291
        self.to_transport.ensure_base() # XXX: Handle errors (add
 
292
                                        # --create-prefix option ?)
311
293
        with self.tree.lock_read():
312
294
            for relpath, ie in self.tree.iter_entries_by_dir():
313
295
                if relpath in ('', '.bzrignore', '.bzrignore-upload'):
320
302
                        self.outf.write('Ignoring %s\n' % relpath)
321
303
                    continue
322
304
                if ie.kind == 'file':
323
 
                    self.upload_file_robustly(relpath)
324
 
                elif ie.kind == 'symlink':
325
 
                    try:
326
 
                        self.upload_symlink_robustly(
327
 
                            relpath, ie.symlink_target)
328
 
                    except errors.TransportNotPossible:
329
 
                        if not self.quiet:
330
 
                            target = self.tree.path_content_summary(relpath)[3]
331
 
                            self.outf.write('Not uploading symlink %s -> %s\n'
332
 
                                            % (relpath, target))
 
305
                    self.upload_file_robustly(relpath, ie.file_id)
333
306
                elif ie.kind == 'directory':
334
307
                    self.make_remote_dir_robustly(relpath)
 
308
                elif ie.kind == 'symlink':
 
309
                    if not self.quiet:
 
310
                        target = self.tree.path_content_summary(relpath)[3]
 
311
                        self.outf.write('Not uploading symlink %s -> %s\n'
 
312
                                        % (relpath, target))
335
313
                else:
336
314
                    raise NotImplementedError
337
315
            self.set_uploaded_revid(self.rev_id)
355
333
                self.outf.write('Remote location already up to date\n')
356
334
 
357
335
        from_tree = self.branch.repository.revision_tree(rev_id)
358
 
        self.to_transport.ensure_base()  # XXX: Handle errors (add
359
 
        # --create-prefix option ?)
 
336
        self.to_transport.ensure_base() # XXX: Handle errors (add
 
337
                                        # --create-prefix option ?)
360
338
        changes = self.tree.changes_from(from_tree)
361
339
        with self.tree.lock_read():
362
 
            for change in changes.removed:
363
 
                if self.is_ignored(change.path[0]):
 
340
            for (path, id, kind) in changes.removed:
 
341
                if self.is_ignored(path):
364
342
                    if not self.quiet:
365
 
                        self.outf.write('Ignoring %s\n' % change.path[0])
 
343
                        self.outf.write('Ignoring %s\n' % path)
366
344
                    continue
367
 
                if change.kind[0] == 'file':
368
 
                    self.delete_remote_file(change.path[0])
369
 
                elif change.kind[0] == 'directory':
370
 
                    self.delete_remote_dir_maybe(change.path[0])
371
 
                elif change.kind[0] == 'symlink':
372
 
                    self.delete_remote_file(change.path[0])
 
345
                if kind is 'file':
 
346
                    self.delete_remote_file(path)
 
347
                elif kind is  'directory':
 
348
                    self.delete_remote_dir_maybe(path)
 
349
                elif kind == 'symlink':
 
350
                    if not self.quiet:
 
351
                        target = self.tree.path_content_summary(path)[3]
 
352
                        self.outf.write('Not deleting remote symlink %s -> %s\n'
 
353
                                        % (path, target))
373
354
                else:
374
355
                    raise NotImplementedError
375
356
 
376
 
            for change in changes.renamed:
377
 
                if self.is_ignored(change.path[0]) and self.is_ignored(change.path[1]):
 
357
            for (old_path, new_path, id, kind,
 
358
                 content_change, exec_change) in changes.renamed:
 
359
                if self.is_ignored(old_path) and self.is_ignored(new_path):
378
360
                    if not self.quiet:
379
 
                        self.outf.write('Ignoring %s\n' % change.path[0])
380
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
 
361
                        self.outf.write('Ignoring %s\n' % old_path)
 
362
                        self.outf.write('Ignoring %s\n' % new_path)
381
363
                    continue
382
 
                if change.changed_content:
383
 
                    # We update the change.path[0] content because renames and
 
364
                if content_change:
 
365
                    # We update the old_path content because renames and
384
366
                    # deletions are differed.
385
 
                    self.upload_file(change.path[0], change.path[1])
386
 
                self.rename_remote(change.path[0], change.path[1])
 
367
                    self.upload_file(old_path, id)
 
368
                if kind == 'symlink':
 
369
                    if not self.quiet:
 
370
                        self.outf.write('Not renaming remote symlink %s to %s\n'
 
371
                                        % (old_path, new_path))
 
372
                else:
 
373
                    self.rename_remote(old_path, new_path)
387
374
            self.finish_renames()
388
375
            self.finish_deletions()
389
376
 
390
 
            for change in changes.kind_changed:
391
 
                if self.is_ignored(change.path[1]):
392
 
                    if not self.quiet:
393
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
394
 
                    continue
395
 
                if change.kind[0] in ('file', 'symlink'):
396
 
                    self.delete_remote_file(change.path[0])
397
 
                elif change.kind[0] == 'directory':
398
 
                    self.delete_remote_dir(change.path[0])
399
 
                else:
400
 
                    raise NotImplementedError
401
 
 
402
 
                if change.kind[1] == 'file':
403
 
                    self.upload_file(change.path[1], change.path[1])
404
 
                elif change.kind[1] == 'symlink':
405
 
                    target = self.tree.get_symlink_target(change.path[1])
406
 
                    self.upload_symlink(change.path[1], target)
407
 
                elif change.kind[1] == 'directory':
408
 
                    self.make_remote_dir(change.path[1])
409
 
                else:
410
 
                    raise NotImplementedError
411
 
 
412
 
            for change in changes.added + changes.copied:
413
 
                if self.is_ignored(change.path[1]):
414
 
                    if not self.quiet:
415
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
416
 
                    continue
417
 
                if change.kind[1] == 'file':
418
 
                    self.upload_file(change.path[1], change.path[1])
419
 
                elif change.kind[1] == 'directory':
420
 
                    self.make_remote_dir(change.path[1])
421
 
                elif change.kind[1] == 'symlink':
422
 
                    target = self.tree.get_symlink_target(change.path[1])
423
 
                    try:
424
 
                        self.upload_symlink(change.path[1], target)
425
 
                    except errors.TransportNotPossible:
426
 
                        if not self.quiet:
427
 
                            self.outf.write('Not uploading symlink %s -> %s\n'
428
 
                                            % (change.path[1], target))
 
377
            for (path, id, old_kind, new_kind) in changes.kind_changed:
 
378
                if self.is_ignored(path):
 
379
                    if not self.quiet:
 
380
                        self.outf.write('Ignoring %s\n' % path)
 
381
                    continue
 
382
                if old_kind == 'file':
 
383
                    self.delete_remote_file(path)
 
384
                elif old_kind ==  'directory':
 
385
                    self.delete_remote_dir(path)
 
386
                else:
 
387
                    raise NotImplementedError
 
388
 
 
389
                if new_kind == 'file':
 
390
                    self.upload_file(path, id)
 
391
                elif new_kind is 'directory':
 
392
                    self.make_remote_dir(path)
 
393
                else:
 
394
                    raise NotImplementedError
 
395
 
 
396
            for (path, id, kind) in changes.added:
 
397
                if self.is_ignored(path):
 
398
                    if not self.quiet:
 
399
                        self.outf.write('Ignoring %s\n' % path)
 
400
                    continue
 
401
                if kind == 'file':
 
402
                    self.upload_file(path, id)
 
403
                elif kind == 'directory':
 
404
                    self.make_remote_dir(path)
 
405
                elif kind == 'symlink':
 
406
                    if not self.quiet:
 
407
                        target = self.tree.path_content_summary(path)[3]
 
408
                        self.outf.write('Not uploading symlink %s -> %s\n'
 
409
                                        % (path, target))
429
410
                else:
430
411
                    raise NotImplementedError
431
412
 
432
413
            # XXX: Add a test for exec_change
433
 
            for change in changes.modified:
434
 
                if self.is_ignored(change.path[1]):
 
414
            for (path, id, kind,
 
415
                 content_change, exec_change) in changes.modified:
 
416
                if self.is_ignored(path):
435
417
                    if not self.quiet:
436
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
 
418
                        self.outf.write('Ignoring %s\n' % path)
437
419
                    continue
438
 
                if change.kind[1] == 'file':
439
 
                    self.upload_file(change.path[1], change.path[1])
440
 
                elif change.kind[1] == 'symlink':
441
 
                    target = self.tree.get_symlink_target(change.path[1])
442
 
                    self.upload_symlink(change.path[1], target)
 
420
                if kind is 'file':
 
421
                    self.upload_file(path, id)
443
422
                else:
444
423
                    raise NotImplementedError
445
424
 
446
425
            self.set_uploaded_revid(self.rev_id)
447
426
 
448
427
 
449
 
class CannotUploadToWorkingTree(errors.CommandError):
 
428
class CannotUploadToWorkingTree(errors.BzrCommandError):
450
429
 
451
430
    _fmt = 'Cannot upload to a bzr managed working tree: %(url)s".'
452
431
 
453
432
 
454
 
class DivergedUploadedTree(errors.CommandError):
 
433
class DivergedUploadedTree(errors.BzrCommandError):
455
434
 
456
435
    _fmt = ("Your branch (%(revid)s)"
457
436
            " and the uploaded tree (%(uploaded_revid)s) have diverged: ")
473
452
        'overwrite',
474
453
        option.Option('full', 'Upload the full working tree.'),
475
454
        option.Option('quiet', 'Do not output what is being done.',
476
 
                      short_name='q'),
 
455
                       short_name='q'),
477
456
        option.Option('directory',
478
457
                      help='Branch to upload from, '
479
458
                      'rather than the one containing the working directory.',
480
459
                      short_name='d',
481
 
                      type=str,
 
460
                      type=text_type,
482
461
                      ),
483
462
        option.Option('auto',
484
463
                      'Trigger an upload from this branch whenever the tip '
485
464
                      'revision changes.')
486
 
        ]
 
465
       ]
487
466
 
488
467
    def run(self, location=None, full=False, revision=None, remember=None,
489
468
            directory=None, quiet=False, auto=None, overwrite=False
496
475
             directory)
497
476
 
498
477
        if wt:
 
478
            wt.lock_read()
499
479
            locked = wt
500
480
        else:
 
481
            branch.lock_read()
501
482
            locked = branch
502
 
        with locked.lock_read():
 
483
        try:
503
484
            if wt:
504
485
                changes = wt.changes_from(wt.basis_tree())
505
486
 
506
 
                if revision is None and changes.has_changed():
 
487
                if revision is None and  changes.has_changed():
507
488
                    raise errors.UncommittedChanges(wt)
508
489
 
509
490
            conf = branch.get_config_stack()
510
491
            if location is None:
511
492
                stored_loc = conf.get('upload_location')
512
493
                if stored_loc is None:
513
 
                    raise errors.CommandError(
 
494
                    raise errors.BzrCommandError(
514
495
                        'No upload location known or specified.')
515
496
                else:
516
497
                    # FIXME: Not currently tested
517
498
                    display_url = urlutils.unescape_for_display(stored_loc,
518
 
                                                                self.outf.encoding)
 
499
                            self.outf.encoding)
519
500
                    self.outf.write("Using saved location: %s\n" % display_url)
520
501
                    location = stored_loc
521
502
 
524
505
            # Check that we are not uploading to a existing working tree.
525
506
            try:
526
507
                to_bzr_dir = controldir.ControlDir.open_from_transport(
527
 
                    to_transport)
 
508
                        to_transport)
528
509
                has_wt = to_bzr_dir.has_workingtree()
529
510
            except errors.NotBranchError:
530
511
                has_wt = False
538
519
                rev_id = branch.last_revision()
539
520
            else:
540
521
                if len(revision) != 1:
541
 
                    raise errors.CommandError(
 
522
                    raise errors.BzrCommandError(
542
523
                        'bzr upload --revision takes exactly 1 argument')
543
524
                rev_id = revision[0].in_history(branch).rev_id
544
525
 
557
538
                uploader.upload_full_tree()
558
539
            else:
559
540
                uploader.upload_tree()
 
541
        finally:
 
542
            locked.unlock()
560
543
 
561
544
        # We uploaded successfully, remember it
562
 
        with branch.lock_write():
 
545
        branch.lock_write()
 
546
        try:
563
547
            upload_location = conf.get('upload_location')
564
548
            if upload_location is None or remember:
565
549
                conf.set('upload_location',
566
550
                         urlutils.unescape(to_transport.base))
567
551
            if auto is not None:
568
552
                conf.set('upload_auto', auto)
 
553
        finally:
 
554
            branch.unlock()
 
555