from common import runner
from common.utils import retry
+from common.utils import Workdir
from gbp.git.repository import GitRepository
from gbp.git.repository import GitRepositoryError
def __init__(self, path):
GitRepository.__init__(self, path)
log.setup('auto', log.DEBUG)
+ self._git_dir = os.path.join(path, '.git')
+
+ def _exec_git(self, command, args=[]):
+ """Exec a git command and return the output
+ """
+
+ if self._git_dir:
+ cmd = ['git --git-dir=%s ' % self._git_dir, command] + args
+ else:
+ cmd = ['git ', command] + args
+
+ cmdln = ' '.join(cmd)
+ #print('run command: %s' % cmdln)
+
+ with Workdir(self.path):
+ ret, outs = runner.show(cmdln)
+
+ #if ret:
+ # raise errors.GitError("command error for: %s" % cmdln)
+
+ return ret, outs
def get_tag(self, tag_name):
"""Get tag info though tag name"""
print 'git branch contains %s' % branches
return branches
+ def create_overwrite_commit(self, branch, commit):
+ ret, outs = self._exec_git('log', ['-n1', '--pretty=%H','origin/%s' %(branch), '--'])
+ if ret != 0:
+ print('not found commit of %s' % branch)
+ return (False, '')
+ deprecated_commit = outs.strip()
+ ret, outs = self._exec_git('diff', ['--stat', '--exit-code', deprecated_commit, commit])
+ if ret == 0:
+ print('%s branch is same as %s, no create overwrite commit' % (branch, commit))
+ return (True, '')
+ ret, outs = self._exec_git('log', ['-n1', '--pretty=%T', commit])
+ if ret != 0:
+ print('not found tree object of %s' % commit)
+ return (False, '')
+ tree_object = outs.strip()
+ msg = '"[SCM] %s branch is overwritten by %s"' % (branch, commit)
+ ret, outs = self._exec_git('commit-tree', [tree_object, '-p', commit, '-p', deprecated_commit, '-m', msg])
+ if ret != 0:
+ print('commit-tree failed(tree:%s, parent: %s %s)' % (tree_object, commit, deprecated_commit))
+ return (False, '')
+ overwrite_commit = outs.strip()
+ return (True, overwrite_commit)
+
+
def _update_gitproject(localdir, gitpath=None):
"""Fetch latest code to local dir"""
git = Git.create(localdir, bare)
git.fetch(repo=giturl, refspec=refspec)
git.checkout('FETCH_HEAD')
+
--- /dev/null
+#!/usr/bin/env python
+
+import os
+import sys
+import base64
+import json
+import re
+import shutil
+import tempfile
+import traceback
+import urllib2
+import xml.etree.ElementTree as ET
+import ast
+from common import gerrit
+from common import git
+from common import utils
+from common import runner
+from common.buildtrigger import trigger_info, trigger_next
+from common.send_mail import prepare_mail
+from time import sleep
+
+GIT_URL = 'ssh://%s@%s:%s' % (os.getenv('GERRIT_USERNAME'),
+ os.getenv('GERRIT_HOSTNAME'),
+ os.getenv('GERRIT_SSHPORT'))
+HIGHLIGHT = '+'
+GREYEDOUT = '-'
+
+class GitUpdateError(Exception): pass
+class RevisionError(Exception): pass
+class UpstreamError(Exception): pass
+class OverwriteError(Exception): pass
+
+class MailSender(object):
+ email_title = ''
+ email_head = ''
+ email_body = ''
+ email_footer = '\n\n--------------------------------------------------------\n'\
+ 'Automatically generated by backend service.\n'\
+ 'Please DO NOT Reply!'
+ email_to = []
+
+ def __init__(self, receiver=None, title=None, body=None):
+ if receiver is not None: self.email_to = receiver
+ if title is not None: self.email_title = title
+ if body is not None: self.email_body = body
+
+ def add_receiver(self, add_new):
+ """ add receiver """
+ if type(add_new) == list:
+ self.email_to.extend(x for x in add_new)
+ elif type(add_new) == str:
+ self.email_to.append(add_new)
+ else:
+ print 'TYPE(%s) == %s' % (add_new, type(add_new))
+ self.email_to = list(set(self.email_to))
+
+ def add_title(self, add_new):
+ """ add title """
+ self.email_title = self.email_title + ' ' + add_new
+
+ def add_message(self, add_new, top=None):
+ """ add message """
+ if top is not None:
+ self.email_body = add_new + '\n' + self.email_body
+ else:
+ self.email_body = self.email_body + '\n' + add_new
+
+ def add_maintainers(self, mygerrit, group_name=None, project=None):
+ """ add maintainers """
+ if not mygerrit:
+ print 'mygerrit is Null...'
+ return
+
+ if not project and group_name:
+ mbrs = mygerrit.ls_members(['\'\"%s\"\'' % group_name, '--recursive'])
+ for line in mbrs:
+ self.add_receiver(line.split('\t')[3])
+ return
+
+ if project:
+ grps = mygerrit.ls_groups(['--project %s' % project])
+ dest_grp = [s for s in grps if " - Maintainers" in s]
+ for dg in dest_grp:
+ mbrs = mygerrit.ls_members(['\'\"%s\"\'' % dg, '--recursive'])
+ for line in mbrs:
+ self.add_receiver(line.split('\t')[3])
+ return
+
+ def send_mail(self):
+ """ send mail """
+ self.email_body = self.email_head + self.email_body + self.email_footer
+
+ self.email_to = [x for x in self.email_to if x != 'n/a']
+ print '\n\n'
+ print self.email_title
+ #m_body = ''
+ #for m in self.email_body.splitlines():
+ # m_body += '\n'.join(m[i:i+128] for i in xrange(0, len(m), 128)) + '\n'
+ #self.email_body = m_body
+ print self.email_body
+ print self.email_to
+
+ prepare_mail("%s.env" % os.getenv('BUILD_TAG'), \
+ self.email_title, \
+ self.email_body, \
+ os.getenv('NOREPLY_EMAIL_SENDER'), \
+ self.email_to)
+
+def conv_rev2commit(gitprj, git_dir, revision):
+ commit = ''
+ try:
+ retcode, outs = runner.show('git --git-dir=%s/.git cat-file -t %s' % (git_dir, revision))
+ if retcode != 0:
+ raise RevisionError('not found object type(%s)' % revision)
+ obj_type = outs.strip()
+ if obj_type == 'commit' and re.match(r'[0-9a-f]{5,40}', revision):
+ commit = revision
+ else:
+ rev_name = gitprj.name_rev('--name-only %s' % (revision))
+ if rev_name == 'undefined':
+ rev_name = revision
+ commits = gitprj.show('-s', '--format=%H', rev_name)
+ if not commits or len(commits) != 1:
+ raise RevisionError('not found commit(%s)' % revision)
+ commit = commits[0]
+ except RevisionError, exc:
+ print 'Error:', exc
+ return commit
+
+def update_sync_for_git_sync(tmpdir, private_gerrit, target, requests, request_snapshot):
+ """
+ Update sync for git sync.
+ """
+
+ target_project = target.get('target') or []
+ target_fork_prefix = target.get('fork') or []
+ branch = target.get('branch') or [] # tizen_4.0_mcd_z4
+ source_branch = target.get('source_branch') or [] # public_tizen
+ email_to_members = target.get('notify') or []
+
+ GIT_PREFIX = target_fork_prefix
+ UPSTREAM_BRANCH = "public_" + source_branch
+ overwrite_branches = [branch]
+ request_projects = []
+ new_private_projects = []
+ overwrite_alreadys = []
+ overwrite_successs = []
+ upstream_failures = []
+ overwrite_failures = []
+
+ private_projects = private_gerrit.ls_projects()
+
+ upstream_git_dir = ''
+ private_git_dir = ''
+
+ for item in requests[requests.keys()[0]]:
+ project = item['gerrit_project']
+ revision = item['cid']
+ submitter = item['submitter']
+ git_tag = item['git_tag']
+
+ if project.startswith(HIGHLIGHT):
+ continue
+ else:
+ project = project[1:]
+ request_projects.append((project, revision, submitter, git_tag))
+
+ try:
+ print '\n-----[Manifest Information]-------------------------------'
+ print 'GIT_PREFIX:', GIT_PREFIX
+ print 'UPSTREAM_BRANCH: ', UPSTREAM_BRANCH
+ print 'Project:', project
+ print 'Revision:', revision
+
+ if not project or not revision:
+ raise UpstreamError('not found information(%s, %s)' % ( project, revision))
+
+ print '\n* Update upstream git repo %s' % (project)
+ if not git.clone_gitproject(project, os.path.join(tmpdir, project)):
+ raise UpstreamError('upstream git update failed(%s)' % (project))
+
+ upstream_git_dir = os.path.join(tmpdir, project)
+ upstream_gitprj = git.Git(upstream_git_dir)
+
+ commit = conv_rev2commit(upstream_gitprj, upstream_git_dir, revision)
+ if not commit:
+ raise UpstreamError('failure to convert revision to commit(%s)' % revision)
+
+ private_project = '%s%s' % (GIT_PREFIX, project)
+
+ if not private_project in private_projects:
+ print '\n* Does not exist Private git repo %s' % (private_project)
+ #private_gerrit.create_project(aname=private_project, parent='Tizen-Projects', empty_commit=True)
+ #private_gerrit.create_project(private_project, '-p', os.getenv('GERRIT_PARENT_PROJECT'))
+ new_private_projects.append(private_project)
+ continue
+
+ print '\n* Push %s %s %s' % (commit, UPSTREAM_BRANCH, private_project)
+ ret = upstream_gitprj._git_inout('push',['-q', '-f', '%s/%s' % (GIT_URL, private_project), \
+ '%s:refs/heads/%s' % (commit, UPSTREAM_BRANCH)])
+ if ret == None:
+ raise UpstreamError('git push failed(%s)' % (private_project))
+
+ print '\n* Overwrite Branches:', overwrite_branches
+ if not overwrite_branches:
+ print 'not found overwrite branch information of %s, skip overwrite..' % (private_project)
+ continue
+
+ print '\n* Update private git repo %s' % (private_project)
+ if not git.clone_gitproject(private_project, os.path.join(tmpdir, private_project)):
+ raise OverwriteError('private git update failed(%s)' % (private_project))
+
+ private_git_dir = os.path.join(tmpdir, private_project)
+ private_gitprj = git.Git(private_git_dir)
+ # ERROR: missing Change-Id in commit message footer
+ retcode, outs = runner.show('scp -p -P %s %s@%s:hooks/commit-msg %s/.git/hooks/' \
+ %(os.getenv('GERRIT_SSHPORT'), os.getenv('GERRIT_USERNAME'),
+ os.getenv('GERRIT_HOSTNAME'), private_git_dir))
+ if retcode != 0:
+ raise RevisionError('error')
+
+ for branch in overwrite_branches:
+ print '\n* Overwrite %s %s %s' % (commit, branch, private_project)
+ ret, overwrite_commit = private_gitprj.create_overwrite_commit(branch, commit)
+ if not ret:
+ raise OverwriteError('overwrite %s branch failed(%s, %s)' % (branch, private_project, commit))
+
+ if not overwrite_commit:
+ print 'already overwrite %s branch..' % (branch)
+ overwrite_alreadys.append((private_project, commit))
+ continue
+
+ print '\n* checkout %s ' %(overwrite_commit)
+ private_gitprj.checkout(overwrite_commit)
+
+ #print '\n* Commit --amend --no-edit.. '
+ ret = private_gitprj._exec_git('commit', ['--amend', '--no-edit'])
+ if ret == None:
+ raise OverwriteError('git commit --amend --no-edit failed(%s)' % (private_project))
+
+ ret, outs = private_gitprj._exec_git('log', ['-n1', '--pretty=%H'])
+ if ret == None:
+ raise OverwriteError('git log -n1 --pretty=%H failed(%s)' % (private_project))
+ #change overwrite_commit
+ overwrite_commit = outs.strip()
+
+ print '\n* Push %s %s %s' % (overwrite_commit, branch, private_project)
+ ret = private_gitprj._exec_git('push',['-q', 'origin', '%s:refs/for/%s' % (overwrite_commit, branch)])
+ if ret == None:
+ raise OverwriteError('git push failed(%s)' % (private_project))
+ print '\n* Submit', overwrite_commit
+ private_gerrit.review(commit = overwrite_commit, project =private_project, \
+ message = 'Submitted by system administrator', verified = 1, \
+ codereview = 2, submit = True)
+ overwrite_successs.append((private_project, '%s -> %s' %(commit, overwrite_commit)))
+ except UpstreamError, exc:
+ upstream_failures.append((project, revision, exc))
+ print 'Error:', exc
+ except OverwriteError, exc:
+ overwrite_failures.append((project, revision, exc))
+ print 'Error:', exc
+ finally:
+ if upstream_git_dir and os.path.exists(upstream_git_dir):
+ shutil.rmtree(upstream_git_dir)
+ if private_git_dir and os.path.exists(private_git_dir):
+ shutil.rmtree(private_git_dir)
+
+ if request_projects:
+ print '\n-----[ Request Mixed Git Repository List]----------'
+ print '\n'.join(str(item) for item in request_projects)
+
+ if new_private_projects:
+ print '\n-----[Does not exist Private Git Repository List]----------'
+ print '\n'.join(new_private_projects)
+
+ if overwrite_alreadys:
+ print '\n----[ Already Overwrite into %s Branch List]-----------'%(branch)
+ print '\n'.join(str(item) for item in overwrite_alreadys)
+
+ if overwrite_successs:
+ print '\n----[Overwrite into %s Branch Success List]-----------'%(branch)
+ print '\n'.join(str(item) for item in overwrite_successs)
+
+ if upstream_failures:
+ print '\n-----[Update Upstream %s Branch Failure List]----------------'%(UPSTREAM_BRANCH)
+ print '\n'.join(str(item) for item in upstream_failures)
+
+ if overwrite_failures:
+ print '\n-----[Overwrite into %s Branch Failure List]----------'%(branch)
+ print '\n'.join(str(item) for item in overwrite_failures)
+
+ #### Send mail to maintainers
+ if True:
+ ### Init MailSender ####
+ my_mail = MailSender()
+
+ my_mail.add_title('[Auto Git-Sync] Target Project:%s Branch:%s' %(target_project, branch))
+ my_mail.add_message('Hello\n A Build System infrom you about Auto Git-Sync results\n\n')
+ my_mail.add_message('Public Source Snapshot: %s Upstream Branch: %s\nTarget Project: %s\nTarget Branch: %s' \
+ %(request_snapshot, UPSTREAM_BRANCH, target_project, branch))
+
+ print 'members:',email_to_members
+ # Add maintatiners to mail
+ [my_mail.add_maintainers(private_gerrit, group_name = name) for name in email_to_members]
+
+ if new_private_projects:
+ my_mail.add_message('\n-----[Does not exist Private Git Repository List]-----------')
+ [my_mail.add_message(str(item)) for item in new_private_projects]
+
+ if overwrite_alreadys:
+ my_mail.add_message('\n----[ Already Overwrite into %s Branch List]-----------'%(branch))
+ [my_mail.add_message(str(item)) for item in overwrite_alreadys]
+
+ if overwrite_successs:
+ my_mail.add_message('\n-----[Overwrite into %s Branch Success List]-----------'%(branch))
+ [my_mail.add_message(str(item)) for item in overwrite_successs]
+
+ if upstream_failures:
+ my_mail.add_message('\n-----[Update Upstream %s Branch Failure List]-----------'%(UPSTREAM_BRANCH))
+ [my_mail.add_message(str(item)) for item in upstream_failures]
+
+ if overwrite_failures:
+ my_mail.add_message('\n-----[Overwrite into %s Branch Failure List]----------'%(branch))
+ [my_mail.add_message(str(item)) for item in overwrite_failures]
+
+ # Send mail to maintainers
+ my_mail.send_mail()
+
+
+def main():
+ """
+ Script entry point.
+ """
+
+ print '---[JOB STARTED]-------------------------'
+
+ if os.getenv('TRIGGER_INFO', None):
+ content = trigger_info(os.getenv('TRIGGER_INFO'))
+ else:
+ return
+
+ if not os.getenv('SR_SYNC_PROJECTS'):
+ print 'No SR_SYNC_PROJECTS'
+ return
+
+ enabled_projects = ast.literal_eval(os.getenv('SR_SYNC_PROJECTS'))
+
+ private_gerrit = gerrit.Gerrit(os.getenv('GERRIT_HOSTNAME'),
+ os.getenv('GERRIT_USERNAME'),
+ os.getenv('GERRIT_SSHPORT'),
+ int(os.getenv('GERRIT_SILENT_MODE')))
+
+ #print enabled_projects
+ for target in enabled_projects[content['obs_target_prj']]:
+ if target.get('git-sync') == 'Yes':
+ tmpdir = tempfile.mkdtemp(prefix=os.getenv('WORKSPACE')+'/')
+ update_sync_for_git_sync(tmpdir, private_gerrit, target, content['requests'][0], content['snapshot'])
+ else:
+ print '%s project : git-sync option is not enabled..' %(target.get('target'))
+
+if __name__ == '__main__':
+ sys.exit(main())
+
+