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