~bzr-pqm/bzr/bzr.dev

2395.1.1 by Martin Pool
rename 'revision store' to 'repository' in bzr info
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2
#
77 by mbp at sourcefrog
- split info command out into separate file
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.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
7
#
77 by mbp at sourcefrog
- split info command out into separate file
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.
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
12
#
77 by mbp at sourcefrog
- split info command out into separate file
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
77 by mbp at sourcefrog
- split info command out into separate file
16
1534.5.1 by Robert Collins
Give info some reasonable output and tests.
17
__all__ = ['show_bzrdir_info']
18
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
19
from cStringIO import StringIO
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
20
import os
77 by mbp at sourcefrog
- split info command out into separate file
21
import time
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
22
import sys
1534.5.1 by Robert Collins
Give info some reasonable output and tests.
23
1551.9.22 by Aaron Bentley
Use urlutils for info. Fixes bug #76229
24
from bzrlib import (
2363.5.5 by Aaron Bentley
add info.describe_format
25
    bzrdir,
1551.9.22 by Aaron Bentley
Use urlutils for info. Fixes bug #76229
26
    diff,
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
27
    errors,
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
28
    hooks as _mod_hooks,
1551.9.22 by Aaron Bentley
Use urlutils for info. Fixes bug #76229
29
    osutils,
30
    urlutils,
31
    )
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
32
from bzrlib.errors import (NoWorkingTree, NotBranchError,
33
                           NoRepositoryPresent, NotLocalUrl)
1587.1.14 by Robert Collins
Make bound branch creation happen via 'checkout'
34
from bzrlib.missing import find_unmerged
77 by mbp at sourcefrog
- split info command out into separate file
35
462 by Martin Pool
- New form 'file_id in tree' to check if the file is present
36
1563.2.28 by Robert Collins
Add total_size to the revision_store api.
37
def plural(n, base='', pl=None):
38
    if n == 1:
39
        return base
1963.2.6 by Robey Pointer
pychecker is on crack; go back to using 'is None'.
40
    elif pl is not None:
1563.2.28 by Robert Collins
Add total_size to the revision_store api.
41
        return pl
42
    else:
43
        return 's'
44
45
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
46
class LocationList(object):
47
48
    def __init__(self, base_path):
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
49
        self.locs = []
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
50
        self.base_path = base_path
51
52
    def add_url(self, label, url):
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
53
        """Add a URL to the list, converting it to a path if possible"""
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
54
        if url is None:
55
            return
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
56
        try:
57
            path = urlutils.local_path_from_url(url)
58
        except errors.InvalidURL:
59
            self.locs.append((label, url))
60
        else:
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
61
            self.add_path(label, path)
2363.5.18 by Aaron Bentley
Get all tests passing
62
63
    def add_path(self, label, path):
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
64
        """Add a path, converting it to a relative path if possible"""
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
65
        try:
66
            path = osutils.relpath(self.base_path, path)
67
        except errors.PathNotChild:
68
            pass
69
        else:
70
            if path == '':
71
                path = '.'
72
        if path != '/':
73
            path = path.rstrip('/')
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
74
        self.locs.append((label, path))
2363.5.18 by Aaron Bentley
Get all tests passing
75
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
76
    def get_lines(self):
77
        max_len = max(len(l) for l, u in self.locs)
78
        return ["  %*s: %s\n" % (max_len, l, u) for l, u in self.locs ]
2363.5.18 by Aaron Bentley
Get all tests passing
79
80
81
def gather_location_info(repository, branch=None, working=None):
82
    locs = {}
1694.2.6 by Martin Pool
[merge] bzr.dev
83
    repository_path = repository.bzrdir.root_transport.base
2363.5.18 by Aaron Bentley
Get all tests passing
84
    if branch is not None:
85
        branch_path = branch.bzrdir.root_transport.base
86
        master_path = branch.get_bound_location()
87
        if master_path is None:
88
            master_path = branch_path
89
    else:
90
        branch_path = None
91
        master_path = None
92
    if working:
1694.2.6 by Martin Pool
[merge] bzr.dev
93
        working_path = working.bzrdir.root_transport.base
94
        if working_path != branch_path:
2363.5.18 by Aaron Bentley
Get all tests passing
95
            locs['light checkout root'] = working_path
96
        if master_path != branch_path:
1694.2.6 by Martin Pool
[merge] bzr.dev
97
            if repository.is_shared():
2363.5.18 by Aaron Bentley
Get all tests passing
98
                locs['repository checkout root'] = branch_path
1694.2.6 by Martin Pool
[merge] bzr.dev
99
            else:
2363.5.18 by Aaron Bentley
Get all tests passing
100
                locs['checkout root'] = branch_path
101
        if working_path != master_path:
102
            locs['checkout of branch'] = master_path
1694.2.6 by Martin Pool
[merge] bzr.dev
103
        elif repository.is_shared():
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
104
            locs['repository branch'] = branch_path
2363.5.18 by Aaron Bentley
Get all tests passing
105
        elif branch_path is not None:
1694.2.6 by Martin Pool
[merge] bzr.dev
106
            # standalone
2363.5.18 by Aaron Bentley
Get all tests passing
107
            locs['branch root'] = branch_path
108
    else:
109
        working_path = None
1624.3.48 by Olaf Conradi
Add info on standalone branches without a working tree.
110
        if repository.is_shared():
2363.5.18 by Aaron Bentley
Get all tests passing
111
            # lightweight checkout of branch in shared repository
112
            if branch_path is not None:
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
113
                locs['repository branch'] = branch_path
2363.5.18 by Aaron Bentley
Get all tests passing
114
        elif branch_path is not None:
115
            # standalone
116
            locs['branch root'] = branch_path
2363.5.19 by Aaron Bentley
Add support for bound branches
117
            if master_path != branch_path:
118
                locs['bound to branch'] = master_path
1624.3.48 by Olaf Conradi
Add info on standalone branches without a working tree.
119
        else:
2363.5.18 by Aaron Bentley
Get all tests passing
120
            locs['repository'] = repository_path
121
    if repository.is_shared():
122
        # lightweight checkout of branch in shared repository
123
        locs['shared repository'] = repository_path
2363.5.23 by Aaron Bentley
Output 2-tuples from gather_locations
124
    order = ['light checkout root', 'repository checkout root',
125
             'checkout root', 'checkout of branch', 'shared repository',
126
             'repository', 'repository branch', 'branch root',
127
             'bound to branch']
128
    return [(n, locs[n]) for n in order if n in locs]
2363.5.18 by Aaron Bentley
Get all tests passing
129
130
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
131
def _show_location_info(locs, outfile):
2363.5.18 by Aaron Bentley
Get all tests passing
132
    """Show known locations for working, branch and repository."""
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
133
    outfile.write('Location:\n')
2804.4.3 by Alexander Belchenko
fix for test_info-tests: using osutils.getcwd instead of os.getcwd (sigh)
134
    path_list = LocationList(osutils.getcwd())
2363.5.23 by Aaron Bentley
Output 2-tuples from gather_locations
135
    for name, loc in locs:
136
        path_list.add_url(name, loc)
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
137
    outfile.writelines(path_list.get_lines())
138
1694.2.6 by Martin Pool
[merge] bzr.dev
139
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
140
def _gather_related_branches(branch):
2804.4.3 by Alexander Belchenko
fix for test_info-tests: using osutils.getcwd instead of os.getcwd (sigh)
141
    locs = LocationList(osutils.getcwd())
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
142
    locs.add_url('public branch', branch.get_public_branch())
143
    locs.add_url('push branch', branch.get_push_location())
144
    locs.add_url('parent branch', branch.get_parent())
145
    locs.add_url('submit branch', branch.get_submit_branch())
3221.11.21 by Robert Collins
Have info report on stacked branches.
146
    try:
3537.3.1 by Martin Pool
Rename branch.get_stacked_on to get_stacked_on_url
147
        locs.add_url('stacked on', branch.get_stacked_on_url())
3221.11.21 by Robert Collins
Have info report on stacked branches.
148
    except (errors.UnstackableBranchFormat, errors.UnstackableRepositoryFormat,
149
        errors.NotStacked):
150
        pass
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
151
    return locs
1694.2.6 by Martin Pool
[merge] bzr.dev
152
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
153
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
154
def _show_related_info(branch, outfile):
1694.2.6 by Martin Pool
[merge] bzr.dev
155
    """Show parent and push location of branch."""
1551.15.41 by Aaron Bentley
Make info provide more related brances, and format all branches nicely
156
    locs = _gather_related_branches(branch)
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
157
    if len(locs.locs) > 0:
2911.6.1 by Blake Winton
Change 'print >> f,'s to 'f.write('s.
158
        outfile.write('\n')
159
        outfile.write('Related branches:\n')
1551.15.43 by Aaron Bentley
Provide ways of getting at unicode-clean output
160
        outfile.writelines(locs.get_lines())
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
161
162
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
163
def _show_format_info(control=None, repository=None, branch=None,
164
                      working=None, outfile=None):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
165
    """Show known formats for control, working, branch and repository."""
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
166
    outfile.write('\n')
167
    outfile.write('Format:\n')
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
168
    if control:
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
169
        outfile.write('       control: %s\n' %
170
            control._format.get_format_description())
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
171
    if working:
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
172
        outfile.write('  working tree: %s\n' %
173
            working._format.get_format_description())
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
174
    if branch:
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
175
        outfile.write('        branch: %s\n' %
176
            branch._format.get_format_description())
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
177
    if repository:
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
178
        outfile.write('    repository: %s\n' %
179
            repository._format.get_format_description())
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
180
181
182
def _show_locking_info(repository, branch=None, working=None, outfile=None):
1694.2.6 by Martin Pool
[merge] bzr.dev
183
    """Show locking status of working, branch and repository."""
184
    if (repository.get_physical_lock_status() or
185
        (branch and branch.get_physical_lock_status()) or
186
        (working and working.get_physical_lock_status())):
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
187
        outfile.write('\n')
188
        outfile.write('Lock status:\n')
1694.2.6 by Martin Pool
[merge] bzr.dev
189
        if working:
190
            if working.get_physical_lock_status():
191
                status = 'locked'
192
            else:
193
                status = 'unlocked'
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
194
            outfile.write('  working tree: %s\n' % status)
1694.2.6 by Martin Pool
[merge] bzr.dev
195
        if branch:
196
            if branch.get_physical_lock_status():
197
                status = 'locked'
198
            else:
199
                status = 'unlocked'
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
200
            outfile.write('        branch: %s\n' % status)
1694.2.6 by Martin Pool
[merge] bzr.dev
201
        if repository:
202
            if repository.get_physical_lock_status():
203
                status = 'locked'
204
            else:
205
                status = 'unlocked'
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
206
            outfile.write('    repository: %s\n' % status)
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
207
208
209
def _show_missing_revisions_branch(branch, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
210
    """Show missing master revisions in branch."""
1587.1.14 by Robert Collins
Make bound branch creation happen via 'checkout'
211
    # Try with inaccessible branch ?
1624.3.2 by Olaf Conradi
Implemented table of constructs from BzrInfo specification.
212
    master = branch.get_master_branch()
1587.1.14 by Robert Collins
Make bound branch creation happen via 'checkout'
213
    if master:
1624.3.2 by Olaf Conradi
Implemented table of constructs from BzrInfo specification.
214
        local_extra, remote_extra = find_unmerged(branch, master)
1587.1.14 by Robert Collins
Make bound branch creation happen via 'checkout'
215
        if remote_extra:
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
216
            outfile.write('\n')
217
            outfile.write(('Branch is out of date: missing %d '
218
                'revision%s.\n') % (len(remote_extra),
219
                plural(len(remote_extra))))
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
220
221
222
def _show_missing_revisions_working(working, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
223
    """Show missing revisions in working tree."""
224
    branch = working.branch
225
    basis = working.basis_tree()
226
    work_inv = working.inventory
2249.4.2 by Wouter van Heyst
Convert callers of Branch.revision_history() to Branch.last_revision_info() where sensible.
227
    branch_revno, branch_last_revision = branch.last_revision_info()
1908.7.6 by Robert Collins
Deprecate WorkingTree.last_revision.
228
    try:
229
        tree_last_id = working.get_parent_ids()[0]
230
    except IndexError:
231
        tree_last_id = None
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
232
2249.4.2 by Wouter van Heyst
Convert callers of Branch.revision_history() to Branch.last_revision_info() where sensible.
233
    if branch_revno and tree_last_id != branch_last_revision:
1624.3.11 by Olaf Conradi
Test cases exposed a bug in missing revisions count of working tree. It
234
        tree_last_revno = branch.revision_id_to_revno(tree_last_id)
2249.4.2 by Wouter van Heyst
Convert callers of Branch.revision_history() to Branch.last_revision_info() where sensible.
235
        missing_count = branch_revno - tree_last_revno
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
236
        outfile.write('\n')
237
        outfile.write(('Working tree is out of date: missing %d '
238
            'revision%s.\n') % (missing_count, plural(missing_count)))
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
239
240
241
def _show_working_stats(working, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
242
    """Show statistics about a working tree."""
243
    basis = working.basis_tree()
244
    work_inv = working.inventory
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
245
    delta = working.changes_from(basis, want_unchanged=True)
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
246
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
247
    outfile.write('\n')
248
    outfile.write('In the working tree:\n')
249
    outfile.write('  %8s unchanged\n' % len(delta.unchanged))
250
    outfile.write('  %8d modified\n' % len(delta.modified))
251
    outfile.write('  %8d added\n' % len(delta.added))
252
    outfile.write('  %8d removed\n' % len(delta.removed))
253
    outfile.write('  %8d renamed\n' % len(delta.renamed))
462 by Martin Pool
- New form 'file_id in tree' to check if the file is present
254
255
    ignore_cnt = unknown_cnt = 0
256
    for path in working.extras():
257
        if working.is_ignored(path):
258
            ignore_cnt += 1
259
        else:
260
            unknown_cnt += 1
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
261
    outfile.write('  %8d unknown\n' % unknown_cnt)
262
    outfile.write('  %8d ignored\n' % ignore_cnt)
462 by Martin Pool
- New form 'file_id in tree' to check if the file is present
263
264
    dir_cnt = 0
1731.1.39 by Aaron Bentley
Reject removing is_root
265
    for file_id in work_inv:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
266
        if (work_inv.get_file_kind(file_id) == 'directory' and
1731.1.39 by Aaron Bentley
Reject removing is_root
267
            not work_inv.is_root(file_id)):
268
            dir_cnt += 1
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
269
    outfile.write('  %8d versioned %s\n' % (dir_cnt,
270
        plural(dir_cnt, 'subdirectory', 'subdirectories')))
77 by mbp at sourcefrog
- split info command out into separate file
271
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
272
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
273
def _show_branch_stats(branch, verbose, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
274
    """Show statistics about a branch."""
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
275
    revno, head = branch.last_revision_info()
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
276
    outfile.write('\n')
277
    outfile.write('Branch history:\n')
278
    outfile.write('  %8d revision%s\n' % (revno, plural(revno)))
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
279
    stats = branch.repository.gather_stats(head, committers=verbose)
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
280
    if verbose:
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
281
        committers = stats['committers']
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
282
        outfile.write('  %8d committer%s\n' % (committers,
283
            plural(committers)))
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
284
    if revno:
285
        timestamp, timezone = stats['firstrev']
286
        age = int((time.time() - timestamp) / 3600 / 24)
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
287
        outfile.write('  %8d day%s old\n' % (age, plural(age)))
288
        outfile.write('   first revision: %s\n' %
289
            osutils.format_date(timestamp, timezone))
2258.1.1 by Robert Collins
Move info branch statistics gathering into the repository to allow smart server optimisation (Robert Collins).
290
        timestamp, timezone = stats['latestrev']
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
291
        outfile.write('  latest revision: %s\n' %
292
            osutils.format_date(timestamp, timezone))
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
293
    return stats
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
294
295
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
296
def _show_repository_info(repository, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
297
    """Show settings of a repository."""
298
    if repository.make_working_trees():
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
299
        outfile.write('\n')
300
        outfile.write('Create working tree for new branches inside '
301
            'the repository.\n')
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
302
303
4307.3.3 by Jelmer Vernooij
Add repository argument to 'repository' info hook, per Roberts review.
304
def _show_repository_stats(repository, stats, outfile):
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
305
    """Show statistics about a repository."""
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
306
    f = StringIO()
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
307
    if 'revisions' in stats:
308
        revisions = stats['revisions']
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
309
        f.write('  %8d revision%s\n' % (revisions, plural(revisions)))
2258.1.2 by Robert Collins
New version of gather_stats which gathers aggregate data too.
310
    if 'size' in stats:
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
311
        f.write('  %8d KiB\n' % (stats['size']/1024))
312
    for hook in hooks['repository']:
4307.3.3 by Jelmer Vernooij
Add repository argument to 'repository' info hook, per Roberts review.
313
        hook(repository, stats, f)
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
314
    if f.getvalue() != "":
315
        outfile.write('\n')
316
        outfile.write('Repository:\n')
317
        outfile.write(f.getvalue())
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
318
1624.3.21 by Olaf Conradi
Make bzr info command work on both local and remote locations. Support
319
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
320
def show_bzrdir_info(a_bzrdir, verbose=False, outfile=None):
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
321
    """Output to stdout the 'info' for a_bzrdir."""
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
322
    if outfile is None:
323
        outfile = sys.stdout
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
324
    try:
2363.5.9 by Aaron Bentley
Merge from bzr.dev
325
        tree = a_bzrdir.open_workingtree(
326
            recommend_upgrade=False)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
327
    except (NoWorkingTree, NotLocalUrl):
328
        tree = None
329
        try:
330
            branch = a_bzrdir.open_branch()
331
        except NotBranchError:
332
            branch = None
333
            try:
334
                repository = a_bzrdir.open_repository()
335
            except NoRepositoryPresent:
336
                # Return silently; cmd_info already returned NotBranchError
337
                # if no bzrdir could be opened.
338
                return
339
            else:
340
                lockable = repository
341
        else:
342
            repository = branch.repository
343
            lockable = branch
344
    else:
345
        branch = tree.branch
346
        repository = branch.repository
347
        lockable = tree
348
349
    lockable.lock_read()
350
    try:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
351
        show_component_info(a_bzrdir, repository, branch, tree, verbose,
352
                            outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
353
    finally:
354
        lockable.unlock()
355
356
357
def show_component_info(control, repository, branch=None, working=None,
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
358
    verbose=1, outfile=None):
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
359
    """Write info about all bzrdir components to stdout"""
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
360
    if outfile is None:
361
        outfile = sys.stdout
2363.5.7 by Aaron Bentley
Make verbose mean what I want
362
    if verbose is False:
363
        verbose = 1
364
    if verbose is True:
365
        verbose = 2
2363.5.6 by Aaron Bentley
Add short format description
366
    layout = describe_layout(repository, branch, working)
367
    format = describe_format(control, repository, branch, working)
2968.2.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``
368
    outfile.write("%s (format: %s)\n" % (layout, format))
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
369
    _show_location_info(gather_location_info(repository, branch, working),
370
                        outfile)
2584.2.1 by Adeodato Simó
Make `bzr info` show related branches in non-verbose mode.
371
    if branch is not None:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
372
        _show_related_info(branch, outfile)
2363.5.7 by Aaron Bentley
Make verbose mean what I want
373
    if verbose == 0:
374
        return
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
375
    _show_format_info(control, repository, branch, working, outfile)
376
    _show_locking_info(repository, branch, working, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
377
    if branch is not None:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
378
        _show_missing_revisions_branch(branch, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
379
    if working is not None:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
380
        _show_missing_revisions_working(working, outfile)
381
        _show_working_stats(working, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
382
    elif branch is not None:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
383
        _show_missing_revisions_branch(branch, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
384
    if branch is not None:
4032.2.1 by Ian Clatworthy
omit branch committers from info -v (now requires -vv)
385
        show_committers = verbose >= 2
386
        stats = _show_branch_stats(branch, show_committers, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
387
    else:
388
        stats = repository.gather_stats()
389
    if branch is None and working is None:
2904.3.1 by Lukáš Lalinský
Unicode-safe output from ``bzr info``.
390
        _show_repository_info(repository, outfile)
4307.3.3 by Jelmer Vernooij
Add repository argument to 'repository' info hook, per Roberts review.
391
    _show_repository_stats(repository, stats, outfile)
2363.5.1 by Aaron Bentley
Unify info display into show_component_info
392
393
2363.5.2 by Aaron Bentley
Implement layout description
394
def describe_layout(repository=None, branch=None, tree=None):
395
    """Convert a control directory layout into a user-understandable term
396
397
    Common outputs include "Standalone tree", "Repository branch" and
398
    "Checkout".  Uncommon outputs include "Unshared repository with trees"
399
    and "Empty control directory"
400
    """
401
    if repository is None:
402
        return 'Empty control directory'
403
    if branch is None and tree is None:
404
        if repository.is_shared():
405
            phrase = 'Shared repository'
406
        else:
407
            phrase = 'Unshared repository'
408
        if repository.make_working_trees():
409
            phrase += ' with trees'
410
        return phrase
411
    else:
412
        if repository.is_shared():
413
            independence = "Repository "
414
        else:
415
            independence = "Standalone "
416
        if tree is not None:
417
            phrase = "tree"
418
        else:
419
            phrase = "branch"
420
        if branch is None and tree is not None:
421
            phrase = "branchless tree"
422
        else:
423
            if (tree is not None and tree.bzrdir.root_transport.base !=
424
                branch.bzrdir.root_transport.base):
2363.5.4 by Aaron Bentley
Eliminate the concept of a 'repository lightweight checkout'
425
                independence = ''
2363.5.2 by Aaron Bentley
Implement layout description
426
                phrase = "Lightweight checkout"
427
            elif branch.get_bound_location() is not None:
428
                if independence == 'Standalone ':
429
                    independence = ''
430
                if tree is None:
431
                    phrase = "Bound branch"
432
                else:
433
                    phrase = "Checkout"
434
        if independence != "":
435
            phrase = phrase.lower()
436
        return "%s%s" % (independence, phrase)
437
438
2363.5.5 by Aaron Bentley
add info.describe_format
439
def describe_format(control, repository, branch, tree):
440
    """Determine the format of an existing control directory
441
442
    Several candidates may be found.  If so, the names are returned as a
2363.5.17 by Aaron Bentley
Change separator from '/' to 'or'
443
    single string, separated by ' or '.
2363.5.5 by Aaron Bentley
add info.describe_format
444
445
    If no matching candidate is found, "unnamed" is returned.
446
    """
447
    candidates  = []
2363.5.6 by Aaron Bentley
Add short format description
448
    if (branch is not None and tree is not None and
449
        branch.bzrdir.root_transport.base !=
450
        tree.bzrdir.root_transport.base):
451
        branch = None
452
        repository = None
3152.2.2 by Robert Collins
The bzrdir format registry now accepts an ``alias`` keyword to
453
    non_aliases = set(bzrdir.format_registry.keys())
454
    non_aliases.difference_update(bzrdir.format_registry.aliases())
455
    for key in non_aliases:
2363.5.5 by Aaron Bentley
add info.describe_format
456
        format = bzrdir.format_registry.make_bzrdir(key)
457
        if isinstance(format, bzrdir.BzrDirMetaFormat1):
458
            if (tree and format.workingtree_format !=
459
                tree._format):
460
                continue
461
            if (branch and format.get_branch_format() !=
462
                branch._format):
463
                continue
464
            if (repository and format.repository_format !=
465
                repository._format):
466
                continue
467
        if format.__class__ is not control._format.__class__:
468
            continue
469
        candidates.append(key)
470
    if len(candidates) == 0:
471
        return 'unnamed'
3152.2.2 by Robert Collins
The bzrdir format registry now accepts an ``alias`` keyword to
472
    candidates.sort()
2363.5.6 by Aaron Bentley
Add short format description
473
    new_candidates = [c for c in candidates if not
474
        bzrdir.format_registry.get_info(c).hidden]
475
    if len(new_candidates) > 0:
3152.2.2 by Robert Collins
The bzrdir format registry now accepts an ``alias`` keyword to
476
        # If there are any non-hidden formats that match, only return those to
477
        # avoid listing hidden formats except when only a hidden format will
478
        # do.
2363.5.6 by Aaron Bentley
Add short format description
479
        candidates = new_candidates
2363.5.17 by Aaron Bentley
Change separator from '/' to 'or'
480
    return ' or '.join(candidates)
4307.3.1 by Jelmer Vernooij
Allow registering hooks that extend the Repository section in 'bzr info -v'.
481
482
483
class InfoHooks(_mod_hooks.Hooks):
484
    """Hooks for the info command."""
485
486
    def __init__(self):
487
        self.create_hook(_mod_hooks.HookPoint('repository',
488
            "Invoked when displaying the statistics for a repository. "
489
            "repository is called with a statistics dictionary as returned "
490
            "by the repository and a file-like object to write to.", (1, 15), 
491
            None))
492
493
494
hooks = InfoHooks()