1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import calendar
17 from zope.interface import implements
18 from twisted.python import log
19 from twisted.internet import defer
20 from buildbot import interfaces, sourcestamp
21 from buildbot.process import properties
22 from buildbot.status.results import FAILURE
23 from buildbot.db import buildrequests
26 """
27
28 A rolled-up encapsulation of all of the data relevant to a build request.
29
30 This class is used by the C{nextBuild} and C{mergeRequests} configuration
31 parameters, as well as in starting a build. Construction of a BuildRequest
32 object is a heavyweight process involving a lot of database queries, so
33 it should be avoided where possible. See bug #1894.
34
35 Build requests have a SourceStamp which specifies what sources to build.
36 This may specify a specific revision of the source tree (so source.branch,
37 source.revision, and source.patch are used). The .patch attribute is either
38 None or a tuple of (patchlevel, diff), consisting of a number to use in
39 'patch -pN', and a unified-format context diff.
40
41 Alternatively, the SourceStamp may specify a set of Changes to be built,
42 contained in source.changes. In this case, the requeset may be mergeable
43 with other BuildRequests on the same branch.
44
45 @type source: L{buildbot.sourcestamp.SourceStamp}
46 @ivar source: the source stamp that this BuildRequest use
47
48 @type reason: string
49 @ivar reason: the reason this Build is being requested. Schedulers provide
50 this, but for forced builds the user requesting the build will provide a
51 string. It comes from the buildsets table.
52
53 @type properties: L{properties.Properties}
54 @ivar properties: properties that should be applied to this build, taken
55 from the buildset containing this build request
56
57 @ivar submittedAt: a timestamp (seconds since epoch) when this request was
58 submitted to the Builder. This is used by the CVS step to compute a
59 checkout timestamp, as well as by the master to prioritize build requests
60 from oldest to newest.
61
62 @ivar buildername: name of the requested builder
63
64 @ivar priority: request priority
65
66 @ivar id: build request ID
67
68 @ivar bsid: ID of the parent buildset
69 """
70
71 source = None
72 sources = None
73 submittedAt = None
74
75 @classmethod
77 """
78 Construct a new L{BuildRequest} from a dictionary as returned by
79 L{BuildRequestsConnectorComponent.getBuildRequest}.
80
81 This method uses a cache, which may result in return of stale objects;
82 for the most up-to-date information, use the database connector
83 methods.
84
85 @param master: current build master
86 @param brdict: build request dictionary
87
88 @returns: L{BuildRequest}, via Deferred
89 """
90 cache = master.caches.get_cache("BuildRequests", cls._make_br)
91 return cache.get(brdict['brid'], brdict=brdict, master=master)
92
93 @classmethod
94 @defer.inlineCallbacks
95 - def _make_br(cls, brid, brdict, master):
123
124 dlist = []
125 for ssdict in sslist:
126 d = sourcestamp.SourceStamp.fromSsdict(master, ssdict)
127 d.addCallback(store_source)
128 dlist.append(d)
129
130 yield defer.gatherResults(dlist)
131
132 if buildrequest.sources:
133 buildrequest.source = buildrequest.sources.values()[0]
134
135 defer.returnValue(buildrequest)
136
138 self_codebases = set(self.sources.iterkeys())
139 other_codebases = set(other.sources.iterkeys())
140 return self_codebases == other_codebases
141
143
144
145
146
147
148
149
150
151
152
153
154 self_codebases = set(self.sources.iterkeys())
155 other_codebases = set(other.sources.iterkeys())
156 if self_codebases != other_codebases:
157 return False
158
159 for c in self_codebases:
160
161 if ((len(self.sources[c].changes) > 0)
162 != (len(other.sources[c].changes) > 0)):
163 return False
164
165 return True
166
185
187 """ Returns one merged sourcestamp for every codebase """
188
189 all_codebases = set(self.sources.iterkeys())
190 for other in others:
191 all_codebases |= set(other.sources.iterkeys())
192
193 all_merged_sources = {}
194
195 for codebase in all_codebases:
196 all_sources = []
197 if codebase in self.sources:
198 all_sources.append(self.sources[codebase])
199 for other in others:
200 if codebase in other.sources:
201 all_sources.append(other.sources[codebase])
202 assert len(all_sources)>0, "each codebase should have atleast one sourcestamp"
203 all_merged_sources[codebase] = all_sources[0].mergeWith(all_sources[1:])
204
205 return [source for source in all_merged_sources.itervalues()]
206
208 """Return a reason for the merged build request."""
209 reasons = []
210 for req in [self] + others:
211 if req.reason and req.reason not in reasons:
212 reasons.append(req.reason)
213 return ", ".join(reasons)
214
217
218 @defer.inlineCallbacks
236
238 implements(interfaces.IBuildRequestControl)
239
241 self.original_builder = builder
242 self.original_request = request
243 self.brid = request.id
244
246 raise NotImplementedError
247
249 raise NotImplementedError
250
254