diff options
author | Ying Yi <maggieyi666@gmail.com> | 2017-11-23 12:48:41 +0000 |
---|---|---|
committer | Ying Yi <maggieyi666@gmail.com> | 2017-11-23 12:48:41 +0000 |
commit | da18ebeb4eb31f10379a83920f5a27bdc9e35d46 (patch) | |
tree | 994db0e1b655d3c62a809e8a5a27bbe3e360d44c /utils/lit/lit | |
parent | 30e25c33bc96066d1ed550e870a86b88766b97f1 (diff) |
[lit] Implement non-pipelined ‘mkdir’, ‘diff’ and ‘rm’ commands internally
Summary:
The internal shell already supports 'cd', ‘export’ and ‘echo’ commands.
This patch adds implementation of non-pipelined ‘mkdir’, ‘diff’ and ‘rm’
commands as the internal shell builtins.
Reviewers: Zachary Turner, Reid Kleckner
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D39567
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318911 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/lit/lit')
-rw-r--r-- | utils/lit/lit/TestRunner.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 4def05d8870..1bf5f66f02e 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -1,7 +1,13 @@ from __future__ import absolute_import +import difflib +import functools +import itertools +import getopt import os, signal, subprocess, sys import re +import stat import platform +import shutil import tempfile import threading @@ -302,6 +308,143 @@ def executeBuiltinEcho(cmd, shenv): return stdout.getvalue() return "" +def executeBuiltinMkdir(cmd, cmd_shenv): + """executeBuiltinMkdir - Create new directories.""" + args = expand_glob_expressions(cmd.args, cmd_shenv.cwd)[1:] + try: + opts, args = getopt.gnu_getopt(args, 'p') + except getopt.GetoptError as err: + raise InternalShellError(cmd, "Unsupported: 'mkdir': %s" % str(err)) + + parent = False + for o, a in opts: + if o == "-p": + parent = True + else: + assert False, "unhandled option" + + if len(args) == 0: + raise InternalShellError(cmd, "Error: 'mkdir' is missing an operand") + + for dir in args: + if not os.path.isabs(dir): + dir = os.path.realpath(os.path.join(cmd_shenv.cwd, dir)) + if parent: + lit.util.mkdir_p(dir) + else: + try: + os.mkdir(dir) + except OSError as e: + raise InternalShellError(cmd, "Error: 'mkdir' command failed") + +def executeBuiltinDiff(cmd, cmd_shenv): + """executeBuiltinDiff - Compare files line by line.""" + args = expand_glob_expressions(cmd.args, cmd_shenv.cwd)[1:] + try: + opts, args = getopt.gnu_getopt(args, "wbu", ["strip-trailing-cr"]) + except getopt.GetoptError as err: + raise InternalShellError(cmd, "Unsupported: 'diff': %s" % str(err)) + + filelines, filepaths = ([] for i in range(2)) + ignore_all_space = False + ignore_space_change = False + unified_diff = False + strip_trailing_cr = False + for o, a in opts: + if o == "-w": + ignore_all_space = True + elif o == "-b": + ignore_space_change = True + elif o == "-u": + unified_diff = True + elif o == "--strip-trailing-cr": + strip_trailing_cr = True + else: + assert False, "unhandled option" + + if len(args) != 2: + raise InternalShellError(cmd, "Error: missing or extra operand") + + different = False + try: + for file in args: + if not os.path.isabs(file): + file = os.path.realpath(os.path.join(cmd_shenv.cwd, file)) + filepaths.append(file) + with open(file, 'r') as f: + filelines.append(f.readlines()) + + def compose2(f, g): + return lambda x: f(g(x)) + + f = lambda x: x + if strip_trailing_cr: + f = compose2(lambda line: line.rstrip('\r'), f) + if ignore_all_space or ignore_space_change: + ignoreSpace = lambda line, separator: separator.join(line.split()) + ignoreAllSpaceOrSpaceChange = functools.partial(ignoreSpace, separator='' if ignore_all_space else ' ') + f = compose2(ignoreAllSpaceOrSpaceChange, f) + + for idx, lines in enumerate(filelines): + filelines[idx]= [f(line) for line in lines] + + func = difflib.unified_diff if unified_diff else difflib.context_diff + for diff in func(filelines[0], filelines[1], filepaths[0], filepaths[1]): + sys.stdout.write(diff) + different = True + except IOError as e: + raise InternalShellError(cmd, "Error: 'diff' command failed") + + if different: + raise InternalShellError(cmd, "Error: The contents " + "of fromfile and tofile are different") + +def executeBuiltinRm(cmd, cmd_shenv): + """executeBuiltinRm - Removes (deletes) files or directories.""" + args = expand_glob_expressions(cmd.args, cmd_shenv.cwd)[1:] + try: + opts, args = getopt.gnu_getopt(args, "frR", ["--recursive"]) + except getopt.GetoptError as err: + raise InternalShellError(cmd, "Unsupported: 'rm': %s" % str(err)) + + force = False + recursive = False + for o, a in opts: + if o == "-f": + force = True + elif o in ("-r", "-R", "--recursive"): + recursive = True + else: + assert False, "unhandled option" + + if len(args) == 0: + raise InternalShellError(cmd, "Error: 'rm' is missing an operand") + + def on_rm_error(func, path, exc_info): + # path contains the path of the file that couldn't be removed + # let's just assume that it's read-only and remove it. + os.chmod(path, stat.S_IMODE( os.stat(path).st_mode) | stat.S_IWRITE) + os.remove(path) + + for dir in args: + if not os.path.isabs(dir): + dir = os.path.realpath(os.path.join(cmd_shenv.cwd, dir)) + if force and not os.path.exists(dir): + continue + try: + if os.path.isdir(dir): + if not recursive: + raise InternalShellError(cmd, "Error: " + "%s is a directory" % dir) + shutil.rmtree(dir, onerror = on_rm_error if force else None) + else: + if force and not os.access(dir, os.W_OK): + os.chmod(dir, + stat.S_IMODE(os.stat(dir).st_mode) | stat.S_IWRITE) + os.remove(dir) + except OSError as e: + raise InternalShellError(cmd, "Error: 'rm' command failed") + def processRedirects(cmd, stdin_source, cmd_shenv, opened_files): """Return the standard fds for cmd after applying redirects @@ -460,6 +603,27 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper): updateEnv(shenv, cmd.commands[0]) return 0 + if cmd.commands[0].args[0] == 'mkdir': + if len(cmd.commands) != 1: + raise InternalShellError(cmd.commands[0], "Unsupported: 'mkdir' " + "cannot be part of a pipeline") + executeBuiltinMkdir(cmd.commands[0], shenv) + return 0 + + if cmd.commands[0].args[0] == 'diff': + if len(cmd.commands) != 1: + raise InternalShellError(cmd.commands[0], "Unsupported: 'diff' " + "cannot be part of a pipeline") + executeBuiltinDiff(cmd.commands[0], shenv) + return 0 + + if cmd.commands[0].args[0] == 'rm': + if len(cmd.commands) != 1: + raise InternalShellError(cmd.commands[0], "Unsupported: 'rm' " + "cannot be part of a pipeline") + executeBuiltinRm(cmd.commands[0], shenv) + return 0 + procs = [] default_stdin = subprocess.PIPE stderrTempFiles = [] |