/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: 2017-06-08 23:30:31 UTC
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170608233031-3qavls2o7a1pqllj
Update imports.

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
 
40
 
 
41
43
auto_option = config.Option(
42
44
    'upload_auto', default=False, from_unicode=config.bool_from_store,
43
45
    help="""\
147
149
        if self._ignored is None:
148
150
            try:
149
151
                ignore_file_path = '.bzrignore-upload'
150
 
                ignore_file = self.tree.get_file(ignore_file_path)
151
 
            except errors.NoSuchFile:
 
152
                ignore_file_id = self.tree.path2id(ignore_file_path)
 
153
                ignore_file = self.tree.get_file(ignore_file_id,
 
154
                                                 ignore_file_path)
 
155
                ignored_patterns = ignores.parse_ignore_file(ignore_file)
 
156
            except errors.NoSuchId:
152
157
                ignored_patterns = []
153
 
            else:
154
 
                ignored_patterns = ignores.parse_ignore_file(ignore_file)
155
158
            self._ignored = globbing.Globster(ignored_patterns)
156
159
        return self._ignored
157
160
 
168
171
                    dir = os.path.dirname(dir)
169
172
        return ignored
170
173
 
171
 
    def upload_file(self, old_relpath, new_relpath, mode=None):
 
174
    def upload_file(self, relpath, id, mode=None):
172
175
        if mode is None:
173
 
            if self.tree.is_executable(new_relpath):
174
 
                mode = 0o775
 
176
            if self.tree.is_executable(id):
 
177
                mode = 0775
175
178
            else:
176
 
                mode = 0o664
 
179
                mode = 0664
177
180
        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):
 
181
            self.outf.write('Uploading %s\n' % relpath)
 
182
        self._up_put_bytes(relpath, self.tree.get_file_text(id), mode)
 
183
 
 
184
    def upload_file_robustly(self, relpath, id, mode=None):
 
185
        """Upload a file, clearing the way on the remote side.
 
186
 
 
187
        When doing a full upload, it may happen that a directory exists where
 
188
        we want to put our file.
 
189
        """
183
190
        try:
184
191
            st = self._up_stat(relpath)
185
192
            if stat.S_ISDIR(st.st_mode):
186
193
                # A simple rmdir may not be enough
187
194
                if not self.quiet:
188
195
                    self.outf.write('Clearing %s/%s\n' % (
189
 
                        self.to_transport.external_url(), relpath))
 
196
                            self.to_transport.external_url(), relpath))
190
197
                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
198
        except errors.PathError:
197
199
            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)
 
200
        self.upload_file(relpath, id, mode)
222
201
 
223
202
    def make_remote_dir(self, relpath, mode=None):
224
203
        if mode is None:
225
 
            mode = 0o775
 
204
            mode = 0775
226
205
        self._up_mkdir(relpath, mode)
227
206
 
228
207
    def make_remote_dir_robustly(self, relpath, mode=None):
236
215
            if not stat.S_ISDIR(st.st_mode):
237
216
                if not self.quiet:
238
217
                    self.outf.write('Deleting %s/%s\n' % (
239
 
                        self.to_transport.external_url(), relpath))
 
218
                            self.to_transport.external_url(), relpath))
240
219
                self._up_delete(relpath)
241
220
            else:
242
221
                # Ok the remote dir already exists, nothing to do
292
271
 
293
272
        stamp = '.tmp.%.9f.%d.%d' % (time.time(),
294
273
                                     os.getpid(),
295
 
                                     random.randint(0, 0x7FFFFFFF))
 
274
                                     random.randint(0,0x7FFFFFFF))
296
275
        if not self.quiet:
297
276
            self.outf.write('Renaming %s to %s\n' % (old_relpath, new_relpath))
298
277
        self._up_rename(old_relpath, stamp)
306
285
        self._pending_renames = []
307
286
 
308
287
    def upload_full_tree(self):
309
 
        self.to_transport.ensure_base()  # XXX: Handle errors (add
310
 
        # --create-prefix option ?)
311
 
        with self.tree.lock_read():
 
288
        self.to_transport.ensure_base() # XXX: Handle errors (add
 
289
                                        # --create-prefix option ?)
 
290
        self.tree.lock_read()
 
291
        try:
312
292
            for relpath, ie in self.tree.iter_entries_by_dir():
313
293
                if relpath in ('', '.bzrignore', '.bzrignore-upload'):
314
294
                    # skip root ('')
320
300
                        self.outf.write('Ignoring %s\n' % relpath)
321
301
                    continue
322
302
                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))
 
303
                    self.upload_file_robustly(relpath, ie.file_id)
333
304
                elif ie.kind == 'directory':
334
305
                    self.make_remote_dir_robustly(relpath)
 
306
                elif ie.kind == 'symlink':
 
307
                    if not self.quiet:
 
308
                        target = self.tree.path_content_summary(relpath)[3]
 
309
                        self.outf.write('Not uploading symlink %s -> %s\n'
 
310
                                        % (relpath, target))
335
311
                else:
336
312
                    raise NotImplementedError
337
313
            self.set_uploaded_revid(self.rev_id)
 
314
        finally:
 
315
            self.tree.unlock()
338
316
 
339
317
    def upload_tree(self):
340
318
        # If we can't find the revid file on the remote location, upload the
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
 
        with self.tree.lock_read():
362
 
            for change in changes.removed:
363
 
                if self.is_ignored(change.path[0]):
 
339
        self.tree.lock_read()
 
340
        try:
 
341
            for (path, id, kind) in changes.removed:
 
342
                if self.is_ignored(path):
364
343
                    if not self.quiet:
365
 
                        self.outf.write('Ignoring %s\n' % change.path[0])
 
344
                        self.outf.write('Ignoring %s\n' % path)
366
345
                    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])
 
346
                if kind is 'file':
 
347
                    self.delete_remote_file(path)
 
348
                elif kind is  'directory':
 
349
                    self.delete_remote_dir_maybe(path)
 
350
                elif kind == 'symlink':
 
351
                    if not self.quiet:
 
352
                        target = self.tree.path_content_summary(path)[3]
 
353
                        self.outf.write('Not deleting remote symlink %s -> %s\n'
 
354
                                        % (path, target))
373
355
                else:
374
356
                    raise NotImplementedError
375
357
 
376
 
            for change in changes.renamed:
377
 
                if self.is_ignored(change.path[0]) and self.is_ignored(change.path[1]):
 
358
            for (old_path, new_path, id, kind,
 
359
                 content_change, exec_change) in changes.renamed:
 
360
                if self.is_ignored(old_path) and self.is_ignored(new_path):
378
361
                    if not self.quiet:
379
 
                        self.outf.write('Ignoring %s\n' % change.path[0])
380
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
 
362
                        self.outf.write('Ignoring %s\n' % old_path)
 
363
                        self.outf.write('Ignoring %s\n' % new_path)
381
364
                    continue
382
 
                if change.changed_content:
383
 
                    # We update the change.path[0] content because renames and
 
365
                if content_change:
 
366
                    # We update the old_path content because renames and
384
367
                    # deletions are differed.
385
 
                    self.upload_file(change.path[0], change.path[1])
386
 
                self.rename_remote(change.path[0], change.path[1])
 
368
                    self.upload_file(old_path, id)
 
369
                if kind == 'symlink':
 
370
                    if not self.quiet:
 
371
                        self.outf.write('Not renaming remote symlink %s to %s\n'
 
372
                                        % (old_path, new_path))
 
373
                else:
 
374
                    self.rename_remote(old_path, new_path)
387
375
            self.finish_renames()
388
376
            self.finish_deletions()
389
377
 
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))
 
378
            for (path, id, old_kind, new_kind) in changes.kind_changed:
 
379
                if self.is_ignored(path):
 
380
                    if not self.quiet:
 
381
                        self.outf.write('Ignoring %s\n' % path)
 
382
                    continue
 
383
                if old_kind == 'file':
 
384
                    self.delete_remote_file(path)
 
385
                elif old_kind ==  'directory':
 
386
                    self.delete_remote_dir(path)
 
387
                else:
 
388
                    raise NotImplementedError
 
389
 
 
390
                if new_kind == 'file':
 
391
                    self.upload_file(path, id)
 
392
                elif new_kind is 'directory':
 
393
                    self.make_remote_dir(path)
 
394
                else:
 
395
                    raise NotImplementedError
 
396
 
 
397
            for (path, id, kind) in changes.added:
 
398
                if self.is_ignored(path):
 
399
                    if not self.quiet:
 
400
                        self.outf.write('Ignoring %s\n' % path)
 
401
                    continue
 
402
                if kind == 'file':
 
403
                    self.upload_file(path, id)
 
404
                elif kind == 'directory':
 
405
                    self.make_remote_dir(path)
 
406
                elif kind == 'symlink':
 
407
                    if not self.quiet:
 
408
                        target = self.tree.path_content_summary(path)[3]
 
409
                        self.outf.write('Not uploading symlink %s -> %s\n'
 
410
                                        % (path, target))
429
411
                else:
430
412
                    raise NotImplementedError
431
413
 
432
414
            # XXX: Add a test for exec_change
433
 
            for change in changes.modified:
434
 
                if self.is_ignored(change.path[1]):
 
415
            for (path, id, kind,
 
416
                 content_change, exec_change) in changes.modified:
 
417
                if self.is_ignored(path):
435
418
                    if not self.quiet:
436
 
                        self.outf.write('Ignoring %s\n' % change.path[1])
 
419
                        self.outf.write('Ignoring %s\n' % path)
437
420
                    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)
 
421
                if kind is 'file':
 
422
                    self.upload_file(path, id)
443
423
                else:
444
424
                    raise NotImplementedError
445
425
 
446
426
            self.set_uploaded_revid(self.rev_id)
447
 
 
448
 
 
449
 
class CannotUploadToWorkingTree(errors.CommandError):
 
427
        finally:
 
428
            self.tree.unlock()
 
429
 
 
430
 
 
431
class CannotUploadToWorkingTree(errors.BzrCommandError):
450
432
 
451
433
    _fmt = 'Cannot upload to a bzr managed working tree: %(url)s".'
452
434
 
453
435
 
454
 
class DivergedUploadedTree(errors.CommandError):
 
436
class DivergedUploadedTree(errors.BzrCommandError):
455
437
 
456
438
    _fmt = ("Your branch (%(revid)s)"
457
439
            " and the uploaded tree (%(uploaded_revid)s) have diverged: ")
473
455
        'overwrite',
474
456
        option.Option('full', 'Upload the full working tree.'),
475
457
        option.Option('quiet', 'Do not output what is being done.',
476
 
                      short_name='q'),
 
458
                       short_name='q'),
477
459
        option.Option('directory',
478
460
                      help='Branch to upload from, '
479
461
                      'rather than the one containing the working directory.',
480
462
                      short_name='d',
481
 
                      type=str,
 
463
                      type=unicode,
482
464
                      ),
483
465
        option.Option('auto',
484
466
                      'Trigger an upload from this branch whenever the tip '
485
467
                      'revision changes.')
486
 
        ]
 
468
       ]
487
469
 
488
470
    def run(self, location=None, full=False, revision=None, remember=None,
489
471
            directory=None, quiet=False, auto=None, overwrite=False
496
478
             directory)
497
479
 
498
480
        if wt:
 
481
            wt.lock_read()
499
482
            locked = wt
500
483
        else:
 
484
            branch.lock_read()
501
485
            locked = branch
502
 
        with locked.lock_read():
 
486
        try:
503
487
            if wt:
504
488
                changes = wt.changes_from(wt.basis_tree())
505
489
 
506
 
                if revision is None and changes.has_changed():
 
490
                if revision is None and  changes.has_changed():
507
491
                    raise errors.UncommittedChanges(wt)
508
492
 
509
493
            conf = branch.get_config_stack()
510
494
            if location is None:
511
495
                stored_loc = conf.get('upload_location')
512
496
                if stored_loc is None:
513
 
                    raise errors.CommandError(
 
497
                    raise errors.BzrCommandError(
514
498
                        'No upload location known or specified.')
515
499
                else:
516
500
                    # FIXME: Not currently tested
517
501
                    display_url = urlutils.unescape_for_display(stored_loc,
518
 
                                                                self.outf.encoding)
 
502
                            self.outf.encoding)
519
503
                    self.outf.write("Using saved location: %s\n" % display_url)
520
504
                    location = stored_loc
521
505
 
524
508
            # Check that we are not uploading to a existing working tree.
525
509
            try:
526
510
                to_bzr_dir = controldir.ControlDir.open_from_transport(
527
 
                    to_transport)
 
511
                        to_transport)
528
512
                has_wt = to_bzr_dir.has_workingtree()
529
513
            except errors.NotBranchError:
530
514
                has_wt = False
538
522
                rev_id = branch.last_revision()
539
523
            else:
540
524
                if len(revision) != 1:
541
 
                    raise errors.CommandError(
 
525
                    raise errors.BzrCommandError(
542
526
                        'bzr upload --revision takes exactly 1 argument')
543
527
                rev_id = revision[0].in_history(branch).rev_id
544
528
 
557
541
                uploader.upload_full_tree()
558
542
            else:
559
543
                uploader.upload_tree()
 
544
        finally:
 
545
            locked.unlock()
560
546
 
561
547
        # We uploaded successfully, remember it
562
 
        with branch.lock_write():
 
548
        branch.lock_write()
 
549
        try:
563
550
            upload_location = conf.get('upload_location')
564
551
            if upload_location is None or remember:
565
552
                conf.set('upload_location',
566
553
                         urlutils.unescape(to_transport.base))
567
554
            if auto is not None:
568
555
                conf.set('upload_auto', auto)
 
556
        finally:
 
557
            branch.unlock()
 
558