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)