Mercurial > hg
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]: |