1be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarclass Command: 2be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __init__(self, args, redirects): 3be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.args = list(args) 4be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.redirects = list(redirects) 5be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 6be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __repr__(self): 7be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return 'Command(%r, %r)' % (self.args, self.redirects) 8be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 9304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar def __eq__(self, other): 10be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not isinstance(other, Command): 11304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return False 12be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 13304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return ((self.args, self.redirects) == 14304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar (other.args, other.redirects)) 15be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 16be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def toShell(self, file): 17be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for arg in self.args: 18be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if "'" not in arg: 19be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar quoted = "'%s'" % arg 20be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif '"' not in arg and '$' not in arg: 21be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar quoted = '"%s"' % arg 22be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 2326e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar raise NotImplementedError('Unable to quote %r' % arg) 240d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write(quoted) 25be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # For debugging / validation. 27ba3931b667ea2c8f30dff4cd176a106d6d4cb51cDaniel Dunbar import ShUtil 28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar dequoted = list(ShUtil.ShLexer(quoted).lex()) 29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if dequoted != [arg]: 3026e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar raise NotImplementedError('Unable to quote %r' % arg) 31be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for r in self.redirects: 33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if len(r[0]) == 1: 340d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write("%s '%s'" % (r[0][0], r[1])) 35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 360d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write("%s%s '%s'" % (r[0][1], r[0][0], r[1])) 37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarclass Pipeline: 39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __init__(self, commands, negate=False, pipe_err=False): 40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.commands = commands 41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.negate = negate 42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.pipe_err = pipe_err 43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __repr__(self): 45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return 'Pipeline(%r, %r, %r)' % (self.commands, self.negate, 46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.pipe_err) 47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 48304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar def __eq__(self, other): 49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not isinstance(other, Pipeline): 50304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return False 51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 52304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return ((self.commands, self.negate, self.pipe_err) == 53304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar (other.commands, other.negate, self.pipe_err)) 54be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def toShell(self, file, pipefail=False): 56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if pipefail != self.pipe_err: 5726e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar raise ValueError('Inconsistent "pipefail" attribute!') 58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if self.negate: 590d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write('! ') 60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for cmd in self.commands: 61be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmd.toShell(file) 62be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd is not self.commands[-1]: 630d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write('|\n ') 64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarclass Seq: 66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __init__(self, lhs, op, rhs): 67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar assert op in (';', '&', '||', '&&') 68be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.op = op 69be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.lhs = lhs 70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.rhs = rhs 71be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def __repr__(self): 73be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return 'Seq(%r, %r, %r)' % (self.lhs, self.op, self.rhs) 74be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 75304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar def __eq__(self, other): 76be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not isinstance(other, Seq): 77304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return False 78be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 79304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar return ((self.lhs, self.op, self.rhs) == 80304a0b03980996669ce2afc09b2bfe21381c5fdfDaniel Dunbar (other.lhs, other.op, other.rhs)) 81be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 82be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def toShell(self, file, pipefail=False): 83be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.lhs.toShell(file, pipefail) 840d038e3e8852bf4fde949136ca9c2815f64febd0Daniel Dunbar file.write(' %s\n' % self.op) 85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar self.rhs.toShell(file, pipefail) 86