~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/info.py

  • Committer: Martin Pool
  • Date: 2006-06-05 16:23:59 UTC
  • mto: This revision was merged to the branch mainline in revision 1752.
  • Revision ID: mbp@sourcefrog.net-20060605162359-2405198cadc86895
[broken] NotBranchError should unescape the url if possible

(Fixes some info blackbox tests)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005 by Martin Pool
2
 
# Copyright (C) 2005 by Canonical Ltd
3
 
 
4
 
 
 
1
# Copyright (C) 2005, 2006 by Canonical Ltd
 
2
5
3
# This program is free software; you can redistribute it and/or modify
6
4
# it under the terms of the GNU General Public License as published by
7
5
# the Free Software Foundation; either version 2 of the License, or
8
6
# (at your option) any later version.
9
 
 
 
7
10
8
# This program is distributed in the hope that it will be useful,
11
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
11
# GNU General Public License for more details.
14
 
 
 
12
15
13
# You should have received a copy of the GNU General Public License
16
14
# along with this program; if not, write to the Free Software
17
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
16
 
19
 
from sets import Set
 
17
__all__ = ['show_bzrdir_info']
 
18
 
20
19
import time
21
20
 
22
 
import bzrlib
23
 
from osutils import format_date
24
 
 
25
 
def show_info(b):
26
 
    print 'branch format:', b.controlfile('branch-format', 'r').readline().rstrip('\n')
27
 
 
28
 
    def plural(n, base='', pl=None):
29
 
        if n == 1:
30
 
            return base
31
 
        elif pl != None:
32
 
            return pl
33
 
        else:
34
 
            return 's'
35
 
 
36
 
    count_version_dirs = 0
37
 
 
38
 
    count_status = {'A': 0, 'D': 0, 'M': 0, 'R': 0, '?': 0, 'I': 0, '.': 0}
39
 
    for st_tup in bzrlib.diff_trees(b.basis_tree(), b.working_tree()):
40
 
        fs = st_tup[0]
41
 
        count_status[fs] += 1
42
 
        if fs not in ['I', '?'] and st_tup[4] == 'directory':
43
 
            count_version_dirs += 1
44
 
 
45
 
    print
46
 
    print 'in the working tree:'
47
 
    for name, fs in (('unchanged', '.'),
48
 
                     ('modified', 'M'), ('added', 'A'), ('removed', 'D'),
49
 
                     ('renamed', 'R'), ('unknown', '?'), ('ignored', 'I'),
50
 
                     ):
51
 
        print '  %8d %s' % (count_status[fs], name)
52
 
    print '  %8d versioned subdirector%s' % (count_version_dirs,
53
 
                                             plural(count_version_dirs, 'y', 'ies'))
54
 
 
55
 
    print
56
 
    print 'branch history:'
57
 
    history = b.revision_history()
 
21
 
 
22
import bzrlib.diff as diff
 
23
from bzrlib.errors import (NoWorkingTree, NotBranchError,
 
24
                           NoRepositoryPresent, NotLocalUrl)
 
25
from bzrlib.missing import find_unmerged
 
26
import bzrlib.osutils as osutils
 
27
from bzrlib.symbol_versioning import *
 
28
 
 
29
 
 
30
def plural(n, base='', pl=None):
 
31
    if n == 1:
 
32
        return base
 
33
    elif pl != None:
 
34
        return pl
 
35
    else:
 
36
        return 's'
 
37
 
 
38
 
 
39
def _repo_relpath(repo_path, path):
 
40
    """Return path with common prefix of repository path removed.
 
41
 
 
42
    If path is not part of the repository, the original path is returned.
 
43
    If path is equal to the repository, the current directory marker '.' is
 
44
    returned.
 
45
    """
 
46
    path = osutils.normalizepath(path)
 
47
    repo_path = osutils.normalizepath(repo_path)
 
48
    if path == repo_path:
 
49
        return '.'
 
50
    if osutils.is_inside(repo_path, path):
 
51
        return osutils.relpath(repo_path, path)
 
52
    return path
 
53
 
 
54
 
 
55
def _show_location_info(repository, branch=None, working=None):
 
56
    """Show known locations for working, branch and repository."""
 
57
    repository_path = repository.bzrdir.root_transport.base
 
58
    print 'Location:'
 
59
    if working and branch:
 
60
        working_path = working.bzrdir.root_transport.base
 
61
        branch_path = branch.bzrdir.root_transport.base
 
62
        if working_path != branch_path:
 
63
            # lightweight checkout
 
64
            print '  light checkout root: %s' % working_path
 
65
            if repository.is_shared():
 
66
                # lightweight checkout of branch in shared repository
 
67
                print '    shared repository: %s' % repository_path
 
68
                print '    repository branch: %s' % (
 
69
                    _repo_relpath(repository_path, branch_path))
 
70
            else:
 
71
                # lightweight checkout of standalone branch
 
72
                print '   checkout of branch: %s' % branch_path
 
73
        elif repository.is_shared():
 
74
            # branch with tree inside shared repository
 
75
            print '    shared repository: %s' % repository_path
 
76
            print '  repository checkout: %s' % (
 
77
                _repo_relpath(repository_path, branch_path))
 
78
        elif branch.get_bound_location():
 
79
            # normal checkout
 
80
            print '       checkout root: %s' % working_path
 
81
            print '  checkout of branch: %s' % branch.get_bound_location()
 
82
        else:
 
83
            # standalone
 
84
            print '  branch root: %s' % working_path
 
85
    elif branch:
 
86
        # branch is part of shared repository
 
87
        assert repository.is_shared()
 
88
        branch_path = branch.bzrdir.root_transport.base
 
89
        print '  shared repository: %s' % repository_path
 
90
        print '  repository branch: %s' % (
 
91
            _repo_relpath(repository_path, branch_path))
 
92
    else:
 
93
        # shared repository
 
94
        assert repository.is_shared()
 
95
        print '  shared repository: %s' % repository_path
 
96
 
 
97
 
 
98
def _show_related_info(branch):
 
99
    """Show parent and push location of branch."""
 
100
    if branch.get_parent() or branch.get_push_location():
 
101
        print
 
102
        print 'Related branches:'
 
103
        if branch.get_parent():
 
104
            if branch.get_push_location():
 
105
                print '      parent branch: %s' % branch.get_parent()
 
106
            else:
 
107
                print '  parent branch: %s' % branch.get_parent()
 
108
        if branch.get_push_location():
 
109
            print '  publish to branch: %s' % branch.get_push_location()
 
110
 
 
111
 
 
112
def _show_format_info(control=None, repository=None, branch=None, working=None):
 
113
    """Show known formats for control, working, branch and repository."""
 
114
    print
 
115
    print 'Format:'
 
116
    if control:
 
117
        print '       control: %s' % control._format.get_format_description()
 
118
    if working:
 
119
        print '  working tree: %s' % working._format.get_format_description()
 
120
    if branch:
 
121
        print '        branch: %s' % branch._format.get_format_description()
 
122
    if repository:
 
123
        print '    repository: %s' % repository._format.get_format_description()
 
124
 
 
125
 
 
126
def _show_locking_info(repository, branch=None, working=None):
 
127
    """Show locking status of working, branch and repository."""
 
128
    if (repository.get_physical_lock_status() or
 
129
        (branch and branch.get_physical_lock_status()) or
 
130
        (working and working.get_physical_lock_status())):
 
131
        print
 
132
        print 'Lock status:'
 
133
        if working:
 
134
            if working.get_physical_lock_status():
 
135
                status = 'locked'
 
136
            else:
 
137
                status = 'unlocked'
 
138
            print '  working tree: %s' % status
 
139
        if branch:
 
140
            if branch.get_physical_lock_status():
 
141
                status = 'locked'
 
142
            else:
 
143
                status = 'unlocked'
 
144
            print '        branch: %s' % status
 
145
        if repository:
 
146
            if repository.get_physical_lock_status():
 
147
                status = 'locked'
 
148
            else:
 
149
                status = 'unlocked'
 
150
            print '    repository: %s' % status
 
151
 
 
152
 
 
153
def _show_missing_revisions_branch(branch):
 
154
    """Show missing master revisions in branch."""
 
155
    # Try with inaccessible branch ?
 
156
    master = branch.get_master_branch()
 
157
    if master:
 
158
        local_extra, remote_extra = find_unmerged(branch, master)
 
159
        if remote_extra:
 
160
            print
 
161
            print 'Branch is out of date: missing %d revision%s.' % (
 
162
                len(remote_extra), plural(len(remote_extra)))
 
163
 
 
164
 
 
165
def _show_missing_revisions_working(working):
 
166
    """Show missing revisions in working tree."""
 
167
    branch = working.branch
 
168
    basis = working.basis_tree()
 
169
    work_inv = working.inventory
 
170
    delta = diff.compare_trees(basis, working, want_unchanged=True)
 
171
    history = branch.revision_history()
 
172
    tree_last_id = working.last_revision()
 
173
 
 
174
    if len(history) and tree_last_id != history[-1]:
 
175
        tree_last_revno = branch.revision_id_to_revno(tree_last_id)
 
176
        missing_count = len(history) - tree_last_revno
 
177
        print
 
178
        print 'Working tree is out of date: missing %d revision%s.' % (
 
179
            missing_count, plural(missing_count))
 
180
 
 
181
 
 
182
def _show_working_stats(working):
 
183
    """Show statistics about a working tree."""
 
184
    basis = working.basis_tree()
 
185
    work_inv = working.inventory
 
186
    delta = diff.compare_trees(basis, working, want_unchanged=True)
 
187
 
 
188
    print
 
189
    print 'In the working tree:'
 
190
    print '  %8s unchanged' % len(delta.unchanged)
 
191
    print '  %8d modified' % len(delta.modified)
 
192
    print '  %8d added' % len(delta.added)
 
193
    print '  %8d removed' % len(delta.removed)
 
194
    print '  %8d renamed' % len(delta.renamed)
 
195
 
 
196
    ignore_cnt = unknown_cnt = 0
 
197
    for path in working.extras():
 
198
        if working.is_ignored(path):
 
199
            ignore_cnt += 1
 
200
        else:
 
201
            unknown_cnt += 1
 
202
    print '  %8d unknown' % unknown_cnt
 
203
    print '  %8d ignored' % ignore_cnt
 
204
 
 
205
    dir_cnt = 0
 
206
    for file_id in work_inv:
 
207
        if work_inv.get_file_kind(file_id) == 'directory':
 
208
            dir_cnt += 1
 
209
    print '  %8d versioned %s' \
 
210
          % (dir_cnt,
 
211
             plural(dir_cnt, 'subdirectory', 'subdirectories'))
 
212
 
 
213
 
 
214
def _show_branch_stats(branch, verbose):
 
215
    """Show statistics about a branch."""
 
216
    repository = branch.repository
 
217
    history = branch.revision_history()
 
218
 
 
219
    print
 
220
    print 'Branch history:'
58
221
    revno = len(history)
59
222
    print '  %8d revision%s' % (revno, plural(revno))
60
 
    committers = Set()
61
 
    for rev in history:
62
 
        committers.add(b.get_revision(rev).committer)
63
 
    print '  %8d committer%s' % (len(committers), plural(len(committers)))
 
223
    if verbose:
 
224
        committers = {}
 
225
        for rev in history:
 
226
            committers[repository.get_revision(rev).committer] = True
 
227
        print '  %8d committer%s' % (len(committers), plural(len(committers)))
64
228
    if revno > 0:
65
 
        firstrev = b.get_revision(history[0])
 
229
        firstrev = repository.get_revision(history[0])
66
230
        age = int((time.time() - firstrev.timestamp) / 3600 / 24)
67
231
        print '  %8d day%s old' % (age, plural(age))
68
 
        print '   first revision: %s' % format_date(firstrev.timestamp,
69
 
                                                    firstrev.timezone)
70
 
 
71
 
        lastrev = b.get_revision(history[-1])
72
 
        print '  latest revision: %s' % format_date(lastrev.timestamp,
73
 
                                                    lastrev.timezone)
74
 
 
75
 
    print
76
 
    print 'text store:'
77
 
    c, t = b.text_store.total_size()
78
 
    print '  %8d file texts' % c
79
 
    print '  %8d kB' % (t/1024)
80
 
 
81
 
    print
82
 
    print 'revision store:'
83
 
    c, t = b.revision_store.total_size()
84
 
    print '  %8d revisions' % c
85
 
    print '  %8d kB' % (t/1024)
86
 
 
87
 
 
88
 
    print
89
 
    print 'inventory store:'
90
 
    c, t = b.inventory_store.total_size()
91
 
    print '  %8d inventories' % c
92
 
    print '  %8d kB' % (t/1024)
93
 
 
 
232
        print '   first revision: %s' % osutils.format_date(firstrev.timestamp,
 
233
                                                            firstrev.timezone)
 
234
 
 
235
        lastrev = repository.get_revision(history[-1])
 
236
        print '  latest revision: %s' % osutils.format_date(lastrev.timestamp,
 
237
                                                            lastrev.timezone)
 
238
 
 
239
#     print
 
240
#     print 'Text store:'
 
241
#     c, t = branch.text_store.total_size()
 
242
#     print '  %8d file texts' % c
 
243
#     print '  %8d KiB' % (t/1024)
 
244
 
 
245
#     print
 
246
#     print 'Inventory store:'
 
247
#     c, t = branch.inventory_store.total_size()
 
248
#     print '  %8d inventories' % c
 
249
#     print '  %8d KiB' % (t/1024)
 
250
 
 
251
 
 
252
def _show_repository_info(repository):
 
253
    """Show settings of a repository."""
 
254
    if repository.make_working_trees():
 
255
        print
 
256
        print 'Create working tree for new branches inside the repository.'
 
257
 
 
258
 
 
259
def _show_repository_stats(repository):
 
260
    """Show statistics about a repository."""
 
261
    if repository.bzrdir.root_transport.listable():
 
262
        print
 
263
        print 'Revision store:'
 
264
        c, t = repository._revision_store.total_size(repository.get_transaction())
 
265
        print '  %8d revision%s' % (c, plural(c))
 
266
        print '  %8d KiB' % (t/1024)
 
267
 
 
268
 
 
269
@deprecated_function(zero_eight)
 
270
def show_info(b):
 
271
    """Please see show_bzrdir_info."""
 
272
    return show_bzrdir_info(b.bzrdir)
 
273
 
 
274
 
 
275
def show_bzrdir_info(a_bzrdir, verbose=False):
 
276
    """Output to stdout the 'info' for a_bzrdir."""
 
277
    try:
 
278
        working = a_bzrdir.open_workingtree()
 
279
        working.lock_read()
 
280
        try:
 
281
            show_tree_info(working, verbose)
 
282
        finally:
 
283
            working.unlock()
 
284
        return
 
285
    except (NoWorkingTree, NotLocalUrl):
 
286
        pass
 
287
 
 
288
    try:
 
289
        branch = a_bzrdir.open_branch()
 
290
        branch.lock_read()
 
291
        try:
 
292
            show_branch_info(branch, verbose)
 
293
        finally:
 
294
            branch.unlock()
 
295
        return
 
296
    except NotBranchError:
 
297
        pass
 
298
 
 
299
    try:
 
300
        repository = a_bzrdir.open_repository()
 
301
        repository.lock_read()
 
302
        try:
 
303
            show_repository_info(repository, verbose)
 
304
        finally:
 
305
            repository.unlock()
 
306
        return
 
307
    except NoRepositoryPresent:
 
308
        pass
 
309
 
 
310
    # Return silently, cmd_info already returned NotBranchError if no bzrdir
 
311
    # could be opened.
 
312
 
 
313
 
 
314
def show_tree_info(working, verbose):
 
315
    """Output to stdout the 'info' for working."""
 
316
    branch = working.branch
 
317
    repository = branch.repository
 
318
    control = working.bzrdir
 
319
 
 
320
    _show_location_info(repository, branch, working)
 
321
    _show_related_info(branch)
 
322
    _show_format_info(control, repository, branch, working)
 
323
    _show_locking_info(repository, branch, working)
 
324
    _show_missing_revisions_branch(branch)
 
325
    _show_missing_revisions_working(working)
 
326
    _show_working_stats(working)
 
327
    _show_branch_stats(branch, verbose)
 
328
    _show_repository_stats(repository)
 
329
 
 
330
 
 
331
def show_branch_info(branch, verbose):
 
332
    """Output to stdout the 'info' for branch."""
 
333
    repository = branch.repository
 
334
    control = branch.bzrdir
 
335
 
 
336
    _show_location_info(repository, branch)
 
337
    _show_related_info(branch)
 
338
    _show_format_info(control, repository, branch)
 
339
    _show_locking_info(repository, branch)
 
340
    _show_missing_revisions_branch(branch)
 
341
    _show_branch_stats(branch, verbose)
 
342
    _show_repository_stats(repository)
 
343
 
 
344
 
 
345
def show_repository_info(repository, verbose):
 
346
    """Output to stdout the 'info' for repository."""
 
347
    control = repository.bzrdir
 
348
 
 
349
    _show_location_info(repository)
 
350
    _show_format_info(control, repository)
 
351
    _show_locking_info(repository)
 
352
    _show_repository_info(repository)
 
353
    _show_repository_stats(repository)