From 4a3e00f574c3a977e1e18b6a311c4c66ce3bda56 Mon Sep 17 00:00:00 2001 From: Ed Bartosh Date: Fri, 12 Dec 2014 16:43:51 +0200 Subject: [PATCH] Reworked repa diff Now repa diff uses _service:gbs:_git-meta to get tags from compare project. It makes it much faster and reliable than previously. Fixes: #1869 Change-Id: I5b11845afe2c73b2de38cb830d050fb57742c0ed Signed-off-by: Ed Bartosh --- repa.1 | 20 +++++------ repa/common.py | 7 ++++ repa/diff.py | 105 ++++++++++++++++++++++++++++----------------------------- repa/obs.py | 18 ++++++++++ 4 files changed, 86 insertions(+), 64 deletions(-) diff --git a/repa.1 b/repa.1 index 6a14762..c4674ef 100644 --- a/repa.1 +++ b/repa.1 @@ -314,31 +314,31 @@ Print short help text about the "rmgroup" command and exit. .\" .\" The "diff" command description .\" -.SS \fBdiff\fR [\-\-help] +.SS \fBdiff\fR [\-\-help] .RS 2 -Show the difference between manifest of target project and manifest of in the following format: +Show the difference between manifest of target project and manifest of in the following format: - + .RS 0 Example of output: $ repa -p Tizen:IVI diff Tizen:Common ivi_0140508.2_ia32.xml common_20140507.5_ia32.xml -platform/core/appfw/aul-1 3644ad5459 e4f2b22012 submit/tizen/20140502.084937 pending +platform/core/appfw/aul-1 3644ad5459 e4f2b22012 submit/tizen/20140502.084937 .RS 0 -platform/core/appfw/shortcut 502c7807b3 27bbf892e0 submit/tizen/20140430.020549 pending +platform/core/appfw/shortcut 502c7807b3 27bbf892e0 submit/tizen/20140430.020549 .RS 0 -platform/core/connectivity/nfc-manager-neard ea952dc454 88793ab1ff +platform/core/connectivity/nfc-manager-neard ea952dc454 88793ab1ff None .RS 0 -platform/core/connectivity/smartcard-service e45ae0bdfb 7d5da70551 submit/tizen/20140506.101200 pending +platform/core/connectivity/smartcard-service e45ae0bdfb 7d5da70551 submit/tizen/20140506.101200 .RS 0 -platform/core/messaging/msg-service c988cc8b55 a9eed6a734 submit/tizen/20140502.105814 pending +platform/core/messaging/msg-service c988cc8b55 a9eed6a734 submit/tizen/20140502.105814 .RS 0 -platform/core/system/tlm 3ddbc6bc14 dc72779317 submit/tizen/20140430.130050 +platform/core/system/tlm 3ddbc6bc14 None submit/tizen/20140430.130050 .RS 0 -platform/framework/web/crosswalk 42dcc1327b 4280e52757 submit/tizen/20140506.123703 pending +platform/framework/web/crosswalk 42dcc1327b 4280e52757 submit/tizen/20140506.123703 .RS 0 Status 'pending' means that submission is pending for the target project. In colorized mode pending submissions are colorized and 'pending' status is not shown. diff --git a/repa/common.py b/repa/common.py index 630dc6a..c98b1ed 100644 --- a/repa/common.py +++ b/repa/common.py @@ -45,6 +45,13 @@ def get_prerelease_projects(obs, target_prj, tag=None): """Get list of prerelease projects for specified target project.""" return obs.get_project_list('^%s%s:' % (OBS_PROJECT_PREFIX, target_prj)) +def prerelease_exists(obs, name, target): + """Check if prerelease project exists.""" + if name.startswith('submitgroup/'): + name += '-group' + project = '%s%s:%s' % (OBS_PROJECT_PREFIX, target, name.replace('/', ':')) + return obs.exists(project) + def get_project_by_name(obs, name, target): """Lookup for a project in OBS by submission or group name.""" if name.startswith('submitgroup/'): diff --git a/repa/diff.py b/repa/diff.py index 5863470..613ec01 100644 --- a/repa/diff.py +++ b/repa/diff.py @@ -29,7 +29,7 @@ import json import xml.etree.ElementTree as ET -from repa.common import RepaException, Colorizer, get_prerelease_projects +from repa.common import RepaException, Colorizer, get_prerelease from repa.obs import OBS from repa.main import sub_main @@ -44,58 +44,55 @@ def gen_data(manifest): for project in etree.getroot().findall('project'): yield project.get('path'), project.get('revision') - -def get_tag(obs, project, package, revision): - """Get tag from the latest accepted SR.""" - for sreq in obs.get_srs(project, 'accepted', package): - descr = sreq[-1] - if descr and 'Commit: %s' % revision in descr: - return descr.split('Tag: ')[-1].split()[0] - return 'Not found' - - -def get_pending(obs, target_proj): - """Get pair of git path: tag for pending prerelease projects.""" - result = {} - for proj in get_prerelease_projects(obs, target_proj): - meta = json.loads(obs.get_description(proj)) - for path in meta["projects"]: - result[path] = meta["git_tag"] - return result - - -def diff(obs, target_project, project1, target_manifest, manifest1, - is_colorize=False): - """Show the difference between project1 and project2.""" +def get_tag(obs, project, package): + """Get tag from _git-meta file in target project.""" + context = obs.get_file(project, package, "_service:gbs:_git-meta") + if not context: + return None + try: + data = json.loads(context) + except ValueError: + return None + if "tag" in data: + return data["tag"]["tagname"] + + return None + +def diff(obs, cmp_project, target_project, cmp_manifest, + target_manifest, is_colorize=False): + """ + Show the difference between two projects in terms of + revisions and tags. + """ colorizer = Colorizer(is_colorize) target_data = dict(gen_data(target_manifest)) - data1 = dict(gen_data(manifest1)) - - pending = get_pending(obs, target_project) - - for path in sorted(data1): - # if submission is not pending in target project - # and revisions are the same - skip it - if path not in pending and \ - (path in target_data and data1[path] == target_data[path]): - continue - - package = os.path.basename(path) - tag1 = get_tag(obs, project1, package, data1[path]) - target_tag = get_tag(obs, target_project, package, - target_data.get(path)) - - if tag1 in pending.values(): - if is_colorize: - tag1 = colorizer.green(tag1) - else: - tag1 += ' ready' - print "%-50s %s %s %-37s %-37s %s" % \ - (path, target_data.get(path, 'Not found ')[:10], - data1[path][:10], target_tag, tag1, - pending.get(path, 'Not found')) - + cmp_data = dict(gen_data(cmp_manifest)) + + for path in sorted(cmp_data): + rev_target = target_data.get(path) + rev_cmp = cmp_data[path] + if rev_target != rev_cmp: + package = os.path.basename(path) + + # Get tag, accepted to cmp_project + cmp_tag = get_tag(obs, cmp_project, package) + status = '' + # Colorize tag if it's pending in target project + if cmp_tag: + try: + prerelease = get_prerelease(cmp_tag, target_project) + if obs.exists(prerelease): + if is_colorize: + cmp_tag = colorizer.green(cmp_tag) + else: + status = 'pending' + except RepaException: + pass + + print "%-55s %-12s %-12s %-40s %s" % (path, rev_cmp[:10], + str(rev_target)[:10], + cmp_tag, status) class Diff(object): """Subcommand: diff projects.""" @@ -107,16 +104,16 @@ class Diff(object): @staticmethod def add_arguments(parser, _config): """Adds arguments to the parser. Called from [sub_]main.""" - parser.add_argument('project1', help='Compared OBS project') + parser.add_argument('cmp_project', help='Compared OBS project') + parser.add_argument('cmp_manifest', help='Manifest of compared project') parser.add_argument('manifest', help='Manifest of current project') - parser.add_argument('manifest1', help='Manifest of compared project') @staticmethod def run(argv): """Command line entry point. Called from [sub_]main.""" obs = OBS(argv.apiurl, argv.apiuser, argv.apipasswd) - return diff(obs, argv.project, argv.project1, - argv.manifest, argv.manifest1, argv.colorize) + return diff(obs, argv.cmp_project, argv.project, + argv.cmp_manifest, argv.manifest, argv.colorize) if __name__ == '__main__': sys.exit(sub_main(sys.argv[1:], Diff())) diff --git a/repa/obs.py b/repa/obs.py index dd3d373..6cfd810 100644 --- a/repa/obs.py +++ b/repa/obs.py @@ -36,6 +36,7 @@ should be contributed to oscapi. import sys import re import cgi +import locale from base64 import b64encode from xml.etree import cElementTree as ET @@ -239,3 +240,20 @@ class OBS(OSC): elem.clear() ET.SubElement(elem, value) self.set_meta(ET.tostring(root), prj, pkg) + + def get_file(self, prj, pkg, fname, rev=None): + """Get file content from OBS.""" + query = {'expand': 1} + if rev: + query['rev'] = rev + encoded_fname = core.pathname2url( + fname.encode(locale.getpreferredencoding(), 'replace')) + url = core.makeurl(self.apiurl, + ['source', prj, pkg, encoded_fname], + query=query) + try: + return self.core_http(core.http_GET, url).read() + except OSCError as error: + if error.message == "HTTP Error 404: Not Found": + return None + raise -- 2.7.4