diff --git a/NEWS b/NEWS index ee3ea8cc..fc662d8f 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ * Use 'osc ls /' if you really want to list all projects. * This is meant as a proof of concept. I intend to generalize this usage of '.' for all osc commands. Feedback welcome. + # + # Features which require OBS 1.7 + # + - search: allow to limit results via existing attibutes 0.123 - IMPORTANT: ssl certificate checks are actually performed now to diff --git a/osc/commandline.py b/osc/commandline.py index 1a54efcc..943c0ca1 100755 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -3064,6 +3064,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='search for matches in the \'title\' element') @cmdln.option('--description', action='store_true', help='search for matches in the \'description\' element') + @cmdln.option('-a', '--limit-to-attribute', metavar='ATTRIBUTE', + help='match only when given attribute exists in meta data') @cmdln.option('-v', '--verbose', action='store_true', help='show more information') @cmdln.option('-i', '--involved', action='store_true', @@ -3115,6 +3117,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. search_list = [] search_for = [] + extra_limiter = "" if opts.title: search_list.append('title') if opts.description: @@ -3125,6 +3128,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.project: search_list.append('@name') search_for.append('project') + if opts.limit_to_attribute: + extra_limiter='attribute/@name="%s"' % (opts.limit_to_attribute) + role_filter=None if for_user: @@ -3141,7 +3147,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not search_for: search_for = [ 'project', 'package' ] for kind in search_for: - result = search(conf.config['apiurl'], set(search_list), kind, search_term, opts.verbose, opts.exact, opts.repos_baseurl, role_filter) + result = search(conf.config['apiurl'], set(search_list), kind, search_term, opts.verbose, opts.exact, opts.repos_baseurl, role_filter, extra_limiter) if not result: print 'No matches found for \'%s\' in %ss' % (role_filter or search_term, kind) diff --git a/osc/core.py b/osc/core.py index 8b5282ec..e34e792b 100755 --- a/osc/core.py +++ b/osc/core.py @@ -3747,19 +3747,23 @@ def checkRevision(prj, pac, revision, apiurl=None): except (ValueError, TypeError): return False -def build_xpath_predicate(search_list, search_term, exact_matches): +def build_xpath_predicate(search_list, search_term, exact_matches, extra_limiter): """ Builds and returns a xpath predicate """ predicate = ['['] for i, elem in enumerate(search_list): + predicate.append('(') if i > 0 and i < len(search_list): predicate.append(' or ') if exact_matches: predicate.append('%s=\'%s\'' % (elem, search_term)) else: predicate.append('contains(%s, \'%s\')' % (elem, search_term)) + if extra_limiter: + predicate.append(' and %s' % (extra_limiter)) + predicate.append(')') predicate.append(']') return predicate @@ -3811,7 +3815,7 @@ def build_table(col_num, data = [], headline = [], width=1, csv = False): separator = '' return [separator.join(row) for row in table] -def search(apiurl, search_list, kind, search_term, verbose = False, exact_matches = False, repos_baseurl = False, role_filter = None): +def search(apiurl, search_list, kind, search_term, verbose = False, exact_matches = False, repos_baseurl = False, role_filter = None, extra_limiter = None): """ Perform a search for 'search_term'. A list which contains the results will be returned on success otherwise 'None'. If 'verbose' is true @@ -3822,7 +3826,7 @@ def search(apiurl, search_list, kind, search_term, verbose = False, exact_matche if role_filter: role_filter = role_filter.split(':') - predicate = build_xpath_predicate(search_list, search_term, exact_matches) + predicate = build_xpath_predicate(search_list, search_term, exact_matches, extra_limiter) u = makeurl(apiurl, ['search', kind], ['match=%s' % quote_plus(''.join(predicate))]) f = http_GET(u) root = ET.parse(f).getroot()