1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """ This package implements the new update work area functionality.
21
22 """
23
24 import logging
25 import os
26 import shutil
27 import time
28 import xml.dom.minidom
29
30 import ccm
31 import ccm.extra
32 import configuration
33 import fileutils
34
35
36
37 logging.basicConfig(level=logging.INFO)
38 _logger = logging.getLogger("preparation.ccmgetinput")
39
40
41 DEFAULT_THREADS = 1
42 THREADS_MIN_TOTAL = 1
43 THREADS_MAX_TOTAL = 10
44
45
46 -def find(function, seq):
47 """Return first item in sequence where f(item) == True."""
48 for item in seq:
49 if function(item):
50 return item
51 return None
52
53
55 """ Implements an abstract preparation function. """
56
58 self._config = config
59 self._builder = builder
60
62 """ Checks if project is available in synergy. """
63 self._check_object(self._config.name)
64
66 """ Check if ccmobject exists in synergy database. """
67 session = self.get_session()
68 ccm_object = session.create(fpn)
69 if ccm_object.exists():
70 _logger.info("Checking '%s'...Ok" % fpn)
71 else:
72 _logger.info("Checking '%s'...Not Found!" % fpn)
73 raise Exception("Could not find object %s in the database." % fpn)
74
76 """ This method needs to be override by child class.
77
78 It should implement the action to achieve.
79 """
80 pass
81
83 """ Helper that retreive the session from the builder. Setting threads correctly. """
84 if self._config.has_key('host'):
85 return self._builder.session(self._config['database'], self.get_threads(), self._config['host'], self._config['dbpath'])
86 return self._builder.session(self._config['database'], self.get_threads())
87
96
97
99 """ Implements a Snapshot preparation function.
100
101 Support the parallel snapshotter.
102 """
103
107
109 """ Method that implements snapshoting of the project into a folder. """
110 _logger.info("=== Stage=snapshot = %s" % self._config.name)
111 _logger.info("++ Started at %s" % time.strftime("%H:%M:%S", time.localtime()))
112 session = self.get_session()
113 project = session.create(self._config.name)
114
115 target_dir = os.path.join(self._config['dir'], project.name)
116 if not self._check_version(target_dir):
117 if (not os.path.exists(target_dir)):
118 _logger.info("Creating '%s'." % target_dir)
119 os.makedirs(target_dir)
120 else:
121 _logger.info("Project needs to be updated, so deleting '%s'." % target_dir)
122 fileutils.rmtree(target_dir)
123
124 try:
125 _logger.info("Snapshotting project.")
126 if self.get_threads() == 1:
127 _logger.info(project.snapshot(target_dir, True))
128 else:
129 _logger.info(ccm.extra.FastSnapshot(project, target_dir, self.get_threads()))
130
131
132 _logger.info("Saving project version information.")
133 versionfile = open(os.path.join(self._config['dir'], project.name, 'project.version'), "w+")
134 versionfile.write(str(project))
135 versionfile.close()
136 except Exception, exc:
137 if isinstance(exc, ccm.extra.CCMExtraException):
138 for sexc in exc.subexceptions:
139 _logger.info(sexc)
140 _logger.info("ERROR: snapshotting %s" % self._config.name)
141 _logger.info(exc)
142 raise exc
143 else:
144 _logger.info("Project snapshot is still up to date. Nothing to do.")
145
146 _logger.info("++ Finished at %s" % time.strftime("%H:%M:%S", time.localtime()))
147
149 """ Check the version file for snaphot and identify if the project has to be snapshot or not.
150 Returns True if the content of the file matches the project to snapshot (nothing to do).
151 Returns falls either if the file is missing, or the content is different.
152 """
153 versionfile = os.path.join(targetdir,'project.version')
154 if (os.path.exists(versionfile)):
155 file_ = open(versionfile, "r")
156 projectname = file_.read().strip()
157 file_.close()
158 if (projectname == self._config.name):
159 return True
160 return False
161
162
164 """ Handle the checkout and update of project content. """
168
200
202 """ Creates a checkout of the project, or updates an existing checkout if one is found.
203
204 The work area is maintained as part of this.
205 """
206 _logger.info("=== Stage=checkout = %s" % self._config.name)
207 _logger.info("++ Started at %s" % time.strftime("%H:%M:%S", time.localtime()))
208 session = self.get_session()
209 project = session.create(self._config.name)
210
211 session.home = self._config['dir']
212
213 result = self.__find_project(project)
214
215 if (result != None):
216 _logger.info("Project found: '%s'" % result)
217
218
219 self.__setup_project(project, result)
220 else:
221 _logger.info("Checking out from '%s'." % project)
222
223 purpose = None
224 if self._config.has_key('purpose'):
225 purpose = self._config['purpose']
226 _logger.info("Using purpose: '%s'" % purpose)
227
228 version = None
229 if self._config.has_key('version'):
230 version = self._config['version']
231 _logger.info("Using version: '%s'" % version)
232
233 try:
234 result = project.checkout(session.create(self._config['release']), version=version, purpose=purpose)
235 ccm.log_result(result, ccm.CHECKOUT_LOG_RULES, _logger)
236 except ccm.CCMException, exc:
237 ccm.log_result(exc.result, ccm.CHECKOUT_LOG_RULES, _logger)
238 raise exc
239 _logger.info('Checkout complete')
240
241 if result.project != None and result.project.exists():
242 _logger.info("Project checked out: '%s'" % result.project)
243
244
245 _logger.info("Maintaining the workarea...")
246 if self.get_threads() == 1:
247 _logger.info(result.project.work_area(True, True, True, self._config['dir'], result.project.name))
248 else:
249
250 _logger.info(ccm.extra.FastMaintainWorkArea(result.project, self._config['dir'], result.project.name, self.get_threads()))
251 self.__setup_project(project, result.project)
252 else:
253 raise Exception("Error checking out '%s'" % project)
254 _logger.info("++ Finished at %s" % time.strftime("%H:%M:%S", time.localtime()))
255
275
277 """ Private method. """
278 session = self.get_session()
279 role = session.role
280 if self._config.has_key('purpose'):
281 co_role = ccm.get_role_for_purpose(session, self._config['purpose'])
282 _logger.info("Switching user to role: %s" % co_role)
283 session.role = co_role
284
285 newprojs = []
286 if not self._config.get_boolean('use.reconfigure.template', False):
287 _logger.info("Validating release")
288 self.__set_release(coproject)
289 _logger.info("Setting update properties to manual")
290 coproject.set_update_method('manual', True)
291 _logger.info("Setting the baseline to '%s'" % project)
292 coproject.set_baseline(project, True)
293 self.__set_subbaselines(coproject)
294 _logger.info("Cleaning up update properties")
295 self._clean_update_properties(coproject)
296 _logger.info("Setting update properties.")
297 self._set_tasks_and_folders(coproject)
298 _logger.info("Applying update properties.")
299 coproject.apply_update_properties(baseline=False)
300 else:
301 _logger.info("Validating release")
302 self.__set_release(coproject)
303
304 replace_subprojects = True
305 if not self._config.get_boolean('replace.subprojects', True):
306 _logger.info("NOT replacing subprojects")
307 replace_subprojects = False
308 update_keepgoing = True
309 if self._config.get_boolean('update.failonerror', False):
310 _logger.info("The build will fail with update errors")
311 update_keepgoing = False
312 _logger.info("Updating...")
313 result = coproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(coproject.session))
314
315 if self._config.get_boolean('fix.missing.baselines', False) and replace_subprojects:
316 newprojs = self.__fix_baseline(coproject)
317 if len(newprojs) > 0:
318 result = coproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(coproject.session))
319 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
320 _logger.info("Detected additional projects into baseline - Maintaining the whole toplevel project again...")
321 coproject.work_area(True, True)
322 else:
323 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
324 else:
325 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
326
327
328 self._sync(coproject)
329
330
331 self._check_conflicts(coproject)
332
333 _logger.info("Switching user to role: %s" % role)
334 session.role = role
335
336 - def _sync(self, coproject):
344
345
355
357 """ Check for project in a different status, then check them out. """
358 newprojs = []
359 _logger.info("Looking for new projects in the check out.")
360 status = coproject['status']
361 for subproj in coproject.subprojects:
362 if subproj['status'] == status:
363 continue
364 _logger.info("New project detected in the checkout '%s'" % subproj.objectname)
365 purpose = None
366 if self._config.has_key('purpose'):
367 purpose = self._config['purpose']
368 _logger.info("Using purpose: '%s'" % purpose)
369
370 version = None
371 if self._config.has_key('version'):
372 version = self._config['version']
373 _logger.info("Using version: '%s'" % version)
374
375 result = subproj.checkout(subproj.session.create(self._config['release']), version=version, purpose=purpose, subprojects=False)
376 _logger.info('Checkout complete')
377 if result.project != None and result.project.exists():
378 newcop = result.project
379 newprojs.append(newcop)
380
381 _logger.info("Setting is_relative to true")
382 if "is_relative" in newcop.keys():
383 newcop["is_relative"] = "TRUE"
384 else:
385 newcop.create_attribute("is_relative", "boolean", "TRUE")
386
387 if not self._config.get_boolean('use.reconfigure.template', False):
388 newcop.set_update_method('manual', False)
389
390 _logger.info("Setting the baseline to '%s'" % subproj)
391 newcop.set_baseline(subproj, True)
392
393 _logger.info("Cleaning up update properties")
394 self._clean_update_properties(newcop)
395
396 _logger.info("Setting update properties.")
397 self._set_tasks_and_folders(newcop)
398 return newprojs
399
407
408
409
410
411
412
413
414 @staticmethod
421
422 @staticmethod
424 """ Private method. """
425 for subproj in subprojects:
426 if subproj.is_same_family(project):
427 return subproj
428 raise Exception("Error could not identify check out project for '%s'" % project)
429
439
441 """ Private method. """
442 result = []
443 if (self._config.has_key(key)):
444 if isinstance(self._config[key], type([])):
445 for value in self._config[key]:
446 value = value.strip()
447 if len(value) > 0:
448 result.append(value)
449 else:
450 value = self._config[key].strip()
451 if len(value) > 0:
452 result.append(value)
453 return result
454
456 """ Private method. """
457 return self.__get_array('subbaselines')
458
460 """ Private method. """
461 return self.__get_array('tasks')
462
464 """ Private method. """
465 return self.__get_array('folders')
466
475
477 """ Synergy project updater. """
478
482
494
496 """ Updating the mentioned project. """
497
498 session = self.get_session()
499 ccmproject = session.create(self._config.name)
500 role = session.role
501
502 status = ccmproject['status']
503 co_role = ccm.get_role_for_status(session, status)
504 session.role = co_role
505
506 if not self._config.get_boolean('use.reconfigure.template', False):
507 _logger.info("Setting update properties to manual")
508 ccmproject.set_update_method('manual', True)
509 _logger.info("Cleaning up update properties")
510 self._clean_update_properties(ccmproject)
511 _logger.info("Setting update properties.")
512 self._set_tasks_and_folders(ccmproject)
513 _logger.info("Applying update properties.")
514 ccmproject.apply_update_properties(baseline=False)
515 replace_subprojects = True
516 if not self._config.get_boolean('replace.subprojects', True):
517 _logger.info("NOT replacing subprojects")
518 replace_subprojects = False
519 update_keepgoing = True
520 if self._config.get_boolean('update.failonerror', False):
521 _logger.info("The build will fail with update errors")
522 update_keepgoing = False
523
524 _logger.info("Updating %s..." % ccmproject.objectname)
525 result = ccmproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(ccmproject.session))
526 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
527
528 self._sync(ccmproject)
529
530 self._check_conflicts(ccmproject)
531
532 session.role = role
533
535 """ Creates an updated work area from a configuration. """
536 - def __init__(self, configs, username = None, password = None, cache=None):
551
553 """ Check that all dependencies are there. """
554 for action in self._actions:
555 action.check()
556
557 - def get_content(self):
558 """ Run the each action. """
559 for action in self._actions:
560 action.execute()
561
562 - def session(self, database, size=1, engine=None, dbpath=None):
580
582 """ This is the preparation cleanup method.
583 It closes all opened sessions.
584 """
585 _logger.debug("Closing sessions...")
586 dbs = self._sessions.keys()
587 while len(dbs) > 0:
588 session = self._sessions.pop(dbs.pop())
589 session.close()
590 self.__provider.close()
591 self.__provider = None
592
593
596