~abentley/bzrtools/bzrtools.dev

147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
1
# Copyright (C) 2004 Aaron Bentley
2
# <aaron.bentley@utoronto.ca>
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
147.2.3 by Aaron Bentley
Fixed import issues w/ PyBaz
18
import pybaz
19
from pybaz.backends.baz import sequence_cmd
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
20
import re
21
22
__docformat__ = "restructuredtext"
23
__doc__ = "Utility functions to be used by commands"
147.1.24 by Robert Collins
trim fai cribbage
24
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
25
def direct_merges(merges):
26
    """Get a list of direct merges, from a list of direct and indirect
27
    
28
    :param merges: Iterator of merge patchlogs
147.1.26 by Robert Collins
be consistent about pybaz vs arch naming in the fai derived code
29
    :type merges: iter of `pybaz.Patchlog`
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
30
    :return: The direct merges
147.1.26 by Robert Collins
be consistent about pybaz vs arch naming in the fai derived code
31
    :rtype: list of `pybaz.Patchlog`
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
32
    """
33
    indirect = []
34
    direct = []
35
    logs = list(merges)
147.1.5 by Robert Collins
test and implement direct merge support of 2-in-a-row patches
36
    if not logs:
37
        return []
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
38
    for log in logs:
39
        indirect.extend([f for f in log.new_patches if f != log.revision])
147.1.7 by Robert Collins
handle inaccessible sibling archives somewhat - note version-0 is still not handled
40
        if log.continuation_of is not None:
41
            # continuations list everything in new_patches
42
            continue
43
        try:
44
            # ask baz if we can
45
            ancestor = log.revision.ancestor
46
        except pybaz.errors.ExecProblem:
47
            # baz does not know
48
            # guess
147.1.9 by Robert Collins
determine version-0 ancestors from a tree when possible
49
            if log.revision.patchlevel != 'version-0': 
50
                ancestor = namespace_previous(log.revision)
51
            else:
52
                found = False
53
                ancestor = None
54
                # ancestor might be in the tree
55
                for tree_log in pybaz.WorkingTree(log.tree).iter_logs(
56
                    log.revision.version, reverse=True):
57
                    if found:
58
                        ancestor = tree_log.revision
59
                        break
60
                    if tree_log.revision == log.revision:
61
                        found = True
62
                print "ancestor of %s is %s" % (log.revision, ancestor)
147.1.8 by Robert Collins
handle version-xxx and base-0 correctly in namespace_previous
63
        if ancestor is not None:
147.1.7 by Robert Collins
handle inaccessible sibling archives somewhat - note version-0 is still not handled
64
            indirect.append(ancestor)
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
65
    return [log for log in logs if not log.revision in indirect]
66
147.1.7 by Robert Collins
handle inaccessible sibling archives somewhat - note version-0 is still not handled
67
def namespace_previous(revision):
147.1.8 by Robert Collins
handle version-xxx and base-0 correctly in namespace_previous
68
    if revision.patchlevel == 'base-0':
69
        return None
147.1.7 by Robert Collins
handle inaccessible sibling archives somewhat - note version-0 is still not handled
70
    if revision.patchlevel == 'patch-1':
71
        return revision.version['base-0']
72
    if revision.patchlevel.startswith('patch'):
73
        level = int(revision.patchlevel[len('patch-'):]) -1
74
        return revision.version['patch-%d' % level]
75
    if revision.patchlevel == 'version-0':
76
        raise RuntimeError("cannot determine prior namespace level for a "
147.1.9 by Robert Collins
determine version-0 ancestors from a tree when possible
77
                           "version-0 patch ('%s')" % revision)
147.1.29 by Robert Collins
update to latest bzr api
78
    if revision.patchlevel == 'versionfix-1':
147.1.7 by Robert Collins
handle inaccessible sibling archives somewhat - note version-0 is still not handled
79
        return revision.version['version-0']
147.1.29 by Robert Collins
update to latest bzr api
80
    if revision.patchlevel.startswith('versionfix'):
81
        level = int(revision.patchlevel[len('versionfix-'):]) -1
82
        return revision.version['versionfix-%d' % level]
147.1.8 by Robert Collins
handle version-xxx and base-0 correctly in namespace_previous
83
    raise NotImplementedError
147.1.3 by Robert Collins
test and deliver basic pending-merges into bzr so that merging is recorded
84
147.1.24 by Robert Collins
trim fai cribbage
85
def iter_new_merges(tree, version, reverse=False):
86
    """List patchlogs that are new in this tree since the last commit.
87
88
    :param tree: The working tree to calculate new revisions in
89
    :type tree: str
90
    :param version: The version to use when determining new logs
91
    :type version: str
92
    :param reverse: If true, list backwards, from newest to oldest
93
    :type reverse: bool
94
    :return: An iterator for new revision logs in this tree
147.1.26 by Robert Collins
be consistent about pybaz vs arch naming in the fai derived code
95
    :rtype: Iterator of `pybaz.Patchlog`
147.1.24 by Robert Collins
trim fai cribbage
96
    """
147.1.26 by Robert Collins
be consistent about pybaz vs arch naming in the fai derived code
97
    assert (isinstance(version, pybaz.Version))
147.1.24 by Robert Collins
trim fai cribbage
98
    for line in _iter_new_merges(tree, version.fullname, reverse):
147.1.26 by Robert Collins
be consistent about pybaz vs arch naming in the fai derived code
99
        yield pybaz.Patchlog(line, tree)
147.1.24 by Robert Collins
trim fai cribbage
100
101
def _iter_new_merges(directory, version, reverse):
102
    """List patchlogs that are new in this tree since the last commit.
103
104
    :param directory: The working tree to calculate new revisions in
105
    :type directory: str
106
    :param version: The version to use when determining new logs
107
    :type version: str
108
    :param reverse: If true, list backwards, from newest to oldest
109
    :type reverse: bool
110
    :return: An iterator for names of revisions new in this tree
111
    :rtype: Iterator of str
112
    """
113
    args = [ 'new-merges', '--dir', directory ]
114
    if reverse: 
115
        args.append('--reverse')
116
    args.append(version)
117
    return sequence_cmd(args)