Package ccm :: Module conflict |
[hide private]
[frames] | no frames]

# Source Code for Module ccm.conflict

      1  #============================================================================
      2  #Name        : conflict.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  """ CCM conflict detection module. """
     21
     22
     23  import threading
     24
     25  import ccm
     26  import threadpool
     27
     28
     29 -def get_tasks_from_project(project):
     30      result = []
     31      for folder in project.folders:
     32          result.extend(get_tasks(folder))
     33      result.extend(project.tasks)
     34      return result
     35
     36
     37 -def get_tasks_information_from_project(project):
     38      result = []
     39      for folder in project.folders:
     40          result.extend(get_tasks_information(folder))
     41      for task in project.tasks:
     42          query = ccm.Query(folder.session, "name= '%s'and version='%s' and type='%s'and instance='%s'" % (task.name, task.version, task.type, task.instance),
     43                            ['objectname', 'owner', 'task_synopsis', 'displayname'],
     44                            ['ccmobject', 'string', 'string', 'string'])
     45          result.extend(query.execute().output)
     46      return result
     47
     48
     49 -def get_tasks_information(folder):
     50      """ Get tasks from folder. If the folder is query based it uses the query to determine the list of task.
     51          But the folder contents itself remains untouch.
     52      """
     53      query = None
     54      if folder.is_query_based:
     55          query = ccm.Query(folder.session, "type='task' and " + folder.query,
     56                            ['objectname', 'owner', 'task_synopsis', 'displayname'],
     57                            ['ccmobject', 'string', 'string', 'string'])
     58      else:
     59          query = ccm.Query(folder.session, folder.objectname,
     60                            ['objectname', 'owner', 'task_synopsis', 'displayname'],
     61                            ['ccmobject', 'string', 'string', 'string'],
     62                            "folder -show tasks")
     63      # executing the query
     64      return query.execute().output
     65
     66
     67
     68 -def get_tasks(folder):
     69      """ Get tasks from folder. If the folder is query based it uses the query to determine the list of task.
     70          But the folder contents itself remains untouch.
     71      """
     72      if folder.is_query_based:
     73          r = folder.session.execute("query -u -t task \"%s\" -f \"%%objectname\"" % folder.query, ccm.ObjectListResult(folder.session))
     74          return r.output
     75      else:
     76          return folder.tasks
     77
     78
     79 -class ObjectAndTask:
     80      """ Wrapper object which link an object to a task. """
     81 -    def __init__(self, object, task):
     82          self.object = object
     83          self.task = task
     84          self.overridenby = []
     85
     86 -    def has_successor_in_list(self, oatl):
     87          """ Has our object any successor in the list. """
     88          for oat in oatl:
     89              if self.object.__ne__(oat.object) and oat.object.is_recursive_successor_of_fast(self.object):
     90                  self.overridenby.append(oat)
     91                  return True
     92          return False
     93
     94 -    def __repr__(self):
     95          return "<ObjectAndTask %s, %s>" % (self.object.objectname, self.task.objectname)
     96
     97
     98 -class TaskModel:
     99      """ Task wrapper object which contains objectandtask object. """
    100
    101 -    def __init__ (self, task):
    102          """ Init from task object. """
    103          self.task = task
    104          self.objectandtasks = {}
    105          for object in self.task.objects:
    106              self.objectandtasks[str(object)] = ObjectAndTask(object, task)
    107
    108 -    def is_useless(self):
    109          """ Is the task containing any usable objects. """
    110          count = 0
    111          for object in self.objectandtasks.keys():
    112              oat = self.objectandtasks[object]
    113              if len(oat.overridenby) > 0:
    114                  count += 1
    115          if len(self.objectandtasks.keys()) == 0 or count == len(self.objectandtasks.keys()):
    116              return True
    117          return False
    118
    119
    120 -def tasks_to_objectandtask(tasks):
    121      object_families = {}
    122      for task in tasks:
    123          for object in task.objects:
    124              if not object.family in object_families:
    125                  object_families[object.family] = []
    126              object_families[object.family].append(ObjectAndTask(object, task))
    127      return object_families
    128
    129
    130 -def tasks_to_families_and_taskmodels(tasks, size=1):
    131      object_families = {}
    132      taskmodels = []
    133      lock = threading.Lock()
    134
    135      def __work(task):
    136          tm = TaskModel(task)
    137
    138          lock.acquire()
    139          taskmodels.append(tm)
    140          lock.release()
    141
    142          for oatk in tm.objectandtasks.keys():
    143              oat = tm.objectandtasks[oatk]
    144              lock.acquire()
    145              if not oat.object.family in object_families:
    146                  object_families[oat.object.family] = []
    147              object_families[oat.object.family].append(oat)
    148              lock.release()
    149
    150
    151      if size > 1:
    152          pool = threadpool.ThreadPool(size)
    153          for task in tasks:
    154              pool.addWork(__work, args=[task])
    155          pool.wait()
    156      else:
    157          for task in tasks:
    158              __work(task)
    159
    160      return (object_families, taskmodels)
    161
    162
    163 -def check_task_conflicts(tasks, size=1):
    164      """ Validates objects a list of task.
    165          It returns a list of list of conflicting ObjectAndTask.
    166      """
    167
    168      object_families, taskmodels = tasks_to_families_and_taskmodels(tasks, size)
    169      conflicts = []
    170      lock = threading.Lock()
    171
    172      pool = threadpool.ThreadPool(size)
    173
    174      def __work(family):
    175          result = []
    176          for oat in object_families[family]:
    177              if oat.has_successor_in_list(object_families[family]) == False:
    178                  add = True
    179                  for roat in result:
    180                      if roat.object == oat.object:
    181                          add = False
    182                          break
    183                  if add:
    184                      result.append(oat)
    185
    186          if len(result)>1:
    187              lock.acquire()
    188              conflicts.append(result)
    189              lock.release()
    190
    191      for family in object_families.keys():
    192          pool.addWork(__work, args=[family])
    193
    194      pool.wait()
    195
    196      return conflicts, taskmodels
    197
    198
    199 -class Conflict:
    200 -    def __init__(self, baseline, comment):
    201          self.baseline = baseline
    202          self._comment = comment
    203
    204 -    def comment(self):
    205          return self._comment
    206
    207
    208 -class MultipleObjectInBaselineConflict(Conflict):
    209 -    def __init__(self, baseline, objectlist):
    210          Conflict.__init__(self, baseline, "")
    211          self.objectlist = objectlist
    212
    213 -    def comment(self):
    214          output = "Multiple objects from the same family found under the baseline (%s).\n" % self.baseline.objectname
    215          output += "\n".join(lambda x: x.objectname, self.objectlist)
    216          return output
    217
    218
    219 -class ObjectAndBaselineConflict(Conflict):
    220 -    def __init__(self, baseline, object, oat):
    221          Conflict.__init__(self, baseline, "")
    222          self.object = object
    223          self.oat = oat
    224
    225 -    def comment(self):
    226          pass
    227
    228
    229 -class ObjectNotFoundInBaselineConflict(Conflict):
    230 -    def __init__(self, baseline, object):
    231          Conflict.__init__(self, baseline, "")
    232          self.object = object
    233
    234 -    def comment(self):
    235          return "No object fom '%s' family found under the baseline." % self.object.family
    236
    237
    238 -def check_task_and_baseline_conflicts(tasks, baseline):
    239      """ Validates objects a list of task.
    240          It returns a list of list of conflicting ObjectAndTask.
    241      """
    242
    243      object_families = tasks_to_objectandtask(tasks)
    244      conflicts = []
    245
    246      for family in object_families:
    247          result = family[0].session.execute("query \"name='%s' and type='%s' and instance='%s'\" and recursive_is_member_of('%s', none) " %
    248                                                          (family[0].name, family[0].type, family[0].instance, baseline.objectname),
    249                                                          ccm.ObjectListResult(family[0].session))
    250          if len(result.output) == 1:
    251              bo = result.output[0]
    252              potential_conflicts = []
    253              for oat in family:
    254                  if bo.recursive_predecessor_of(oat.object):
    255                      potential_conflicts.append(ObjectAndBaselineConflict(baseline, bo, oat, "Conflict between baseline object and task object"))
    256              if len(family) == len(potential_conflicts):
    257                  conflicts.extend(potential_conflicts)
    258          elif len(result.output) > 1:
    259              conflicts.append(MultipleObjectInBaselineConflict(baseline, result.output))
    260          else:
    261              conflicts.append(ObjectNotFoundInBaselineConflict(baseline, family[0]))
    262