buildframework/helium/sf/python/pythoncore/lib/preparation.py
changeset 587 85df38eb4012
child 588 c7c26511138f
child 618 df88fead2976
equal deleted inserted replaced
217:0f5e3a7fb6af 587:85df38eb4012
       
     1 #============================================================================ 
       
     2 #Name        : preparation.py 
       
     3 #Part of     : Helium 
       
     4 
       
     5 #Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     6 #All rights reserved.
       
     7 #This component and the accompanying materials are made available
       
     8 #under the terms of the License "Eclipse Public License v1.0"
       
     9 #which accompanies this distribution, and is available
       
    10 #at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    11 #
       
    12 #Initial Contributors:
       
    13 #Nokia Corporation - initial contribution.
       
    14 #
       
    15 #Contributors:
       
    16 #
       
    17 #Description:
       
    18 #===============================================================================
       
    19 
       
    20 """ This package implements the new update work area functionality.
       
    21 
       
    22 """
       
    23 
       
    24 import logging
       
    25 import os
       
    26 import time
       
    27 
       
    28 import ccm
       
    29 import ccm.extra
       
    30 import fileutils
       
    31 
       
    32 # Uncomment this line to enable logging in this module, or configure logging elsewhere
       
    33 logging.basicConfig(level=logging.INFO)
       
    34 _logger = logging.getLogger("preparation.ccmgetinput")
       
    35 
       
    36 
       
    37 DEFAULT_THREADS = 1
       
    38 THREADS_MIN_TOTAL = 1
       
    39 THREADS_MAX_TOTAL = 10
       
    40 
       
    41 
       
    42 def find(function, seq):
       
    43     """Return first item in sequence where f(item) == True."""
       
    44     for item in seq:
       
    45         if function(item): 
       
    46             return item
       
    47     return None
       
    48 
       
    49 
       
    50 class PreparationAction(object):
       
    51     """ Implements an abstract preparation function. """
       
    52     
       
    53     def __init__(self, config, builder):
       
    54         self._config = config
       
    55         self._builder = builder
       
    56 
       
    57     def check(self):
       
    58         """ Checks if project is available in synergy. """
       
    59         self._check_object(self._config.name)
       
    60         
       
    61     def _check_object(self, fpn):
       
    62         """ Check if ccmobject exists in synergy database. """
       
    63         session = self.get_session()
       
    64         ccm_object = session.create(fpn)
       
    65         if ccm_object.exists():
       
    66             _logger.info("Checking '%s'...Ok" % fpn)
       
    67         else:
       
    68             _logger.info("Checking '%s'...Not Found!" % fpn)
       
    69             raise Exception("Could not find  object %s in the database." % fpn)
       
    70 
       
    71     def execute(self):
       
    72         """ This method needs to be overridden by child class.
       
    73         
       
    74         It should implement the action to achieve.
       
    75         """
       
    76         pass
       
    77     
       
    78     def cleanup(self):
       
    79         """ This method needs to be overridden by child class.
       
    80             It should implement the action to achieve.
       
    81         """
       
    82         pass
       
    83         
       
    84 
       
    85     def get_session(self):
       
    86         """ Helper that retreive the session from the builder. Setting threads correctly. """
       
    87         if self._config.has_key('database'):
       
    88             return self._builder.session(self._config['database'], self.get_threads())
       
    89         if not self._config.has_key('host'):
       
    90             raise Exception("Database engine host configuration is not found")
       
    91         elif not self._config.has_key('dbpath'):
       
    92             raise Exception("Database path configuration is not found")
       
    93         else:
       
    94             return self._builder.session(None, self.get_threads(), self._config['host'], self._config['dbpath'])
       
    95 
       
    96     def get_threads(self):
       
    97         """ Returning the number of threads that should be used. """
       
    98         threads = self._config.get_int('threads', DEFAULT_THREADS)
       
    99         if threads < THREADS_MIN_TOTAL:
       
   100             threads = THREADS_MIN_TOTAL
       
   101         if threads > THREADS_MAX_TOTAL:
       
   102             threads = THREADS_MAX_TOTAL
       
   103         return threads
       
   104 
       
   105 
       
   106 class PreparationSnapshot(PreparationAction):
       
   107     """ Implements a Snapshot preparation function. 
       
   108     
       
   109     Support the parallel snapshotter.
       
   110     """
       
   111     
       
   112     def __init__(self, config, builder):
       
   113         """ Initialization. """
       
   114         PreparationAction.__init__(self, config, builder)
       
   115 
       
   116     def cleanup(self):
       
   117         """ Method that implement the cleanup of create snapshots """
       
   118         session = self.get_session()
       
   119         project = session.create(self._config.name)
       
   120 
       
   121         target_dir = os.path.normpath(os.path.join(self._config['dir'], project.name))
       
   122         _logger.info("Deleting snapshot under %s." % target_dir)
       
   123         if os.path.exists(target_dir):
       
   124             _logger.info("Deleting '%s'." % target_dir)
       
   125             fileutils.rmtree(target_dir)
       
   126         
       
   127     def execute(self):
       
   128         """ Method that implements snapshoting of the project into a folder. """        
       
   129         _logger.info("=== Stage=snapshot = %s" % self._config.name)
       
   130         _logger.info("++ Started at %s" % time.strftime("%H:%M:%S", time.localtime()))
       
   131         session = self.get_session()
       
   132         project = session.create(self._config.name)
       
   133 
       
   134         target_dir = os.path.normpath(os.path.join(self._config['dir'], project.name))
       
   135         _logger.info("Looking for snapshot under %s." % target_dir)
       
   136         if not self._check_version(project, target_dir):
       
   137             if not os.path.exists(target_dir):
       
   138                 _logger.info("Creating '%s'." % target_dir)
       
   139                 os.makedirs(target_dir)
       
   140             else:
       
   141                 _logger.info("Project needs to be updated, so deleting '%s'." % target_dir)
       
   142                 fileutils.rmtree(target_dir)
       
   143             
       
   144             try:
       
   145                 _logger.info("Snapshotting project.")                
       
   146                 if self.get_threads() == 1:                    
       
   147                     _logger.info(project.snapshot(target_dir, True))
       
   148                 else:
       
   149                     _logger.info(ccm.extra.FastSnapshot(project, target_dir, self.get_threads()))
       
   150                                     
       
   151                 # writing version file                
       
   152                 _logger.info("Saving project version information.")
       
   153                 versionfile = open(os.path.join(self._config['dir'], project.name, 'project.version'), "w+")
       
   154                 versionfile.write(str(project))
       
   155                 versionfile.close()                
       
   156             except Exception, exc:
       
   157                 if isinstance(exc, ccm.extra.CCMExtraException):
       
   158                     for sexc in exc.subexceptions:
       
   159                         _logger.info(sexc)
       
   160                 _logger.info("ERROR: snapshotting %s" % self._config.name)
       
   161                 _logger.info(exc)
       
   162                 raise exc
       
   163         else:
       
   164             _logger.info("Project snapshot is still up to date. Nothing to do.")
       
   165 
       
   166         _logger.info("++ Finished at %s" % time.strftime("%H:%M:%S", time.localtime()))
       
   167     
       
   168     def _check_version(self, project, targetdir):
       
   169         """ Check the version file for snaphot and identify if the project has to be snapshot or not.
       
   170             Returns True if the content of the file matches the project to snapshot (nothing to do).
       
   171             Returns falls either if the file is missing, or the content is different.
       
   172         """
       
   173         versionfile = os.path.join(targetdir, 'project.version')
       
   174         if (os.path.exists(versionfile)):
       
   175             file_ = open(versionfile, "r")
       
   176             projectname = file_.read().strip()
       
   177             file_.close()
       
   178             if (projectname == project.objectname):
       
   179                 return True
       
   180         return False
       
   181     
       
   182     
       
   183 class PreparationCheckout(PreparationAction):
       
   184     """ Handle the checkout and update of project content. """
       
   185     def __init__(self, config, builder):
       
   186         """ Initialization. """
       
   187         PreparationAction.__init__(self, config, builder)
       
   188         self.__role = None
       
   189 
       
   190     def check(self):
       
   191         """ Checks if all synergy resources are available. """
       
   192         PreparationAction.check(self)
       
   193         if self._config.has_key('release'):
       
   194             self._check_object(str(self._config['release']))
       
   195         else:
       
   196             raise Exception("'release' property is not defined for %s" % self._config.name)
       
   197 
       
   198         for task in self.__get_tasks():
       
   199             self._check_object("Task %s" % task)
       
   200         for folder in self.__get_folders():
       
   201             self._check_object("Folder %s" % folder)
       
   202         
       
   203         for project in self.__get_subbaselines():
       
   204             self._check_object(project)
       
   205         
       
   206         try:
       
   207             if (not os.path.exists(self._config['dir'])):
       
   208                 os.makedirs(self._config['dir'])
       
   209         except Exception:
       
   210             _logger.info("ERROR: Not able to create the synergy workarea %s " % (self._config['dir']))
       
   211             raise Exception("ERROR: Not able to create the synergy workarea %s" % self._config.name)
       
   212             
       
   213         # checking if the purpose exists
       
   214         if self._config.has_key('purpose'):
       
   215             session = self.get_session()
       
   216             purposes = session.purposes()
       
   217             if purposes.has_key(str(self._config['purpose'])):
       
   218                 _logger.info("Checking purpose '%s'...Ok" % (self._config['purpose']))
       
   219             else:
       
   220                 _logger.info("Checking purpose '%s'...Not Found!" % (self._config['purpose']))
       
   221                 raise Exception("Could not find purpose %s in the database." % self._config['purpose'])
       
   222             
       
   223             role = session.role
       
   224             co_role = ccm.get_role_for_purpose(session, str(self._config['purpose']))
       
   225             _logger.info("Try to switch user to role: %s" % co_role)
       
   226             session.role = co_role
       
   227             session.role = role
       
   228 
       
   229     def cleanup(self):
       
   230         """ Method that implement the deletion of checked out projects. """
       
   231         session = self.get_session()
       
   232         project = session.create(self._config.name)
       
   233         
       
   234         session.home = self._config['dir']
       
   235         
       
   236         result = self.__find_project(project)
       
   237         if (result != None):
       
   238             _logger.info("Project found: '%s'" % result)
       
   239             role = session.role
       
   240             co_role = ccm.get_role_for_purpose(session, str(self._config['purpose']))
       
   241             session.role = co_role
       
   242             try:
       
   243                 delResult = result.delete(recurse=True)
       
   244             finally:
       
   245                 session.role = role
       
   246             ccm.log_result(delResult, ccm.CHECKOUT_LOG_RULES, _logger)
       
   247             
       
   248 
       
   249         
       
   250     def execute(self):
       
   251         """ Creates a checkout of the project, or updates an existing checkout if one is found.
       
   252         
       
   253         The work area is maintained as part of this.
       
   254         """
       
   255         _logger.info("=== Stage=checkout = %s" % self._config.name)
       
   256         _logger.info("++ Started at %s" % time.strftime("%H:%M:%S", time.localtime()))
       
   257         session = self.get_session()
       
   258         project = session.create(self._config.name)
       
   259         
       
   260         session.home = self._config['dir']
       
   261         
       
   262         result = self.__find_project(project)
       
   263         # for testing: result = session.create("ppd_sw-fa1f5132#wbernard2:project:sa1spp#1")
       
   264         if (result != None):
       
   265             _logger.info("Project found: '%s'" % result)
       
   266 
       
   267             # setting up the project
       
   268             self.__setup_project(project, result)
       
   269         else:
       
   270             _logger.info("Checking out from '%s'." % project)
       
   271             
       
   272             purpose = None
       
   273             if self._config.has_key('purpose'):
       
   274                 purpose = self._config['purpose']
       
   275                 _logger.info("Using purpose: '%s'" % purpose)
       
   276                 
       
   277             version = None
       
   278             if self._config.has_key('version'):
       
   279                 version = self._config['version']
       
   280                 _logger.info("Using version: '%s'" % version)
       
   281 
       
   282             try:
       
   283                 self.__setRole(session)
       
   284                 result = project.checkout(session.create(self._config['release']), version=version, purpose=purpose)
       
   285                 ccm.log_result(result, ccm.CHECKOUT_LOG_RULES, _logger)
       
   286             except ccm.CCMException, exc:
       
   287                 ccm.log_result(exc.result, ccm.CHECKOUT_LOG_RULES, _logger)
       
   288                 raise exc
       
   289             finally:
       
   290                 self.__restoreRole(session)
       
   291             _logger.info('Checkout complete')
       
   292             
       
   293             if result.project != None and result.project.exists():                
       
   294                 _logger.info("Project checked out: '%s'" % result.project)
       
   295                 
       
   296                 try:
       
   297                     self.__setRole(session)
       
   298                     _logger.info("Maintaining the workarea...")
       
   299                     if self.get_threads() == 1:
       
   300                         output = result.project.work_area(True, True, True, self._config['dir'], result.project.name)
       
   301                     else:
       
   302                         output = ccm.extra.FastMaintainWorkArea(result.project, self._config['dir'], result.project.name, self.get_threads())
       
   303                     ccm.log_result(output, ccm.CHECKOUT_LOG_RULES, _logger)
       
   304                 finally:
       
   305                     self.__restoreRole(session)
       
   306                 self.__setup_project(project, result.project)
       
   307             else:
       
   308                 raise Exception("Error checking out '%s'" % project)
       
   309 
       
   310         _logger.info("++ Finished at %s" % time.strftime("%H:%M:%S", time.localtime()))
       
   311 
       
   312     def __find_project(self, project):
       
   313         """ Private method. """
       
   314         if (os.path.exists(os.path.join(self._config['dir'], project.name, "project.version"))):
       
   315             _logger.info("Snapshot to checkout deleting '%s'." % os.path.join(self._config['dir'], project.name))
       
   316             fileutils.rmtree(os.path.join(self._config['dir'], project.name))
       
   317             return None
       
   318         
       
   319         path = os.path.join(self._config['dir'], project.name, project.name)
       
   320         try:
       
   321             result = project.session.get_workarea_info(path)
       
   322             if(result == None):
       
   323                 fileutils.rmtree(path)
       
   324                 return result
       
   325             return result['project']
       
   326         except ccm.CCMException:
       
   327             # Delete the project dir if found
       
   328             if os.path.exists(os.path.dirname(path)):
       
   329                 fileutils.rmtree(os.path.dirname(path))
       
   330             return None
       
   331 
       
   332     def __setRole(self, session):
       
   333         """ Updating the role of a session. """
       
   334         self.__role = session.role
       
   335         if self._config.has_key('purpose'):
       
   336             co_role = ccm.get_role_for_purpose(session, self._config['purpose'])
       
   337             _logger.info("Switching user to role: %s" % co_role)
       
   338             session.role = co_role
       
   339             _logger.info("Switched user to role: %s" % session._get_role())
       
   340 
       
   341     
       
   342     def __restoreRole(self, session):
       
   343         """ Restoring to default user role. """
       
   344         if self.__role:
       
   345             _logger.info("Switching user to role: %s" % self.__role)
       
   346 
       
   347             session.role = self.__role
       
   348             self.__role = None
       
   349             _logger.info("Switched user to role: %s" % session._get_role())
       
   350 
       
   351             
       
   352     def __setup_project(self, project, coproject):
       
   353         """ Private method. """
       
   354         session = self.get_session()
       
   355         self.__setRole(session)
       
   356         
       
   357         newprojs = []
       
   358         if not self._config.get_boolean('use.reconfigure.template', False):
       
   359             _logger.info("Validating release")
       
   360             self.__set_release(coproject)
       
   361             _logger.info("Setting update properties to manual")
       
   362             coproject.set_update_method('manual', True)
       
   363             _logger.info("Setting the baseline to '%s'" % project)
       
   364             coproject.set_baseline(project, True)
       
   365             self.__set_subbaselines(coproject)
       
   366             _logger.info("Cleaning up update properties")
       
   367             self._clean_update_properties(coproject)
       
   368             _logger.info("Setting update properties.")
       
   369             self._set_tasks_and_folders(coproject)
       
   370             _logger.info("Applying update properties.")
       
   371             coproject.apply_update_properties(baseline=False)
       
   372         else:
       
   373             _logger.info("Validating release")
       
   374             self.__set_release(coproject)
       
   375                         
       
   376         replace_subprojects = True
       
   377         if not self._config.get_boolean('replace.subprojects', True):
       
   378             _logger.info("NOT replacing subprojects")
       
   379             replace_subprojects = False
       
   380         update_keepgoing = True
       
   381         if self._config.get_boolean('update.failonerror', False):
       
   382             _logger.info("The build will fail with update errors")
       
   383             update_keepgoing = False
       
   384         _logger.info("Updating...")
       
   385         result = coproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(coproject.session))
       
   386         
       
   387         if self._config.get_boolean('fix.missing.baselines', False) and replace_subprojects:
       
   388             newprojs = self.__fix_baseline(coproject)
       
   389             if len(newprojs) > 0:
       
   390                 result = coproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(coproject.session))
       
   391                 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
       
   392                 _logger.info("Detected additional projects into baseline - Maintaining the whole toplevel project again...")
       
   393                 coproject.work_area(True, True)
       
   394             else:
       
   395                 ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
       
   396         else:
       
   397             ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
       
   398 
       
   399         # Running sync
       
   400         self._sync(coproject)
       
   401 
       
   402         # Running check conflicts
       
   403         self._check_conflicts(coproject)
       
   404         
       
   405         self.__restoreRole(session)
       
   406 
       
   407     def _sync(self, coproject):
       
   408         """ Run the sync if the 'sync' property is defined to true in the 
       
   409             configuration
       
   410         """
       
   411         if self._config.get_boolean('sync', False):
       
   412             _logger.info("Synchronizing...")
       
   413             result = coproject.sync(True, True)
       
   414             ccm.log_result(result, ccm.SYNC_LOG_RULES, _logger)
       
   415 
       
   416 
       
   417     def __set_release(self, project):
       
   418         """ Update the release of the project hierarchy if required. """
       
   419         release = project.session.create(self._config['release'])
       
   420         _logger.info("Current release: '%s'" % project.release)
       
   421         _logger.info("Configuration release: '%s'" % release)
       
   422         if project.release != release:
       
   423             _logger.info("Updating release on the project hierarchy.")
       
   424             for subp in [project] + project.subprojects:
       
   425                 subp.release = release
       
   426         
       
   427     def __fix_baseline(self, coproject):
       
   428         """ Check for project in a different status, then check them out. """
       
   429         newprojs = []
       
   430         _logger.info("Looking for new projects in the check out.")
       
   431         status = coproject['status']
       
   432         for subproj in coproject.subprojects:
       
   433             if subproj['status'] == status:
       
   434                 continue           
       
   435             _logger.info("New project detected in the checkout '%s'" % subproj.objectname)
       
   436             purpose = None
       
   437             if self._config.has_key('purpose'):
       
   438                 purpose = self._config['purpose']
       
   439                 _logger.info("Using purpose: '%s'" % purpose)
       
   440                 
       
   441             version = None
       
   442             if self._config.has_key('version'):
       
   443                 version = self._config['version']
       
   444                 _logger.info("Using version: '%s'" % version)
       
   445 
       
   446             result = subproj.checkout(subproj.session.create(self._config['release']), version=version, purpose=purpose, subprojects=False)
       
   447             _logger.info('Checkout complete')
       
   448             if result.project != None and result.project.exists():
       
   449                 newcop = result.project
       
   450                 newprojs.append(newcop)
       
   451                 
       
   452                 _logger.info("Setting is_relative to true")                    
       
   453                 if "is_relative" in newcop.keys():
       
   454                     newcop["is_relative"] = "TRUE"
       
   455                 else:
       
   456                     newcop.create_attribute("is_relative", "boolean", "TRUE")
       
   457                 
       
   458                 if not self._config.get_boolean('use.reconfigure.template', False):
       
   459                     newcop.set_update_method('manual', False)
       
   460                     
       
   461                     _logger.info("Setting the baseline to '%s'" % subproj)
       
   462                     newcop.set_baseline(subproj, True)
       
   463                                             
       
   464                     _logger.info("Cleaning up update properties")
       
   465                     self._clean_update_properties(newcop)
       
   466                     
       
   467                     _logger.info("Setting update properties.")
       
   468                     self._set_tasks_and_folders(newcop)
       
   469         return newprojs        
       
   470 
       
   471     def _check_conflicts(self, coproject):
       
   472         """ Private method. """
       
   473         conflictsobjects = self._config.get_boolean('show.conflicts.objects', False)
       
   474         
       
   475         if self._config.get_boolean('show.conflicts', False) or conflictsobjects:
       
   476             result = coproject.conflicts(True, not conflictsobjects)
       
   477             ccm.log_result(result, ccm.CONFLICTS_LOG_RULES, _logger)
       
   478 #        for project in result.keys():
       
   479 #            for error in result[project]:
       
   480 #                if 'object' in error:
       
   481 #                    _logger.info("CONFLICTS: %s" % error['comment'])
       
   482 #                else:
       
   483 #                    _logger.info("CONFLICTS: %s" % error['comment'])
       
   484         
       
   485     @staticmethod
       
   486     def _clean_update_properties(project):
       
   487         """ Private method. """
       
   488         for task in project.tasks:
       
   489             project.remove_task(task)        
       
   490         for folder in project.folders:
       
   491             project.remove_folder(folder)
       
   492 
       
   493     @staticmethod
       
   494     def __find_subproject(subprojects, project):
       
   495         """ Private method. """
       
   496         for subproj in subprojects:
       
   497             if subproj.is_same_family(project):
       
   498                 return subproj
       
   499         raise Exception("Error could not identify check out project for '%s'" % project)
       
   500     
       
   501     def __set_subbaselines(self, project):
       
   502         """ Private method. """
       
   503         if len(self.__get_subbaselines()) > 0:
       
   504             subprojects = project.subprojects
       
   505             for subbaseline in self.__get_subbaselines():
       
   506                 subbaseline = project.session.create(subbaseline)
       
   507                 subproj = self.__find_subproject(subprojects, subbaseline)
       
   508                 _logger.info("Setting subproject '%s' baseline to '%s'" % (subproj, subbaseline))
       
   509                 subproj.set_baseline(subbaseline, True)
       
   510     
       
   511     def __get_array(self, key):
       
   512         """ Private method. """
       
   513         result = []
       
   514         if (self._config.has_key(key)):
       
   515             if isinstance(self._config[key], type([])):                
       
   516                 for value in self._config[key]:
       
   517                     value = value.strip()
       
   518                     if len(value) > 0:
       
   519                         result.append(value) 
       
   520             else:
       
   521                 value = self._config[key].strip()
       
   522                 if len(value) > 0:
       
   523                     result.append(value)
       
   524         return result
       
   525 
       
   526     def __get_subbaselines(self):
       
   527         """ Private method. """
       
   528         return self.__get_array('subbaselines')
       
   529     
       
   530     def __get_tasks(self):
       
   531         """ Private method. """
       
   532         return self.__get_array('tasks')
       
   533 
       
   534     def __get_folders(self):
       
   535         """ Private method. """
       
   536         return self.__get_array('folders')
       
   537     
       
   538     def _set_tasks_and_folders(self, project):
       
   539         """ Private method. """
       
   540         for task in self.__get_tasks():
       
   541             _logger.info("Adding task %s" % task)
       
   542             project.add_task(project.session.create("Task %s" % task))
       
   543         for folder in self.__get_folders():
       
   544             _logger.info("Adding folder %s" % folder)
       
   545             project.add_folder(project.session.create("Folder %s" % folder))
       
   546 
       
   547 class PreparationUpdate(PreparationCheckout):
       
   548     """ Synergy project updater. """
       
   549     
       
   550     def __init__(self, config, builder):
       
   551         """ Initialization. """
       
   552         PreparationCheckout.__init__(self, config, builder)
       
   553 
       
   554     def check(self):
       
   555         """ Checks if all synergy resources are available. """
       
   556         PreparationAction.check(self)
       
   557 
       
   558         session = self.get_session()
       
   559         ccm_object = session.create(self._config.name)
       
   560         role = session.role
       
   561         co_role = ccm.get_role_for_status(ccm_object['status'])
       
   562         _logger.info("Try to switch user to role: %s" % co_role)
       
   563         session.role = co_role
       
   564         session.role = role
       
   565 
       
   566     def execute(self):
       
   567         """ Updating the mentioned project. """
       
   568 
       
   569         session = self.get_session()
       
   570         ccmproject = session.create(self._config.name)
       
   571         role = session.role
       
   572 
       
   573         status = ccmproject['status']
       
   574         co_role = ccm.get_role_for_status(status)
       
   575         session.role = co_role
       
   576 
       
   577         if not self._config.get_boolean('use.reconfigure.template', False):
       
   578             _logger.info("Setting update properties to manual")
       
   579             ccmproject.set_update_method('manual', True)
       
   580             _logger.info("Cleaning up update properties")
       
   581             self._clean_update_properties(ccmproject)
       
   582             _logger.info("Setting update properties.")
       
   583             self._set_tasks_and_folders(ccmproject)
       
   584             _logger.info("Applying update properties.")
       
   585             ccmproject.apply_update_properties(baseline=False)
       
   586         replace_subprojects = True
       
   587         if not self._config.get_boolean('replace.subprojects', True):
       
   588             _logger.info("NOT replacing subprojects")
       
   589             replace_subprojects = False
       
   590         update_keepgoing = True
       
   591         if self._config.get_boolean('update.failonerror', False):
       
   592             _logger.info("The build will fail with update errors")
       
   593             update_keepgoing = False
       
   594 
       
   595         _logger.info("Updating %s..." % ccmproject.objectname)
       
   596         result = ccmproject.update(True, replace_subprojects, update_keepgoing, result=ccm.UpdateResultSimple(ccmproject.session))
       
   597         ccm.log_result(result, ccm.UPDATE_LOG_RULES, _logger)
       
   598         
       
   599         self._sync(ccmproject)
       
   600         
       
   601         self._check_conflicts(ccmproject)
       
   602         
       
   603         session.role = role
       
   604 
       
   605 class PreparationBuilder(object):
       
   606     """ Creates an updated work area from a configuration. """
       
   607     def __init__(self, configs, username = None, password = None, cache=None):
       
   608         """ Initialization. """
       
   609         self._configs = configs
       
   610         self._sessions = {}
       
   611         self._actions = []
       
   612         self.__username = username
       
   613         self.__password = password
       
   614         self.__provider = ccm.extra.CachedSessionProvider(cache=cache)
       
   615         for config in self._configs:
       
   616             if config.type == "snapshot":
       
   617                 self._actions.append(PreparationSnapshot(config, self))
       
   618             elif config.type == "checkout":
       
   619                 self._actions.append(PreparationCheckout(config, self))        
       
   620             elif config.type == "update":
       
   621                 self._actions.append(PreparationUpdate(config, self))
       
   622         
       
   623     def check(self):
       
   624         """ Check that all dependencies are there. """
       
   625         for action in self._actions:
       
   626             action.check()
       
   627     
       
   628     def cleanup(self):
       
   629         """ Check that all dependencies are there. """
       
   630         for action in self._actions:
       
   631             action.cleanup()
       
   632 
       
   633     def get_content(self):
       
   634         """ Run the each action. """
       
   635         for action in self._actions:
       
   636             action.execute()
       
   637 
       
   638     def session(self, database, size=1, engine=None, dbpath=None):
       
   639         """ Handles pool rather that sessions. """
       
   640         assert size > 0, "The pool must contains at least one session!"
       
   641         if self.__provider is None:
       
   642             raise Exception("The builder has been closed.") 
       
   643         if not self._sessions.has_key(database):
       
   644             _logger.info("Get a session for %s" % database)
       
   645             session = ccm.SessionPool(self.__username, self.__password, engine, dbpath, database, size, opener=self.__provider.get)
       
   646             self._sessions[database] = session
       
   647             # be developer by default
       
   648             session.role = "developer"
       
   649         session = self._sessions[database]
       
   650         if session.size < size:
       
   651             _logger.info("Resizing the pool for database %s to %d" % (database, size))
       
   652             session.size = size
       
   653             # be developer by default
       
   654             session.role = "developer"
       
   655         return session
       
   656     
       
   657     def close(self):
       
   658         """ This is the preparation cleanup method.
       
   659             It closes all opened sessions.
       
   660         """
       
   661         _logger.debug("Closing sessions...")
       
   662         dbs = self._sessions.keys()
       
   663         while len(dbs) > 0:
       
   664             session = self._sessions.pop(dbs.pop())
       
   665             session.close()
       
   666         if self.__provider is not None:
       
   667             self.__provider.close()
       
   668             self.__provider = None
       
   669         
       
   670     
       
   671     def __del__(self):
       
   672         self.close()
       
   673             
       
   674         
       
   675