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']
19
from cStringIO import StringIO
23
23
from bzrlib import (
30
30
from bzrlib.errors import (NoWorkingTree, NotBranchError,
31
31
NoRepositoryPresent, NotLocalUrl)
32
32
from bzrlib.missing import find_unmerged
33
from bzrlib.symbol_versioning import (deprecated_function,
34
zero_eight, zero_eighteen)
35
37
def plural(n, base='', pl=None):
126
128
return [(n, locs[n]) for n in order if n in locs]
129
def _show_location_info(locs, outfile):
131
def _show_location_info(locs):
130
132
"""Show known locations for working, branch and repository."""
131
outfile.write('Location:\n')
132
path_list = LocationList(osutils.getcwd())
134
path_list = LocationList(os.getcwd())
133
135
for name, loc in locs:
134
136
path_list.add_url(name, loc)
135
outfile.writelines(path_list.get_lines())
137
sys.stdout.writelines(path_list.get_lines())
138
139
def _gather_related_branches(branch):
139
locs = LocationList(osutils.getcwd())
140
locs = LocationList(os.getcwd())
140
141
locs.add_url('public branch', branch.get_public_branch())
141
142
locs.add_url('push branch', branch.get_push_location())
142
143
locs.add_url('parent branch', branch.get_parent())
143
144
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
147
def _show_related_info(branch, outfile):
153
148
"""Show parent and push location of branch."""
154
149
locs = _gather_related_branches(branch)
155
150
if len(locs.locs) > 0:
157
outfile.write('Related branches:\n')
152
print >> outfile, 'Related branches:'
158
153
outfile.writelines(locs.get_lines())
161
def _show_format_info(control=None, repository=None, branch=None,
162
working=None, outfile=None):
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()
213
work_inv = working.inventory
224
214
branch_revno, branch_last_revision = branch.last_revision_info()
226
216
tree_last_id = working.get_parent_ids()[0]
230
220
if branch_revno and tree_last_id != branch_last_revision:
231
221
tree_last_revno = branch.revision_id_to_revno(tree_last_id)
232
222
missing_count = branch_revno - tree_last_revno
234
outfile.write(('Working tree is out of date: missing %d '
235
'revision%s.\n') % (missing_count, plural(missing_count)))
238
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):
239
229
"""Show statistics about a working tree."""
240
230
basis = working.basis_tree()
231
work_inv = working.inventory
241
232
delta = working.changes_from(basis, want_unchanged=True)
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))
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)
251
242
ignore_cnt = unknown_cnt = 0
252
243
for path in working.extras():
257
outfile.write(' %8d unknown\n' % unknown_cnt)
258
outfile.write(' %8d ignored\n' % ignore_cnt)
248
print ' %8d unknown' % unknown_cnt
249
print ' %8d ignored' % ignore_cnt
261
root_id = working.get_root_id()
262
for path, entry in working.iter_entries_by_dir():
263
if entry.kind == 'directory' and entry.file_id != root_id:
252
for file_id in work_inv:
253
if (work_inv.get_file_kind(file_id) == 'directory' and
254
not work_inv.is_root(file_id)):
265
outfile.write(' %8d versioned %s\n' % (dir_cnt,
266
plural(dir_cnt, 'subdirectory', 'subdirectories')))
269
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):
270
262
"""Show statistics about a branch."""
271
263
revno, head = branch.last_revision_info()
273
outfile.write('Branch history:\n')
274
outfile.write(' %8d revision%s\n' % (revno, plural(revno)))
265
print 'Branch history:'
266
print ' %8d revision%s' % (revno, plural(revno))
275
267
stats = branch.repository.gather_stats(head, committers=verbose)
277
269
committers = stats['committers']
278
outfile.write(' %8d committer%s\n' % (committers,
270
print ' %8d committer%s' % (committers, plural(committers))
281
272
timestamp, timezone = stats['firstrev']
282
273
age = int((time.time() - timestamp) / 3600 / 24)
283
outfile.write(' %8d day%s old\n' % (age, plural(age)))
284
outfile.write(' first revision: %s\n' %
285
osutils.format_date(timestamp, timezone))
274
print ' %8d day%s old' % (age, plural(age))
275
print ' first revision: %s' % osutils.format_date(timestamp,
286
277
timestamp, timezone = stats['latestrev']
287
outfile.write(' latest revision: %s\n' %
288
osutils.format_date(timestamp, timezone))
278
print ' latest revision: %s' % osutils.format_date(timestamp,
292
def _show_repository_info(repository, outfile):
283
def _show_repository_info(repository):
293
284
"""Show settings of a repository."""
294
285
if repository.make_working_trees():
296
outfile.write('Create working tree for new branches inside '
300
def _show_repository_stats(repository, stats, outfile):
287
print 'Create working tree for new branches inside the repository.'
290
def _show_repository_stats(stats):
301
291
"""Show statistics about a repository."""
292
if 'revisions' in stats or 'size' in stats:
303
295
if 'revisions' in stats:
304
296
revisions = stats['revisions']
305
f.write(' %8d revision%s\n' % (revisions, plural(revisions)))
297
print ' %8d revision%s' % (revisions, plural(revisions))
306
298
if 'size' in stats:
307
f.write(' %8d KiB\n' % (stats['size']/1024))
308
for hook in hooks['repository']:
309
hook(repository, stats, f)
310
if f.getvalue() != "":
312
outfile.write('Repository:\n')
313
outfile.write(f.getvalue())
316
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):
317
302
"""Output to stdout the 'info' for a_bzrdir."""
321
304
tree = a_bzrdir.open_workingtree(
322
305
recommend_upgrade=False)
345
328
lockable.lock_read()
347
show_component_info(a_bzrdir, repository, branch, tree, verbose,
330
show_component_info(a_bzrdir, repository, branch, tree, verbose)
350
332
lockable.unlock()
353
335
def show_component_info(control, repository, branch=None, working=None,
354
verbose=1, outfile=None):
355
337
"""Write info about all bzrdir components to stdout"""
358
338
if verbose is False:
360
340
if verbose is True:
362
342
layout = describe_layout(repository, branch, working)
363
343
format = describe_format(control, repository, branch, working)
364
outfile.write("%s (format: %s)\n" % (layout, format))
365
_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))
367
346
if branch is not None:
368
_show_related_info(branch, outfile)
347
_show_related_info(branch, sys.stdout)
371
_show_format_info(control, repository, branch, working, outfile)
372
_show_locking_info(repository, branch, working, outfile)
350
_show_format_info(control, repository, branch, working)
351
_show_locking_info(repository, branch, working)
373
352
if branch is not None:
374
_show_missing_revisions_branch(branch, outfile)
353
_show_missing_revisions_branch(branch)
375
354
if working is not None:
376
_show_missing_revisions_working(working, outfile)
377
_show_working_stats(working, outfile)
355
_show_missing_revisions_working(working)
356
_show_working_stats(working)
378
357
elif branch is not None:
379
_show_missing_revisions_branch(branch, outfile)
358
_show_missing_revisions_branch(branch)
380
359
if branch is not None:
381
show_committers = verbose >= 2
382
stats = _show_branch_stats(branch, show_committers, outfile)
360
stats = _show_branch_stats(branch, verbose==2)
384
362
stats = repository.gather_stats()
385
363
if branch is None and working is None:
386
_show_repository_info(repository, outfile)
387
_show_repository_stats(repository, stats, outfile)
364
_show_repository_info(repository)
365
_show_repository_stats(stats)
390
368
def describe_layout(repository=None, branch=None, tree=None):
464
441
candidates.append(key)
465
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
468
447
new_candidates = [c for c in candidates if not
469
448
bzrdir.format_registry.get_info(c).hidden]
470
449
if len(new_candidates) > 0:
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
474
450
candidates = new_candidates
475
451
return ' or '.join(candidates)
478
class InfoHooks(_mod_hooks.Hooks):
479
"""Hooks for the info command."""
482
super(InfoHooks, self).__init__("bzrlib.info", "hooks")
483
self.add_hook('repository',
484
"Invoked when displaying the statistics for a repository. "
485
"repository is called with a statistics dictionary as returned "
486
"by the repository and a file-like object to write to.", (1, 15))
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)