Show More
@@ -67,20 +67,53 b' decode/encode::' | |||
|
67 | 67 | localization/canonicalization of files. |
|
68 | 68 | |
|
69 | 69 | Filters consist of a filter pattern followed by a filter command. |
|
70 | The command must accept data on stdin and return the transformed | |
|
71 | data on stdout. | |
|
70 | Filter patterns are globs by default, rooted at the repository | |
|
71 | root. For example, to match any file ending in ".txt" in the root | |
|
72 | directory only, use the pattern "*.txt". To match any file ending | |
|
73 | in ".c" anywhere in the repository, use the pattern "**.c". | |
|
72 | 74 | |
|
73 | Example: | |
|
75 | The filter command can start with a specifier, either "pipe:" or | |
|
76 | "tempfile:". If no specifier is given, "pipe:" is used by default. | |
|
77 | ||
|
78 | A "pipe:" command must accept data on stdin and return the | |
|
79 | transformed data on stdout. | |
|
80 | ||
|
81 | Pipe example: | |
|
74 | 82 | |
|
75 | 83 | [encode] |
|
76 | 84 | # uncompress gzip files on checkin to improve delta compression |
|
77 | 85 | # note: not necessarily a good idea, just an example |
|
78 | *.gz = gunzip | |
|
86 | *.gz = pipe: gunzip | |
|
79 | 87 | |
|
80 | 88 | [decode] |
|
81 | # recompress gzip files when writing them to the working dir | |
|
89 | # recompress gzip files when writing them to the working dir (we | |
|
90 | # can safely omit "pipe:", because it's the default) | |
|
82 | 91 | *.gz = gzip |
|
83 | 92 | |
|
93 | A "tempfile:" command is a template. The string INFILE is replaced | |
|
94 | with the name of a temporary file that contains the data to be | |
|
95 | filtered by the command. The string OUTFILE is replaced with the | |
|
96 | name of an empty temporary file, where the filtered data must be | |
|
97 | written by the command. | |
|
98 | ||
|
99 | NOTE: the tempfile mechanism is recommended for Windows systems, | |
|
100 | where the standard shell I/O redirection operators often have | |
|
101 | strange effects. In particular, if you are doing line ending | |
|
102 | conversion on Windows using the popular dos2unix and unix2dos | |
|
103 | programs, you *must* use the tempfile mechanism, as using pipes will | |
|
104 | corrupt the contents of your files. | |
|
105 | ||
|
106 | Tempfile example: | |
|
107 | ||
|
108 | [encode] | |
|
109 | # convert files to unix line ending conventions on checkin | |
|
110 | **.txt = tempfile: dos2unix -n INFILE OUTFILE | |
|
111 | ||
|
112 | [decode] | |
|
113 | # convert files to windows line ending conventions when writing | |
|
114 | # them to the working dir | |
|
115 | **.txt = tempfile: unix2dos -n INFILE OUTFILE | |
|
116 | ||
|
84 | 117 | hooks:: |
|
85 | 118 | Commands that get automatically executed by various actions such as |
|
86 | 119 | starting or finishing a commit. |
@@ -12,10 +12,10 b' platform-specific details from the core.' | |||
|
12 | 12 | |
|
13 | 13 | import os, errno |
|
14 | 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): | |
|
18 |
|
|
|
17 | def pipefilter(s, cmd): | |
|
18 | '''filter string S through command CMD, returning its output''' | |
|
19 | 19 | (pout, pin) = popen2.popen2(cmd, -1, 'b') |
|
20 | 20 | def writer(): |
|
21 | 21 | pin.write(s) |
@@ -30,6 +30,45 b' def filter(s, cmd):' | |||
|
30 | 30 | w.join() |
|
31 | 31 | return f |
|
32 | 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) | |
|
71 | ||
|
33 | 72 | def patch(strip, patchname, ui): |
|
34 | 73 | """apply the patch <patchname> to the working directory. |
|
35 | 74 | a list of patched files is returned""" |
@@ -43,7 +82,7 b' def patch(strip, patchname, ui):' | |||
|
43 | 82 | files.setdefault(pf, 1) |
|
44 | 83 | code = fp.close() |
|
45 | 84 | if code: |
|
46 |
raise Abort("patch command failed: |
|
|
85 | raise Abort("patch command failed: %s" % explain_exit(code)) | |
|
47 | 86 | return files.keys() |
|
48 | 87 | |
|
49 | 88 | def binary(s): |
General Comments 0
You need to be logged in to leave comments.
Login now