~bzr-pqm/bzr/bzr.dev

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