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
31
from bzrlib.missing import find_unmerged
33
def _repo_rel_url(repo_url, inner_url):
34
"""Return path with common prefix of repository path removed.
36
If path is not part of the repository, the original path is returned.
37
If path is equal to the repository, the current directory marker '.' is
39
Otherwise, a relative path is returned, with trailing '/' stripped.
41
inner_url = urlutils.normalize_url(inner_url)
42
repo_url = urlutils.normalize_url(repo_url)
43
if inner_url == repo_url:
45
result = urlutils.relative_url(repo_url, inner_url)
46
if result != inner_url:
47
result = result.rstrip('/')
50
def get_location_info(repository, branch=None, working=None):
51
""" Get known locations for working, branch and repository.
53
:return: a dictionary containing the needed infos
56
repository_path = repository.bzrdir.root_transport.base
57
if working and branch:
58
working_path = working.bzrdir.root_transport.base
59
branch_path = branch.bzrdir.root_transport.base
60
if working_path != branch_path:
61
# lightweight checkout
62
ret['lightcoroot'] = working_path
63
if repository.is_shared():
64
# lightweight checkout of branch in shared repository
65
ret['sharedrepo'] = repository_path
66
ret['repobranch'] = _repo_rel_url(repository_path, branch_path)
68
# lightweight checkout of standalone branch
69
ret['cobranch'] = branch_path
70
elif repository.is_shared():
71
# branch with tree inside shared repository
72
ret['sharedrepo'] = repository_path
73
ret['repoco'] = _repo_rel_url(repository_path, branch_path)
74
elif branch.get_bound_location():
76
ret['coroot'] = working_path
77
ret['cobranch'] = branch.get_bound_location()
80
ret['branchroot'] = working_path
82
branch_path = branch.bzrdir.root_transport.base
83
if repository.is_shared():
84
# branch is part of shared repository
85
ret['sharedrepo'] = repository_path
86
ret['repobranch'] = _repo_rel_url(repository_path, branch_path)
89
ret['branchroot'] = branch_path
92
assert repository.is_shared()
93
ret['sharedrepo'] = repository_path
97
def get_related_info(branch):
98
""" Get parent and push location of branch.
100
:return: a dictionary containing the needed infos
103
if branch.get_parent() or branch.get_push_location():
104
if branch.get_parent():
105
ret['parentbranch'] = branch.get_parent()
106
if branch.get_push_location():
107
ret['publishbranch'] = branch.get_push_location()
112
def get_format_info(control=None, repository=None, branch=None, working=None):
113
""" Get known formats for control, working, branch and repository.
115
:return: a dictionary containing the needed infos
119
ret['control'] = control._format.get_format_description()
121
ret['workingtree'] = working._format.get_format_description()
123
ret['branch'] = branch._format.get_format_description()
125
ret['repository'] = repository._format.get_format_description()
130
def get_locking_info(repository, branch=None, working=None):
131
""" Get locking status of working, branch and repository.
133
:return: a dictionary containing the needed infos
136
if (repository.get_physical_lock_status() or
137
(branch and branch.get_physical_lock_status()) or
138
(working and working.get_physical_lock_status())):
140
if working.get_physical_lock_status():
144
ret['workingtree'] = status
146
if branch.get_physical_lock_status():
150
ret['branch'] = status
152
if repository.get_physical_lock_status():
156
ret['repository'] = status
160
def get_missing_revisions_branch(branch):
161
""" Get missing master revisions in branch.
163
:return: a dictionary containing the needed infos
166
# Try with inaccessible branch ?
167
master = branch.get_master_branch()
169
local_extra, remote_extra = find_unmerged(branch, master)
171
ret = len(remote_extra)
176
def get_missing_revisions_working(working):
177
""" Get missing revisions in working tree.
179
:return: a dictionary containing the needed infos
181
if (bzrlib.version_info[0] == 0) and (bzrlib.version_info[1] < 9):
182
# function deprecated after 0.9
183
from bzrlib.delta import compare_trees
186
branch = working.branch
187
basis = working.basis_tree()
189
if (bzrlib.version_info[0] == 0) and (bzrlib.version_info[1] < 9):
190
delta = compare_trees(basis, working, want_unchanged=True)
192
delta = working.changes_from(basis, want_unchanged=True)
194
history = branch.revision_history()
195
tree_last_id = working.last_revision()
197
if len(history) and tree_last_id != history[-1]:
198
tree_last_revno = branch.revision_id_to_revno(tree_last_id)
199
missing_count = len(history) - tree_last_revno
205
def get_working_stats(working):
206
""" Get statistics about a working tree.
208
:return: a dictionary containing the needed infos
210
if (bzrlib.version_info[0] == 0) and (bzrlib.version_info[1] < 9):
211
# function deprecated after 0.9
212
from bzrlib.delta import compare_trees
215
basis = working.basis_tree()
217
if (bzrlib.version_info[0] == 0) and (bzrlib.version_info[1] < 9):
218
delta = compare_trees(basis, working, want_unchanged=True)
220
delta = working.changes_from(basis, want_unchanged=True)
222
ret['unchanged'] = len(delta.unchanged)
223
ret['modified'] = len(delta.modified)
224
ret['added'] = len(delta.added)
225
ret['removed'] = len(delta.removed)
226
ret['renamed'] = len(delta.renamed)
228
ignore_cnt = unknown_cnt = 0
229
for path in working.extras():
230
if working.is_ignored(path):
234
ret['unknown'] = unknown_cnt
235
ret['ignored'] = ignore_cnt
238
for path, ie in working.iter_entries_by_dir():
239
if ie.kind == 'directory':
241
ret['subdirs'] = dir_cnt
245
def get_branch_stats(branch):
246
""" Get statistics about a branch.
248
:return: a dictionary containing the needed infos
251
repository = branch.repository
252
history = branch.revision_history()
258
committers[repository.get_revision(rev).committer] = True
259
ret['commiters'] = len(committers)
261
firstrev = repository.get_revision(history[0])
262
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
264
ret['firstrev'] = osutils.format_date(firstrev.timestamp,
267
lastrev = repository.get_revision(history[-1])
268
ret['lastrev'] = osutils.format_date(lastrev.timestamp,
273
def get_repository_stats(repository):
274
""" Get statistics about a repository.
276
:return: a dictionary containing the needed infos
279
if repository.bzrdir.root_transport.listable():
280
c, t = repository._revision_store.total_size(repository.get_transaction())
286
def diff_helper(tree, specific_files, external_diff_options,
287
old_revision_spec=None, new_revision_spec=None,
288
old_label='a/', new_label='b/', output=None):
291
:param tree: a WorkingTree
293
:param specific_files: the specific files to compare, or None
295
:param external_diff_options: if non-None, run an external diff, and pass it these options
297
:param old_revision_spec: if None, use basis tree as old revision, otherwise use the tree for the specified revision.
299
:param new_revision_spec: if None, use working tree as new revision, otherwise use the tree for the specified revision.
303
from bzrlib.diff import show_diff_trees
309
revision_id = spec.in_store(tree.branch).rev_id
310
return tree.branch.repository.revision_tree(revision_id)
312
if old_revision_spec is None:
313
old_tree = tree.basis_tree()
315
old_tree = spec_tree(old_revision_spec)
317
if new_revision_spec is None:
320
new_tree = spec_tree(new_revision_spec)
322
return show_diff_trees(old_tree, new_tree, output, specific_files,
323
external_diff_options,
324
old_label=old_label, new_label=new_label)