xref: /llvm-project/llvm/utils/lit/lit/ShCommands.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
1class Command:
2    def __init__(self, args, redirects):
3        self.args = list(args)
4        self.redirects = list(redirects)
5
6    def __repr__(self):
7        return "Command(%r, %r)" % (self.args, self.redirects)
8
9    def __eq__(self, other):
10        if not isinstance(other, Command):
11            return False
12
13        return (self.args, self.redirects) == (other.args, other.redirects)
14
15    def toShell(self, file):
16        for arg in self.args:
17            if "'" not in arg:
18                quoted = "'%s'" % arg
19            elif '"' not in arg and "$" not in arg:
20                quoted = '"%s"' % arg
21            else:
22                raise NotImplementedError("Unable to quote %r" % arg)
23            file.write(quoted)
24
25            # For debugging / validation.
26            import ShUtil
27
28            dequoted = list(ShUtil.ShLexer(quoted).lex())
29            if dequoted != [arg]:
30                raise NotImplementedError("Unable to quote %r" % arg)
31
32        for r in self.redirects:
33            if len(r[0]) == 1:
34                file.write("%s '%s'" % (r[0][0], r[1]))
35            else:
36                file.write("%s%s '%s'" % (r[0][1], r[0][0], r[1]))
37
38
39class GlobItem:
40    def __init__(self, pattern):
41        self.pattern = pattern
42
43    def __repr__(self):
44        return self.pattern
45
46    def __eq__(self, other):
47        if not isinstance(other, Command):
48            return False
49
50        return self.pattern == other.pattern
51
52    def resolve(self, cwd):
53        import glob
54        import os
55
56        if os.path.isabs(self.pattern):
57            abspath = self.pattern
58        else:
59            abspath = os.path.join(cwd, self.pattern)
60        results = glob.glob(abspath)
61        return [self.pattern] if len(results) == 0 else results
62
63
64class Pipeline:
65    def __init__(self, commands, negate=False, pipe_err=False):
66        self.commands = commands
67        self.negate = negate
68        self.pipe_err = pipe_err
69
70    def __repr__(self):
71        return "Pipeline(%r, %r, %r)" % (self.commands, self.negate, self.pipe_err)
72
73    def __eq__(self, other):
74        if not isinstance(other, Pipeline):
75            return False
76
77        return (self.commands, self.negate, self.pipe_err) == (
78            other.commands,
79            other.negate,
80            self.pipe_err,
81        )
82
83    def toShell(self, file, pipefail=False):
84        if pipefail != self.pipe_err:
85            raise ValueError('Inconsistent "pipefail" attribute!')
86        if self.negate:
87            file.write("! ")
88        for cmd in self.commands:
89            cmd.toShell(file)
90            if cmd is not self.commands[-1]:
91                file.write("|\n  ")
92
93
94class Seq:
95    def __init__(self, lhs, op, rhs):
96        assert op in (";", "&", "||", "&&")
97        self.op = op
98        self.lhs = lhs
99        self.rhs = rhs
100
101    def __repr__(self):
102        return "Seq(%r, %r, %r)" % (self.lhs, self.op, self.rhs)
103
104    def __eq__(self, other):
105        if not isinstance(other, Seq):
106            return False
107
108        return (self.lhs, self.op, self.rhs) == (other.lhs, other.op, other.rhs)
109
110    def toShell(self, file, pipefail=False):
111        self.lhs.toShell(file, pipefail)
112        file.write(" %s\n" % self.op)
113        self.rhs.toShell(file, pipefail)
114