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) == 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 file.write(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 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 38class GlobItem: 39 def __init__(self, pattern): 40 self.pattern = pattern 41 42 def __repr__(self): 43 return self.pattern 44 45 def __eq__(self, other): 46 if not isinstance(other, Command): 47 return False 48 49 return (self.pattern == other.pattern) 50 51 def resolve(self, cwd): 52 import glob 53 import os 54 if os.path.isabs(self.pattern): 55 abspath = self.pattern 56 else: 57 abspath = os.path.join(cwd, self.pattern) 58 results = glob.glob(abspath) 59 return [self.pattern] if len(results) == 0 else results 60 61class Pipeline: 62 def __init__(self, commands, negate=False, pipe_err=False): 63 self.commands = commands 64 self.negate = negate 65 self.pipe_err = pipe_err 66 67 def __repr__(self): 68 return 'Pipeline(%r, %r, %r)' % (self.commands, self.negate, 69 self.pipe_err) 70 71 def __eq__(self, other): 72 if not isinstance(other, Pipeline): 73 return False 74 75 return ((self.commands, self.negate, self.pipe_err) == 76 (other.commands, other.negate, self.pipe_err)) 77 78 def toShell(self, file, pipefail=False): 79 if pipefail != self.pipe_err: 80 raise ValueError('Inconsistent "pipefail" attribute!') 81 if self.negate: 82 file.write('! ') 83 for cmd in self.commands: 84 cmd.toShell(file) 85 if cmd is not self.commands[-1]: 86 file.write('|\n ') 87 88class Seq: 89 def __init__(self, lhs, op, rhs): 90 assert op in (';', '&', '||', '&&') 91 self.op = op 92 self.lhs = lhs 93 self.rhs = rhs 94 95 def __repr__(self): 96 return 'Seq(%r, %r, %r)' % (self.lhs, self.op, self.rhs) 97 98 def __eq__(self, other): 99 if not isinstance(other, Seq): 100 return False 101 102 return ((self.lhs, self.op, self.rhs) == 103 (other.lhs, other.op, other.rhs)) 104 105 def toShell(self, file, pipefail=False): 106 self.lhs.toShell(file, pipefail) 107 file.write(' %s\n' % self.op) 108 self.rhs.toShell(file, pipefail) 109