comparison mercurial/util.py @ 1293:a6ffcebd3315

Enhance the file filtering capabilities. We now allow filtering through either pipes or pairs of temporary files. The latter appear to be mandatory for use on Windows.
author Bryan O'Sullivan <bos@serpentine.com>
date Wed, 21 Sep 2005 11:44:08 -0700
parents 141951276ba1
children c9cf171f30dd
comparison
equal deleted inserted replaced
1292:141951276ba1 1293:a6ffcebd3315
10 platform-specific details from the core. 10 platform-specific details from the core.
11 """ 11 """
12 12
13 import os, errno 13 import os, errno
14 from demandload import * 14 from demandload import *
15 demandload(globals(), "re cStringIO shutil popen2 threading") 15 demandload(globals(), "re cStringIO shutil popen2 tempfile threading")
16 16
17 def filter(s, cmd): 17 def pipefilter(s, cmd):
18 "filter a string through a command that transforms its input to its output" 18 '''filter string S through command CMD, returning its output'''
19 (pout, pin) = popen2.popen2(cmd, -1, 'b') 19 (pout, pin) = popen2.popen2(cmd, -1, 'b')
20 def writer(): 20 def writer():
21 pin.write(s) 21 pin.write(s)
22 pin.close() 22 pin.close()
23 23
27 w.start() 27 w.start()
28 f = pout.read() 28 f = pout.read()
29 pout.close() 29 pout.close()
30 w.join() 30 w.join()
31 return f 31 return f
32
33 def tempfilter(s, cmd):
34 '''filter string S through a pair of temporary files with CMD.
35 CMD is used as a template to create the real command to be run,
36 with the strings INFILE and OUTFILE replaced by the real names of
37 the temporary files generated.'''
38 inname, outname = None, None
39 try:
40 infd, inname = tempfile.mkstemp(prefix='hgfin')
41 fp = os.fdopen(infd, 'wb')
42 fp.write(s)
43 fp.close()
44 outfd, outname = tempfile.mkstemp(prefix='hgfout')
45 os.close(outfd)
46 cmd = cmd.replace('INFILE', inname)
47 cmd = cmd.replace('OUTFILE', outname)
48 code = os.system(cmd)
49 if code: raise Abort("command '%s' failed: %s" %
50 (cmd, explain_exit(code)))
51 return open(outname, 'rb').read()
52 finally:
53 try:
54 if inname: os.unlink(inname)
55 except: pass
56 try:
57 if outname: os.unlink(outname)
58 except: pass
59
60 filtertable = {
61 'tempfile:': tempfilter,
62 'pipe:': pipefilter,
63 }
64
65 def filter(s, cmd):
66 "filter a string through a command that transforms its input to its output"
67 for name, fn in filtertable.iteritems():
68 if cmd.startswith(name):
69 return fn(s, cmd[len(name):].lstrip())
70 return pipefilter(s, cmd)
32 71
33 def patch(strip, patchname, ui): 72 def patch(strip, patchname, ui):
34 """apply the patch <patchname> to the working directory. 73 """apply the patch <patchname> to the working directory.
35 a list of patched files is returned""" 74 a list of patched files is returned"""
36 fp = os.popen('patch -p%d < "%s"' % (strip, patchname)) 75 fp = os.popen('patch -p%d < "%s"' % (strip, patchname))
41 if line.startswith('patching file '): 80 if line.startswith('patching file '):
42 pf = parse_patch_output(line) 81 pf = parse_patch_output(line)
43 files.setdefault(pf, 1) 82 files.setdefault(pf, 1)
44 code = fp.close() 83 code = fp.close()
45 if code: 84 if code:
46 raise Abort("patch command failed: exit status %s " % code) 85 raise Abort("patch command failed: %s" % explain_exit(code))
47 return files.keys() 86 return files.keys()
48 87
49 def binary(s): 88 def binary(s):
50 """return true if a string is binary data using diff's heuristic""" 89 """return true if a string is binary data using diff's heuristic"""
51 if s and '\0' in s[:4096]: 90 if s and '\0' in s[:4096]: