From 8d8d72a21ffaea111e426ce09d748274bf8f8edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Thu, 22 Nov 2012 11:37:32 +0100 Subject: [PATCH] - support default maintainer/bugowner search based on binary package names --- NEWS | 6 +- osc/commandline.py | 140 ++++++++++++++++++++++++++++++--------------- osc/core.py | 26 +++++++++ 3 files changed, 124 insertions(+), 48 deletions(-) diff --git a/NEWS b/NEWS index 3e0724d5..4684300c 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ 0.137 - - support delete requests for repositories. - support single binary download via getbinaries command +# +# Features which requires OBS 2.4 +# + - support delete requests for repositories. + - support default maintainer/bugowner search based on binary package names 0.136 - prefer TLS v1.1 or v1.2 if available diff --git a/osc/commandline.py b/osc/commandline.py index 87cfb68c..597e3ecf 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -6444,9 +6444,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. def do_bugowner(self, subcmd, opts, *args): """${cmd_name}: Show bugowners of a project/package + osc bugowner + osc bugowner BINARY osc bugowner PRJ osc bugowner PRJ PKG + The tool looks up the default responsible person for a certain project or package, + but limits the search to bugowner settings. + When using with an OBS 2.4 (or later) server it is doing the lookup for + a given binary according to the server side configuration of default owners. + PRJ and PKG default to current working-copy path. Prints bugowner if defined, or maintainer otherwise. @@ -6461,11 +6468,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. opts.delete = None opts.devel_project = None - if len(args) == 1: - def_p = find_default_project(self.get_api_url(), args[0]) - print >>sys.stderr, 'defaulting to %s/%s' % (def_p, args[0]) - # python has no args.unshift ??? - args = [ def_p, args[0] ] return self.do_maintainer(subcmd, opts, *args) @@ -6491,18 +6493,26 @@ Please submit there instead, or use --nodevelproject to force direct submission. def do_maintainer(self, subcmd, opts, *args): """${cmd_name}: Show maintainers of a project/package + osc maintainer + osc maintainer BINARY osc maintainer PRJ osc maintainer PRJ PKG + The tool looks up the default responsible person for a certain project or package. + When using with an OBS 2.4 (or later) server it is doing the lookup for + a given binary according to the server side configuration of default owners. + PRJ and PKG default to current working-copy path. ${cmd_usage} ${cmd_option_list} """ - pac = None + binary = None prj = None - root = None + pac = None + metaroot = None + searchresult = None roles = [ 'bugowner', 'maintainer' ] if len(opts.role): roles = opts.role @@ -6516,7 +6526,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. pass prj = store_read_project('.') elif len(args) == 1: - prj = args[0] + # it is unclear if one argument is a binary or a project, try binary first for new OBS 2.4 + binary = prj = args[0] elif len(args) == 2: prj = args[0] pac = args[1] @@ -6537,58 +6548,93 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: if pac: m = show_package_meta(apiurl, prj, pac) - root = ET.fromstring(''.join(m)) + metaroot = ET.fromstring(''.join(m)) if not opts.nodevelproject: - while root.findall('devel'): - d = root.find('devel') + while metaroot.findall('devel'): + d = metaroot.find('devel') prj = d.get('project', prj) pac = d.get('package', pac) if opts.verbose: print "Following to the development space: %s/%s" % (prj, pac) m = show_package_meta(apiurl, prj, pac) - root = ET.fromstring(''.join(m)) - if not root.findall('person'): + metaroot = ET.fromstring(''.join(m)) + if not metaroot.findall('person'): if opts.verbose: print "No dedicated persons in package defined, showing the project persons." pac = None m = show_project_meta(apiurl, prj) - root = ET.fromstring(''.join(m)) + metaroot = ET.fromstring(''.join(m)) else: - m = show_project_meta(apiurl, prj) - root = ET.fromstring(''.join(m)) + # Try the OBS 2.4 way first + if binary: + searchresult = owner(apiurl, binary, usefilter=roles) + # fallback to project lookup for old servers + if not searchresult: + m = show_project_meta(apiurl, prj) + metaroot = ET.fromstring(''.join(m)) + + # extract the maintainers + projects = [] + # from owner search + if searchresult: + for result in searchresult.findall('owner'): + maintainers = {} + maintainers.setdefault("project", result.get('project')) + maintainers.setdefault("package", result.get('package')) + for person in result.findall('person'): + maintainers.setdefault(person.get('role'), []).append(person.get('name')) + projects = projects + [maintainers] + # from meta data + if metaroot: + # we have just one result + maintainers = {} + for person in metaroot.findall('person'): + maintainers.setdefault(person.get('role'), []).append(person.get('userid')) + projects = [maintainers] # showing the maintainers - maintainers = {} - for person in root.findall('person'): - maintainers.setdefault(person.get('role'), []).append(person.get('userid')) - for role in roles: - if opts.bugowner and not len(maintainers.get(role, [])): - role = 'maintainer' - if pac: - print "%s of %s/%s : " %(role, prj, pac) - else: - print "%s of %s : " %(role, prj) - if opts.email: - emails = [] - for maintainer in maintainers.get(role, []): - user = get_user_data(apiurl, maintainer, 'email') - if len(user): - emails.append(''.join(user)) - print ', '.join(emails) or '-' - elif opts.verbose: - userdata = [] - for maintainer in maintainers.get(role, []): - user = get_user_data(apiurl, maintainer, 'login', 'realname', 'email') - userdata.append(user[0]) - if user[1] != '-': - userdata.append("%s <%s>"%(user[1], user[2])) - else: - userdata.append(user[2]) - for row in build_table(2, userdata, None, 3): - print row - else: - print ', '.join(maintainers.get(role, [])) or '-' - print + for maintainers in projects: + indent="" + definingproject=maintainers.get("project") + if definingproject: + definingpackage=maintainers.get("package") + indent=" " + if definingpackage: + print "Defined in package: %s/%s " %(definingproject, definingpackage) + else: + print "Defined in project: ", definingproject + + for role in roles: + if opts.bugowner and not len(maintainers.get(role, [])): + role = 'maintainer' + if pac: + print "%s%s of %s/%s : " %(indent, role, prj, pac) + else: + print "%s%s of %s : " %(indent, role, prj) + if opts.email: + emails = [] + for maintainer in maintainers.get(role, []): + user = get_user_data(apiurl, maintainer, 'email') + if len(user): + emails.append(''.join(user)) + print indent, + print ', '.join(emails) or '-' + elif opts.verbose: + userdata = [] + for maintainer in maintainers.get(role, []): + user = get_user_data(apiurl, maintainer, 'login', 'realname', 'email') + userdata.append(user[0]) + if user[1] != '-': + userdata.append("%s <%s>"%(user[1], user[2])) + else: + userdata.append(user[2]) + for row in build_table(2, userdata, None, 3): + print indent, + print row + else: + print indent, + print ', '.join(maintainers.get(role, [])) or '-' + print @cmdln.alias('who') @cmdln.alias('user') diff --git a/osc/core.py b/osc/core.py index be7b9643..a73e69c6 100644 --- a/osc/core.py +++ b/osc/core.py @@ -5653,6 +5653,32 @@ def search(apiurl, **kwargs): res[urlpath] = ET.parse(f).getroot() return res +def owner(apiurl, binary, attribute=None, project=None, usefilter=None, devel=None, limit=None): + """ + Perform a binary package owner search. This is supported since OBS 2.4. + """ + # find default project, if not specified + query = { 'binary': binary } + if attribute: + query['attribute'] = attribute + if project: + query['project'] = project + if devel: + query['devel'] = devel + if limit: + query['limit'] = limit + if usefilter: + query['filter'] = ",".join(usefilter) + u = makeurl(apiurl, [ 'search', 'owner' ], query) + res = None + try: + f = http_GET(u) + res = ET.parse(f).getroot() + except urllib2.HTTPError, e: + # old server not supporting this search + pass + return res + def set_link_rev(apiurl, project, package, revision='', expand=False, baserev=False): """ updates the rev attribute of the _link xml. If revision is set to None