#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (c) 2014, 2015, 2016 Samsung Electronics.Co.Ltd.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; version 2 of the License
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
import os
import re
import sys
import base64
import json
import requests
import urlparse
import ast
from time import sleep
from datetime import datetime
from datetime import timedelta

import urllib2
import copy

from osc import conf, core
from common.buildservice import BuildService
from common.buildtrigger import trigger_info, trigger_next, remote_jenkins_build_job
from gitbuildsys.errors import ObsError
import xml.etree.ElementTree as ET
import xml.etree.cElementTree as ElementTree
from common.mapping import get_ref_map, get_sync_map_list
from common.gerrit import GerritEnv
from common.upload_service import UploadError

class LocalError(Exception):
    """Local error exception."""
    pass

def get_snapshot_sr_increment(src, target):
    # Select matching SR info
    # Get snapshots from dashboard db
    if True:
        n_start_date = int(src.split(':')[-1].split('.')[0])
        n_end_date = int(target.split(':')[-1].split('.')[0])
        start_version = int(src.split(':')[-1].split('.')[1])
        end_version = int(target.split(':')[-1].split('.')[1])

        start_date = datetime.strptime('%d' % n_start_date, '%Y%m%d') - timedelta(days=7)
        end_date = datetime.strptime('%d' % n_end_date, '%Y%m%d') + timedelta(days=2)
        start_date = start_date.strftime('%Y/%m/%d')
        end_date = end_date.strftime('%Y/%m/%d')

        path = os.path.join(os.getenv('PUBLIC_DASHBOARD_API_URL'),
                            'snapshot.code?start=%s&end=%s&profile_filter=%s'
                             % (start_date, end_date, target.split(':ref:')[0]))


        sys.stdout.flush()

        snapshot_history = []
        board_data = requests.get(path).text

        for line in board_data.replace('\\n', '').replace('\\', '').replace('null','""').split('\n'):
            if line is None or line == '' or len(line) <= 0:
                continue
            full_list = ast.literal_eval(line)
            # Make sure ordering
            full_list = sorted(full_list, key=lambda k:k['start_time'], reverse=False)
            for sn in full_list:
                sr_count = 0
                if sn.get('project_name', None) == target.split(':ref:')[0]:# and sn.get('snapshot_url', None):
                    this_date = int(sn.get('snapshot_name').split('_')[-1].split('.')[0])
                    this_version = int(sn.get('snapshot_name').split('_')[-1].split('.')[1])
                    # Skip older/newer ones
                    if n_start_date > this_date: continue
                    if n_start_date == this_date and start_version >= this_version: continue
                    if n_end_date < this_date: continue
                    if n_end_date == this_date and end_version < this_version: continue

                    path = os.path.join(os.getenv('PUBLIC_DASHBOARD_API_URL'),
                                                  'snapshot.code?snapshot=%s' % (sn.get('snapshot_name')))
                    srs_in_snapshot = requests.get(path).text
                    for line2 in srs_in_snapshot.replace('\\n', '').replace('\\', '').replace('null','""').split('\n'):
                        if line2 is None or line2 == '' or line2 == '\n' or len(line2) <= 0:
                            continue
                        sr_list = ast.literal_eval(line2)
                        for sr in sr_list:
                            sr_count += 1
                            single_item = {'snapshot': sn.get('snapshot_name')}
                            single_item.update(sr)
                            snapshot_history.append(single_item)
                print '%s %d' % (sn.get('snapshot_name'), sr_count)
                sys.stdout.flush()

        # Ordering in DESC
        snapshot_history.reverse()
        for x in snapshot_history:
            x.get('packages').reverse()
            x.get('submitters').reverse()

        for x in snapshot_history:
            print '\n', x.get('snapshot'), x.get('sr')
            for pkgs in x.get('packages'):
                print '  ', pkgs.get('repo'), pkgs.get('cid')

    return snapshot_history

class ref_create_project_obs(object):
    """ create reference project to obs """
    if os.getenv("REF_ACTIVE_PRJS"):
        profiles = ast.literal_eval(os.getenv("REF_ACTIVE_PRJS"))
    else:
        profiles = ''
    pattern = r'tizen[0-9a-zA-Z_\-\.]*[0-9]{8}.[0-9]{1,2}'

    def setup_profile(self, project, repo_path=None):
        # set up profile
        for l in self.profiles:
            if project == l['project']:
                self.profile = l
                self.profile['snapshot_url'] = os.path.dirname(os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"),
                                                                             repo_path))
                self.profile['snapshot_username'] = os.getenv("REF_SNAPSHOT_USERNAME",'')
                self.profile['snapshot_password'] = os.getenv("REF_SNAPSHOT_PASSWORD",'')
                print 'project = %s' % (project)
                return self.profile
        return False

    def remove_duplicates(self, t, s):
        """docstring for make_unique:"""
        result=[]
        result=list(set(t) - set(s))
        return result

    def get_manifest_filelists_snapshot(self, profile, request_url, timeout=5, group=None):
        """ get manifest filelists from snapshot"""
        #p = re.compile(r'alt=\"\[(TXT|DIR|   )]*\]\".*<a href=\"(.*)\">')
        #p = re.compile(r'.*<a href=\"(.*)\">')
        #FIXME: Ubuntu Apache 2.4.18
        p = re.compile(r'.*<a href=\"(.*)\">.*</a>.*')

        if not request_url:
            return []
        print request_url
        # get data from url
        for loop in range(10):
            try:
                f = requests.get(request_url,
                                 auth=(profile['snapshot_username'],
                                       profile['snapshot_password']),
                                 timeout=timeout)
                if f.status_code == 200:
                    break
            except requests.exceptions.Timeout as e:
                print(e)
                continue
            except requests.exceptions.ConnectionError as e:
                print(e)
                continue
            except Exception as e:
                print(e)
                raise Exception('exception from get manifest filelists')
        else:
            raise Exception('can\'t get manifest filelists')

        # returns
        results = {}
        exclude_pkgs = []
        found_links = p.findall(f.text)
        for link in found_links:
            if link == '../':
                continue
            if not link.endswith('.xml'):
                continue
            manifest_url = os.path.join(request_url, link)
            f = requests.get(manifest_url,
                             auth=(profile['snapshot_username'],
                                   profile['snapshot_password']),
                             timeout=timeout)
            try:
                tree = ElementTree.fromstring(f.text)
            except ElementTree.ParseError:
                raise ElementTree.ParseError
            for result in tree.findall('project'):
                if '_preloadapp.xml' in link:
                    exclude_pkgs.append(''.join(result.get('path')))
                else:
                    results[''.join(result.get('path'))] = result.get('revision')

        if group == 'abs':
            preloadapp_pkgs = {}
            for app in exclude_pkgs:
                preloadapp_pkgs[app] = results[app]
            return preloadapp_pkgs

        #print results
        return results


    def get_snapshot_version(self, profile, timeout=5):
        p = re.compile(self.pattern)
        
        if not profile['snapshot_url']:
            return []

        # get data from url
        for loop in range(10):
            try:
                f = requests.get(profile['snapshot_url'],
                                 auth=(profile['snapshot_username'],
                                       profile['snapshot_password']),
                                 timeout=timeout)
                if f.status_code == 200:
                    break
            except requests.exceptions.Timeout as e:
                print(e)
                continue
            except requests.exceptions.ConnectionError as e:
                print(e)
                continue
            except Exception as e:
                print(e)
                raise Exception('exception from get_latest_snapshot_version')
        else:
            raise Exception('can\'t get latest snapshot version')

        # return snapshot version
        results = [str(s) for s in p.findall(f.text)]
        #print results
        if len(results) > 2:
            return [results[-1], results[-3]]
        else:
            return [results[-1]]

    def update_build_flag_project(self, build, target, flag=None):
        """
        Update a build flag on project
        """
        if flag is None: # None is disable
            build.disable_build_flag(target, repo = None, flag="publish", status="disable")
            build.disable_build_flag(target, repo = None, flag="build", status="disable")
        else: # default
            build.default_build_flag(target, repo = None, flag="build")
            build.default_build_flag(target, repo = None, flag="publish")

    def create_project(self, build, target, info, meta=None, config=None, baserefproject=None):
        """
        create project
        """

        try:
            if not build.exists(target):
                try:
                    build.create_project(target, None, description=json.dumps(info))
                except ObsError, error:
                    raise LocalError("Unable to create project %s: %s" % (target, error))

                if meta:
                    # set meta
                    xml_meta = ElementTree.fromstringlist(meta)
                    #change the target project name
                    xml_meta.set('name',target)
                    #delete remote person
                    for person_element in xml_meta.findall('person'):
                        xml_meta.remove(person_element)
                #delete link project
                for link in xml_meta.findall('link'):
                    xml_meta.remove(link)

                # replace
                if baserefproject:
                    for repo_element in xml_meta.findall('repository'):
                        for element in repo_element.findall('path'):
                            element.set('project',baserefproject)

                #print ElementTree.tostring(xml_meta)
                #add target person
                element = ElementTree.Element('person', {"userid": "%s" % (os.getenv("OBS_API_USERNAME")),
                                                         "role": "maintainer"})
                xml_meta.append(element)
                print ElementTree.tostring(xml_meta)
                build.set_meta(ElementTree.tostring(xml_meta), target)
                # set project config
                #print config
                build.set_project_config(target, config)

                #disable publish flag
                build.disable_build_flag(target, repo = None, flag="publish", status="disable")
                #disable build flag
                build.disable_build_flag(target, repo = None, flag="build", status="disable")
                print "\nTarget project %s created" %(target)
                return True
            else:
                print "\nTarget project %s exist" %(target)
                return False
        except ObsError, error:
            raise LocalError("Unable to create project %s: %s" % (target, error))

    def list_packages_from_remote(self, remote_build, build, profile, target, 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)
        upload_packages=""
        if packages:
            upload_packages = packages
        else:
            upload_packages = [ package for package in sourceinfo if not re.search("_aggregate", package) ]
        for package in upload_packages:
            if sourceinfo[package]:
                print "    [sourceinfo(%s)] %s" % (package, sourceinfo[package])
                link_prj, link_pkg = sourceinfo[package][-1].split('/')
                if link_prj and link_pkg :
                    continue
            elif re.search("_aggregate", package):
                print "    [_aggregate] %s/%s" % (profile, package)
                aggregate_file_name="_aggregate"
                remote_build.get_source_file(profile, package, aggregate_file_name)
                content = ""
                with open(aggregate_file_name, 'r') as f:
                    content = f.read()

                if not re.search("qemu_aggregate", package):
                    content_xml_root = ElementTree.fromstringlist(content)
                    for element in content_xml_root.findall('aggregate'):
                        element.set('project',target)
                    content = ElementTree.tostring(content_xml_root)

                print "      [_aggregate] O %s" % (package)

                meta = remote_build.get_meta(profile, package)
                xml_meta = ElementTree.fromstringlist(meta)
                xml_meta.set('project',target)
                meta = ElementTree.tostring(xml_meta)
                print "      [_aggregate] META %s: %s" % (package, meta)

                ret_dict[package] = {'type': aggregate_file_name, \
                                     'content': content, \
                                     'meta': meta}
            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 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:
            print 'UPDATE %s' % package
            sys.stdout.flush()
            dbg_idx += 1
            _update_type = upload_packages[package]['type']
            raw = upload_packages[package]['content']
            with open(_update_type, 'w') as f:
                f.write(raw)
            #if not build.exists(target, package):
            if True:
                try:
                    build.create_package(target, package)
                except ObsError, error:
                    #raise UploadError('[%s] Unable to create package %s/%s :%s' \
                    print '[%s] Unable to create package %s/%s :%s' \
                                      % (_update_type, target, package, error)
            commit_msg="uploaded to package %s/%s from %s" % (target, package, profile)
            try:
                build.commit_files(target, package,
                       [(_update_type, True)], commit_msg)
            except ObsError, error:
                raise UploadError("Unable to upload %s to %s: %s" % \
                    (_update_type, target, error))

            sleep(0.5) # Wait 0.5 seconds...

            if _update_type == '_aggregate':
                build.set_meta(upload_packages[package]['meta'], target, package)

    def update_packages(self, remote_build, build, profile, target, upload_packages):
        print '  Total packages to check... %d' % len(upload_packages)
        plain_packages = upload_packages.copy()

        # Move time-consuming packages to front
        power_packages = {}
        if os.getenv("REF_UPLOAD_BIG_PKG_LIST"):
            for x in os.getenv("REF_UPLOAD_BIG_PKG_LIST").split(','):
                if x in upload_packages:
                    power_packages[x] = upload_packages[x]
                    del plain_packages[x]
            if power_packages:
                self._update_packages(remote_build, build, profile, target, power_packages)
        if upload_packages:
            self._update_packages(remote_build, build, profile, target, plain_packages)

    def create_related_packages(self, remote_build, build, profile, target):
        """create the 'link' package that relate the original package
           profile is the base project
           target  is the target project
        """
        sourceinfo = remote_build.get_sourceinfo_list(profile)
        sys.stdout.flush()
        for package in sourceinfo:
            if sourceinfo[package]:
                link_prj, link_pkg = sourceinfo[package][-1].split('/')
                if link_prj and link_pkg:
                    if package in build.get_package_list(target):
                        print 'Trying to delete %s/%s' % (target, package)
                        sys.stdout.flush()
                        build.delete_package(target, package)
                    if link_pkg in build.get_package_list(target):
                        build.create_link_pac(target, link_pkg, \
                                               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:
                    print '  >> DIFFER (%s) -> (%s) %s' % (rev_my, rev_snapshot, item)
                    todo_dict_merge[item]['rev'] = rev_snapshot
                    todo_dict_merge[item]['content'] = todo_dict_merge[item]['content'].replace(rev_my, rev_snapshot)
                    todo_dict_merge[item]['exist'] = False
                    cnt += 1
        print 'Differs %d' % cnt

        # Remove packages that are already exists which do not need to update
        for k, v in todo_dict_merge.items():
            if 'exist' in v and v['exist'] == True:
                del todo_dict_merge[k]
        return {'merge_items': todo_dict_merge, 'conflicts': conflict_list}

    def run_profile_update(self, build, this_project, target):
        """ run update profile project """
        if build.exists(this_project):
            try:
                build.unlink_project(this_project)
            except Exception, err:
                print 'Your project %s is broken: %s. Re-create it!' % (this_project, err)
                build.cleanup(this_project, "Create new.")
                sleep(10) # Wait 30 seconds...
                build.create_project(this_project, target)
        else:
            build.create_project(this_project, target)

        build.disable_build_flag(this_project, repo = None, flag='build', status='disable')
        build.disable_build_flag(this_project, repo = None, flag='publish', status='disable')

        #build.link_project(this_project, src=target, linktype=None)

        target_meta = build.get_meta(target)
        target_config = build.get_project_config(target)
        print 'OK we got target_meta...\n%s' % target_meta
        target_xml_meta = ElementTree.fromstringlist(target_meta)
        target_xml_meta.attrib['name'] = this_project
        target_xml_meta.find('title').text = 'Reference from %s' % target
        for repo_element in target_xml_meta.findall('repository'):
            for element in repo_element.findall('path'):
                repo_element.remove(element)
            #element.set('project', target)
            #element.set('repository', repo_element.get('name'))
            repo_element.insert(-1, ElementTree.Element('path', project=target, repository=repo_element.get('name')))

        print 'set meta started...\n%s' % ElementTree.tostring(target_xml_meta)
        build.set_meta(ElementTree.tostring(target_xml_meta), this_project)

        build.set_project_config(this_project, target_config)

        build.link_project(this_project, src=target, linktype=None)

        print 'Profile %s updated to %s' % (this_project, target)

    def update_title(self, build, target, title):
        """
        Update title 
        """
        target_meta = build.get_meta(target)
        print 'OK we got target_meta...\n%s' % target_meta
        target_xml_meta = ElementTree.fromstringlist(target_meta)
        target_xml_meta.find('title').text = 'Reference from %s' % title
        print 'set meta started...\n%s' % ElementTree.tostring(target_xml_meta)
        build.set_meta(ElementTree.tostring(target_xml_meta), target)

    def precheck_all_error_package(self, build, target):
        """
        Precheck all error package list from project
        """

        need_runservice = []
        for _wait in range(0,30):
            sys.stdout.flush()
            sleep(10) # Wait 10 seconds...
            viewinfofile = build.get_source_viewinfo(target, nofilename=0)
            root = ElementTree.parse(viewinfofile).getroot()
            errpackages = ''
            errpackages = [ s.get('package') for s in root.iter('sourceinfo') if s.findall('error') ]
            for x in root.iter('sourceinfo'):
                for y in x.findall('filename'):
                    if '_service:gbs:service-error.spec' in y.text:
                        errpackages.append(x.get('package'))
                        break
                for y in x.findall('error'):
                    print x.get('package'),y.text
                    if 'bad build configuration, no build type' in y.text:
                        errpackages.remove(x.get('package'))
                        print errpackages
            if errpackages:
                print '    5-1) Under packages are still... (%d)\n    %s' % (len(errpackages), errpackages)
                # Retrigger git sync
                for item in errpackages:
                    pkgview = ElementTree.fromstring(build.get_source_info(target, item))
                    for sv in pkgview.findall('serviceinfo'):
                        if sv.get('code') != 'failed': continue
                        for er in sv.findall('error'):
                            print '        %s %s with cause: (%s)' % (item, sv.get('code'), er.text)
                            need_runservice.append(item)
                sys.stdout.flush()
                sleep(30) # Wait 30 seconds...
                for item in need_runservice:
                    print '        runservice for %s' % item
                    build.runservice(target, item)
                need_runservice = []
            else:
                print '    5-2) All packages imported.'
                break

        return errpackages


    def run_manual_sr_sync(self, obs_api, obs_user, obs_passwd,
                            remote_obs_api, remote_obs_user, remote_obs_passwd,
                            gerrit_env,
                            current_ref, new_ref, snapshot_dir,
                            is_the_same_snapshot):
        print '---[MANUAL SR SYNC]---'

        remote_package_list = ''
        todo_dict = {}

        print '\nJOB Started at %s' % (str(datetime.now()))

        #### remote buildservice ####
        remote_build = BuildService(remote_obs_api, remote_obs_user, remote_obs_passwd)
        #### target buildservice ####
        build = BuildService(obs_api, obs_user, obs_passwd, \
                             remote_obs_api, remote_obs_user, remote_obs_passwd)

        src = current_ref
        target = new_ref
        build_src = build
        print "src = %s , target = %s" %(src, target)
        sys.stdout.flush()

        #TODO: Select matching SR info
        snapshot_history = get_snapshot_sr_increment(src, target)

        print "  0) Get package list from remote [ %s ]" % (src)
        remote_package_list = [ p for p in remote_build.get_sourceinfo_list(src) ]
        print '\nGet Package List from Remote Done at %s' % (str(datetime.now()))
        if 'patchinfo' in remote_package_list:
            remote_package_list.remove('patchinfo')
            print 'Please check patchinfo'
        sys.stdout.flush()

        print "\n    0-1) copy package list (%d):\n" %(len(remote_package_list))
        if not build.exists(target):
            print "\n    0-2) Sorry, target %s does not exist" % (target)
            sys.exit(-1)
        todo_dict = self.list_packages_from_remote(build_src, build, src, target)

        print '\nListing from Remote Done at %s' % (str(datetime.now()))
        print 'todo_dict(%d):' % (len(todo_dict))

        if True:
            package_list = [ x for x in todo_dict ]
            print "\n********"
            #print "  1) package list of target project \n %s" %(package_list)

            #FIXME:
            profile = {'project': target.split(':ref:')[0],
                       'baseproject': None,
                       'snapshot_url': os.path.dirname(os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"))),
                       'snapshot_username': os.getenv("REF_SNAPSHOT_USERNAME",''),
                       'snapshot_password': os.getenv("REF_SNAPSHOT_PASSWORD",'')}

            manifest_packages = self.get_manifest_filelists_snapshot(profile, \
                                                 os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"), \
                                                 snapshot_dir, \
                                                 "builddata/manifest"))

            print '2-0) Manifest packages %d' % len(manifest_packages)
            print profile
            print os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"), \
                                          snapshot_dir, \
                                          "builddata/manifest")
            for x in manifest_packages:
                print "%s > %s" % (x, manifest_packages[x])
                sys.stdout.flush()

            # Changed git repo check
            print '\n\n'
            git_changed_packages = []
            for x in todo_dict:
                if todo_dict[x].get('git', None) and todo_dict[x].get('git') not in manifest_packages:
                    print 'Git repository change detected! %s' % todo_dict[x]
                    sys.stdout.flush()
                    git_changed_packages.append(x)
                    package_list.remove(x)
                    if x in remote_package_list:
                        remote_package_list.remove(x)
            print '\n\n'

            packages = self.remove_duplicates(package_list, remote_package_list)
            packages.extend(git_changed_packages)
            print "\n********"
            print "  2) remove package %s" %(packages)
            for pkgname in packages:
                del todo_dict[pkgname]
            sys.stdout.flush()

            packages = self.remove_duplicates(remote_package_list, package_list)
            print "\n********"
            print "  3) add packages %s" %(packages)
            if packages:
                ret_dict_add = self.list_packages_from_remote(\
                                        remote_build, build, src, target, packages=packages)
                if ret_dict_add:
                    todo_dict.update(ret_dict_add)
            print '\nAdd Remove Done at %s' % (str(datetime.now()))
            sys.stdout.flush()

            if not is_the_same_snapshot:
                print "\n********"
                print "  4) compare package project "
                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:
                    if todo_dict_latest[td].get('rev') == todo_dict[td].get('rev'):
                        del todo_dict_latest[td]
            else:
                todo_dict_latest = copy.deepcopy(todo_dict)

            print '\n  4-1) Final packages to be updated %d' % len(todo_dict_latest)
            for td in todo_dict_latest:
                sys.stdout.flush()
                print "%s > %s" % (todo_dict_latest[td].get('git'), todo_dict_latest[td].get('rev'))

            # Select matching SR info
            todo_dict_repos = [ todo_dict_latest[x].get('git') for x in todo_dict_latest ]
            tgt = src.split(':%s:' % target.split(':ref:')[0])[0]
            #FIXME:
            #request_info = {'source': target.split(':ref:')[0],
            #                'target': tgt,
            request_info = {'source': target.split(':ref:')[0],
                            'target': os.getenv('SYNC_TARGET_PROJECT'),
                            'project_to_create_timestamp': datetime.utcnow().strftime("%Y%m%d.%H%M%S"),
                            'sr': []}
            request_sr_list = []
            print '\n\nChecking snapshot history...'
            snapshot_history_count = 0
            if not is_the_same_snapshot:
                for sh in snapshot_history:
                    b_added = False
                    for sh_packages in sh.get('packages'):
                        if sh_packages.get('repo') in todo_dict_repos:
                            todo_dict_repos.remove(sh_packages.get('repo'))
                            print 'Adding %s' % sh_packages.get('repo')
                            b_added = True
                            sys.stdout.flush()
                            if len(sh.get('packages')) > 0 and sh not in request_info.get('sr'):
                                snapshot_history_count += 1
                            else:
                                print 'Empty packages %s' % sh
                    if b_added == True:
                        request_sr_list.append(sh)
            else:
                request_sr_list.append({'sr': 'submit',
                                        'snapshot': 'no_snapshot',
                                        'submitters': ['nobody']*len(todo_dict_latest),
                                        'packages': [ {'package': os.path.basename(todo_dict_latest[x].get('git')), 
                                                       'repo': todo_dict_latest[x].get('git'),
                                                       'cid': todo_dict_latest[x].get('rev')} for x in todo_dict_latest ]})
                snapshot_history_count = len(todo_dict_repos)

            print 'snapshot_history_count = %d' % snapshot_history_count

            # Remove duplicated repo
            print '\n\nChecking duplicated entries...'
            reqinfo_count = 0
            todo_dict_repos = []
            for reqinfo in request_sr_list:
                print reqinfo.get('sr'), "\n======="
                start_index = 0
                debug_cnt = 0
                while True:
                    debug_cnt += 1
                    if debug_cnt >= 1000: assert False
                    prev_start_index = start_index
                    for index in range(start_index, len(reqinfo.get('packages'))):
                        repo = reqinfo.get('packages')[index].get('repo')
                        cid = reqinfo.get('packages')[index].get('cid')
                        if repo in todo_dict_repos:
                            print "-", repo, cid
                            del reqinfo.get('packages')[index]
                            del reqinfo.get('submitters')[index]
                            start_index = index + 1
                            break
                        else:
                            todo_dict_repos.append(repo)
                            print "+", repo, cid
                            reqinfo_count += 1
                        sys.stdout.flush()
                    if start_index == prev_start_index: break
                    if start_index > len(reqinfo.get('packages')): break
                    start_index -= 1
            print 'reqinfo_count = %d' % reqinfo_count

            # Ordering by ASC
            request_sr_list.reverse()
            print 'Final empty list...'
            print [ x for x in request_sr_list if len(x.get('packages')) <= 0 ]
            request_sr_list = [ x for x in request_sr_list if len(x.get('packages')) > 0 ]
            print 'Final count : %d' % sum([ len(x.get('packages')) for x in request_sr_list ])

            request_info['sr'] = request_sr_list

            #trigger_next('SUBMIT-REQUEST-SYNC', request_info, show=False)
            # remote trigger by using file param
            fname = 'SUBMIT-REQUEST-SYNC.parm'
            with open(fname, 'w') as f:
                f.write(json.dumps({'parameter': request_info}))
            remote_jenkins_build_job(os.getenv('JENKINS_URL_INTERNAL'),
                                     os.getenv('JENKINS_USER'),
                                     os.getenv('JENKINS_PW'),
                                     os.getenv('SR_SYNC_TRIGGER_JOB_NAME'),
                                     None, None, [(fname, fname)])

            print '\n\nFinal data to be sync...'
            rqinfo_count = 0
            for rqinfo in request_info.get('sr'):
                rqinfo_count += len(rqinfo.get('packages'))
            print 'rqinfo_count = %d' % rqinfo_count

            # Check final and reqinfo
            print '\n\nChecking increment diff...'
            todo_dict_repos = [ todo_dict_latest[x].get('git') for x in todo_dict_latest ]
            for rqinfo in request_info.get('sr'):
                for q in rqinfo.get('packages'):
                    if q.get('repo') not in todo_dict_repos:
                        print 'EXTRA %s' % q

        print "\n********"
        print "  7) Sync Done..."

        return 0

    def run_ref_create_project_obs(self, obs_api, obs_user, obs_passwd,
                             remote_obs_api, remote_obs_user, remote_obs_passwd,
                             gerrit_env, fields=None):

        print '---[JOB STARTED]-------------------------'

        remote_meta = ''
        config = ''
        remote_package_list = ''

        todo_dict = {}

        self.profile = self.setup_profile(fields['project'], fields['repo_path'])
        if not self.profile:
            print 'Skip Sync OBS project %s' % fields['project']
            return 0

        print '\nJOB Started at %s' % (str(datetime.now()))

        src = profile = self.profile['project']
        baseproject = self.profile['baseproject']
        build_id = fields['build_id']
        buildid = fields['build_id'].split('_')[1]
        snapshotdir = fields['repo_path']
        #print "buildid %s" %(buildid)

        refname = "%s:ref:" % (profile)
        target = "%s%s" %(refname,buildid)

        #### remote buildservice ####
        remote_build = BuildService(remote_obs_api, remote_obs_user, remote_obs_passwd)
        #### target buildservice ####
        build = BuildService(obs_api, obs_user, obs_passwd, \
                             remote_obs_api, remote_obs_user, remote_obs_passwd)

        #### Update description for ref project ####
        if os.getenv('TRIGGER_MISC') == 'importrpmdone':
            return self.run_profile_update(build, self.profile['project'], target)

        #get project list
        projectlist = [ prj for prj in build.get_package_list("") if prj.split(':')[0] == "Tizen" ]
        #print "\n********\n  Project List=%s" % projectlist

        refprojectlist = [ obj for obj in projectlist if refname in obj ]
        #exclude target project in refprojectlist
        if target in refprojectlist:
            refprojectlist.remove(target)
        #print "\n  Ref Project List=%s" % refprojectlist

        # get base ref project
        # get list of ref projects from git-ref-mapping
        obs_ref_prjs = get_ref_map(baseproject, None, \
                                   gitcache=gerrit_env.gitcache, \
                                   gerrit_hostname=gerrit_env.hostname, \
                                   gerrit_username=gerrit_env.username, \
                                   gerrit_sshport=gerrit_env.sshport
                                   )
        print 'baseproject:%s' % baseproject
        print 'obs_ref_prjs:%s' % obs_ref_prjs
        base_mapping_list = [ x['OBS_package'] for x in obs_ref_prjs if x['OBS_project'] == baseproject ]
        print 'base_mapping_list:%s' % base_mapping_list
        baserefproject = ''
        if base_mapping_list:
            baserefproject = base_mapping_list[0]
            print "\n  Ref Base Project from mapping=[%s]" % baserefproject
        else:
            if baseproject:
                basereflists = []
                [ basereflists.append(obj) for obj in projectlist \
                  if "%s:ref:" % (baseproject) in obj ]
                if basereflists:
                    baserefproject = list(basereflists)[-1]
                    print "\n  Ref Base Project from latest=[%s]" % baserefproject
        print "\n********"

        if not refprojectlist:
            src = profile
            build_src = remote_build
        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)
        remote_meta = remote_build.get_meta(profile)
        config = remote_build.get_project_config(profile)
        remote_package_list = [ p for p in remote_build.get_sourceinfo_list(profile) ]
        print '\nGet Package List from Remote Done at %s' % (str(datetime.now()))
        if 'patchinfo' in remote_package_list:
            remote_package_list.remove('patchinfo')
            print 'Please check patchinfo'

        print "\n    0-1) copy package list (%d):\n %s" %(len(remote_package_list), remote_package_list)

        if not build.exists(target):
            print "\n    0-2) create project: %s" %(target)
            self.create_project(build, target, None, remote_meta, config, baserefproject)
            todo_dict = self.list_packages_from_remote(build_src, build, src, target)
        else:
            print "\n    0-2) project already exists: %s" %(target)
            todo_dict = self.list_packages_from_remote(build_src, build, target, target, existing=True)

        print '\nListing from Remote Done at %s' % (str(datetime.now()))
        print 'todo_dict(%d):' % (len(todo_dict))

        if True:
            package_list = [ x for x in todo_dict ]
            print "\n********"
            print "  1) package list of target project \n %s" %(package_list)

            manifest_packages = self.get_manifest_filelists_snapshot(self.profile, \
                                                 os.path.join(os.getenv("URL_PUBLIC_REPO_BASE"), \
                                                 snapshotdir,\
                                                 "builddata/manifest"))

            # Changed git repo check
            git_changed_packages = []
            for x in todo_dict:
                if todo_dict[x].get('git', None) and todo_dict[x].get('git') not in manifest_packages:
                    print 'Git repository change detected! %s' % todo_dict[x]
                    git_changed_packages.append(x)
                    package_list.remove(x)
                    if x in remote_package_list:
                        remote_package_list.remove(x)

            packages = self.remove_duplicates(package_list, remote_package_list)
            packages.extend(git_changed_packages)
            print "\n********"
            print "  2) remove package %s" %(packages)
            for pkgname in packages:
                del todo_dict[pkgname]
                if build.exists(target, pkgname):
                    build.delete_package(target, pkgname)

            packages = self.remove_duplicates(remote_package_list, package_list)
            print "\n********"
            print "  3) add packages %s" %(packages)
            if packages:
                print 'profile:%s' % profile
                print 'target:%s' % target
                print 'packages:%s' % packages
                ret_dict_add = self.list_packages_from_remote(\
                                        remote_build, build, profile, target, packages=packages)
                if ret_dict_add:
                    todo_dict.update(ret_dict_add)
            print '\nAdd Remove Done at %s' % (str(datetime.now()))
 
            print "\n********"
            print "  4) compare package project "
            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:'
            try:
                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_latest[ci_pkg]['git']
                        old_rev     = todo_dict_latest[ci_pkg]['rev']
                        old_content = todo_dict_latest[ci_pkg]['content']
                        new_content = old_content.replace(old_git, ci_git).replace(old_rev, ci_rev)
                        todo_dict_latest[ci_pkg]['git'] = ci_git
                        todo_dict_latest[ci_pkg]['rev'] = ci_rev
                        todo_dict_latest[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)
            except Exception as err:
                print "Exception while checking conflicts"

            print '\nCompare With Manifest Done at %s' % (str(datetime.now()))

            print '\n  4-1) Final packages to be updated %d' % len(todo_dict_latest)
            sys.stdout.flush()
            print '\n\n-------'
            for x in todo_dict_latest:
                print x, todo_dict_latest[x]
            print '-------\n\n'
            self.update_packages(remote_build, build, profile, target, todo_dict_latest)
            print '\nUpdate Packages Done at %s' % (str(datetime.now()))

        print "\n********"
        print "  5) Precheck all error package list from project"
        errpackages = self.precheck_all_error_package(build, target)

        print "\n********"
        print "  6) create related packages \n"
        self.create_related_packages(remote_build, build, profile, target)

        print "\n********"
        print "  7) Sync Done..."

        # importrpm trigger next
        fields['profile'] = profile
        fields['target'] = target
        trigger_next("REF_IMPORT_RPM_OBS", fields)
        print "\n********"
        print "  8) Sync Copy Project."
        if os.getenv('SR_SYNC_PROJECTS'):
            enabled_projects = ast.literal_eval(os.getenv('SR_SYNC_PROJECTS'))
            count = 0
            if enabled_projects.get(profile):
                for project in enabled_projects.get(profile):
                    print project
                    if project.get('obs-sync') == 'Yes':
                        data={}
                        data['source'] = target
                        data['target'] = project.get('target')

                        trigger_next("REF_COPY_SYNC_%s" %(count), data)
                        count += 1

        if errpackages:
            return 1
        return 0

    def run_copy_project_obs(self, obs_api, obs_user, obs_passwd,
                             remote_obs_api, remote_obs_user, remote_obs_passwd,
                             gerrit_env, fields=None):
        """ copy project """

        print '---[JOB STARTED]-------------------------'

        remote_meta = ''
        config = ''
        remote_package_list = ''

        todo_dict = {}

        print '\nJOB Started at %s' % (str(datetime.now()))

        #### remote buildservice ####
        remote_build = BuildService(remote_obs_api, remote_obs_user, remote_obs_passwd)
        #### target buildservice ####
        build = BuildService(obs_api, obs_user, obs_passwd, \
                             remote_obs_api, remote_obs_user, remote_obs_passwd)

        src = profile = fields['SRC_PROJECT']
        target = fields['DEST_PROJECT']
        replace_gerrit_url = fields['REPLACE_GERRIT_URL']
        importrpm = fields['IMPORT_RPM']

        copy_inherited_packages = os.getenv('COPY_INHERITED_PACKAGES', 'false')
        if copy_inherited_packages == 'true':
            # Check if link project is the same as source project
            my_meta = build.get_meta(target)
            xml_my_meta = ElementTree.fromstringlist(my_meta)
            _link_prj = xml_my_meta.find('link').get('project')
            if (fields['SRC_PROJECT'] != fields['DEST_PROJECT']) and \
               (fields['SRC_PROJECT'] != _link_prj):
                print 'COPY_INHERITED_PACKAGES only works for matched link project'
                assert False
            print 'We have %d own packages' % len(build.get_package_list(target))

        build_src = build
        print "src = %s , target = %s" %(src, target)

        print "  0) Get meta, config, package list from remote [ %s ]" % (profile)
        remote_meta = remote_build.get_meta(profile)
        config = remote_build.get_project_config(profile)
        remote_package_list = [ p for p in remote_build.get_sourceinfo_list(profile) ]
        print '\nGet Package List from Remote Done at %s' % (str(datetime.now()))
        if 'patchinfo' in remote_package_list:
            remote_package_list.remove('patchinfo')
            print 'Please check patchinfo'

        print "\n    0-1) copy package list (%d):\n %s" %(len(remote_package_list), remote_package_list)
        if not build.exists(target):
            print "\n    0-2) create project: %s" %(target)
            self.create_project(build, target, None, remote_meta, config)
            todo_dict = self.list_packages_from_remote(build_src, build, src, target,
                                                       replace_gerrit_url=replace_gerrit_url)
        else:
            print "\n    0-2) project already exists: %s" %(target)
            todo_dict = self.list_packages_from_remote(build_src, build, target, target, existing=True,
                                                       replace_gerrit_url=replace_gerrit_url)

        print '\nListing from Remote Done at %s' % (str(datetime.now()))
        print 'todo_dict(%d):' % (len(todo_dict))

        if True:
            package_list = [ x for x in todo_dict ]
            print "\n********"
            print "  1) package list of target project \n %s" %(package_list)

            packages = self.remove_duplicates(package_list, remote_package_list)
            print "\n********"
            print "  2) remove package %s" %(packages)
            for pkgname in packages:
                del todo_dict[pkgname]
                if build.exists(target, pkgname):
                    if copy_inherited_packages != 'true':
                        print 'Deleting %s' % pkgname
                        build.delete_package(target, pkgname)

            packages = self.remove_duplicates(remote_package_list, package_list)
            print "\n********"
            print "  3) add packages %s" %(packages)
            sys.stdout.flush()
            if packages:
                print 'Checking %s' % packages
                ret_dict_add = self.list_packages_from_remote(\
                                        remote_build, build, profile, target, packages=packages,
                                        replace_gerrit_url=replace_gerrit_url)
                if ret_dict_add:
                    todo_dict.update(ret_dict_add)

            if copy_inherited_packages == 'true':
                print "  3-1) Handling inherited packages"
                own_packages = build.get_package_list(target)
                print '       We have %d own packages' % len(own_packages)
                for op in own_packages:
                    if op in todo_dict:
                        del todo_dict[op]

            print '\nAdd Remove Done at %s' % (str(datetime.now()))

            print '\n  4-1) Final packages to be updated %d' % len(todo_dict)
            sys.stdout.flush()
            self.update_packages(remote_build, build, profile, target, todo_dict)
            print '\nUpdate Packages Done at %s' % (str(datetime.now()))

        print "\n********"
        print "  5) Precheck all error package list from project"
        errpackages = self.precheck_all_error_package(build, target)

        print "\n********"
        print "  6) create related packages \n"
        self.create_related_packages(remote_build, build, profile, target)

        print "\n********"
        print "  7) Sync Done..."

        if importrpm is not None and importrpm == 'true':
            # importrpm trigger next
            data={}
            data['profile'] = profile
            data['target'] = target
            data['repo_path'] = os.path.join(fields['REPO_PATH'],
                                             fields['BUILDID'])
            data['build_id'] = fields['BUILDID']
            trigger_next("REF_IMPORT_RPM_OBS", data)
            print "  9) trigger_next import rpm .."
        else:
            self.update_build_flag_project(build, target, flag=True)
            print "\n********"
            print "  8) Update build flag=default..."

        if errpackages:
            return 1
        return 0

    def run_obs_sync_mapping_project_obs(self, obs_api, obs_user, obs_passwd,
                             remote_obs_api, remote_obs_user, remote_obs_passwd,
                             gerrit_env, fields=None):
        """ Sync Mapping project """

        print '---[JOB STARTED]-------------------------'

        remote_meta = ''
        config = ''
        remote_package_list = ''

        todo_dict = {}

        print '\nJOB Started at %s' % (str(datetime.now()))

        #### remote buildservice ####
        remote_build = BuildService(remote_obs_api, remote_obs_user, remote_obs_passwd)
        #### target buildservice ####
        build = BuildService(obs_api, obs_user, obs_passwd, \
                             remote_obs_api, remote_obs_user, remote_obs_passwd)

        src = profile = fields.get('source')
        target = fields.get('target')
        replace_gerrit_url = None
        addPrefix = 'Sync' + ':' + src
        # get sync list
        # ex) source : Tizen:4.0:Unified:ref:20170724.2
        # ex) target : Tizen:4.0:MCD:AI_SPeaker
        #     Add prefix : Sync
        sync_prj_list = get_sync_map_list(target)          
        target = "%s:%s" %(target, addPrefix)
        
        if not sync_prj_list:
            print "\nSKIP Sync Copy for the (%s) !!!\n" %(target)
            return

        build_src = build
        print "src = %s , target = %s" %(src, target)

        print "  0) Get meta, config, package list from remote [ %s ]" % (profile)
        remote_meta = remote_build.get_meta(profile)
        config = remote_build.get_project_config(profile)
        sourceinfo = remote_build.get_sourceinfo_list(profile)
        remote_package_list = [ p for p in sourceinfo if len(sourceinfo[p]) == 0 ]
        print '\nGet Package List from Remote Done at %s' % (str(datetime.now()))
        if 'patchinfo' in remote_package_list:
            remote_package_list.remove('patchinfo')
            print 'Please check patchinfo'

        print "\n    0-1) copy package list (%d):\n %s" %(len(remote_package_list), remote_package_list)
        if not build.exists(target):
            print "\n    0-2) create project: %s" %(target)
            self.create_project(build, target, None, remote_meta, config)
            src_todo_dict = self.list_packages_from_remote(build_src, build, src, target)
            todo_dict = self.list_packages_from_remote(build_src, build, target, target)
            self.update_title(build_src, target, src)
        else:
            print "\n    0-2) project already exists: %s" %(target)
            src_todo_dict = self.list_packages_from_remote(build_src, build, src, target)
            todo_dict = self.list_packages_from_remote(build_src, build, target, target, existing=True)
            self.update_title(build_src, target, src)

        print '\nListing from Remote Done at %s' % (str(datetime.now()))
        print 'todo_dict(%d):' % (len(todo_dict))

        if True:
            package_list = [ x for x in todo_dict ]
            print "\n********"
            print "  1) package list of target project \n %s" %(package_list)

            packages = self.remove_duplicates(package_list, remote_package_list)
            print "\n********"
            print "  2) remove package %s" %(packages)
            for pkgname in packages:
                del todo_dict[pkgname]
                if build.exists(target, pkgname):
                    print 'Deleting %s' % pkgname
                    build.delete_package(target, pkgname)

            packages = self.remove_duplicates(remote_package_list, package_list)
            print "\n********"
            print "  3) add packages %s" %(packages)
            sys.stdout.flush()
            if packages:
                add_src_packages = {}
                print 'Checking %s' % packages
                for x in packages:
                    add_src_packages[x] = src_todo_dict[x]
                todo_dict.update(add_src_packages)

            print '\nAdd Remove Done at %s' % (str(datetime.now()))
            # Compare to Sync mapping
            print "  4) compare package project in Sync mapping"
            sync_remove_packages = []
            for x in todo_dict:
                if todo_dict[x].get('git', None) not in sync_prj_list:
                    print 'Git repository is not in Sync mapping! %s' % todo_dict[x].get('git',None)
                    sync_remove_packages.append(x)
            for x in sync_remove_packages:
                del todo_dict[x]

            print '\nCompare With Sync mapping Done at %s' % (str(datetime.now()))
            print "  4-1) compare package project "
            todo_dict_merge = copy.deepcopy(todo_dict)
            cnt = 0
            for item in todo_dict_merge:
                if 'git' in todo_dict_merge[item] and todo_dict_merge[item]['git'] \
                    and item in src_todo_dict:
                    rev_my = todo_dict_merge[item]['rev']
                    rev_snapshot = src_todo_dict[item]['rev']
                    if rev_my != rev_snapshot:
                        print '  >> DIFFER (%s) -> (%s) %s' % (rev_my, rev_snapshot, item)
                        todo_dict_merge[item]['rev'] = rev_snapshot
                        todo_dict_merge[item]['content'] = todo_dict_merge[item]['content'].replace(rev_my, rev_snapshot)
                        todo_dict_merge[item]['exist'] = False
                        cnt += 1
            print 'Differs %d' % cnt

            # Remove packages that are already exists which do not need to update
            for k, v in todo_dict_merge.items():
                if 'exist' in v and v['exist'] == True:
                    del todo_dict_merge[k]
            todo_dict = todo_dict_merge

            print '\nCompare With project Done at %s' % (str(datetime.now()))

            print '\n  4-2) Final packages to be updated %d' % len(todo_dict)
            sys.stdout.flush()
            self.update_packages(remote_build, build, profile, target, todo_dict)
            print '\nUpdate Packages Done at %s' % (str(datetime.now()))

        print "\n********"
        print "  5) Precheck all error package list from project"
        errpackages = self.precheck_all_error_package(build, target)

        print "\n********"
        print "  6) create related packages \n"
        self.create_related_packages(remote_build, build, profile, target)

        print "\n********"
        print "  7) Sync Done..."

        if errpackages:
            return 1
        return 0


    def main(self, action=None):
        """
        main
        """
        print('-----[JOB STARTED: ref_create_project_obs ]-----')

        for loop in range(1):
            #try:
                if action == 'create' or action is None:

                    remote_obs_api = obs_api = os.getenv("REF_TARGET_OBS_API_URL")
                    remote_obs_user = obs_user = os.getenv("REF_TARGET_OBS_API_USERNAME")
                    remote_obs_passwd = obs_passwd = os.getenv("REF_TARGET_OBS_API_PASSWD")
                    gerrit_env = GerritEnv("")

                    fields = trigger_info(os.getenv('TRIGGER_INFO'))
                    # Check if we've got required field in TRIGGER_INFO
                    for field in ('repo_path', 'build_id', 'project'):
                        if field not in fields:
                            print 'Error: TRIGGER_INFO doesn\'t contain %s' % field
                            return -1

                    return self.run_ref_create_project_obs(obs_api, obs_user, obs_passwd,
                                                     remote_obs_api, remote_obs_user, remote_obs_passwd,
                                                     gerrit_env, fields)
                elif action == 'copy':

                    remote_obs_api = obs_api = os.getenv("REF_TARGET_OBS_API_URL")
                    remote_obs_user = obs_user = os.getenv("REF_TARGET_OBS_API_USERNAME")
                    remote_obs_passwd = obs_passwd = os.getenv("REF_TARGET_OBS_API_PASSWD")
                    gerrit_env = GerritEnv("")

                    if os.getenv('SRC_PROJECT') and os.getenv('DEST_PROJECT'):
                        fields = {'SRC_PROJECT': os.getenv('SRC_PROJECT'),
                                  'DEST_PROJECT': os.getenv('DEST_PROJECT'),
                                  'REPLACE_GERRIT_URL': os.getenv('REPLACE_GERRIT_URL'),
                                  'IMPORT_RPM': os.getenv('IMPORT_RPM'),
                                  'REPO_PATH': os.getenv('REPO_PATH'),
                                  'BUILDID': os.getenv('BUILDID'),
                                 }
                    else:
                        fields = trigger_info(os.getenv('TRIGGER_INFO'))
                        # Check if we've got required field in TRIGGER_INFO
                        for field in ('SRC_PROJECT', 'DEST_PROJECT'):
                            if field not in fields:
                                print 'Error: TRIGGER_INFO doesn\'t contain %s' % field
                                return -1

                    return self.run_copy_project_obs(obs_api, obs_user, obs_passwd,
                                                     remote_obs_api, remote_obs_user, remote_obs_passwd,
                                                     gerrit_env, fields)
                elif action == 'remote-create':

                    obs_api = os.getenv("REF_TARGET_OBS_API_URL")
                    obs_user = os.getenv("REF_TARGET_OBS_API_USERNAME")
                    obs_passwd = os.getenv("REF_TARGET_OBS_API_PASSWD")

                    remote_obs_api = os.getenv("REF_REMOTE_OBS_API_URL")
                    remote_obs_user = os.getenv("REF_REMOTE_OBS_API_USERNAME")
                    remote_obs_passwd = os.getenv("REF_REMOTE_OBS_API_PASSWD")
                    # default value is null
                    if os.getenv("REF_GERRIT_NAME"):
                        gerrit_env = GerritEnv(os.getenv("REF_GERRIT_NAME"))
                    else:
                        gerrit_env = GerritEnv("")

                    fields = trigger_info(os.getenv('TRIGGER_INFO'))
                    # Check if we've got required field in TRIGGER_INFO
                    for field in ('repo_path', 'build_id', 'project'):
                        if field not in fields:
                            print 'Error: TRIGGER_INFO doesn\'t contain %s' % field
                            return -1

                    return self.run_ref_create_project_obs(obs_api, obs_user, obs_passwd,
                                                     remote_obs_api, remote_obs_user, remote_obs_passwd,
                                                     gerrit_env, fields)

                elif action == 'trigger_manual_sr_sync':

                    obs_api = os.getenv("REF_TARGET_OBS_API_URL")
                    obs_user = os.getenv("REF_TARGET_OBS_API_USERNAME")
                    obs_passwd = os.getenv("REF_TARGET_OBS_API_PASSWD")

                    # default value is null
                    if os.getenv("REF_GERRIT_NAME"):
                        gerrit_env = GerritEnv(os.getenv("REF_GERRIT_NAME"))
                    else:
                        gerrit_env = GerritEnv("")

                    current_ref  = os.getenv("CURRENT_REF")
                    new_ref      = os.getenv("NEW_REF")
                    snapshot_dir = os.getenv("SNAPSHOT_DIR")

                    is_the_same_snapshot = current_ref.split(':')[-1] == new_ref.split(':')[-1]

                    return self.run_manual_sr_sync(obs_api, obs_user, obs_passwd,
                                                   obs_api, obs_user, obs_passwd,
                                                   gerrit_env,
                                                   current_ref, new_ref, snapshot_dir,
                                                   is_the_same_snapshot
                                                   )
                elif action == 'obs_sync_mapping':

                    remote_obs_api = obs_api = os.getenv("REF_TARGET_OBS_API_URL")
                    remote_obs_user = obs_user = os.getenv("REF_TARGET_OBS_API_USERNAME")
                    remote_obs_passwd = obs_passwd = os.getenv("REF_TARGET_OBS_API_PASSWD")
                    gerrit_env = GerritEnv("")

                    if os.getenv('source') and os.getenv('target'):
                        fields = {'source': os.getenv('source'),
                                  'target': os.getenv('target'),
                                 }
                    else:
                        fields = trigger_info(os.getenv('TRIGGER_INFO'))
                        # Check if we've got required field in TRIGGER_INFO
                        for field in ('source', 'target'):
                            if field not in fields:
                                print 'Error: TRIGGER_INFO doesn\'t contain %s' % field
                                return -1

                    return self.run_obs_sync_mapping_project_obs(obs_api, obs_user, obs_passwd,
                                                     remote_obs_api, remote_obs_user, remote_obs_passwd,
                                                     gerrit_env, fields)

                else:
                    print 'not enable action = %s' %(action)
                    return -1

            #except Exception, err:
            #    print 'run_ef_create_project_obs operation failed, retrying...'
            #    print err
            #    raise LocalError("FAIL %s" % (err))
            #    sleep(5)

        return True

if __name__ == '__main__':

#    try:
        trigger = ref_create_project_obs()
        sys.exit(trigger.main(sys.argv[1]))
#    except Exception as e:
#        print(e)
#        sys.exit(1)

