/brz/remove-bazaar

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