|
|
@@ -1630,9 +1630,48 @@ def cmd_drop(options, persona, objstr, cache): |
|
|
|
for i in options.uuids: |
|
|
|
objstr.drop_uuid(i) |
|
|
|
|
|
|
|
def do_xargs_escape(s): |
|
|
|
sset = set(s) |
|
|
|
escapeset = set(' \t\n"\'\\') |
|
|
|
if not (escapeset & sset): |
|
|
|
return s |
|
|
|
|
|
|
|
needescape = sset & escapeset |
|
|
|
|
|
|
|
if '\n' not in needescape and len(needescape & set('"\'')) <= 1: |
|
|
|
# simple escape works |
|
|
|
if "'" in sset and '"' not in sset: |
|
|
|
escape_char = '"' |
|
|
|
else: |
|
|
|
escape_char = "'" |
|
|
|
return escape_char + s + escape_char |
|
|
|
elif '\n' not in needescape: |
|
|
|
# be lazy and escape everything with backslash |
|
|
|
return re.sub('([%s\\\\])' % ''.join(escapeset - set('\\')), r'\\\1', s) |
|
|
|
|
|
|
|
# XXX handle s w/ both ' and " |
|
|
|
|
|
|
|
# split on new lines, as they have to be manually escaped |
|
|
|
segs = (do_xargs_escape(x) for x in s.split('\n')) |
|
|
|
|
|
|
|
return '\\\n'.join(segs) |
|
|
|
|
|
|
|
@init_datastructs |
|
|
|
def cmd_search(options, persona, objstr, cache): |
|
|
|
args = options.args.copy() |
|
|
|
do_xargs = False |
|
|
|
|
|
|
|
while args[0].startswith('--'): |
|
|
|
if args[0] == '--help': |
|
|
|
options.search_argparser.print_help() |
|
|
|
sys.exit(0) |
|
|
|
elif args[0] == '--xargs': |
|
|
|
do_xargs = True |
|
|
|
args.pop(0) |
|
|
|
else: |
|
|
|
print('Unknown option: %s' % args[0], file=sys.stderr) |
|
|
|
options.search_argparser.print_usage(sys.stderr) |
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
_type = args.pop(0) |
|
|
|
|
|
|
@@ -1822,7 +1861,16 @@ def cmd_search(options, persona, objstr, cache): |
|
|
|
else: |
|
|
|
raise ValueError('unhandled type: %s' % repr(_type)) |
|
|
|
|
|
|
|
printed_warning = False |
|
|
|
for i in r: |
|
|
|
i = str(i) |
|
|
|
if do_xargs: |
|
|
|
i = do_xargs_escape(i) |
|
|
|
elif '\n' in i: |
|
|
|
if not printed_warning: |
|
|
|
print('Warning: file with neline in name was skipped.', file=sys.stderr) |
|
|
|
printed_warning = True |
|
|
|
continue |
|
|
|
print(i) |
|
|
|
|
|
|
|
def main(): |
|
|
@@ -1936,6 +1984,7 @@ def main(): |
|
|
|
parser_search.set_defaults(func=cmd_search) |
|
|
|
|
|
|
|
options = parser.parse_args() |
|
|
|
options.search_argparser = parser_search |
|
|
|
|
|
|
|
if options.debug: |
|
|
|
enable_debug() |
|
|
@@ -2105,6 +2154,23 @@ class _TestMigrations(unittest.IsolatedAsyncioTestCase): |
|
|
|
|
|
|
|
self.assertEqual(c, 2) |
|
|
|
|
|
|
|
class _TestPureFunctions(unittest.TestCase): |
|
|
|
def test_do_xargs_escape(self): |
|
|
|
# To verify with xargs: |
|
|
|
# a, b = testcase |
|
|
|
# proc = subprocess.run('xargs -n 1 -J % printf %s %'.split(), |
|
|
|
# input=a.encode('utf-8'), stdout=subprocess.PIPE) |
|
|
|
# b == proc.stdout.decode('utf-8') |
|
|
|
for s, es in [ |
|
|
|
('"foo', "'\"foo'"), |
|
|
|
("'bar", '"\'bar"'), |
|
|
|
('dfkj sdfkj', "'dfkj sdfkj'"), |
|
|
|
('dfkj\nsdfkj', "dfkj\\\nsdfkj"), |
|
|
|
('dfkj\n', "dfkj\\\n"), |
|
|
|
('d f\'k\\j\n\\\n\'\n"\n\', "dfkj\\\n', '"d f\'k\\j"\\\n\'\\\'\\\n"\'"\\\n\'"\'\\\n\\\',\\ \\"dfkj\\\\\\\n'), |
|
|
|
]: |
|
|
|
self.assertEqual(do_xargs_escape(s), es) |
|
|
|
|
|
|
|
class _TestCases(unittest.TestCase): |
|
|
|
def setUp(self): |
|
|
|
self.fixtures = pathlib.Path('fixtures').resolve() |
|
|
@@ -2735,6 +2801,8 @@ class _TestCases(unittest.TestCase): |
|
|
|
elif special == 'delete files': |
|
|
|
for i in cmd['files']: |
|
|
|
os.unlink(i) |
|
|
|
elif special == 'create file': |
|
|
|
(self.tempdir / cmd['file']).write_text(cmd['contents']) |
|
|
|
elif special == 'setup file': |
|
|
|
shutil.copy(self.fixtures / |
|
|
|
cmd['file'], self.tempdir) |
|
|
@@ -2786,6 +2854,17 @@ class _TestCases(unittest.TestCase): |
|
|
|
# XXX - Minor hack till other tests fixed |
|
|
|
sys.exit(0) |
|
|
|
|
|
|
|
# with the correct err output |
|
|
|
err = cmd.get('stderr') |
|
|
|
errre = cmd.get('stderr_re') |
|
|
|
if not errre and not err: |
|
|
|
err = '' |
|
|
|
|
|
|
|
if err: |
|
|
|
self.assertEqual(stderr.getvalue(), err) |
|
|
|
if errre: |
|
|
|
self.assertRegex(stderr.getvalue(), errre) |
|
|
|
|
|
|
|
# with the correct output |
|
|
|
self.maxDiff = None |
|
|
|
outeq = cmd.get('stdout') |
|
|
@@ -2803,8 +2882,6 @@ class _TestCases(unittest.TestCase): |
|
|
|
stdout.seek(0) |
|
|
|
self.objcompare(_json_objstream(stdout), outcheck) |
|
|
|
|
|
|
|
self.assertEqual(stderr.getvalue(), cmd.get('stderr', '')) |
|
|
|
|
|
|
|
self.assertEqual(cm.exception.code, cmd.get('exit', 0)) |
|
|
|
|
|
|
|
# any store commands: |
|
|
|