~lifeless/bzrtools/trunk

« back to all changes in this revision

Viewing changes to baz_helper.py

  • Committer: Robert Collins
  • Date: 2008-07-08 04:11:21 UTC
  • mfrom: (623.1.33 bzrtools)
  • Revision ID: robertc@robertcollins.net-20080708041121-lo0k7os2y03uclt2
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004 Aaron Bentley
2
 
# <aaron@aaronbentley.com>
3
 
#
4
 
#    This program is free software; you can redistribute it and/or modify
5
 
#    it under the terms of the GNU General Public License as published by
6
 
#    the Free Software Foundation; either version 2 of the License, or
7
 
#    (at your option) any later version.
8
 
#
9
 
#    This program is distributed in the hope that it will be useful,
10
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
#    GNU General Public License for more details.
13
 
#
14
 
#    You should have received a copy of the GNU General Public License
15
 
#    along with this program; if not, write to the Free Software
16
 
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 
 
18
 
import pybaz
19
 
from pybaz.backends.baz import sequence_cmd
20
 
import re
21
 
 
22
 
__docformat__ = "restructuredtext"
23
 
__doc__ = "Utility functions to be used by commands"
24
 
 
25
 
def direct_merges(merges, excludes=[]):
26
 
    """Get a list of direct merges, from a list of direct and indirect
27
 
 
28
 
    :param merges: Iterator of merge patchlogs
29
 
    :type merges: iter of `pybaz.Patchlog`
30
 
    :return: The direct merges
31
 
    :rtype: list of `pybaz.Patchlog`
32
 
    """
33
 
    indirect = set()
34
 
    logs = list(merges)
35
 
    if not logs:
36
 
        return []
37
 
    for log in logs:
38
 
        try:
39
 
            this_indirect = set([str(f) for f in log.new_patches
40
 
                                 if f != log.revision and
41
 
                                     str(f) not in indirect])
42
 
        except pybaz.errors.NamespaceError:
43
 
            print
44
 
            print "log ", log, " unusable, attempting to use archive copy."
45
 
            log = pybaz.Revision(str(log.revision)).patchlog
46
 
            this_indirect = set([str(f) for f in log.new_patches
47
 
                                 if f != log.revision and
48
 
                                     str(f) not in indirect])
49
 
        indirect.update(this_indirect)
50
 
        if log.continuation_of is not None:
51
 
            # continuations list everything in new_patches
52
 
            continue
53
 
        try:
54
 
            # ask baz if we can
55
 
            ancestor = log.revision.ancestor
56
 
        except pybaz.errors.ExecProblem:
57
 
            # baz does not know
58
 
            # guess
59
 
            if log.revision.patchlevel != 'version-0':
60
 
                ancestor = namespace_previous(log.revision)
61
 
            else:
62
 
                found = False
63
 
                ancestor = None
64
 
                # ancestor might be in the tree
65
 
                for tree_log in pybaz.WorkingTree(log.tree).iter_logs(
66
 
                    log.revision.version, reverse=True):
67
 
                    if found:
68
 
                        ancestor = tree_log.revision
69
 
                        break
70
 
                    if tree_log.revision == log.revision:
71
 
                        found = True
72
 
                print "ancestor of %s is %s" % (log.revision, ancestor)
73
 
        if ancestor is not None:
74
 
            indirect.add(str(ancestor))
75
 
    return [log.revision for log in logs if not str(log.revision) in indirect
76
 
            and log.revision not in excludes]
77
 
 
78
 
 
79
 
def namespace_previous(revision):
80
 
    if revision.patchlevel == 'base-0':
81
 
        return None
82
 
    if revision.patchlevel == 'patch-1':
83
 
        return revision.version['base-0']
84
 
    if revision.patchlevel.startswith('patch'):
85
 
        level = int(revision.patchlevel[len('patch-'):]) -1
86
 
        return revision.version['patch-%d' % level]
87
 
    if revision.patchlevel == 'version-0':
88
 
        raise RuntimeError("cannot determine prior namespace level for a "
89
 
                           "version-0 patch ('%s')" % revision)
90
 
    if revision.patchlevel == 'versionfix-1':
91
 
        return revision.version['version-0']
92
 
    if revision.patchlevel.startswith('versionfix'):
93
 
        level = int(revision.patchlevel[len('versionfix-'):]) -1
94
 
        return revision.version['versionfix-%d' % level]
95
 
    raise NotImplementedError
96
 
 
97
 
def iter_new_merges(tree, version, reverse=False):
98
 
    """List patchlogs that are new in this tree since the last commit.
99
 
 
100
 
    :param tree: The working tree to calculate new revisions in
101
 
    :type tree: str
102
 
    :param version: The version to use when determining new logs
103
 
    :type version: str
104
 
    :param reverse: If true, list backwards, from newest to oldest
105
 
    :type reverse: bool
106
 
    :return: An iterator for new revision logs in this tree
107
 
    :rtype: Iterator of `pybaz.Patchlog`
108
 
    """
109
 
    assert (isinstance(version, pybaz.Version))
110
 
    for line in _iter_new_merges(tree, version.fullname, reverse):
111
 
        yield pybaz.Patchlog(line, tree)
112
 
 
113
 
def _iter_new_merges(directory, version, reverse):
114
 
    """List patchlogs that are new in this tree since the last commit.
115
 
 
116
 
    :param directory: The working tree to calculate new revisions in
117
 
    :type directory: str
118
 
    :param version: The version to use when determining new logs
119
 
    :type version: str
120
 
    :param reverse: If true, list backwards, from newest to oldest
121
 
    :type reverse: bool
122
 
    :return: An iterator for names of revisions new in this tree
123
 
    :rtype: Iterator of str
124
 
    """
125
 
    args = [ 'new-merges', '--dir', directory ]
126
 
    if reverse:
127
 
        args.append('--reverse')
128
 
    args.append(version)
129
 
    return sequence_cmd(args)