1
# Copyright (C) 2005, 2006 Canonical Ltd
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.
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.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
__all__ = ['show_bzrdir_info']
27
from bzrlib.errors import (NoWorkingTree, NotBranchError,
28
NoRepositoryPresent, NotLocalUrl)
29
from bzrlib.missing import find_unmerged
30
from bzrlib.symbol_versioning import (deprecated_function,
34
def plural(n, base='', pl=None):
43
def _repo_rel_url(repo_url, inner_url):
44
"""Return path with common prefix of repository path removed.
46
If path is not part of the repository, the original path is returned.
47
If path is equal to the repository, the current directory marker '.' is
49
Otherwise, a relative path is returned, with trailing '/' stripped.
51
inner_url = urlutils.normalize_url(inner_url)
52
repo_url = urlutils.normalize_url(repo_url)
53
if inner_url == repo_url:
55
result = urlutils.relative_url(repo_url, inner_url)
56
if result != inner_url:
57
result = result.rstrip('/')
61
def _show_location_info(repository, branch=None, working=None):
62
"""Show known locations for working, branch and repository."""
63
repository_path = repository.bzrdir.root_transport.base
65
if working and branch:
66
working_path = working.bzrdir.root_transport.base
67
branch_path = branch.bzrdir.root_transport.base
68
if working_path != branch_path:
69
# lightweight checkout
70
print ' light checkout root: %s' % working_path
71
if repository.is_shared():
72
# lightweight checkout of branch in shared repository
73
print ' shared repository: %s' % repository_path
74
print ' repository branch: %s' % (
75
_repo_rel_url(repository_path, branch_path))
77
# lightweight checkout of standalone branch
78
print ' checkout of branch: %s' % branch_path
79
elif repository.is_shared():
80
# branch with tree inside shared repository
81
print ' shared repository: %s' % repository_path
82
print ' repository checkout: %s' % (
83
_repo_rel_url(repository_path, branch_path))
84
elif branch.get_bound_location():
86
print ' checkout root: %s' % working_path
87
print ' checkout of branch: %s' % branch.get_bound_location()
90
print ' branch root: %s' % working_path
92
branch_path = branch.bzrdir.root_transport.base
93
if repository.is_shared():
94
# branch is part of shared repository
95
print ' shared repository: %s' % repository_path
96
print ' repository branch: %s' % (
97
_repo_rel_url(repository_path, branch_path))
100
print ' branch root: %s' % branch_path
103
assert repository.is_shared()
104
print ' shared repository: %s' % repository_path
107
def _show_related_info(branch):
108
"""Show parent and push location of branch."""
109
if branch.get_parent() or branch.get_push_location():
111
print 'Related branches:'
112
if branch.get_parent():
113
if branch.get_push_location():
114
print ' parent branch: %s' % branch.get_parent()
116
print ' parent branch: %s' % branch.get_parent()
117
if branch.get_push_location():
118
print ' publish to branch: %s' % branch.get_push_location()
121
def _show_format_info(control=None, repository=None, branch=None, working=None):
122
"""Show known formats for control, working, branch and repository."""
126
print ' control: %s' % control._format.get_format_description()
128
print ' working tree: %s' % working._format.get_format_description()
130
print ' branch: %s' % branch._format.get_format_description()
132
print ' repository: %s' % repository._format.get_format_description()
135
def _show_locking_info(repository, branch=None, working=None):
136
"""Show locking status of working, branch and repository."""
137
if (repository.get_physical_lock_status() or
138
(branch and branch.get_physical_lock_status()) or
139
(working and working.get_physical_lock_status())):
143
if working.get_physical_lock_status():
147
print ' working tree: %s' % status
149
if branch.get_physical_lock_status():
153
print ' branch: %s' % status
155
if repository.get_physical_lock_status():
159
print ' repository: %s' % status
162
def _show_missing_revisions_branch(branch):
163
"""Show missing master revisions in branch."""
164
# Try with inaccessible branch ?
165
master = branch.get_master_branch()
167
local_extra, remote_extra = find_unmerged(branch, master)
170
print 'Branch is out of date: missing %d revision%s.' % (
171
len(remote_extra), plural(len(remote_extra)))
174
def _show_missing_revisions_working(working):
175
"""Show missing revisions in working tree."""
176
branch = working.branch
177
basis = working.basis_tree()
178
work_inv = working.inventory
179
delta = working.changes_from(basis, want_unchanged=True)
180
history = branch.revision_history()
182
tree_last_id = working.get_parent_ids()[0]
186
if len(history) and tree_last_id != history[-1]:
187
tree_last_revno = branch.revision_id_to_revno(tree_last_id)
188
missing_count = len(history) - tree_last_revno
190
print 'Working tree is out of date: missing %d revision%s.' % (
191
missing_count, plural(missing_count))
194
def _show_working_stats(working):
195
"""Show statistics about a working tree."""
196
basis = working.basis_tree()
197
work_inv = working.inventory
198
delta = working.changes_from(basis, want_unchanged=True)
201
print 'In the working tree:'
202
print ' %8s unchanged' % len(delta.unchanged)
203
print ' %8d modified' % len(delta.modified)
204
print ' %8d added' % len(delta.added)
205
print ' %8d removed' % len(delta.removed)
206
print ' %8d renamed' % len(delta.renamed)
208
ignore_cnt = unknown_cnt = 0
209
for path in working.extras():
210
if working.is_ignored(path):
214
print ' %8d unknown' % unknown_cnt
215
print ' %8d ignored' % ignore_cnt
218
for file_id in work_inv:
219
if (work_inv.get_file_kind(file_id) == 'directory' and
220
not work_inv.is_root(file_id)):
222
print ' %8d versioned %s' \
224
plural(dir_cnt, 'subdirectory', 'subdirectories'))
227
def _show_branch_stats(branch, verbose):
228
"""Show statistics about a branch."""
229
repository = branch.repository
230
history = branch.revision_history()
233
print 'Branch history:'
235
print ' %8d revision%s' % (revno, plural(revno))
239
committers[repository.get_revision(rev).committer] = True
240
print ' %8d committer%s' % (len(committers), plural(len(committers)))
242
firstrev = repository.get_revision(history[0])
243
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
244
print ' %8d day%s old' % (age, plural(age))
245
print ' first revision: %s' % osutils.format_date(firstrev.timestamp,
248
lastrev = repository.get_revision(history[-1])
249
print ' latest revision: %s' % osutils.format_date(lastrev.timestamp,
253
# print 'Text store:'
254
# c, t = branch.text_store.total_size()
255
# print ' %8d file texts' % c
256
# print ' %8d KiB' % (t/1024)
259
# print 'Inventory store:'
260
# c, t = branch.inventory_store.total_size()
261
# print ' %8d inventories' % c
262
# print ' %8d KiB' % (t/1024)
265
def _show_repository_info(repository):
266
"""Show settings of a repository."""
267
if repository.make_working_trees():
269
print 'Create working tree for new branches inside the repository.'
272
def _show_repository_stats(repository):
273
"""Show statistics about a repository."""
274
if repository.bzrdir.root_transport.listable():
276
print 'Revision store:'
277
c, t = repository._revision_store.total_size(repository.get_transaction())
278
print ' %8d revision%s' % (c, plural(c))
279
print ' %8d KiB' % (t/1024)
282
@deprecated_function(zero_eight)
284
"""Please see show_bzrdir_info."""
285
return show_bzrdir_info(b.bzrdir)
288
def show_bzrdir_info(a_bzrdir, verbose=False):
289
"""Output to stdout the 'info' for a_bzrdir."""
291
working = a_bzrdir.open_workingtree()
294
show_tree_info(working, verbose)
298
except (NoWorkingTree, NotLocalUrl):
302
branch = a_bzrdir.open_branch()
305
show_branch_info(branch, verbose)
309
except NotBranchError:
313
repository = a_bzrdir.open_repository()
314
repository.lock_read()
316
show_repository_info(repository, verbose)
320
except NoRepositoryPresent:
323
# Return silently, cmd_info already returned NotBranchError if no bzrdir
327
def show_tree_info(working, verbose):
328
"""Output to stdout the 'info' for working."""
329
branch = working.branch
330
repository = branch.repository
331
control = working.bzrdir
333
_show_location_info(repository, branch, working)
334
_show_related_info(branch)
335
_show_format_info(control, repository, branch, working)
336
_show_locking_info(repository, branch, working)
337
_show_missing_revisions_branch(branch)
338
_show_missing_revisions_working(working)
339
_show_working_stats(working)
340
_show_branch_stats(branch, verbose)
341
_show_repository_stats(repository)
344
def show_branch_info(branch, verbose):
345
"""Output to stdout the 'info' for branch."""
346
repository = branch.repository
347
control = branch.bzrdir
349
_show_location_info(repository, branch)
350
_show_related_info(branch)
351
_show_format_info(control, repository, branch)
352
_show_locking_info(repository, branch)
353
_show_missing_revisions_branch(branch)
354
_show_branch_stats(branch, verbose)
355
_show_repository_stats(repository)
358
def show_repository_info(repository, verbose):
359
"""Output to stdout the 'info' for repository."""
360
control = repository.bzrdir
362
_show_location_info(repository)
363
_show_format_info(control, repository)
364
_show_locking_info(repository)
365
_show_repository_info(repository)
366
_show_repository_stats(repository)