Rev 4684: Implement globbing and enhance cat to accept multiple files. in file:///home/vila/src/bzr/experimental/shell-like-tests/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Fri Sep 11 15:19:15 BST 2009
At file:///home/vila/src/bzr/experimental/shell-like-tests/
------------------------------------------------------------
revno: 4684
revision-id: v.ladeuil+lp at free.fr-20090911141915-spdcayvr91ighbzs
parent: v.ladeuil+lp at free.fr-20090911121609-4ag5y8wqmpkrqus1
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: shell-like-tests
timestamp: Fri 2009-09-11 16:19:15 +0200
message:
Implement globbing and enhance cat to accept multiple files.
* bzrlib/tests/test_script.py:
(TestSyntax.test_command_with_single_quoted_param,
TestSyntax.test_command_with_double_quoted_param): Quotes are left
in place during command splitting.
(TestArgumentProcessing): Test quote removal and globbing.
(TestCat.test_cat_files_to_file): Cat accepts multiple files now.
* bzrlib/tests/script.py:
(split): Delay quote removal until the command is ready to be
executed.
(ScriptRunner._pre_process_args): Globbing should happen just
before command execution, which imply that quotes removal should
happen at the same time.
(ScriptRunner.run_command): Process arguments for quote and
globbing just before execution or globbing will not be correct.
(ScriptRunner.do_cat): Allow multiple files to be specified.
-------------- next part --------------
=== modified file 'bzrlib/tests/script.py'
--- a/bzrlib/tests/script.py 2009-09-11 12:16:09 +0000
+++ b/bzrlib/tests/script.py 2009-09-11 14:19:15 +0000
@@ -97,6 +97,7 @@
import doctest
import errno
+import glob
import os
import shlex
from cStringIO import StringIO
@@ -113,13 +114,7 @@
scanner.quotes = '\'"`'
scanner.whitespace_split = True
for t in list(scanner):
- # Strip the simple and double quotes since we don't care about them.
- # We leave the backquotes in place though since they have a different
- # semantic.
- if t[0] in ('"', "'") and t[0] == t[-1]:
- yield t[1:-1]
- else:
- yield t
+ yield t
def _script_to_commands(text, file_name=None):
@@ -266,6 +261,26 @@
# output should be decently readable.
self.test_case.assertEqualDiff(expected, actual)
+ def _pre_process_args(self, args):
+ new_args = []
+ for arg in args:
+ # Strip the simple and double quotes since we don't care about
+ # them. We leave the backquotes in place though since they have a
+ # different semantic.
+ if arg[0] in ('"', "'") and arg[0] == arg[-1]:
+ yield arg[1:-1]
+ else:
+ if glob.has_magic(arg):
+ matches = glob.glob(arg)
+ if matches:
+ # We care more about order stability than performance
+ # here
+ matches.sort()
+ for m in matches:
+ yield m
+ else:
+ yield arg
+
def run_command(self, cmd, input, output, error):
mname = 'do_' + cmd[0]
method = getattr(self, mname, None)
@@ -276,7 +291,8 @@
str_input = ''
else:
str_input = ''.join(input)
- retcode, actual_output, actual_error = method(str_input, cmd[1:])
+ args = list(self._pre_process_args(cmd[1:]))
+ retcode, actual_output, actual_error = method(str_input, args)
self._check_output(output, actual_output)
self._check_output(error, actual_error)
@@ -312,19 +328,24 @@
def do_cat(self, input, args):
(in_name, out_name, out_mode, args) = _scan_redirection_options(args)
- if len(args) > 1:
- raise SyntaxError('Usage: cat [file1]')
- if args:
- if in_name is not None:
- raise SyntaxError('Specify a file OR use redirection')
- in_name = args[0]
- try:
- input = self._read_input(input, in_name)
- except IOError, e:
- if e.errno == errno.ENOENT:
- return 1, None, '%s: No such file or directory\n' % (in_name,)
+ if args and in_name is not None:
+ raise SyntaxError('Specify a file OR use redirection')
+
+ inputs = []
+ if input:
+ inputs.append(input)
+ input_names = args
+ if in_name:
+ args.append(in_name)
+ for in_name in input_names:
+ try:
+ inputs.append(self._read_input(None, in_name))
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ return (1, None,
+ '%s: No such file or directory\n' % (in_name,))
# Basically cat copy input to output
- output = input
+ output = ''.join(inputs)
# Handle output redirections
try:
output = self._write_output(output, out_name, out_mode)
=== modified file 'bzrlib/tests/test_script.py'
--- a/bzrlib/tests/test_script.py 2009-09-11 12:16:09 +0000
+++ b/bzrlib/tests/test_script.py 2009-09-11 14:19:15 +0000
@@ -22,7 +22,7 @@
from bzrlib.tests import script
-class TestScriptSyntax(tests.TestCase):
+class TestSyntax(tests.TestCase):
def test_comment_is_ignored(self):
self.assertEquals([], script._script_to_commands('#comment\n'))
@@ -36,13 +36,13 @@
def test_command_with_single_quoted_param(self):
story = """bzr commit -m 'two words'"""
- self.assertEquals([(['bzr', 'commit', '-m', 'two words'],
+ self.assertEquals([(['bzr', 'commit', '-m', "'two words'"],
None, None, None)],
script._script_to_commands(story))
def test_command_with_double_quoted_param(self):
story = """bzr commit -m "two words" """
- self.assertEquals([(['bzr', 'commit', '-m', 'two words'],
+ self.assertEquals([(['bzr', 'commit', '-m', '"two words"'],
None, None, None)],
script._script_to_commands(story))
@@ -117,7 +117,7 @@
-class TestScriptExecution(script.TestCaseWithTransportAndScript):
+class TestExecution(script.TestCaseWithTransportAndScript):
def test_unknown_command(self):
self.assertRaises(SyntaxError, self.run_script, 'foo')
@@ -181,10 +181,34 @@
self.run_script(story)
+class TestArgumentProcessing(script.TestCaseWithTransportAndScript):
+
+ def test_globing(self):
+ self.run_script("""
+echo cat >cat
+echo dog >dog
+cat *
+>cat
+>dog
+""")
+
+ def test_quoted_globbing(self):
+ self.run_script("""
+echo cat >cat
+cat '*'
+2>*: No such file or directory
+""")
+
+ def test_quotes_removal(self):
+ self.run_script("""
+echo 'cat' "dog" '"chicken"' "'dragon'"
+>catdog"chicken"'dragon'
+""")
+
+
class TestCat(script.TestCaseWithTransportAndScript):
def test_cat_usage(self):
- self.assertRaises(SyntaxError, self.run_script, 'cat foo bar baz')
self.assertRaises(SyntaxError, self.run_script, 'cat foo <bar')
def test_cat_input_to_output(self):
@@ -218,6 +242,13 @@
None, None, None)
self.assertFileEqual('content\n', 'file2')
+ def test_cat_files_to_file(self):
+ self.build_tree_contents([('cat', 'cat\n')])
+ self.build_tree_contents([('dog', 'dog\n')])
+ retcode, out, err = self.run_command(['cat', 'cat', 'dog', '>file'],
+ None, None, None)
+ self.assertFileEqual('cat\ndog\n', 'file')
+
def test_cat_bogus_input_file(self):
self.run_script("""
cat <file
More information about the bazaar-commits
mailing list