Ref - Fix not updating duplicated packages 61/172261/1
authorhyokeun <hyokeun.jeon@samsung.com>
Tue, 13 Mar 2018 04:55:58 +0000 (13:55 +0900)
committerhyokeun <hyokeun.jeon@samsung.com>
Tue, 13 Mar 2018 04:56:02 +0000 (13:56 +0900)
Problem: Manifest based ref creation have limitation.
Cause:   If previous reference have the same git repository for multiple packages,
         the next reference cannot update it properly
         because the manifest does not hold package name.
Fix:     If multiple git repository found in todo_dict
         force update related packages based on the manifest content.

Change-Id: I07a9e7da05fb6f6eab2473ec268c9237c710f798

job_ref_create_prj_obs.py

index 06ee4eb..b193588 100644 (file)
@@ -400,6 +400,74 @@ class ref_create_project_obs(object):
 
         return ret_dict
 
+    def find_single_package_info_from_remote(self, remote_build, profile, packages=None, existing=False, replace_gerrit_url=None):
+
+        """
+            "<services><service name='gbs'>" \
+            "<param name='revision'>%s</param>" \
+            "<param name='url'>%s</param>" \
+            "<param name='git-meta'>_git-meta</param>" \
+            "<param name='error-pkg'>2</param>" \
+            "</service></services>"
+        """
+        ret_dict = {}
+
+        sourceinfo = remote_build.get_sourceinfo_list(profile)
+        for package in packages:
+            if sourceinfo[package]:
+                continue
+            elif re.search("_aggregate", package):
+                continue
+            else:
+                service_file_name = "_service"
+                for _retry in [1,2,3]:
+                    sys.stdout.flush()
+                    try:
+                        remote_build.get_source_file(profile, package, service_file_name)
+                        break
+                    except Exception as err:
+                        print "WARN(double linked package?) %s: %s" % (package, repr(err))
+                        sleep(1)
+
+                content = ""
+                with open(service_file_name, 'r') as f:
+                    content = f.read()
+
+                if content:
+                    # base_url,replace_url
+                    if replace_gerrit_url is not None and ',' in replace_gerrit_url:
+                        base_url = replace_gerrit_url.split(',')[0]
+                        replace_url = replace_gerrit_url.split(',')[1]
+                        content = content.replace(base_url, replace_url)
+
+                    _git = ''
+                    _rev = ''
+                    _root = ElementTree.fromstringlist(content)
+                    for elem in _root.findall('service'):
+                        for param in elem.findall('param'):
+                            if param.get('name') == 'url':
+                                _url = param.text
+                                if len(_url.split(os.getenv('GIT_CACHE_DIR')+'/')) == 2:
+                                    _git = _url.split(os.getenv('GIT_CACHE_DIR')+'/')[1]
+                                elif len(_url.split(os.getenv('GERRIT_FETCH_URL')+'/')) == 2:
+                                    _git = _url.split(os.getenv('GIT_CACHE_DIR')+'/')[1]
+                                elif len(_url.split(os.getenv('GERRIT_SSHPORT')+'/')) == 2:
+                                    _git = _url.split(os.getenv('GERRIT_SSHPORT')+'/')[1]
+                            if param.get('name') == 'revision':
+                                _rev = param.text
+
+                    print "      [_service] O %s (%s,%s)" % (package, _git, _rev)
+                    ret_dict[package] = {'type': service_file_name, \
+                                         'content': content, \
+                                         'meta': None, \
+                                         'git': _git, \
+                                         'rev': _rev, \
+                                         'exist': existing}
+                else:
+                    print "      [_service] X %s" % (package)
+
+        return ret_dict
+
     def _update_packages(self, remote_build, build, profile, target, upload_packages):
         dbg_idx = 0
         for package in upload_packages:
@@ -467,14 +535,28 @@ class ref_create_project_obs(object):
                                                target, package)
                         print '  [_link] %s/%s -> %s/%s' % (target, link_pkg, target, package)
 
+    def _find_packages_for_the_same_repo(self, data, repo):
+        ret_list = {}
+        for item in data:
+            if 'git' in data[item] and data[item]['git']:
+                if data[item]['git'] == repo:
+                    ret_list[item] = repo
+        return ret_list
+
     def compare_with_manifest(self, todo_dict, manifest_packages):
         #TODO: If we have changed git path???
         #TODO: If manifest items are not proceeded???
         todo_dict_merge = copy.deepcopy(todo_dict)
         cnt = 0
+        compared_list = []
+        conflict_list = {}
         for item in todo_dict_merge:
             if 'git' in todo_dict_merge[item] and todo_dict_merge[item]['git'] \
                 and todo_dict_merge[item]['git'] in manifest_packages:
+                if todo_dict_merge[item]['git'] in compared_list:
+                    print 'Already exists... %s' % todo_dict_merge[item]['git']
+                    conflict_list = dict(conflict_list.items() + self._find_packages_for_the_same_repo(todo_dict_merge, todo_dict_merge[item]['git']).items())
+                compared_list.append(todo_dict_merge[item]['git'])
                 rev_my = todo_dict_merge[item]['rev']
                 rev_snapshot = manifest_packages[todo_dict_merge[item]['git']]
                 if rev_my != rev_snapshot:
@@ -489,7 +571,7 @@ class ref_create_project_obs(object):
         for k, v in todo_dict_merge.items():
             if 'exist' in v and v['exist'] == True:
                 del todo_dict_merge[k]
-        return todo_dict_merge
+        return {'merge_items': todo_dict_merge, 'conflicts': conflict_list}
 
     def run_profile_update(self, build, this_project, target):
         """ run update profile project """
@@ -693,7 +775,9 @@ class ref_create_project_obs(object):
             if not is_the_same_snapshot:
                 print "\n********"
                 print "  4) compare package project "
-                todo_dict_latest = self.compare_with_manifest(todo_dict, manifest_packages)
+                todo_dict_return = self.compare_with_manifest(todo_dict, manifest_packages)
+                todo_dict_latest = todo_dict_return["merge_items"]
+                todo_dict_conflicts = todo_dict_return["conflicts"]
                 print '\nCompare With Manifest Done at %s' % (str(datetime.now()))
                 sys.stdout.flush()
                 for td in todo_dict:
@@ -897,6 +981,7 @@ class ref_create_project_obs(object):
         else:
             src = list(refprojectlist)[-1]
             build_src = build
+
         print "src = %s , target = %s" %(src, target)
 
         print "  0) Get meta, config, package list from remote [ %s ]" % (profile)
@@ -930,6 +1015,7 @@ class ref_create_project_obs(object):
                                                  os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"), \
                                                  snapshotdir,\
                                                  "builddata/manifest"))
+
             # Changed git repo check
             git_changed_packages = []
             for x in todo_dict:
@@ -964,7 +1050,31 @@ class ref_create_project_obs(object):
  
             print "\n********"
             print "  4) compare package project "
-            todo_dict = self.compare_with_manifest(todo_dict, manifest_packages)
+            todo_dict_return = self.compare_with_manifest(todo_dict, manifest_packages)
+            todo_dict_latest = todo_dict_return["merge_items"]
+            todo_dict_conflicts = todo_dict_return["conflicts"]
+            print 'CONFLICTS:'
+            if todo_dict_conflicts is not None:
+                for cf in todo_dict_conflicts:
+                    cf_pkg = cf
+                    cf_git = todo_dict_conflicts[cf_pkg]
+                    cf_rev = manifest_packages[cf_git]
+                    print '[%s] [%s] [%s]' % (cf_pkg, cf_git, cf_rev)
+                conflict_info = self.find_single_package_info_from_remote(build, profile, packages=[q for q in todo_dict_conflicts])
+                for ci in conflict_info:
+                    ci_pkg = ci
+                    ci_git = conflict_info[ci_pkg]['git']
+                    ci_rev = manifest_packages[ci_git]
+                    old_git     = todo_dict[ci_pkg]['git']
+                    old_rev     = todo_dict[ci_pkg]['rev']
+                    old_content = todo_dict[ci_pkg]['content']
+                    new_content = old_content.replace(old_git, ci_git).replace(old_rev, ci_rev)
+                    todo_dict[ci_pkg]['git'] = ci_git
+                    todo_dict[ci_pkg]['rev'] = ci_rev
+                    todo_dict[ci_pkg]['content'] = new_content
+                    print 'Updating conflicting package info:'
+                    print ' %s: (%s)(%s) -> (%s)(%s)' % (ci_pkg, old_git, old_rev, ci_git, ci_rev)
+
             print '\nCompare With Manifest Done at %s' % (str(datetime.now()))
 
             print '\n  4-1) Final packages to be updated %d' % len(todo_dict)
@@ -999,6 +1109,7 @@ class ref_create_project_obs(object):
                         data={}
                         data['source'] = target
                         data['target'] = project.get('target')
+
                         trigger_next("REF_COPY_SYNC_%s" %(count), data)
                         count += 1