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

  • Committer: Aaron Bentley
  • Date: 2007-05-18 11:42:33 UTC
  • mto: This revision was merged to the branch mainline in revision 2528.
  • Revision ID: aaron.bentley@utoronto.ca-20070518114233-dhywq002d3fi9cti
Prevent repository.get_set_default_format from corrupting inventory

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
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
__all__ = ['show_bzrdir_info']
 
18
 
 
19
import time
 
20
 
 
21
 
 
22
from bzrlib import (
 
23
    bzrdir,
 
24
    diff,
 
25
    osutils,
 
26
    urlutils,
 
27
    )
 
28
from bzrlib.errors import (NoWorkingTree, NotBranchError,
 
29
                           NoRepositoryPresent, NotLocalUrl)
 
30
from bzrlib.missing import find_unmerged
 
31
from bzrlib.symbol_versioning import (deprecated_function,
 
32
        zero_eight, zero_sixteen)
 
33
 
 
34
 
 
35
def plural(n, base='', pl=None):
 
36
    if n == 1:
 
37
        return base
 
38
    elif pl is not None:
 
39
        return pl
 
40
    else:
 
41
        return 's'
 
42
 
 
43
 
 
44
def _repo_rel_url(repo_url, inner_url):
 
45
    """Return path with common prefix of repository path removed.
 
46
 
 
47
    If path is not part of the repository, the original path is returned.
 
48
    If path is equal to the repository, the current directory marker '.' is
 
49
    returned.
 
50
    Otherwise, a relative path is returned, with trailing '/' stripped.
 
51
    """
 
52
    inner_url = urlutils.normalize_url(inner_url)
 
53
    repo_url = urlutils.normalize_url(repo_url)
 
54
    if inner_url == repo_url:
 
55
        return '.'
 
56
    result = urlutils.relative_url(repo_url, inner_url)
 
57
    if result != inner_url:
 
58
        result = result.rstrip('/')
 
59
    return result
 
60
 
 
61
 
 
62
def _show_location_info(repository, branch=None, working=None):
 
63
    """Show known locations for working, branch and repository."""
 
64
    repository_path = repository.bzrdir.root_transport.base
 
65
    print 'Location:'
 
66
    if working and branch:
 
67
        working_path = working.bzrdir.root_transport.base
 
68
        branch_path = branch.bzrdir.root_transport.base
 
69
        if working_path != branch_path:
 
70
            # lightweight checkout
 
71
            print ' light checkout root: %s' % working_path
 
72
            if repository.is_shared():
 
73
                # lightweight checkout of branch in shared repository
 
74
                print '   shared repository: %s' % repository_path
 
75
                print '   repository branch: %s' % (
 
76
                    _repo_rel_url(repository_path, branch_path))
 
77
            else:
 
78
                # lightweight checkout of standalone branch
 
79
                print '  checkout of branch: %s' % branch_path
 
80
        elif repository.is_shared():
 
81
            # branch with tree inside shared repository
 
82
            print '    shared repository: %s' % repository_path
 
83
            print '  repository checkout: %s' % (
 
84
                _repo_rel_url(repository_path, branch_path))
 
85
        elif branch.get_bound_location():
 
86
            # normal checkout
 
87
            print '       checkout root: %s' % working_path
 
88
            print '  checkout of branch: %s' % branch.get_bound_location()
 
89
        else:
 
90
            # standalone
 
91
            print '  branch root: %s' % working_path
 
92
    elif branch:
 
93
        branch_path = branch.bzrdir.root_transport.base
 
94
        if repository.is_shared():
 
95
            # branch is part of shared repository
 
96
            print '  shared repository: %s' % repository_path
 
97
            print '  repository branch: %s' % (
 
98
                _repo_rel_url(repository_path, branch_path))
 
99
        else:
 
100
            # standalone branch
 
101
            print '  branch root: %s' % branch_path
 
102
    else:
 
103
        # shared repository
 
104
        assert repository.is_shared()
 
105
        print '  shared repository: %s' % repository_path
 
106
 
 
107
 
 
108
def _show_related_info(branch):
 
109
    """Show parent and push location of branch."""
 
110
    if branch.get_parent() or branch.get_push_location():
 
111
        print
 
112
        print 'Related branches:'
 
113
        if branch.get_parent():
 
114
            if branch.get_push_location():
 
115
                print '      parent branch: %s' % branch.get_parent()
 
116
            else:
 
117
                print '  parent branch: %s' % branch.get_parent()
 
118
        if branch.get_push_location():
 
119
            print '  publish to branch: %s' % branch.get_push_location()
 
120
 
 
121
 
 
122
def _show_format_info(control=None, repository=None, branch=None, working=None):
 
123
    """Show known formats for control, working, branch and repository."""
 
124
    print
 
125
    print 'Format:'
 
126
    if control:
 
127
        print '       control: %s' % control._format.get_format_description()
 
128
    if working:
 
129
        print '  working tree: %s' % working._format.get_format_description()
 
130
    if branch:
 
131
        print '        branch: %s' % branch._format.get_format_description()
 
132
    if repository:
 
133
        print '    repository: %s' % repository._format.get_format_description()
 
134
 
 
135
 
 
136
def _show_locking_info(repository, branch=None, working=None):
 
137
    """Show locking status of working, branch and repository."""
 
138
    if (repository.get_physical_lock_status() or
 
139
        (branch and branch.get_physical_lock_status()) or
 
140
        (working and working.get_physical_lock_status())):
 
141
        print
 
142
        print 'Lock status:'
 
143
        if working:
 
144
            if working.get_physical_lock_status():
 
145
                status = 'locked'
 
146
            else:
 
147
                status = 'unlocked'
 
148
            print '  working tree: %s' % status
 
149
        if branch:
 
150
            if branch.get_physical_lock_status():
 
151
                status = 'locked'
 
152
            else:
 
153
                status = 'unlocked'
 
154
            print '        branch: %s' % status
 
155
        if repository:
 
156
            if repository.get_physical_lock_status():
 
157
                status = 'locked'
 
158
            else:
 
159
                status = 'unlocked'
 
160
            print '    repository: %s' % status
 
161
 
 
162
 
 
163
def _show_missing_revisions_branch(branch):
 
164
    """Show missing master revisions in branch."""
 
165
    # Try with inaccessible branch ?
 
166
    master = branch.get_master_branch()
 
167
    if master:
 
168
        local_extra, remote_extra = find_unmerged(branch, master)
 
169
        if remote_extra:
 
170
            print
 
171
            print 'Branch is out of date: missing %d revision%s.' % (
 
172
                len(remote_extra), plural(len(remote_extra)))
 
173
 
 
174
 
 
175
def _show_missing_revisions_working(working):
 
176
    """Show missing revisions in working tree."""
 
177
    branch = working.branch
 
178
    basis = working.basis_tree()
 
179
    work_inv = working.inventory
 
180
    branch_revno, branch_last_revision = branch.last_revision_info()
 
181
    try:
 
182
        tree_last_id = working.get_parent_ids()[0]
 
183
    except IndexError:
 
184
        tree_last_id = None
 
185
 
 
186
    if branch_revno and tree_last_id != branch_last_revision:
 
187
        tree_last_revno = branch.revision_id_to_revno(tree_last_id)
 
188
        missing_count = branch_revno - tree_last_revno
 
189
        print
 
190
        print 'Working tree is out of date: missing %d revision%s.' % (
 
191
            missing_count, plural(missing_count))
 
192
 
 
193
 
 
194
def _show_working_stats(working):
 
195
    """Show statistics about a working tree."""
 
196
    basis = working.basis_tree()
 
197
    work_inv = working.inventory
 
198
    delta = working.changes_from(basis, want_unchanged=True)
 
199
 
 
200
    print
 
201
    print 'In the working tree:'
 
202
    print '  %8s unchanged' % len(delta.unchanged)
 
203
    print '  %8d modified' % len(delta.modified)
 
204
    print '  %8d added' % len(delta.added)
 
205
    print '  %8d removed' % len(delta.removed)
 
206
    print '  %8d renamed' % len(delta.renamed)
 
207
 
 
208
    ignore_cnt = unknown_cnt = 0
 
209
    for path in working.extras():
 
210
        if working.is_ignored(path):
 
211
            ignore_cnt += 1
 
212
        else:
 
213
            unknown_cnt += 1
 
214
    print '  %8d unknown' % unknown_cnt
 
215
    print '  %8d ignored' % ignore_cnt
 
216
 
 
217
    dir_cnt = 0
 
218
    for file_id in work_inv:
 
219
        if (work_inv.get_file_kind(file_id) == 'directory' and 
 
220
            not work_inv.is_root(file_id)):
 
221
            dir_cnt += 1
 
222
    print '  %8d versioned %s' \
 
223
          % (dir_cnt,
 
224
             plural(dir_cnt, 'subdirectory', 'subdirectories'))
 
225
 
 
226
 
 
227
def _show_branch_stats(branch, verbose):
 
228
    """Show statistics about a branch."""
 
229
    revno, head = branch.last_revision_info()
 
230
    print
 
231
    print 'Branch history:'
 
232
    print '  %8d revision%s' % (revno, plural(revno))
 
233
    stats = branch.repository.gather_stats(head, committers=verbose)
 
234
    if verbose:
 
235
        committers = stats['committers']
 
236
        print '  %8d committer%s' % (committers, plural(committers))
 
237
    if revno:
 
238
        timestamp, timezone = stats['firstrev']
 
239
        age = int((time.time() - timestamp) / 3600 / 24)
 
240
        print '  %8d day%s old' % (age, plural(age))
 
241
        print '   first revision: %s' % osutils.format_date(timestamp,
 
242
            timezone)
 
243
        timestamp, timezone = stats['latestrev']
 
244
        print '  latest revision: %s' % osutils.format_date(timestamp,
 
245
            timezone)
 
246
    return stats
 
247
 
 
248
 
 
249
def _show_repository_info(repository):
 
250
    """Show settings of a repository."""
 
251
    if repository.make_working_trees():
 
252
        print
 
253
        print 'Create working tree for new branches inside the repository.'
 
254
 
 
255
 
 
256
def _show_repository_stats(stats):
 
257
    """Show statistics about a repository."""
 
258
    if 'revisions' in stats or 'size' in stats:
 
259
        print
 
260
        print 'Repository:'
 
261
    if 'revisions' in stats:
 
262
        revisions = stats['revisions']
 
263
        print '  %8d revision%s' % (revisions, plural(revisions))
 
264
    if 'size' in stats:
 
265
        print '  %8d KiB' % (stats['size']/1024)
 
266
 
 
267
 
 
268
def show_bzrdir_info(a_bzrdir, verbose=False):
 
269
    """Output to stdout the 'info' for a_bzrdir."""
 
270
    try:
 
271
        tree = a_bzrdir.open_workingtree(
 
272
            recommend_upgrade=False)
 
273
    except (NoWorkingTree, NotLocalUrl):
 
274
        tree = None
 
275
        try:
 
276
            branch = a_bzrdir.open_branch()
 
277
        except NotBranchError:
 
278
            branch = None
 
279
            try:
 
280
                repository = a_bzrdir.open_repository()
 
281
            except NoRepositoryPresent:
 
282
                # Return silently; cmd_info already returned NotBranchError
 
283
                # if no bzrdir could be opened.
 
284
                return
 
285
            else:
 
286
                lockable = repository
 
287
        else:
 
288
            repository = branch.repository
 
289
            lockable = branch
 
290
    else:
 
291
        branch = tree.branch
 
292
        repository = branch.repository
 
293
        lockable = tree
 
294
 
 
295
    lockable.lock_read()
 
296
    try:
 
297
        show_component_info(a_bzrdir, repository, branch, tree, verbose)
 
298
    finally:
 
299
        lockable.unlock()
 
300
 
 
301
 
 
302
def show_component_info(control, repository, branch=None, working=None,
 
303
    verbose=1):
 
304
    """Write info about all bzrdir components to stdout"""
 
305
    if verbose is False:
 
306
        verbose = 1
 
307
    if verbose is True:
 
308
        verbose = 2
 
309
    layout = describe_layout(repository, branch, working)
 
310
    format = describe_format(control, repository, branch, working)
 
311
    print "%s (format: %s)" % (layout, format)
 
312
    _show_location_info(repository, branch, working)
 
313
    if verbose == 0:
 
314
        return
 
315
    if branch is not None:
 
316
        _show_related_info(branch)
 
317
    _show_format_info(control, repository, branch, working)
 
318
    _show_locking_info(repository, branch, working)
 
319
    if branch is not None:
 
320
        _show_missing_revisions_branch(branch)
 
321
    if working is not None:
 
322
        _show_missing_revisions_working(working)
 
323
        _show_working_stats(working)
 
324
    elif branch is not None:
 
325
        _show_missing_revisions_branch(branch)
 
326
    if branch is not None:
 
327
        stats = _show_branch_stats(branch, verbose==2)
 
328
    else:
 
329
        stats = repository.gather_stats()
 
330
    if branch is None and working is None:
 
331
        _show_repository_info(repository)
 
332
    _show_repository_stats(stats)
 
333
 
 
334
 
 
335
def describe_layout(repository=None, branch=None, tree=None):
 
336
    """Convert a control directory layout into a user-understandable term
 
337
 
 
338
    Common outputs include "Standalone tree", "Repository branch" and
 
339
    "Checkout".  Uncommon outputs include "Unshared repository with trees"
 
340
    and "Empty control directory"
 
341
    """
 
342
    if repository is None:
 
343
        return 'Empty control directory'
 
344
    if branch is None and tree is None:
 
345
        if repository.is_shared():
 
346
            phrase = 'Shared repository'
 
347
        else:
 
348
            phrase = 'Unshared repository'
 
349
        if repository.make_working_trees():
 
350
            phrase += ' with trees'
 
351
        return phrase
 
352
    else:
 
353
        if repository.is_shared():
 
354
            independence = "Repository "
 
355
        else:
 
356
            independence = "Standalone "
 
357
        if tree is not None:
 
358
            phrase = "tree"
 
359
        else:
 
360
            phrase = "branch"
 
361
        if branch is None and tree is not None:
 
362
            phrase = "branchless tree"
 
363
        else:
 
364
            if (tree is not None and tree.bzrdir.root_transport.base !=
 
365
                branch.bzrdir.root_transport.base):
 
366
                independence = ''
 
367
                phrase = "Lightweight checkout"
 
368
            elif branch.get_bound_location() is not None:
 
369
                if independence == 'Standalone ':
 
370
                    independence = ''
 
371
                if tree is None:
 
372
                    phrase = "Bound branch"
 
373
                else:
 
374
                    phrase = "Checkout"
 
375
        if independence != "":
 
376
            phrase = phrase.lower()
 
377
        return "%s%s" % (independence, phrase)
 
378
 
 
379
 
 
380
def describe_format(control, repository, branch, tree):
 
381
    """Determine the format of an existing control directory
 
382
 
 
383
    Several candidates may be found.  If so, the names are returned as a
 
384
    single string, separated by slashes.
 
385
 
 
386
    If no matching candidate is found, "unnamed" is returned.
 
387
    """
 
388
    candidates  = []
 
389
    if (branch is not None and tree is not None and
 
390
        branch.bzrdir.root_transport.base !=
 
391
        tree.bzrdir.root_transport.base):
 
392
        branch = None
 
393
        repository = None
 
394
    for key in bzrdir.format_registry.keys():
 
395
        format = bzrdir.format_registry.make_bzrdir(key)
 
396
        if isinstance(format, bzrdir.BzrDirMetaFormat1):
 
397
            if (tree and format.workingtree_format !=
 
398
                tree._format):
 
399
                continue
 
400
            if (branch and format.get_branch_format() !=
 
401
                branch._format):
 
402
                continue
 
403
            if (repository and format.repository_format !=
 
404
                repository._format):
 
405
                continue
 
406
        if format.__class__ is not control._format.__class__:
 
407
            continue
 
408
        candidates.append(key)
 
409
    if len(candidates) == 0:
 
410
        return 'unnamed'
 
411
    new_candidates = [c for c in candidates if c != 'default']
 
412
    if len(new_candidates) > 0:
 
413
        candidates = new_candidates
 
414
    new_candidates = [c for c in candidates if not
 
415
        bzrdir.format_registry.get_info(c).hidden]
 
416
    if len(new_candidates) > 0:
 
417
        candidates = new_candidates
 
418
    return ' / '.join(candidates)
 
419
 
 
420
@deprecated_function(zero_eight)
 
421
def show_info(b):
 
422
    """Please see show_bzrdir_info."""
 
423
    return show_bzrdir_info(b.bzrdir)
 
424
 
 
425
 
 
426
@deprecated_function(zero_sixteen)
 
427
def show_tree_info(working, verbose):
 
428
    """Output to stdout the 'info' for working."""
 
429
    branch = working.branch
 
430
    repository = branch.repository
 
431
    control = working.bzrdir
 
432
    show_component_info(control, repository, branch, working, verbose)
 
433
 
 
434
 
 
435
@deprecated_function(zero_sixteen)
 
436
def show_branch_info(branch, verbose):
 
437
    """Output to stdout the 'info' for branch."""
 
438
    repository = branch.repository
 
439
    control = branch.bzrdir
 
440
    show_component_info(control, repository, branch, verbose=verbose)
 
441
 
 
442
 
 
443
@deprecated_function(zero_sixteen)
 
444
def show_repository_info(repository, verbose):
 
445
    """Output to stdout the 'info' for repository."""
 
446
    control = repository.bzrdir
 
447
    show_component_info(control, repository, verbose=verbose)