diff --git a/ui/fixtures/cmd.search.json b/ui/fixtures/cmd.search.json new file mode 100644 index 0000000..13c08e7 --- /dev/null +++ b/ui/fixtures/cmd.search.json @@ -0,0 +1,35 @@ +[ +{ + "title": "gen ident", + "cmd": [ "genident", "name=A Test User" ], + "exit": 0 +}, +{ + "title": "add tag a", + "cmd": [ "modify", "+tag=foo", "+dc:creator=John-Mark Gurney", "newfile.txt" ] +}, +{ + "title": "add tag b", + "cmd": [ "modify", "+tag=bar", "+dc:creator=John-Mark Gurney", "test.txt" ] +}, +{ + "special": "verify store object cnt", + "comment": "should have two file and two metadata", + "count": 4 +}, +{ + "title": "search tag foo", + "cmd": [ "search", "file", "+tag=foo" ], + "stdout_re": "/newfile.txt\n$" +}, +{ + "title": "search tag bar", + "cmd": [ "search", "file", "+tag=bar" ], + "stdout_re": "/test.txt\n$" +}, +{ + "title": "search no tag bar", + "cmd": [ "search", "file", "-tag=bar" ], + "stdout_re": "/newfile.txt\n$" +} +] diff --git a/ui/medashare/cli.py b/ui/medashare/cli.py index c43e5b3..9193662 100644 --- a/ui/medashare/cli.py +++ b/ui/medashare/cli.py @@ -685,6 +685,10 @@ class FileObject(MDBase): 'mtime': _makedatetime, } + @property + def fullname(self): + return os.path.join(self.dir, self.filename) + @staticmethod def make_id(fname, hostid=None): '''Take a local file name, and make the id for it. Note that @@ -1410,6 +1414,45 @@ def cmd_drop(options, persona, objstr, cache): for i in options.uuids: objstr.drop_uuid(i) +@init_datastructs +def cmd_search(options, persona, objstr, cache): + args = options.args.copy() + + _type = args.pop(0) + + searches = [ (x[0], ) + tuple(x[1:].split('=', 1)) for x in args ] + #print(repr(searches), file=_real_stderr) + + def testfun(x, s=searches): + try: + for i in s: + op, key, value = i + if op == '+': + if value not in x[key]: + return False + elif op == '-': + if value in x[key]: + return False + else: + raise ValueError('unhandled op: %s' % repr(op)) + else: + return True + + except KeyError: + return False + + r = [ x for x in objstr if x.type == 'metadata' and testfun(x) ] + + if _type == 'file': + r = [ objstr.by_hash(x['hashes'][0]) for x in r ] + r = [ [ y for y in x if y['type'] == 'file' ] for x in r ] + r = sum(r, []) + r = [ x.fullname for x in r ] + else: + raise ValueError('unhandled type: %s' % repr(_type)) + + print('\n'.join(r)) + def main(): import argparse @@ -1495,6 +1538,12 @@ def main(): help='UUID of object to drop') parser_drop.set_defaults(func=cmd_drop) + parser_search = subparsers.add_parser('search', + help='find objects', prefix_chars='@') + parser_search.add_argument('args', nargs='+', + help='args') + parser_search.set_defaults(func=cmd_search) + options = parser.parse_args() fun = options.func