--- a/src/man/pkg.1.txt Mon May 10 16:08:01 2010 +0100
+++ b/src/man/pkg.1.txt Mon May 10 16:01:41 2010 -0700
@@ -356,10 +356,10 @@
search.match_type Corresponds to the attribute which contained
the string that matched the search query.
- With -p, perform the search and display the packages which contain
- at least one action which matched the query. This is equivalent to
- enclosing the entire query with '<>'. (For a description of the
- '<>' operator, please see below.)
+ With -p, display packages which have some actions that match each
+ query term. Using this option is equivalent to putting '<>' around
+ each term in the query. (For a description of the '<>' operator,
+ please see below.)
By default, and with -r, search the repositories corresponding
to the image's publishers.
--- a/src/modules/client/api.py Mon May 10 16:08:01 2010 +0100
+++ b/src/modules/client/api.py Mon May 10 16:01:41 2010 -0700
@@ -21,8 +21,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
"""This module provides the supported, documented interface for clients to
@@ -1799,10 +1798,13 @@
ssu = None
for i, q in enumerate(query_lst):
try:
- query = qp.parse(q.encoded_text())
- query_rr = qp.parse(q.encoded_text())
+ query = qp.parse(q.text)
+ query_rr = qp.parse(q.text)
if query_rr.remove_root(self.__img.root):
query.add_or(query_rr)
+ if q.return_type == \
+ query_p.Query.RETURN_PACKAGES:
+ query.propagate_pkg_return()
except query_p.BooleanQueryException, e:
raise api_errors.BooleanQueryException(e)
except query_p.ParseError, e:
@@ -1945,15 +1947,16 @@
qp = query_p.QueryParser(l)
for q in query_str_and_args_lst:
try:
- query = qp.parse(q.encoded_text())
- query_rr = qp.parse(q.encoded_text())
+ query = qp.parse(q.text)
+ query_rr = qp.parse(q.text)
if query_rr.remove_root(self.__img.root):
query.add_or(query_rr)
- new_qs.append(query_p.Query(str(query),
- q.case_sensitive, q.return_type,
- q.num_to_return, q.start_point))
- else:
- new_qs.append(q)
+ if q.return_type == \
+ query_p.Query.RETURN_PACKAGES:
+ query.propagate_pkg_return()
+ new_qs.append(query_p.Query(str(query),
+ q.case_sensitive, q.return_type,
+ q.num_to_return, q.start_point))
except query_p.BooleanQueryException, e:
raise api_errors.BooleanQueryException(e)
except query_p.ParseError, e:
@@ -2093,7 +2096,7 @@
l.build()
qp = query_p.QueryParser(l)
try:
- query = qp.parse(q.encoded_text())
+ query = qp.parse(q.text)
except query_p.BooleanQueryException, e:
return api_errors.BooleanQueryException(e)
except query_p.ParseError, e:
--- a/src/modules/client/query_parser.py Mon May 10 16:08:01 2010 +0100
+++ b/src/modules/client/query_parser.py Mon May 10 16:01:41 2010 -0700
@@ -19,8 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
import sys
import threading
@@ -83,6 +82,12 @@
else:
return "<(a AND b)>"
+ def propagate_pkg_return(self):
+ """Makes this node return packages instead of actions.
+ Returns None because no changes need to be made to the tree."""
+ self.return_type = qp.Query.RETURN_PACKAGES
+ return None
+
class OrQuery(qp.OrQuery):
def remove_root(self, img_dir):
--- a/src/modules/query_parser.py Mon May 10 16:08:01 2010 +0100
+++ b/src/modules/query_parser.py Mon May 10 16:01:41 2010 -0700
@@ -21,8 +21,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#
import os
@@ -458,7 +457,7 @@
The "start_point" parameter is the number of results to skip
before returning results to the querier."""
- self.__text = text
+ self.text = text
self.case_sensitive = case_sensitive
self.return_type = return_type
assert self.return_type == Query.RETURN_PACKAGES or \
@@ -471,18 +470,7 @@
return "%s_%s_%s_%s_%s" % (self.case_sensitive,
self.return_type, self.num_to_return, self.start_point,
- self.__text)
-
- def ver_0(self):
- """Return the v0 string representation of this query."""
-
- return self.__text
-
- def encoded_text(self):
- if self.return_type == Query.RETURN_PACKAGES:
- return "<%s>" % self.__text
- else:
- return self.__text
+ self.text)
@staticmethod
def fromstr(s):
@@ -585,6 +573,9 @@
self.lc = left_query
self.rc = right_query
self.return_type = self.lc.return_type
+ self.__check_return_types()
+
+ def __check_return_types(self):
if self.lc.return_type != self.rc.return_type:
if self.lc.return_type == Query.RETURN_ACTIONS:
raise BooleanQueryException(self.lc, self.rc)
@@ -625,6 +616,22 @@
return v > 0 and self.lc.allow_version(v) and \
self.rc.allow_version(v)
+ def propagate_pkg_return(self):
+ """Makes each child return packages instead of actions.
+
+ If a child returns a value that isn't None, that means a new
+ node in the tree has been created which needs to become the
+ new child for this node."""
+ self.return_type = Query.RETURN_PACKAGES
+ new_lc = self.lc.propagate_pkg_return()
+ if new_lc:
+ self.lc = new_lc
+ new_rc = self.rc.propagate_pkg_return()
+ if new_rc:
+ self.rc = new_rc
+ self.__check_return_types()
+ return None
+
class AndQuery(BooleanQuery):
"""Class representing AND queries in the AST."""
@@ -768,6 +775,10 @@
return v > 0 and self.query.allow_version(v)
+ def propagate_pkg_return(self):
+ """Makes this node return packages instead of actions.
+ Returns None because no changes need to be made to the tree."""
+ return None
class PhraseQuery(object):
"""Class representing a phrase search in the AST"""
@@ -788,11 +799,23 @@
self.query.add_trailing_wildcard()
self._case_sensitive = None
+ @property
+ def pkg_name(self):
+ return self.query.pkg_name
+
+ @property
+ def action_type(self):
+ return self.query.action_type
+
+ @property
+ def key(self):
+ return self.query.key
+
def __repr__(self):
return "Phrase Query:'" + self.full_str + "'"
def __str__(self):
- return "'" + self.full_str + "'"
+ return "%s:'%s'" % (self.query.field_strings(), self.full_str)
def add_field_restrictions(self, *params):
self.query.add_field_restrictions(*params)
@@ -847,6 +870,14 @@
"""Returns whether the query supports a query of version v."""
return v > 0 and self.query.allow_version(v)
+
+ def propagate_pkg_return(self):
+ """Inserts a conversion to package results into the tree.
+
+ Creates a new node by wrapping a PkgConversion node around
+ itself. It then returns the new node to its parent for
+ insertion into the tree."""
+ return PkgConversion(self)
class FieldQuery(object):
"""Class representing a structured query in the AST."""
@@ -895,6 +926,14 @@
return v > 0 and self.query.allow_version(v)
+ def propagate_pkg_return(self):
+ """Inserts a conversion to package results into the tree.
+
+ Creates a new node by wrapping a PkgConversion node around
+ itself. It then returns the new node to its parent for
+ insertion into the tree."""
+ return PkgConversion(self)
+
class TopQuery(object):
"""Class which must be at the top of all valid ASTs, and may only be
at the top of an AST. It handles starting N results in, or only
@@ -929,7 +968,8 @@
if self.query.return_type == Query.RETURN_ACTIONS:
return (
- (1, Query.RETURN_ACTIONS, (fmri.PkgFmri(pfmri), fv, l))
+ (1, Query.RETURN_ACTIONS,
+ (fmri.PkgFmri(pfmri), fv, l))
for x, (at, st, pfmri, fv, l)
in enumerate(it)
if self.__keep(x)
@@ -967,6 +1007,17 @@
"""Returns whether the query supports a query of version v."""
return self.query.allow_version(v)
+
+ def propagate_pkg_return(self):
+ """Makes the child return packages instead of actions.
+
+ If a child returns a value that isn't None, that means a new
+ node in the tree has been created which needs to become the
+ new child for this node."""
+ new_child = self.query.propagate_pkg_return()
+ if new_child:
+ self.query = new_child
+ return None
class TermQuery(object):
"""Class representing the a single query term in the AST."""
@@ -1028,19 +1079,31 @@
return "( TermQuery: " + self._term + " )"
def __str__(self):
+ return "%s:%s" % (self.field_strings(),
+ self.__wc_to_string(False, self._term))
+
+ def field_strings(self):
return ":".join([
self.__wc_to_string(wc, v)
for wc, v in [(self.pkg_name_wildcard, self.pkg_name),
(self.action_type_wildcard, self.action_type),
- (self.key_wildcard, self.key), (False, self._term)
+ (self.key_wildcard, self.key)
]
])
+ def propagate_pkg_return(self):
+ """Inserts a conversion to package results into the tree.
+
+ Creates a new node by wrapping a PkgConversion node around
+ itself. It then returns the new node to its parent for
+ insertion into the tree."""
+ return PkgConversion(self)
+
@staticmethod
def __wc_to_string(wc, v):
if wc:
return ""
- return v
+ return "\\:".join(v.split(":"))
def add_field_restrictions(self, pkg_name, action_type, key):
"""Add the information needed to restrict the search domain
--- a/src/modules/server/repository.py Mon May 10 16:08:01 2010 +0100
+++ b/src/modules/server/repository.py Mon May 10 16:01:41 2010 -0700
@@ -19,8 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
import datetime
import errno
@@ -1288,7 +1287,7 @@
l = query_p.QueryLexer()
l.build()
qp = query_p.QueryParser(l)
- query = qp.parse(q.encoded_text())
+ query = qp.parse(q.text)
query.set_info(num_to_return=q.num_to_return,
start_point=q.start_point,
index_dir=self.index_root,
--- a/src/tests/cli/t_pkg_search.py Mon May 10 16:08:01 2010 +0100
+++ b/src/tests/cli/t_pkg_search.py Mon May 10 16:01:41 2010 -0700
@@ -21,8 +21,7 @@
#
#
-# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
import testutils
@@ -501,18 +500,18 @@
# Testing interaction of -o and -p options
self.pkgsend_bulk(durl, self.example_pkg10)
self.pkg("search -o action.name -p pkg", exit=2)
- self.pkg("search -o action.name '<pkg>'", exit=1)
- self.pkg("search -o action.name '<example_path>'", exit=2)
+ self.pkg("search -o action.name -a '<pkg>'", exit=1)
+ self.pkg("search -o action.name -a '<example_path>'", exit=2)
self.pkg("search -o action.key -p pkg", exit=2)
- self.pkg("search -o action.key '<pkg>'", exit=1)
- self.pkg("search -o action.key '<example_path>'", exit=2)
+ self.pkg("search -o action.key -a '<pkg>'", exit=1)
+ self.pkg("search -o action.key -a '<example_path>'", exit=2)
self.pkg("search -o search.match -p pkg", exit=2)
- self.pkg("search -o search.match '<pkg>'", exit=1)
- self.pkg("search -o search.match '<example_path>'", exit=2)
+ self.pkg("search -o search.match -a '<pkg>'", exit=1)
+ self.pkg("search -o search.match -a '<example_path>'", exit=2)
self.pkg("search -o search.match_type -p pkg", exit=2)
- self.pkg("search -o search.match_type '<pkg>'", exit=1)
- self.pkg("search -o search.match_type '<example_path>'", exit=2)
- self.pkg("search -o action.foo pkg", exit=2)
+ self.pkg("search -o search.match_type -a '<pkg>'", exit=1)
+ self.pkg("search -o search.match_type -a '<example_path>'", exit=2)
+ self.pkg("search -o action.foo -a pkg", exit=2)
def test_remote(self):
"""Test remote search."""
@@ -764,18 +763,18 @@
self.image_create(durl)
- self.pkg("search 'dup_lines:set:pkg.fmri:'")
+ self.pkg("search -a 'dup_lines:set:pkg.fmri:'")
self.assertEqual(len(self.output.splitlines()), 2)
- self.pkg("search -o pkg.shortfmri 'a'")
+ self.pkg("search -a -o pkg.shortfmri 'a'")
self.assertEqual(len(self.output.splitlines()), 2)
self.pkg("install dup_lines")
- self.pkg("search -l 'dup_lines:set:pkg.fmri:'")
+ self.pkg("search -a -l 'dup_lines:set:pkg.fmri:'")
self.assertEqual(len(self.output.splitlines()), 2)
- self.pkg("search -l -o pkg.shortfmri,action.key 'a'")
+ self.pkg("search -l -a -o pkg.shortfmri,action.key 'a'")
self.assertEqual(len(self.output.splitlines()), 4)
if __name__ == "__main__":