~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/script.py

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.

Show diffs side-by-side

added added

removed removed

Lines of Context:
97
97
 
98
98
import doctest
99
99
import errno
 
100
import glob
100
101
import os
101
102
import shlex
102
103
from cStringIO import StringIO
113
114
    scanner.quotes = '\'"`'
114
115
    scanner.whitespace_split = True
115
116
    for t in list(scanner):
116
 
        # Strip the simple and double quotes since we don't care about them.
117
 
        # We leave the backquotes in place though since they have a different
118
 
        # semantic.
119
 
        if t[0] in  ('"', "'") and t[0] == t[-1]:
120
 
            yield t[1:-1]
121
 
        else:
122
 
            yield t
 
117
        yield t
123
118
 
124
119
 
125
120
def _script_to_commands(text, file_name=None):
266
261
            # output should be decently readable.
267
262
            self.test_case.assertEqualDiff(expected, actual)
268
263
 
 
264
    def _pre_process_args(self, args):
 
265
        new_args = []
 
266
        for arg in args:
 
267
            # Strip the simple and double quotes since we don't care about
 
268
            # them.  We leave the backquotes in place though since they have a
 
269
            # different semantic.
 
270
            if arg[0] in  ('"', "'") and arg[0] == arg[-1]:
 
271
                yield arg[1:-1]
 
272
            else:
 
273
                if glob.has_magic(arg):
 
274
                    matches = glob.glob(arg)
 
275
                    if matches:
 
276
                        # We care more about order stability than performance
 
277
                        # here
 
278
                        matches.sort()
 
279
                        for m in matches:
 
280
                            yield m
 
281
                else:
 
282
                    yield arg
 
283
 
269
284
    def run_command(self, cmd, input, output, error):
270
285
        mname = 'do_' + cmd[0]
271
286
        method = getattr(self, mname, None)
276
291
            str_input = ''
277
292
        else:
278
293
            str_input = ''.join(input)
279
 
        retcode, actual_output, actual_error = method(str_input, cmd[1:])
 
294
        args = list(self._pre_process_args(cmd[1:]))
 
295
        retcode, actual_output, actual_error = method(str_input, args)
280
296
 
281
297
        self._check_output(output, actual_output)
282
298
        self._check_output(error, actual_error)
312
328
 
313
329
    def do_cat(self, input, args):
314
330
        (in_name, out_name, out_mode, args) = _scan_redirection_options(args)
315
 
        if len(args) > 1:
316
 
            raise SyntaxError('Usage: cat [file1]')
317
 
        if args:
318
 
            if in_name is not None:
319
 
                raise SyntaxError('Specify a file OR use redirection')
320
 
            in_name = args[0]
321
 
        try:
322
 
            input = self._read_input(input, in_name)
323
 
        except IOError, e:
324
 
            if e.errno == errno.ENOENT:
325
 
                return 1, None, '%s: No such file or directory\n' % (in_name,)
 
331
        if args and in_name is not None:
 
332
            raise SyntaxError('Specify a file OR use redirection')
 
333
 
 
334
        inputs = []
 
335
        if input:
 
336
            inputs.append(input)
 
337
        input_names = args
 
338
        if in_name:
 
339
            args.append(in_name)
 
340
        for in_name in input_names:
 
341
            try:
 
342
                inputs.append(self._read_input(None, in_name))
 
343
            except IOError, e:
 
344
                if e.errno == errno.ENOENT:
 
345
                    return (1, None,
 
346
                            '%s: No such file or directory\n' % (in_name,))
326
347
        # Basically cat copy input to output
327
 
        output = input
 
348
        output = ''.join(inputs)
328
349
        # Handle output redirections
329
350
        try:
330
351
            output = self._write_output(output, out_name, out_mode)