13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
__all__ = ['show_bzrdir_info']
23
22
from bzrlib import (
30
28
from bzrlib.errors import (NoWorkingTree, NotBranchError,
31
29
NoRepositoryPresent, NotLocalUrl)
32
30
from bzrlib.missing import find_unmerged
31
from bzrlib.symbol_versioning import (deprecated_function,
32
zero_eight, zero_eighteen)
35
35
def plural(n, base='', pl=None):
44
class LocationList(object):
46
def __init__(self, base_path):
48
self.base_path = base_path
50
def add_url(self, label, url):
51
"""Add a URL to the list, converting it to a path if possible"""
55
path = urlutils.local_path_from_url(url)
56
except errors.InvalidURL:
57
self.locs.append((label, url))
59
self.add_path(label, path)
44
def _repo_rel_url(repo_url, inner_url):
45
"""Return path with common prefix of repository path removed.
47
If path is not part of the repository, the original path is returned.
48
If path is equal to the repository, the current directory marker '.' is
50
Otherwise, a relative path is returned, with trailing '/' stripped.
52
inner_url = urlutils.normalize_url(inner_url)
53
repo_url = urlutils.normalize_url(repo_url)
54
if inner_url == repo_url:
56
result = urlutils.relative_url(repo_url, inner_url)
57
if result != inner_url:
58
result = result.rstrip('/')
61
class _UrlList(object):
66
def add_url(self, label, url):
67
self.add_path(label, urlutils.unescape_for_display(url, 'ascii'))
69
def add_url(self, label, url):
70
self.add_path(label, url)
61
72
def add_path(self, label, path):
62
"""Add a path, converting it to a relative path if possible"""
64
path = osutils.relpath(self.base_path, path)
65
except errors.PathNotChild:
71
path = path.rstrip('/')
72
self.locs.append((label, path))
73
self.urls.append((label, path))
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 ]
75
def print_lines(self):
76
max_len = max(len(l) for l, u in self.urls)
77
for label, url in self.urls:
78
print " %*s: %s" % (max_len, label, url)
79
81
def gather_location_info(repository, branch=None, working=None):
126
130
return [(n, locs[n]) for n in order if n in locs]
129
def _show_location_info(locs, outfile):
133
def _show_location_info(locs):
130
134
"""Show known locations for working, branch and repository."""
131
outfile.write('Location:\n')
132
path_list = LocationList(osutils.getcwd())
136
path_list = _UrlList()
133
137
for name, loc in locs:
134
138
path_list.add_url(name, loc)
135
outfile.writelines(path_list.get_lines())
138
def _gather_related_branches(branch):
139
locs = LocationList(osutils.getcwd())
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())
145
locs.add_url('stacked on', branch.get_stacked_on_url())
146
except (errors.UnstackableBranchFormat, errors.UnstackableRepositoryFormat,
152
def _show_related_info(branch, outfile):
139
path_list.print_lines()
142
def _show_related_info(branch):
153
143
"""Show parent and push location of branch."""
154
locs = _gather_related_branches(branch)
155
if len(locs.locs) > 0:
157
outfile.write('Related branches:\n')
158
outfile.writelines(locs.get_lines())
161
def _show_format_info(control=None, repository=None, branch=None,
162
working=None, outfile=None):
144
if branch.get_parent() or branch.get_push_location():
146
print 'Related branches:'
147
if branch.get_parent():
148
if branch.get_push_location():
149
print ' parent branch: %s' % branch.get_parent()
151
print ' parent branch: %s' % branch.get_parent()
152
if branch.get_push_location():
153
print ' publish to branch: %s' % branch.get_push_location()
156
def _show_format_info(control=None, repository=None, branch=None, working=None):
163
157
"""Show known formats for control, working, branch and repository."""
165
outfile.write('Format:\n')
167
outfile.write(' control: %s\n' %
168
control._format.get_format_description())
161
print ' control: %s' % control._format.get_format_description()
170
outfile.write(' working tree: %s\n' %
171
working._format.get_format_description())
163
print ' working tree: %s' % working._format.get_format_description()
173
outfile.write(' branch: %s\n' %
174
branch._format.get_format_description())
165
print ' branch: %s' % branch._format.get_format_description()
176
outfile.write(' repository: %s\n' %
177
repository._format.get_format_description())
180
def _show_locking_info(repository, branch=None, working=None, outfile=None):
167
print ' repository: %s' % repository._format.get_format_description()
170
def _show_locking_info(repository, branch=None, working=None):
181
171
"""Show locking status of working, branch and repository."""
182
172
if (repository.get_physical_lock_status() or
183
173
(branch and branch.get_physical_lock_status()) or
184
174
(working and working.get_physical_lock_status())):
186
outfile.write('Lock status:\n')
188
178
if working.get_physical_lock_status():
189
179
status = 'locked'
191
181
status = 'unlocked'
192
outfile.write(' working tree: %s\n' % status)
182
print ' working tree: %s' % status
194
184
if branch.get_physical_lock_status():
195
185
status = 'locked'
197
187
status = 'unlocked'
198
outfile.write(' branch: %s\n' % status)
188
print ' branch: %s' % status
200
190
if repository.get_physical_lock_status():
201
191
status = 'locked'
203
193
status = 'unlocked'
204
outfile.write(' repository: %s\n' % status)
207
def _show_missing_revisions_branch(branch, outfile):
194
print ' repository: %s' % status
197
def _show_missing_revisions_branch(branch):
208
198
"""Show missing master revisions in branch."""
209
199
# Try with inaccessible branch ?
210
200
master = branch.get_master_branch()
212
202
local_extra, remote_extra = find_unmerged(branch, master)
215
outfile.write(('Branch is out of date: missing %d '
216
'revision%s.\n') % (len(remote_extra),
217
plural(len(remote_extra))))
220
def _show_missing_revisions_working(working, outfile):
205
print 'Branch is out of date: missing %d revision%s.' % (
206
len(remote_extra), plural(len(remote_extra)))
209
def _show_missing_revisions_working(working):
221
210
"""Show missing revisions in working tree."""
222
211
branch = working.branch
223
212
basis = working.basis_tree()
231
220
if branch_revno and tree_last_id != branch_last_revision:
232
221
tree_last_revno = branch.revision_id_to_revno(tree_last_id)
233
222
missing_count = branch_revno - tree_last_revno
235
outfile.write(('Working tree is out of date: missing %d '
236
'revision%s.\n') % (missing_count, plural(missing_count)))
239
def _show_working_stats(working, outfile):
224
print 'Working tree is out of date: missing %d revision%s.' % (
225
missing_count, plural(missing_count))
228
def _show_working_stats(working):
240
229
"""Show statistics about a working tree."""
241
230
basis = working.basis_tree()
242
231
work_inv = working.inventory
243
232
delta = working.changes_from(basis, want_unchanged=True)
246
outfile.write('In the working tree:\n')
247
outfile.write(' %8s unchanged\n' % len(delta.unchanged))
248
outfile.write(' %8d modified\n' % len(delta.modified))
249
outfile.write(' %8d added\n' % len(delta.added))
250
outfile.write(' %8d removed\n' % len(delta.removed))
251
outfile.write(' %8d renamed\n' % len(delta.renamed))
235
print 'In the working tree:'
236
print ' %8s unchanged' % len(delta.unchanged)
237
print ' %8d modified' % len(delta.modified)
238
print ' %8d added' % len(delta.added)
239
print ' %8d removed' % len(delta.removed)
240
print ' %8d renamed' % len(delta.renamed)
253
242
ignore_cnt = unknown_cnt = 0
254
243
for path in working.extras():
259
outfile.write(' %8d unknown\n' % unknown_cnt)
260
outfile.write(' %8d ignored\n' % ignore_cnt)
248
print ' %8d unknown' % unknown_cnt
249
print ' %8d ignored' % ignore_cnt
263
252
for file_id in work_inv:
264
if (work_inv.get_file_kind(file_id) == 'directory' and
253
if (work_inv.get_file_kind(file_id) == 'directory' and
265
254
not work_inv.is_root(file_id)):
267
outfile.write(' %8d versioned %s\n' % (dir_cnt,
268
plural(dir_cnt, 'subdirectory', 'subdirectories')))
271
def _show_branch_stats(branch, verbose, outfile):
256
print ' %8d versioned %s' \
258
plural(dir_cnt, 'subdirectory', 'subdirectories'))
261
def _show_branch_stats(branch, verbose):
272
262
"""Show statistics about a branch."""
273
263
revno, head = branch.last_revision_info()
275
outfile.write('Branch history:\n')
276
outfile.write(' %8d revision%s\n' % (revno, plural(revno)))
265
print 'Branch history:'
266
print ' %8d revision%s' % (revno, plural(revno))
277
267
stats = branch.repository.gather_stats(head, committers=verbose)
279
269
committers = stats['committers']
280
outfile.write(' %8d committer%s\n' % (committers,
270
print ' %8d committer%s' % (committers, plural(committers))
283
272
timestamp, timezone = stats['firstrev']
284
273
age = int((time.time() - timestamp) / 3600 / 24)
285
outfile.write(' %8d day%s old\n' % (age, plural(age)))
286
outfile.write(' first revision: %s\n' %
287
osutils.format_date(timestamp, timezone))
274
print ' %8d day%s old' % (age, plural(age))
275
print ' first revision: %s' % osutils.format_date(timestamp,
288
277
timestamp, timezone = stats['latestrev']
289
outfile.write(' latest revision: %s\n' %
290
osutils.format_date(timestamp, timezone))
278
print ' latest revision: %s' % osutils.format_date(timestamp,
294
def _show_repository_info(repository, outfile):
283
def _show_repository_info(repository):
295
284
"""Show settings of a repository."""
296
285
if repository.make_working_trees():
298
outfile.write('Create working tree for new branches inside '
302
def _show_repository_stats(stats, outfile):
287
print 'Create working tree for new branches inside the repository.'
290
def _show_repository_stats(stats):
303
291
"""Show statistics about a repository."""
304
292
if 'revisions' in stats or 'size' in stats:
306
outfile.write('Repository:\n')
307
295
if 'revisions' in stats:
308
296
revisions = stats['revisions']
309
outfile.write(' %8d revision%s\n' % (revisions, plural(revisions)))
297
print ' %8d revision%s' % (revisions, plural(revisions))
310
298
if 'size' in stats:
311
outfile.write(' %8d KiB\n' % (stats['size']/1024))
314
def show_bzrdir_info(a_bzrdir, verbose=False, outfile=None):
299
print ' %8d KiB' % (stats['size']/1024)
301
def show_bzrdir_info(a_bzrdir, verbose=False):
315
302
"""Output to stdout the 'info' for a_bzrdir."""
319
304
tree = a_bzrdir.open_workingtree(
320
305
recommend_upgrade=False)
343
328
lockable.lock_read()
345
show_component_info(a_bzrdir, repository, branch, tree, verbose,
330
show_component_info(a_bzrdir, repository, branch, tree, verbose)
348
332
lockable.unlock()
351
335
def show_component_info(control, repository, branch=None, working=None,
352
verbose=1, outfile=None):
353
337
"""Write info about all bzrdir components to stdout"""
356
338
if verbose is False:
358
340
if verbose is True:
360
342
layout = describe_layout(repository, branch, working)
361
343
format = describe_format(control, repository, branch, working)
362
outfile.write("%s (format: %s)\n" % (layout, format))
363
_show_location_info(gather_location_info(repository, branch, working),
344
print "%s (format: %s)" % (layout, format)
345
_show_location_info(gather_location_info(repository, branch, working))
365
346
if branch is not None:
366
_show_related_info(branch, outfile)
347
_show_related_info(branch)
369
_show_format_info(control, repository, branch, working, outfile)
370
_show_locking_info(repository, branch, working, outfile)
350
_show_format_info(control, repository, branch, working)
351
_show_locking_info(repository, branch, working)
371
352
if branch is not None:
372
_show_missing_revisions_branch(branch, outfile)
353
_show_missing_revisions_branch(branch)
373
354
if working is not None:
374
_show_missing_revisions_working(working, outfile)
375
_show_working_stats(working, outfile)
355
_show_missing_revisions_working(working)
356
_show_working_stats(working)
376
357
elif branch is not None:
377
_show_missing_revisions_branch(branch, outfile)
358
_show_missing_revisions_branch(branch)
378
359
if branch is not None:
379
show_committers = verbose >= 2
380
stats = _show_branch_stats(branch, show_committers, outfile)
360
stats = _show_branch_stats(branch, verbose==2)
382
362
stats = repository.gather_stats()
383
363
if branch is None and working is None:
384
_show_repository_info(repository, outfile)
385
_show_repository_stats(stats, outfile)
364
_show_repository_info(repository)
365
_show_repository_stats(stats)
388
368
def describe_layout(repository=None, branch=None, tree=None):
463
441
candidates.append(key)
464
442
if len(candidates) == 0:
444
new_candidates = [c for c in candidates if c != 'default']
445
if len(new_candidates) > 0:
446
candidates = new_candidates
467
447
new_candidates = [c for c in candidates if not
468
448
bzrdir.format_registry.get_info(c).hidden]
469
449
if len(new_candidates) > 0:
470
# If there are any non-hidden formats that match, only return those to
471
# avoid listing hidden formats except when only a hidden format will
473
450
candidates = new_candidates
474
451
return ' or '.join(candidates)
453
@deprecated_function(zero_eight)
455
"""Please see show_bzrdir_info."""
456
return show_bzrdir_info(b.bzrdir)
459
@deprecated_function(zero_eighteen)
460
def show_tree_info(working, verbose):
461
"""Output to stdout the 'info' for working."""
462
branch = working.branch
463
repository = branch.repository
464
control = working.bzrdir
465
show_component_info(control, repository, branch, working, verbose)
468
@deprecated_function(zero_eighteen)
469
def show_branch_info(branch, verbose):
470
"""Output to stdout the 'info' for branch."""
471
repository = branch.repository
472
control = branch.bzrdir
473
show_component_info(control, repository, branch, verbose=verbose)
476
@deprecated_function(zero_eighteen)
477
def show_repository_info(repository, verbose):
478
"""Output to stdout the 'info' for repository."""
479
control = repository.bzrdir
480
show_component_info(control, repository, verbose=verbose)