/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/info.py

  • Committer: Jelmer Vernooij
  • Date: 2018-05-22 01:30:48 UTC
  • mto: (6973.5.4 python3-c)
  • mto: This revision was merged to the branch mainline in revision 6984.
  • Revision ID: jelmer@jelmer.uk-20180522013048-r825wjanpr2yqige
port breezy.bzr.weave to Python3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
 
17
from __future__ import absolute_import
 
18
 
17
19
__all__ = ['show_bzrdir_info']
18
20
 
19
 
from cStringIO import StringIO
20
21
import time
21
22
import sys
22
23
 
23
 
from bzrlib import (
24
 
    bzrdir,
 
24
from . import (
 
25
    branch as _mod_branch,
 
26
    controldir,
25
27
    errors,
26
28
    hooks as _mod_hooks,
27
29
    osutils,
28
30
    urlutils,
29
31
    )
30
 
from bzrlib.errors import (NoWorkingTree, NotBranchError,
 
32
from .bzr import (
 
33
    bzrdir,
 
34
    )
 
35
from .errors import (NoWorkingTree, NotBranchError,
31
36
                           NoRepositoryPresent, NotLocalUrl)
32
 
from bzrlib.missing import find_unmerged
 
37
from .missing import find_unmerged
 
38
from .sixish import (
 
39
    BytesIO,
 
40
    )
33
41
 
34
42
 
35
43
def plural(n, base='', pl=None):
53
61
            return
54
62
        try:
55
63
            path = urlutils.local_path_from_url(url)
56
 
        except errors.InvalidURL:
 
64
        except urlutils.InvalidURL:
57
65
            self.locs.append((label, url))
58
66
        else:
59
67
            self.add_path(label, path)
76
84
        return ["  %*s: %s\n" % (max_len, l, u) for l, u in self.locs ]
77
85
 
78
86
 
79
 
def gather_location_info(repository, branch=None, working=None):
 
87
def gather_location_info(repository=None, branch=None, working=None,
 
88
        control=None):
80
89
    locs = {}
81
 
    repository_path = repository.user_url
82
90
    if branch is not None:
83
91
        branch_path = branch.user_url
84
92
        master_path = branch.get_bound_location()
87
95
    else:
88
96
        branch_path = None
89
97
        master_path = None
 
98
        try:
 
99
            if control is not None and control.get_branch_reference():
 
100
                locs['checkout of branch'] = control.get_branch_reference()
 
101
        except NotBranchError:
 
102
            pass
90
103
    if working:
91
104
        working_path = working.user_url
92
105
        if working_path != branch_path:
105
118
            locs['branch root'] = branch_path
106
119
    else:
107
120
        working_path = None
108
 
        if repository.is_shared():
 
121
        if repository is not None and repository.is_shared():
109
122
            # lightweight checkout of branch in shared repository
110
123
            if branch_path is not None:
111
124
                locs['repository branch'] = branch_path
112
125
        elif branch_path is not None:
113
126
            # standalone
114
127
            locs['branch root'] = branch_path
115
 
            if master_path != branch_path:
116
 
                locs['bound to branch'] = master_path
 
128
        elif repository is not None:
 
129
            locs['repository'] = repository.user_url
 
130
        elif control is not None:
 
131
            locs['control directory'] = control.user_url
117
132
        else:
118
 
            locs['repository'] = repository_path
119
 
    if repository.is_shared():
 
133
            # Really, at least a control directory should be
 
134
            # passed in for this method to be useful.
 
135
            pass
 
136
        if master_path != branch_path:
 
137
            locs['bound to branch'] = master_path
 
138
    if repository is not None and repository.is_shared():
120
139
        # lightweight checkout of branch in shared repository
121
 
        locs['shared repository'] = repository_path
122
 
    order = ['light checkout root', 'repository checkout root',
123
 
             'checkout root', 'checkout of branch', 'shared repository',
 
140
        locs['shared repository'] = repository.user_url
 
141
    order = ['control directory', 'light checkout root',
 
142
             'repository checkout root', 'checkout root',
 
143
             'checkout of branch', 'shared repository',
124
144
             'repository', 'repository branch', 'branch root',
125
145
             'bound to branch']
126
146
    return [(n, locs[n]) for n in order if n in locs]
143
163
    locs.add_url('submit branch', branch.get_submit_branch())
144
164
    try:
145
165
        locs.add_url('stacked on', branch.get_stacked_on_url())
146
 
    except (errors.UnstackableBranchFormat, errors.UnstackableRepositoryFormat,
 
166
    except (_mod_branch.UnstackableBranchFormat, errors.UnstackableRepositoryFormat,
147
167
        errors.NotStacked):
148
168
        pass
149
169
    return locs
158
178
        outfile.writelines(locs.get_lines())
159
179
 
160
180
 
 
181
def _show_control_dir_info(control, outfile):
 
182
    """Show control dir information."""
 
183
    if control._format.colocated_branches:
 
184
        outfile.write('\n')
 
185
        outfile.write('Control directory:\n')
 
186
        outfile.write('         %d branches\n' % len(control.list_branches()))
 
187
 
 
188
 
161
189
def _show_format_info(control=None, repository=None, branch=None,
162
190
                      working=None, outfile=None):
163
191
    """Show known formats for control, working, branch and repository."""
177
205
            repository._format.get_format_description())
178
206
 
179
207
 
180
 
def _show_locking_info(repository, branch=None, working=None, outfile=None):
 
208
def _show_locking_info(repository=None, branch=None, working=None,
 
209
        outfile=None):
181
210
    """Show locking status of working, branch and repository."""
182
 
    if (repository.get_physical_lock_status() or
 
211
    if (repository and repository.get_physical_lock_status() or
183
212
        (branch and branch.get_physical_lock_status()) or
184
213
        (working and working.get_physical_lock_status())):
185
214
        outfile.write('\n')
221
250
    """Show missing revisions in working tree."""
222
251
    branch = working.branch
223
252
    basis = working.basis_tree()
224
 
    work_inv = working.inventory
225
 
    branch_revno, branch_last_revision = branch.last_revision_info()
 
253
    try:
 
254
        branch_revno, branch_last_revision = branch.last_revision_info()
 
255
    except errors.UnsupportedOperation:
 
256
        return
226
257
    try:
227
258
        tree_last_id = working.get_parent_ids()[0]
228
259
    except IndexError:
239
270
def _show_working_stats(working, outfile):
240
271
    """Show statistics about a working tree."""
241
272
    basis = working.basis_tree()
242
 
    work_inv = working.inventory
243
273
    delta = working.changes_from(basis, want_unchanged=True)
244
274
 
245
275
    outfile.write('\n')
260
290
    outfile.write('  %8d ignored\n' % ignore_cnt)
261
291
 
262
292
    dir_cnt = 0
263
 
    for file_id in work_inv:
264
 
        if (work_inv.get_file_kind(file_id) == 'directory' and
265
 
            not work_inv.is_root(file_id)):
 
293
    for path, entry in working.iter_entries_by_dir():
 
294
        if entry.kind == 'directory' and path != '':
266
295
            dir_cnt += 1
267
296
    outfile.write('  %8d versioned %s\n' % (dir_cnt,
268
297
        plural(dir_cnt, 'subdirectory', 'subdirectories')))
270
299
 
271
300
def _show_branch_stats(branch, verbose, outfile):
272
301
    """Show statistics about a branch."""
273
 
    revno, head = branch.last_revision_info()
 
302
    try:
 
303
        revno, head = branch.last_revision_info()
 
304
    except errors.UnsupportedOperation:
 
305
        return {}
274
306
    outfile.write('\n')
275
307
    outfile.write('Branch history:\n')
276
308
    outfile.write('  %8d revision%s\n' % (revno, plural(revno)))
301
333
 
302
334
def _show_repository_stats(repository, stats, outfile):
303
335
    """Show statistics about a repository."""
304
 
    f = StringIO()
 
336
    f = BytesIO()
305
337
    if 'revisions' in stats:
306
338
        revisions = stats['revisions']
307
339
        f.write('  %8d revision%s\n' % (revisions, plural(revisions)))
315
347
        outfile.write(f.getvalue())
316
348
 
317
349
 
318
 
def show_bzrdir_info(a_bzrdir, verbose=False, outfile=None):
319
 
    """Output to stdout the 'info' for a_bzrdir."""
 
350
def show_bzrdir_info(a_controldir, verbose=False, outfile=None):
 
351
    """Output to stdout the 'info' for a_controldir."""
320
352
    if outfile is None:
321
353
        outfile = sys.stdout
322
354
    try:
323
 
        tree = a_bzrdir.open_workingtree(
 
355
        tree = a_controldir.open_workingtree(
324
356
            recommend_upgrade=False)
325
 
    except (NoWorkingTree, NotLocalUrl):
 
357
    except (NoWorkingTree, NotLocalUrl, NotBranchError):
326
358
        tree = None
327
359
        try:
328
 
            branch = a_bzrdir.open_branch()
 
360
            branch = a_controldir.open_branch(name="")
329
361
        except NotBranchError:
330
362
            branch = None
331
363
            try:
332
 
                repository = a_bzrdir.open_repository()
 
364
                repository = a_controldir.open_repository()
333
365
            except NoRepositoryPresent:
334
 
                # Return silently; cmd_info already returned NotBranchError
335
 
                # if no bzrdir could be opened.
336
 
                return
 
366
                lockable = None
 
367
                repository = None
337
368
            else:
338
369
                lockable = repository
339
370
        else:
344
375
        repository = branch.repository
345
376
        lockable = tree
346
377
 
347
 
    lockable.lock_read()
 
378
    if lockable is not None:
 
379
        lockable.lock_read()
348
380
    try:
349
 
        show_component_info(a_bzrdir, repository, branch, tree, verbose,
 
381
        show_component_info(a_controldir, repository, branch, tree, verbose,
350
382
                            outfile)
351
383
    finally:
352
 
        lockable.unlock()
 
384
        if lockable is not None:
 
385
            lockable.unlock()
353
386
 
354
387
 
355
388
def show_component_info(control, repository, branch=None, working=None,
361
394
        verbose = 1
362
395
    if verbose is True:
363
396
        verbose = 2
364
 
    layout = describe_layout(repository, branch, working)
 
397
    layout = describe_layout(repository, branch, working, control)
365
398
    format = describe_format(control, repository, branch, working)
366
399
    outfile.write("%s (format: %s)\n" % (layout, format))
367
 
    _show_location_info(gather_location_info(repository, branch, working),
368
 
                        outfile)
 
400
    _show_location_info(
 
401
        gather_location_info(control=control, repository=repository,
 
402
            branch=branch, working=working),
 
403
        outfile)
369
404
    if branch is not None:
370
405
        _show_related_info(branch, outfile)
371
406
    if verbose == 0:
372
407
        return
373
408
    _show_format_info(control, repository, branch, working, outfile)
374
409
    _show_locking_info(repository, branch, working, outfile)
 
410
    _show_control_dir_info(control, outfile)
375
411
    if branch is not None:
376
412
        _show_missing_revisions_branch(branch, outfile)
377
413
    if working is not None:
382
418
    if branch is not None:
383
419
        show_committers = verbose >= 2
384
420
        stats = _show_branch_stats(branch, show_committers, outfile)
385
 
    else:
 
421
    elif repository is not None:
386
422
        stats = repository.gather_stats()
387
 
    if branch is None and working is None:
 
423
    if branch is None and working is None and repository is not None:
388
424
        _show_repository_info(repository, outfile)
389
 
    _show_repository_stats(repository, stats, outfile)
390
 
 
391
 
 
392
 
def describe_layout(repository=None, branch=None, tree=None):
 
425
    if repository is not None:
 
426
        _show_repository_stats(repository, stats, outfile)
 
427
 
 
428
 
 
429
def describe_layout(repository=None, branch=None, tree=None, control=None):
393
430
    """Convert a control directory layout into a user-understandable term
394
431
 
395
432
    Common outputs include "Standalone tree", "Repository branch" and
396
433
    "Checkout".  Uncommon outputs include "Unshared repository with trees"
397
434
    and "Empty control directory"
398
435
    """
 
436
    if branch is None and control is not None:
 
437
        try:
 
438
            branch_reference = control.get_branch_reference()
 
439
        except NotBranchError:
 
440
            pass
 
441
        else:
 
442
            if branch_reference is not None:
 
443
                return "Dangling branch reference"
399
444
    if repository is None:
400
445
        return 'Empty control directory'
401
446
    if branch is None and tree is None:
403
448
            phrase = 'Shared repository'
404
449
        else:
405
450
            phrase = 'Unshared repository'
 
451
        extra = []
406
452
        if repository.make_working_trees():
407
 
            phrase += ' with trees'
 
453
            extra.append('trees')
 
454
        if len(control.get_branches()) > 0:
 
455
            extra.append('colocated branches')
 
456
        if extra:
 
457
            phrase += ' with ' + " and ".join(extra)
408
458
        return phrase
409
459
    else:
410
460
        if repository.is_shared():
418
468
        if branch is None and tree is not None:
419
469
            phrase = "branchless tree"
420
470
        else:
421
 
            if (tree is not None and tree.user_url !=
422
 
                branch.user_url):
 
471
            if (tree is not None and tree.controldir.control_url !=
 
472
                branch.controldir.control_url):
423
473
                independence = ''
424
474
                phrase = "Lightweight checkout"
425
475
            elif branch.get_bound_location() is not None:
447
497
        branch.user_url != tree.user_url):
448
498
        branch = None
449
499
        repository = None
450
 
    non_aliases = set(bzrdir.format_registry.keys())
451
 
    non_aliases.difference_update(bzrdir.format_registry.aliases())
 
500
    non_aliases = set(controldir.format_registry.keys())
 
501
    non_aliases.difference_update(controldir.format_registry.aliases())
452
502
    for key in non_aliases:
453
 
        format = bzrdir.format_registry.make_bzrdir(key)
 
503
        format = controldir.format_registry.make_controldir(key)
454
504
        if isinstance(format, bzrdir.BzrDirMetaFormat1):
455
505
            if (tree and format.workingtree_format !=
456
506
                tree._format):
468
518
        return 'unnamed'
469
519
    candidates.sort()
470
520
    new_candidates = [c for c in candidates if not
471
 
        bzrdir.format_registry.get_info(c).hidden]
 
521
        controldir.format_registry.get_info(c).hidden]
472
522
    if len(new_candidates) > 0:
473
523
        # If there are any non-hidden formats that match, only return those to
474
524
        # avoid listing hidden formats except when only a hidden format will
481
531
    """Hooks for the info command."""
482
532
 
483
533
    def __init__(self):
484
 
        super(InfoHooks, self).__init__()
485
 
        self.create_hook(_mod_hooks.HookPoint('repository',
 
534
        super(InfoHooks, self).__init__("breezy.info", "hooks")
 
535
        self.add_hook('repository',
486
536
            "Invoked when displaying the statistics for a repository. "
487
537
            "repository is called with a statistics dictionary as returned "
488
 
            "by the repository and a file-like object to write to.", (1, 15), 
489
 
            None))
 
538
            "by the repository and a file-like object to write to.", (1, 15))
490
539
 
491
540
 
492
541
hooks = InfoHooks()