1 |
commit: 2e76c1e480434d43b6be4ade11d6ebd7a7025718 |
2 |
Author: Andre Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Tue May 29 17:06:35 2012 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Tue May 29 17:06:35 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=2e76c1e4 |
7 |
|
8 |
roverlay, ebuildcreator: module that accepts package_files, schedules their processing into jobs and returns ebuilds (but is todo) |
9 |
modified: ebuildcreator.py |
10 |
|
11 |
--- |
12 |
roverlay/ebuildcreator.py | 356 +++++++-------------------------------------- |
13 |
1 files changed, 54 insertions(+), 302 deletions(-) |
14 |
|
15 |
diff --git a/roverlay/ebuildcreator.py b/roverlay/ebuildcreator.py |
16 |
index fa648b8..f439c71 100644 |
17 |
--- a/roverlay/ebuildcreator.py |
18 |
+++ b/roverlay/ebuildcreator.py |
19 |
@@ -1,350 +1,102 @@ |
20 |
-# R Overlay -- ebuild creation |
21 |
+# R Overlay -- ebuild creation, "master" module |
22 |
# Copyright 2006-2012 Gentoo Foundation |
23 |
# Distributed under the terms of the GNU General Public License v2 |
24 |
|
25 |
-# temporary import until logging is implemented |
26 |
-from sys import stderr as logging |
27 |
+from roverlay import ebuildjob.EbuildJob |
28 |
|
29 |
-# temporary import until config and real constants are implemented |
30 |
-from roverlay import tmpconst as const |
31 |
|
32 |
-from roverlay.fileio import DescriptionReader |
33 |
- |
34 |
-# misc TODO notes: |
35 |
-# * could use caching via decorators instead of wrappers (-> later) |
36 |
-# * instead of including the ebuild header in every ebuild 'export' data: |
37 |
-# ** link that header |
38 |
-# ** ebuild_export = [ <header_link>, str, [,str]* ] |
39 |
-# |
40 |
+class EbuildCreator: |
41 |
|
42 |
-class Ebuild: |
43 |
- # could move this to const |
44 |
- EBUILD_INDENT = "\t" |
45 |
|
46 |
- # reading every ebuild header file (copyright, inherit <eclass>) once at most |
47 |
- # <ebuild header file> => [<content of this file>] |
48 |
- # shared among all ebuilds |
49 |
- ebuild_headers = dict() |
50 |
|
51 |
@classmethod |
52 |
def __init__ ( self ): |
53 |
- """Initializes an empty Ebuild. This is an object that can be used to |
54 |
- create text lines for an ebuild file.""" |
55 |
- |
56 |
- #self.name = '' |
57 |
- #self.version = '' |
58 |
- #self.origin = '' |
59 |
- #self.pkg_file = '' |
60 |
- #self.depend = '' |
61 |
- #self.rdepend = '' |
62 |
- #self.rsuggests = '' |
63 |
- #self.description = '' |
64 |
+ """Initializes an EbuildCreator. This is an Object that controls the |
65 |
+ R package -> ebuild creation. It continuously creates EbuildJobs for |
66 |
+ every R package added. |
67 |
+ """ |
68 |
+ self.ebuild_headers = dict () |
69 |
+ self.depresolve_main = None # TODO |
70 |
+ self.ebuild_jobs = [] |
71 |
|
72 |
- # temporary var |
73 |
- #self.TODO = '' |
74 |
+ # --- end of init (...) --- |
75 |
|
76 |
- # this will be a list of str when exported data have been calculated |
77 |
- self._ebuild_export = None |
78 |
|
79 |
@classmethod |
80 |
- def get_ebuild ( self, description_data, force_update=False ): |
81 |
- """ |
82 |
- Wrapper function that returns ebuild 'export' data. |
83 |
- This is a list of str that has no newline chars at the end of each str. |
84 |
+ def add_package ( self, package_file ): |
85 |
+ """Adds an R package to the EbuildCreator, which means that an EbuildJob |
86 |
+ will be created for it. Returns the EbuildJob, which is also stored |
87 |
+ in the job queue. |
88 |
|
89 |
arguments: |
90 |
- * force_update -- force calculation of export data |
91 |
- |
92 |
+ * package_file -- path R package file |
93 |
""" |
94 |
- if force_update or (self._ebuild_export is None): |
95 |
- self._ebuild_export = self._make_export ( description_data ) |
96 |
+ new_job = EbuildJob ( package_file, self.get_resolver ( False ) ) |
97 |
|
98 |
- return self._ebuild_export |
99 |
+ self.ebuild_jobs.append ( new_job ) |
100 |
|
101 |
- @classmethod |
102 |
- def suggest_filename ( self ): |
103 |
- """Suggests a file name for the ebuild. |
104 |
- Calculated using ebuild data, but TODO |
105 |
- """ |
106 |
- # name-version |
107 |
- return None |
108 |
+ return new_job |
109 |
+ |
110 |
+ # --- end of add_package (...) --- |
111 |
|
112 |
@classmethod |
113 |
- def write_ebuild ( self, file_to_write, force_update=False ): |
114 |
- """Writes this ebuild into a file |
115 |
+ def get_resolver ( self, readonly=True ): |
116 |
+ """Returns a communication channel to the dependency resolver. |
117 |
|
118 |
arguments: |
119 |
- * file_to_write -- path of the file to write (will be overwritten if existent) |
120 |
- * force_update -- force calculation of ebuild data, don't use cached results |
121 |
- |
122 |
- **TODO notes : mkdir -p $(dirname) |
123 |
+ readonly -- whether the channel is listen-only (no write methods) or not |
124 |
+ defaults to True |
125 |
""" |
126 |
- try: |
127 |
- # try to get the ebuild lines before opening the file |
128 |
- line = None |
129 |
- # append newline here or add in _make_export() |
130 |
- lines = [ line + "\n" for line in self.get_ebuild ( force_update ) ] |
131 |
- del line |
132 |
- |
133 |
- fh = open ( file_to_write, 'w' ) |
134 |
- fh.writelines ( lines ) |
135 |
- fh.close () |
136 |
- |
137 |
- del lines, fh |
138 |
- return True |
139 |
- except IOError as err: |
140 |
- raise |
141 |
- |
142 |
- # catch failure |
143 |
- return False |
144 |
- |
145 |
- @classmethod |
146 |
- def _make_ebuild_lines ( self, ebuild_content ): |
147 |
- ebuild_export = [] |
148 |
- last_line_empty = False |
149 |
- line = None |
150 |
- |
151 |
- # remove repeated newlines ('repoman sez: ...') |
152 |
- for line in ebuild_content: |
153 |
- line = line.rstrip() |
154 |
- if line: |
155 |
- last_line_empty = False |
156 |
- elif not last_line_empty: |
157 |
- last_line_empty = True |
158 |
- else: |
159 |
- continue |
160 |
- |
161 |
- ebuild_export.append ( line ) |
162 |
+ # <TODO> |
163 |
+ return None |
164 |
+ #return self.depresolve_main.get_channel() |
165 |
|
166 |
- del last_line_empty, line |
167 |
- return ebuild_content |
168 |
+ # --- end of get_resolver (...) --- |
169 |
|
170 |
+ @classmethod |
171 |
+ def run ( self ): |
172 |
+ """Tells all EbuildJobs to run.""" |
173 |
+ for job in self.ebuild_jobs: |
174 |
+ job.run() |
175 |
|
176 |
+ @classmethod |
177 |
+ def collect_ebuilds ( self ): |
178 |
+ """Returns all ebuilds. (They may not be ready / TODO)""" |
179 |
+ return [ job.get_ebuild() for job in self.ebuild_jobs ] |
180 |
|
181 |
- @staticmethod |
182 |
- def _get_ebuild_header ( ebuild_header_file=None ): |
183 |
+ @classmethod |
184 |
+ def get_ebuild_header ( self, ebuild_header_file=None ): |
185 |
"""Reads and returns the content of an ebuild header file. |
186 |
This is a normal file that can be included in ebuilds. |
187 |
Every header file will only be read on first access, it's content will |
188 |
- be stored in a dict that is shared among all Ebuild instances. |
189 |
+ be stored in a dict that is shared among all EbuildCreator instances. |
190 |
|
191 |
arguments: |
192 |
- ebuild_header_file -- path to the header file; defaults to none which |
193 |
- means that nothing will be read and an empty list |
194 |
- is returned |
195 |
+ * ebuild_header_file -- path to the header file; defaults to none which |
196 |
+ means that nothing will be read and an empty list |
197 |
+ is returned. |
198 |
""" |
199 |
+ |
200 |
if ebuild_header_file is None: |
201 |
# nothing to read |
202 |
return [] |
203 |
|
204 |
- elif (ebuild_header_file in ebuild_headers): |
205 |
+ elif ebuild_header_file in self.ebuild_headers: |
206 |
# previously read |
207 |
- return ebuild_headers [ebuild_header_file] |
208 |
+ return self.ebuild_headers [ebuild_header_file] |
209 |
|
210 |
else: |
211 |
- # do read |
212 |
+ # read file |
213 |
try: |
214 |
- fh = open (ebuild_header_file, 'rU') |
215 |
+ fh = open ( ebuild_header_file, 'r' ) |
216 |
lines = fh.readlines() |
217 |
fh.close() |
218 |
- ebuild_headers [ebuild_header_file] = lines |
219 |
- del lines, fh |
220 |
- return ebuild_headers [ebuild_header_file] |
221 |
+ self.ebuild_headers [ebuild_header_file] = lines |
222 |
+ del fh |
223 |
+ return lines |
224 |
|
225 |
except IOError as err: |
226 |
+ # todo |
227 |
raise |
228 |
|
229 |
- @staticmethod |
230 |
- def _make_var ( varname, value=None, indent_level=0 ): |
231 |
- """Returns a variable definitions that can be used in ebuilds, optionally |
232 |
- with indention. |
233 |
- |
234 |
- arguments: |
235 |
- * varname -- name of the variable (e.g. DEPEND) |
236 |
- * value -- value of the variable; an empty var (DEPEND="") will be returned |
237 |
- if unset (the default) |
238 |
- * indent_level -- indent var definition by indent_level levels |
239 |
- """ |
240 |
- |
241 |
- if value: |
242 |
- return indent_level * EBUILD_INDENT + varname + '"' + value + '"' |
243 |
- else: |
244 |
- # empty var |
245 |
- return indent_level * EBUILD_INDENT + varname + '""' |
246 |
- |
247 |
- @classmethod |
248 |
- def _make_export ( self, description_data, ebuild_header=None ): |
249 |
- """Creates ebuild data that can be written into stdout or a file |
250 |
- |
251 |
- arguments: |
252 |
- ebuild_header_file -- path to the header file; defaults to none which |
253 |
- means that nothing will be read and an empty list |
254 |
- is returned |
255 |
- """ |
256 |
- |
257 |
- # this method is todo |
258 |
- |
259 |
- if not isinstance (description_data, dict): |
260 |
- #todo |
261 |
- raise Exception ( "bad description data" ) |
262 |
- |
263 |
- errors = dict() |
264 |
- |
265 |
- ebuild_content = Ebuild._get_ebuild_header ( ebuild_header ) |
266 |
- |
267 |
- # repeated and leading empty lines will be removed later |
268 |
- ebuild_content.append ( "" ) |
269 |
- |
270 |
- # the code below this line does not work |
271 |
- return |
272 |
- #raise Exception ( "under construction ..." ) |
273 |
- |
274 |
- if self.pkg_file: |
275 |
- ebuild_content.append ( _make_var ( "PKG_FILE" , self.pkg_file ) ) |
276 |
- else: |
277 |
- # absense of a pkg source file is an error |
278 |
- errors ['PKG_FILE'] = "missing" |
279 |
- |
280 |
- if self.origin: |
281 |
- ebuild_content.append ( _make_var ( "PKG_ORIGIN", self.origin ) ) |
282 |
- else: |
283 |
- errors ['PKG_ORIGIN'] = "missing" |
284 |
- |
285 |
- ebuild_content.append ( "" ) |
286 |
- |
287 |
- if self.description: |
288 |
- ebuild_content.append ( _make_var ( "DESCRIPTION", self.TODO ) ) |
289 |
- else: |
290 |
- ebuild_content.append ( _make_var ( "DESCRIPTION", "<none>" ) ) |
291 |
- #errors ['DESCRIPTION'] = "missing" |
292 |
- |
293 |
- # determine SRC_URI (origin + pkg_file) |
294 |
- if self.pkg_file and self.origin and False: |
295 |
- # SRC_URI ~= <> + origin + pkg_file |
296 |
- ebuild_content.append ( _make_var ( "SRC_URI", "" ) ) |
297 |
- else: |
298 |
- # either RESTRICT+=" fetch" or treat missing SRC_URI as critical |
299 |
- errors ['SRC_URI'] = "missing" |
300 |
- |
301 |
- ebuild_content.append ( "" ) |
302 |
- |
303 |
- #LICENSE (!!) |
304 |
- |
305 |
- rdepend = '${DEPEND:-} ' + self.rdepend |
306 |
- |
307 |
- # inherit IUSE from eclass |
308 |
- iuse = '${IUSE:-}' |
309 |
- |
310 |
- if self.rsuggests: |
311 |
- iuse += ' R_suggests' |
312 |
- rdepend += ' R_suggests ? ${R_SUGGESTS}' |
313 |
- ebuild_content.append ( _make_var ( "R_SUGGESTS", self.rsuggests ) ) |
314 |
- |
315 |
- ebuild_content.append ( _make_var ( "IUSE", iuse ) ) |
316 |
- ebuild_content.append ( "" ) |
317 |
- |
318 |
- # DEPEND="${DEPEND:-} <pkg dependencies>" to inherit deps from eclass |
319 |
- ebuild_content.append ( _make_var ( |
320 |
- "DEPEND", '${DEPEND:-} ' + self.depend ) ) |
321 |
- |
322 |
- ebuild_content.append ( _make_var ( "RDEPEND", rdepend ) ) |
323 |
- |
324 |
- # (!!) TODO |
325 |
- if errors: |
326 |
- raise Exception ( "^^^missing components for ebuild^^^" ) |
327 |
- #return None |
328 |
- |
329 |
- return self._make_ebuild_lines ( ebuild_content ) |
330 |
- |
331 |
-class EbuildCreator: |
332 |
-# could move this to Ebuild |
333 |
- |
334 |
- @classmethod |
335 |
- def __init__ ( self, description_data ): |
336 |
- """"Initializes an EbuildCreator. |
337 |
- [todo] |
338 |
- """ |
339 |
- self._description_data = description_data |
340 |
- |
341 |
- self._ebuild = None |
342 |
- |
343 |
- @classmethod |
344 |
- def run ( self ): |
345 |
- """Tells this EbuildCreator to operate which produces an Ebuild object |
346 |
- that can later be shown or written into a file. |
347 |
- """ |
348 |
- #todo |
349 |
- self._ebuild = None |
350 |
- |
351 |
- if self._description_data is None: |
352 |
- return False |
353 |
- |
354 |
- ebuild = Ebuild() |
355 |
- dref = self._description_data |
356 |
- |
357 |
- ebuild.name = dref ['Package'] |
358 |
- ebuild.version = dref ['Version'] |
359 |
- |
360 |
- ebuild.origin = "TODO" |
361 |
- ebuild.pkg_file = "TODO" |
362 |
- |
363 |
- # depend rdepend rsuggest |
364 |
- ebuild.depend = "TODO" |
365 |
- ebuild.rdepend = "TODO" |
366 |
- ebuild.suggest = "TODO" |
367 |
- |
368 |
- if 'Description' in dref: |
369 |
- ebuild.description = dref ['Description'] |
370 |
- elif 'Title' in dref: |
371 |
- ebuild.description = dref ['Title'] |
372 |
- else: |
373 |
- ebuild.description = "<none>" |
374 |
- |
375 |
- # <dep resolution here?> |
376 |
- |
377 |
- ebuild.get_ebuild ( self._description_data ) |
378 |
- |
379 |
- # todo |
380 |
- return None |
381 |
- |
382 |
- |
383 |
- @classmethod |
384 |
- def show ( self ): |
385 |
- """Prints the ebuild to stdout/err or into log""" |
386 |
- pass |
387 |
- |
388 |
- @classmethod |
389 |
- def write ( self ): |
390 |
- """Writes the ebuild into a file""" |
391 |
- pass |
392 |
- |
393 |
- @classmethod |
394 |
- def ready ( self ): |
395 |
- """Returns true if an Ebuild has been produced, else false.""" |
396 |
- return not (self._ebuild is None) |
397 |
- |
398 |
- |
399 |
-class EbuildFactory: |
400 |
- |
401 |
- @classmethod |
402 |
- def __init__ ( self ): |
403 |
- """Initializes an ebuild factory. This continously produces EbuildCreator |
404 |
- for every get_ebuild_creator ( tarball ) call. |
405 |
- """ |
406 |
- self.desc_reader = DescriptionReader() |
407 |
- |
408 |
- @classmethod |
409 |
- def get_ebuild_creator ( self, tarball ): |
410 |
- """Creates and returns an ebuild creator that will handle |
411 |
- the data retrieved from <tarball>. |
412 |
- |
413 |
- arguments: |
414 |
- * tarball -- tarball to read |
415 |
- """ |
416 |
- data = self.desc_reader.readfile ( tarball ) |
417 |
- if data: |
418 |
- return EbuildCreator ( data ) |
419 |
- else: |
420 |
- return None |
421 |
- |
422 |
- |
423 |
+ # --- end of get_ebuild_header (...) --- |