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