/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: 2020-03-22 01:35:14 UTC
  • mfrom: (7490.7.6 work)
  • mto: This revision was merged to the branch mainline in revision 7499.
  • Revision ID: jelmer@jelmer.uk-20200322013514-7vw1ntwho04rcuj3
merge lp:brz/3.1.

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
 
 
21
19
from ... import (
22
 
    branch,
23
20
    commands,
24
21
    config,
 
22
    errors,
25
23
    lazy_import,
26
24
    option,
 
25
    osutils,
27
26
    )
28
27
lazy_import.lazy_import(globals(), """
29
28
import stat
30
 
import sys
31
29
 
32
30
from breezy import (
33
31
    controldir,
34
 
    errors,
35
32
    globbing,
36
33
    ignores,
37
34
    revision,
40
37
    )
41
38
""")
42
39
 
43
 
from ...sixish import (
44
 
    text_type,
45
 
    )
46
40
 
47
41
auto_option = config.Option(
48
42
    'upload_auto', default=False, from_unicode=config.bool_from_store,
174
168
                    dir = os.path.dirname(dir)
175
169
        return ignored
176
170
 
177
 
    def upload_file(self, relpath, id, mode=None):
 
171
    def upload_file(self, old_relpath, new_relpath, mode=None):
178
172
        if mode is None:
179
 
            if self.tree.is_executable(relpath, id):
 
173
            if self.tree.is_executable(new_relpath):
180
174
                mode = 0o775
181
175
            else:
182
176
                mode = 0o664
183
177
        if not self.quiet:
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):
 
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):
 
183
        try:
 
184
            st = self._up_stat(relpath)
 
185
            if stat.S_ISDIR(st.st_mode):
 
186
                # A simple rmdir may not be enough
 
187
                if not self.quiet:
 
188
                    self.outf.write('Clearing %s/%s\n' % (
 
189
                        self.to_transport.external_url(), relpath))
 
190
                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
        except errors.PathError:
 
197
            pass
 
198
 
 
199
    def upload_file_robustly(self, relpath, mode=None):
188
200
        """Upload a file, clearing the way on the remote side.
189
201
 
190
202
        When doing a full upload, it may happen that a directory exists where
191
203
        we want to put our file.
192
204
        """
193
 
        try:
194
 
            st = self._up_stat(relpath)
195
 
            if stat.S_ISDIR(st.st_mode):
196
 
                # A simple rmdir may not be enough
197
 
                if not self.quiet:
198
 
                    self.outf.write('Clearing %s/%s\n' % (
199
 
                            self.to_transport.external_url(), relpath))
200
 
                self._up_delete_tree(relpath)
201
 
        except errors.PathError:
202
 
            pass
203
 
        self.upload_file(relpath, id, mode)
 
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)
204
222
 
205
223
    def make_remote_dir(self, relpath, mode=None):
206
224
        if mode is None:
218
236
            if not stat.S_ISDIR(st.st_mode):
219
237
                if not self.quiet:
220
238
                    self.outf.write('Deleting %s/%s\n' % (
221
 
                            self.to_transport.external_url(), relpath))
 
239
                        self.to_transport.external_url(), relpath))
222
240
                self._up_delete(relpath)
223
241
            else:
224
242
                # Ok the remote dir already exists, nothing to do
288
306
        self._pending_renames = []
289
307
 
290
308
    def upload_full_tree(self):
291
 
        self.to_transport.ensure_base() # XXX: Handle errors (add
292
 
                                        # --create-prefix option ?)
 
309
        self.to_transport.ensure_base()  # XXX: Handle errors (add
 
310
        # --create-prefix option ?)
293
311
        with self.tree.lock_read():
294
312
            for relpath, ie in self.tree.iter_entries_by_dir():
295
313
                if relpath in ('', '.bzrignore', '.bzrignore-upload'):
302
320
                        self.outf.write('Ignoring %s\n' % relpath)
303
321
                    continue
304
322
                if ie.kind == 'file':
305
 
                    self.upload_file_robustly(relpath, ie.file_id)
 
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))
306
333
                elif ie.kind == 'directory':
307
334
                    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))
313
335
                else:
314
336
                    raise NotImplementedError
315
337
            self.set_uploaded_revid(self.rev_id)
333
355
                self.outf.write('Remote location already up to date\n')
334
356
 
335
357
        from_tree = self.branch.repository.revision_tree(rev_id)
336
 
        self.to_transport.ensure_base() # XXX: Handle errors (add
337
 
                                        # --create-prefix option ?)
 
358
        self.to_transport.ensure_base()  # XXX: Handle errors (add
 
359
        # --create-prefix option ?)
338
360
        changes = self.tree.changes_from(from_tree)
339
361
        with self.tree.lock_read():
340
 
            for (path, id, kind) in changes.removed:
341
 
                if self.is_ignored(path):
 
362
            for change in changes.removed:
 
363
                if self.is_ignored(change.path[0]):
342
364
                    if not self.quiet:
343
 
                        self.outf.write('Ignoring %s\n' % path)
 
365
                        self.outf.write('Ignoring %s\n' % change.path[0])
344
366
                    continue
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))
 
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])
354
373
                else:
355
374
                    raise NotImplementedError
356
375
 
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):
 
376
            for change in changes.renamed:
 
377
                if self.is_ignored(change.path[0]) and self.is_ignored(change.path[1]):
360
378
                    if not self.quiet:
361
 
                        self.outf.write('Ignoring %s\n' % old_path)
362
 
                        self.outf.write('Ignoring %s\n' % new_path)
 
379
                        self.outf.write('Ignoring %s\n' % change.path[0])
 
380
                        self.outf.write('Ignoring %s\n' % change.path[1])
363
381
                    continue
364
 
                if content_change:
365
 
                    # We update the old_path content because renames and
 
382
                if change.changed_content:
 
383
                    # We update the change.path[0] content because renames and
366
384
                    # deletions are differed.
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)
 
385
                    self.upload_file(change.path[0], change.path[1])
 
386
                self.rename_remote(change.path[0], change.path[1])
374
387
            self.finish_renames()
375
388
            self.finish_deletions()
376
389
 
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))
 
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))
410
429
                else:
411
430
                    raise NotImplementedError
412
431
 
413
432
            # XXX: Add a test for exec_change
414
 
            for (path, id, kind,
415
 
                 content_change, exec_change) in changes.modified:
416
 
                if self.is_ignored(path):
 
433
            for change in changes.modified:
 
434
                if self.is_ignored(change.path[1]):
417
435
                    if not self.quiet:
418
 
                        self.outf.write('Ignoring %s\n' % path)
 
436
                        self.outf.write('Ignoring %s\n' % change.path[1])
419
437
                    continue
420
 
                if kind is 'file':
421
 
                    self.upload_file(path, id)
 
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)
422
443
                else:
423
444
                    raise NotImplementedError
424
445
 
452
473
        'overwrite',
453
474
        option.Option('full', 'Upload the full working tree.'),
454
475
        option.Option('quiet', 'Do not output what is being done.',
455
 
                       short_name='q'),
 
476
                      short_name='q'),
456
477
        option.Option('directory',
457
478
                      help='Branch to upload from, '
458
479
                      'rather than the one containing the working directory.',
459
480
                      short_name='d',
460
 
                      type=text_type,
 
481
                      type=str,
461
482
                      ),
462
483
        option.Option('auto',
463
484
                      'Trigger an upload from this branch whenever the tip '
464
485
                      'revision changes.')
465
 
       ]
 
486
        ]
466
487
 
467
488
    def run(self, location=None, full=False, revision=None, remember=None,
468
489
            directory=None, quiet=False, auto=None, overwrite=False
475
496
             directory)
476
497
 
477
498
        if wt:
478
 
            wt.lock_read()
479
499
            locked = wt
480
500
        else:
481
 
            branch.lock_read()
482
501
            locked = branch
483
 
        try:
 
502
        with locked.lock_read():
484
503
            if wt:
485
504
                changes = wt.changes_from(wt.basis_tree())
486
505
 
487
 
                if revision is None and  changes.has_changed():
 
506
                if revision is None and changes.has_changed():
488
507
                    raise errors.UncommittedChanges(wt)
489
508
 
490
509
            conf = branch.get_config_stack()
496
515
                else:
497
516
                    # FIXME: Not currently tested
498
517
                    display_url = urlutils.unescape_for_display(stored_loc,
499
 
                            self.outf.encoding)
 
518
                                                                self.outf.encoding)
500
519
                    self.outf.write("Using saved location: %s\n" % display_url)
501
520
                    location = stored_loc
502
521
 
505
524
            # Check that we are not uploading to a existing working tree.
506
525
            try:
507
526
                to_bzr_dir = controldir.ControlDir.open_from_transport(
508
 
                        to_transport)
 
527
                    to_transport)
509
528
                has_wt = to_bzr_dir.has_workingtree()
510
529
            except errors.NotBranchError:
511
530
                has_wt = False
538
557
                uploader.upload_full_tree()
539
558
            else:
540
559
                uploader.upload_tree()
541
 
        finally:
542
 
            locked.unlock()
543
560
 
544
561
        # We uploaded successfully, remember it
545
 
        branch.lock_write()
546
 
        try:
 
562
        with branch.lock_write():
547
563
            upload_location = conf.get('upload_location')
548
564
            if upload_location is None or remember:
549
565
                conf.set('upload_location',
550
566
                         urlutils.unescape(to_transport.base))
551
567
            if auto is not None:
552
568
                conf.set('upload_auto', auto)
553
 
        finally:
554
 
            branch.unlock()
555