1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
# Some parts of the code are:
3
# Copyright (C) 2005, 2006 by Canonical Ltd
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
import bzrlib.diff as diff
22
import bzrlib.osutils as osutils
24
from bzrlib.info import _repo_relpath
25
from bzrlib.missing import find_unmerged
27
def get_location_info(repository, branch=None, working=None):
28
""" Get known locations for working, branch and repository.
30
:return: a dictionary containing the needed infos
33
repository_path = repository.bzrdir.root_transport.base
34
if working and branch:
35
working_path = working.bzrdir.root_transport.base
36
branch_path = branch.bzrdir.root_transport.base
37
if working_path != branch_path:
38
# lightweight checkout
39
ret['lightcoroot'] = working_path
40
if repository.is_shared():
41
# lightweight checkout of branch in shared repository
42
ret['sharedrepo'] = repository_path
43
ret['repobranch'] = _repo_relpath(repository_path, branch_path)
45
# lightweight checkout of standalone branch
46
ret['cobranch'] = branch_path
47
elif repository.is_shared():
48
# branch with tree inside shared repository
49
ret['sharedrepo'] = repository_path
50
ret['repoco'] = _repo_relpath(repository_path, branch_path)
51
elif branch.get_bound_location():
53
ret['coroot'] = working_path
54
ret['cobranch'] = branch.get_bound_location()
57
ret['branchroot'] = working_path
59
branch_path = branch.bzrdir.root_transport.base
60
if repository.is_shared():
61
# branch is part of shared repository
62
ret['sharedrepo'] = repository_path
63
ret['repobranch'] = _repo_relpath(repository_path, branch_path)
66
ret['branchroot'] = branch_path
69
assert repository.is_shared()
70
ret['sharedrepo'] = repository_path
74
def get_related_info(branch):
75
""" Get parent and push location of branch.
77
:return: a dictionary containing the needed infos
80
if branch.get_parent() or branch.get_push_location():
81
if branch.get_parent():
82
ret['parentbranch'] = branch.get_parent()
83
if branch.get_push_location():
84
ret['publishbranch'] = branch.get_push_location()
89
def get_format_info(control=None, repository=None, branch=None, working=None):
90
""" Get known formats for control, working, branch and repository.
92
:return: a dictionary containing the needed infos
96
ret['control'] = control._format.get_format_description()
98
ret['workingtree'] = working._format.get_format_description()
100
ret['branch'] = branch._format.get_format_description()
102
ret['repository'] = repository._format.get_format_description()
107
def get_locking_info(repository, branch=None, working=None):
108
""" Get locking status of working, branch and repository.
110
:return: a dictionary containing the needed infos
113
if (repository.get_physical_lock_status() or
114
(branch and branch.get_physical_lock_status()) or
115
(working and working.get_physical_lock_status())):
117
if working.get_physical_lock_status():
121
ret['workingtree'] = status
123
if branch.get_physical_lock_status():
127
ret['branch'] = status
129
if repository.get_physical_lock_status():
133
ret['repository'] = status
137
def get_missing_revisions_branch(branch):
138
""" Get missing master revisions in branch.
140
:return: a dictionary containing the needed infos
143
# Try with inaccessible branch ?
144
master = branch.get_master_branch()
146
local_extra, remote_extra = find_unmerged(branch, master)
148
ret['missing'] = len(remote_extra)
153
def get_missing_revisions_working(working):
154
""" Get missing revisions in working tree.
156
:return: a dictionary containing the needed infos
159
branch = working.branch
160
basis = working.basis_tree()
161
work_inv = working.inventory
162
delta = diff.compare_trees(basis, working, want_unchanged=True)
163
history = branch.revision_history()
164
tree_last_id = working.last_revision()
166
if len(history) and tree_last_id != history[-1]:
167
tree_last_revno = branch.revision_id_to_revno(tree_last_id)
168
missing_count = len(history) - tree_last_revno
169
ret['missing'] = missing_count
174
def get_working_stats(working):
175
""" Get statistics about a working tree.
177
:return: a dictionary containing the needed infos
180
basis = working.basis_tree()
181
work_inv = working.inventory
182
delta = diff.compare_trees(basis, working, want_unchanged=True)
184
ret['unchanged'] = len(delta.unchanged)
185
ret['modified'] = len(delta.modified)
186
ret['added'] = len(delta.added)
187
ret['removed'] = len(delta.removed)
188
ret['renamed'] = len(delta.renamed)
190
ignore_cnt = unknown_cnt = 0
191
for path in working.extras():
192
if working.is_ignored(path):
196
ret['unknown'] = unknown_cnt
197
ret['ignored'] = ignore_cnt
200
for file_id in work_inv:
201
if work_inv.get_file_kind(file_id) == 'directory':
203
ret['subdirs'] = dir_cnt
207
def get_branch_stats(branch):
208
""" Get statistics about a branch.
210
:return: a dictionary containing the needed infos
213
repository = branch.repository
214
history = branch.revision_history()
220
committers[repository.get_revision(rev).committer] = True
221
ret['commiters'] = len(committers)
223
firstrev = repository.get_revision(history[0])
224
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
226
ret['firstrev'] = osutils.format_date(firstrev.timestamp,
229
lastrev = repository.get_revision(history[-1])
230
ret['lastrev'] = osutils.format_date(lastrev.timestamp,
235
def get_repository_stats(repository):
236
""" Get statistics about a repository.
238
:return: a dictionary containing the needed infos
241
if repository.bzrdir.root_transport.listable():
242
c, t = repository._revision_store.total_size(repository.get_transaction())
248
def diff_helper(tree, specific_files, external_diff_options,
249
old_revision_spec=None, new_revision_spec=None,
250
old_label='a/', new_label='b/', output=None):
253
:param tree: a WorkingTree
255
:param specific_files: the specific files to compare, or None
257
:param external_diff_options: if non-None, run an external diff, and pass it these options
259
:param old_revision_spec: if None, use basis tree as old revision, otherwise use the tree for the specified revision.
261
:param new_revision_spec: if None, use working tree as new revision, otherwise use the tree for the specified revision.
265
from bzrlib.diff import show_diff_trees
271
revision_id = spec.in_store(tree.branch).rev_id
272
return tree.branch.repository.revision_tree(revision_id)
274
if old_revision_spec is None:
275
old_tree = tree.basis_tree()
277
old_tree = spec_tree(old_revision_spec)
279
if new_revision_spec is None:
282
new_tree = spec_tree(new_revision_spec)
284
return show_diff_trees(old_tree, new_tree, output, specific_files,
285
external_diff_options,
286
old_label=old_label, new_label=new_label)