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 __cmp__(self, other):
10        if not isinstance(other, Command):
11            return -1
12
13        return cmp((self.args, self.redirects),
14                   (other.args, other.redirects))
15
16    def toShell(self, file):
17        for arg in self.args:
18            if "'" not in arg:
19                quoted = "'%s'" % arg
20            elif '"' not in arg and '$' not in arg:
21                quoted = '"%s"' % arg
22            else:
23                raise NotImplementedError,'Unable to quote %r' % arg
24            print >>file, quoted,
25
26            # For debugging / validation.
27            import ShUtil
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                print >>file, "%s '%s'" % (r[0][0], r[1]),
35            else:
36                print >>file, "%s%s '%s'" % (r[0][1], r[0][0], r[1]),
37
38class Pipeline:
39    def __init__(self, commands, negate=False, pipe_err=False):
40        self.commands = commands
41        self.negate = negate
42        self.pipe_err = pipe_err
43
44    def __repr__(self):
45        return 'Pipeline(%r, %r, %r)' % (self.commands, self.negate,
46                                         self.pipe_err)
47
48    def __cmp__(self, other):
49        if not isinstance(other, Pipeline):
50            return -1
51
52        return cmp((self.commands, self.negate, self.pipe_err),
53                   (other.commands, other.negate, self.pipe_err))
54
55    def toShell(self, file, pipefail=False):
56        if pipefail != self.pipe_err:
57            raise ValueError,'Inconsistent "pipefail" attribute!'
58        if self.negate:
59            print >>file, '!',
60        for cmd in self.commands:
61            cmd.toShell(file)
62            if cmd is not self.commands[-1]:
63                print >>file, '|\n ',
64
65class Seq:
66    def __init__(self, lhs, op, rhs):
67        assert op in (';', '&', '||', '&&')
68        self.op = op
69        self.lhs = lhs
70        self.rhs = rhs
71
72    def __repr__(self):
73        return 'Seq(%r, %r, %r)' % (self.lhs, self.op, self.rhs)
74
75    def __cmp__(self, other):
76        if not isinstance(other, Seq):
77            return -1
78
79        return cmp((self.lhs, self.op, self.rhs),
80                   (other.lhs, other.op, other.rhs))
81
82    def toShell(self, file, pipefail=False):
83        self.lhs.toShell(file, pipefail)
84        print >>file, ' %s\n' % self.op
85        self.rhs.toShell(file, pipefail)
86