3 # ====================================================================
4 # Copyright (c) 2008 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://subversion.tigris.org/.
15 # ====================================================================
17 # Run this without arguments to run unit tests.
18 # Run with a path to a davautocheck ops log to test that it can parse that.
28 import svn_server_log_parse
30 class TestCase(unittest
.TestCase
):
32 # Define a class to stuff everything passed to any handle_
33 # method into self.result.
34 class cls(svn_server_log_parse
.Parser
):
35 def __getattr__(cls_self
, attr
):
36 if attr
.startswith('handle_'):
37 return lambda *a
: setattr(self
, 'result', a
)
39 self
.parse
= cls().parse
41 def test_unknown(self
):
42 line
= 'unknown log line'
44 self
.assertEqual(self
.result
, (line
,))
46 def test_reparent(self
):
47 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'reparent')
48 self
.assertEqual(self
.parse('reparent /'), '')
49 self
.assertEqual(self
.result
, ('/',))
51 def test_get_latest_rev(self
):
52 self
.assertEqual(self
.parse('get-latest-rev'), '')
53 self
.assertEqual(self
.result
, ())
54 self
.assertEqual(self
.parse('get-latest-rev r3'), 'r3')
55 self
.assertEqual(self
.result
, ())
57 def test_get_dated_rev(self
):
58 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
,
60 self
.assertEqual(self
.parse('get-dated-rev 2008-04-15T20:41:24.000000Z'), '')
61 self
.assertEqual(self
.result
, ('2008-04-15T20:41:24.000000Z',))
63 def test_commit(self
):
64 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'commit')
65 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'commit 3')
66 self
.assertEqual(self
.parse('commit r3'), '')
67 self
.assertEqual(self
.result
, (3,))
68 self
.assertEqual(self
.parse('commit r3 leftover'), ' leftover')
69 self
.assertEqual(self
.result
, (3,))
71 def test_get_dir(self
):
72 self
.get_dir_or_file('get-dir')
74 def test_get_file(self
):
75 self
.get_dir_or_file('get-file')
77 def get_dir_or_file(self
, c
):
78 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, c
)
79 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, c
+ ' foo')
80 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, c
+ ' foo 3')
81 self
.assertEqual(self
.parse(c
+ ' /a/b/c r3 ...'), ' ...')
82 self
.assertEqual(self
.result
, ('/a/b/c', 3, False, False))
83 self
.assertEqual(self
.parse(c
+ ' / r3'), '')
84 self
.assertEqual(self
.result
, ('/', 3, False, False))
85 # path must be absolute
86 self
.assertRaises(svn_server_log_parse
.Error
,
87 self
.parse
, c
+ ' a/b/c r3')
88 self
.assertEqual(self
.parse(c
+ ' /k r27 text'), '')
89 self
.assertEqual(self
.result
, ('/k', 27, True, False))
90 self
.assertEqual(self
.parse(c
+ ' /k r27 props'), '')
91 self
.assertEqual(self
.result
, ('/k', 27, False, True))
92 self
.assertEqual(self
.parse(c
+ ' /k r27 text props'), '')
93 self
.assertEqual(self
.result
, ('/k', 27, True, True))
94 # out of order not accepted
95 self
.assertEqual(self
.parse(c
+ ' /k r27 props text'), ' text')
96 self
.assertEqual(self
.result
, ('/k', 27, False, True))
99 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'lock')
100 self
.parse('lock (/foo)')
101 self
.assertEqual(self
.result
, (['/foo'], False))
102 self
.assertEqual(self
.parse('lock (/foo) steal ...'), ' ...')
103 self
.assertEqual(self
.result
, (['/foo'], True))
104 self
.assertEqual(self
.parse('lock (/foo) stear'), ' stear')
106 def test_change_rev_prop(self
):
107 self
.assertRaises(svn_server_log_parse
.Error
,
108 self
.parse
, 'change-rev-prop r3')
109 self
.assertRaises(svn_server_log_parse
.Error
,
110 self
.parse
, 'change-rev-prop r svn:log')
111 self
.assertRaises(svn_server_log_parse
.Error
,
112 self
.parse
, 'change-rev-prop rX svn:log')
113 self
.assertEqual(self
.parse('change-rev-prop r3 svn:log ...'), ' ...')
114 self
.assertEqual(self
.result
, (3, 'svn:log'))
116 def test_rev_proplist(self
):
117 self
.assertRaises(svn_server_log_parse
.Error
,
118 self
.parse
, 'rev-proplist')
119 self
.assertRaises(svn_server_log_parse
.Error
,
120 self
.parse
, 'rev-proplist r')
121 self
.assertRaises(svn_server_log_parse
.Error
,
122 self
.parse
, 'rev-proplist rX')
123 self
.assertEqual(self
.parse('rev-proplist r3 ...'), ' ...')
124 self
.assertEqual(self
.result
, (3,))
126 def test_rev_prop(self
):
127 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'rev-prop')
128 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'rev-prop r')
129 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'rev-prop rX')
130 self
.assertEqual(self
.parse('rev-prop r3 foo ...'), ' ...')
131 self
.assertEqual(self
.result
, (3, 'foo'))
133 def test_unlock(self
):
134 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'unlock')
135 self
.parse('unlock (/foo)')
136 self
.assertEqual(self
.result
, (['/foo'], False))
137 self
.assertEqual(self
.parse('unlock (/foo) break ...'), ' ...')
138 self
.assertEqual(self
.result
, (['/foo'], True))
139 self
.assertEqual(self
.parse('unlock (/foo) bear'), ' bear')
141 def test_get_lock(self
):
142 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'get-lock')
143 self
.parse('get-lock /foo')
144 self
.assertEqual(self
.result
, ('/foo',))
146 def test_get_locks(self
):
147 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'get-locks')
148 self
.parse('get-locks /foo')
149 self
.assertEqual(self
.result
, ('/foo',))
151 def test_get_locations(self
):
152 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
,
154 self
.assertRaises(svn_server_log_parse
.Error
,
155 self
.parse
, 'get-locations /foo 3')
156 self
.assertEqual(self
.parse('get-locations /foo (3 4) ...'), ' ...')
157 self
.assertEqual(self
.result
, ('/foo', [3, 4]))
158 self
.assertEqual(self
.parse('get-locations /foo (3)'), '')
159 self
.assertEqual(self
.result
, ('/foo', [3]))
161 def test_get_location_segments(self
):
162 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
,
163 'get-location-segments')
164 self
.assertRaises(svn_server_log_parse
.Error
,
165 self
.parse
, 'get-location-segments /foo 3')
166 self
.assertEqual(self
.parse('get-location-segments /foo@2 r3:4'), '')
167 self
.assertEqual(self
.result
, ('/foo', 2, 3, 4))
169 def test_get_file_revs(self
):
170 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'get-file-revs')
171 self
.assertRaises(svn_server_log_parse
.Error
,
172 self
.parse
, 'get-file-revs /foo 3')
173 self
.assertRaises(svn_server_log_parse
.Error
,
174 self
.parse
, 'get-file-revs /foo 3:a')
175 self
.assertRaises(svn_server_log_parse
.Error
,
176 self
.parse
, 'get-file-revs /foo r3:a')
177 self
.assertEqual(self
.parse('get-file-revs /foo r3:4 ...'), ' ...')
178 self
.assertEqual(self
.result
, ('/foo', 3, 4, False))
179 self
.assertEqual(self
.parse('get-file-revs /foo r3:4'
180 ' include-merged-revisions ...'), ' ...')
181 self
.assertEqual(self
.result
, ('/foo', 3, 4, True))
183 def test_get_mergeinfo(self
):
184 self
.assertRaises(svn_server_log_parse
.Error
,
185 self
.parse
, 'get-mergeinfo')
186 self
.assertRaises(svn_server_log_parse
.Error
,
187 self
.parse
, 'get-mergeinfo /foo')
188 self
.assertRaises(svn_server_log_parse
.Error
,
189 self
.parse
, 'get-mergeinfo (/foo')
190 self
.assertRaises(svn_server_log_parse
.Error
,
191 self
.parse
, 'get-mergeinfo (/foo /bar')
192 self
.assertRaises(svn_server_log_parse
.Error
,
193 self
.parse
, 'get-mergeinfo (/foo)')
194 self
.assertRaises(svn_server_log_parse
.BadMergeinfoInheritanceError
,
195 self
.parse
, 'get-mergeinfo (/foo) bork')
196 self
.assertEqual(self
.parse('get-mergeinfo (/foo) explicit'), '')
197 self
.assertEqual(self
.result
, (['/foo'],
198 svn
.core
.svn_mergeinfo_explicit
, False))
199 self
.assertEqual(self
.parse('get-mergeinfo (/foo /bar) inherited ...'),
201 self
.assertEqual(self
.result
, (['/foo', '/bar'],
202 svn
.core
.svn_mergeinfo_inherited
, False))
203 self
.assertEqual(self
.result
, (['/foo', '/bar'],
204 svn
.core
.svn_mergeinfo_inherited
, False))
207 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'log')
208 self
.assertRaises(svn_server_log_parse
.Error
,
209 self
.parse
, 'log /foo')
210 self
.assertRaises(svn_server_log_parse
.Error
,
211 self
.parse
, 'log (/foo)')
212 self
.assertEqual(self
.parse('log (/foo) r3:4'
213 ' include-merged-revisions'), '')
214 self
.assertEqual(self
.result
,
215 (['/foo'], 3, 4, 0, False, False, True, []))
216 self
.assertEqual(self
.parse('log (/foo /bar) r3:4 revprops=all ...'),
218 self
.assertEqual(self
.result
,
219 (['/foo', '/bar'], 3, 4, 0, False, False, False, None))
220 self
.assertEqual(self
.parse('log (/foo) r3:4 revprops=(a b) ...'),
222 self
.assertEqual(self
.result
,
223 (['/foo'], 3, 4, 0, False, False, False, ['a', 'b']))
224 self
.assertEqual(self
.parse('log (/foo) r8:1 limit=3'), '')
225 self
.assertEqual(self
.result
,
226 (['/foo'], 8, 1, 3, False, False, False, []))
228 def test_check_path(self
):
229 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'check-path')
230 self
.assertEqual(self
.parse('check-path /foo@9'), '')
231 self
.assertEqual(self
.result
, ('/foo', 9))
234 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'stat')
235 self
.assertEqual(self
.parse('stat /foo@9'), '')
236 self
.assertEqual(self
.result
, ('/foo', 9))
238 def test_replay(self
):
239 self
.assertRaises(svn_server_log_parse
.Error
, self
.parse
, 'replay')
240 self
.assertRaises(svn_server_log_parse
.Error
,
241 self
.parse
, 'replay /foo')
242 self
.assertRaises(svn_server_log_parse
.Error
,
243 self
.parse
, 'replay (/foo) r9')
244 self
.assertRaises(svn_server_log_parse
.Error
,
245 self
.parse
, 'replay (/foo) r9:10')
246 self
.assertEqual(self
.parse('replay /foo r9'), '')
247 self
.assertEqual(self
.result
, ('/foo', 9))
249 def test_checkout_or_export(self
):
250 self
.assertRaises(svn_server_log_parse
.Error
,
251 self
.parse
, 'checkout-or-export')
252 self
.assertRaises(svn_server_log_parse
.Error
,
253 self
.parse
, 'checkout-or-export /foo')
254 self
.assertEqual(self
.parse('checkout-or-export /foo r9'), '')
255 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_unknown
))
256 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
257 'checkout-or-export /foo r9 depth=INVALID-DEPTH')
258 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
259 'checkout-or-export /foo r9 depth=bork')
260 self
.assertEqual(self
.parse('checkout-or-export /foo r9 depth=files .'),
262 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_files
))
264 def test_diff_1path(self
):
265 self
.assertRaises(svn_server_log_parse
.Error
,
267 self
.assertEqual(self
.parse('diff /foo r9:10'), '')
268 self
.assertEqual(self
.result
, ('/foo', 9, 10,
269 svn
.core
.svn_depth_unknown
, False))
270 self
.assertEqual(self
.parse('diff /foo r9:10'
271 ' ignore-ancestry ...'), ' ...')
272 self
.assertEqual(self
.result
, ('/foo', 9, 10,
273 svn
.core
.svn_depth_unknown
, True))
274 self
.assertEqual(self
.parse('diff /foo r9:10 depth=files'), '')
275 self
.assertEqual(self
.result
, ('/foo', 9, 10,
276 svn
.core
.svn_depth_files
, False))
278 def test_diff_2paths(self
):
279 self
.assertEqual(self
.parse('diff /foo@9 /bar@10'), '')
280 self
.assertEqual(self
.result
, ('/foo', 9, '/bar', 10,
281 svn
.core
.svn_depth_unknown
, False))
282 self
.assertEqual(self
.parse('diff /foo@9 /bar@10'
283 ' ignore-ancestry ...'), ' ...')
284 self
.assertEqual(self
.result
, ('/foo', 9, '/bar', 10,
285 svn
.core
.svn_depth_unknown
, True))
286 self
.assertEqual(self
.parse('diff /foo@9 /bar@10'
287 ' depth=files ignore-ancestry'), '')
288 self
.assertEqual(self
.result
, ('/foo', 9, '/bar', 10,
289 svn
.core
.svn_depth_files
, True))
291 def test_status(self
):
292 self
.assertRaises(svn_server_log_parse
.Error
,
293 self
.parse
, 'status')
294 self
.assertRaises(svn_server_log_parse
.Error
,
295 self
.parse
, 'status /foo')
296 self
.assertEqual(self
.parse('status /foo r9'), '')
297 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_unknown
))
298 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
299 'status /foo r9 depth=INVALID-DEPTH')
300 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
301 'status /foo r9 depth=bork')
302 self
.assertEqual(self
.parse('status /foo r9 depth=files .'),
304 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_files
))
306 def test_switch(self
):
307 self
.assertEqual(self
.parse('switch /foo /bar@10 ...'), ' ...')
308 self
.assertEqual(self
.result
, ('/foo', '/bar', 10,
309 svn
.core
.svn_depth_unknown
))
310 self
.assertEqual(self
.parse('switch /foo /bar@10'
312 self
.assertEqual(self
.result
, ('/foo', '/bar', 10,
313 svn
.core
.svn_depth_files
))
315 def test_update(self
):
316 self
.assertRaises(svn_server_log_parse
.Error
,
317 self
.parse
, 'update')
318 self
.assertRaises(svn_server_log_parse
.Error
,
319 self
.parse
, 'update /foo')
320 self
.assertEqual(self
.parse('update /foo r9'), '')
321 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_unknown
,
323 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
324 'update /foo r9 depth=INVALID-DEPTH')
325 self
.assertRaises(svn_server_log_parse
.BadDepthError
, self
.parse
,
326 'update /foo r9 depth=bork')
327 self
.assertEqual(self
.parse('update /foo r9 depth=files .'), ' .')
328 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_files
,
330 self
.assertEqual(self
.parse('update /foo r9 send-copyfrom-args .'),
332 self
.assertEqual(self
.result
, ('/foo', 9, svn
.core
.svn_depth_unknown
,
335 if __name__
== '__main__':
336 if len(sys
.argv
) == 1:
337 # No arguments so run the unit tests.
339 sys
.stderr
.write('unittest.main failed to exit\n')
342 # Use the argument as the path to a log file to test against.
344 # Define a class to reconstruct the SVN-ACTION string.
345 class Test(svn_server_log_parse
.Parser
):
346 def handle_unknown(self
, line
):
347 sys
.stderr
.write('unknown log line at %d:\n%s\n' % (self
.linenum
,
351 def handle_reparent(self
, path
):
352 self
.action
= 'reparent ' + path
354 def handle_get_latest_rev(self
):
355 self
.action
= 'get-latest-rev'
357 def handle_get_dated_rev(self
, date
):
358 self
.action
= 'get-dated-rev ' + date
360 def handle_commit(self
, revision
):
361 self
.action
= 'commit r%d' % (revision
,)
363 def handle_get_dir(self
, path
, revision
, text
, props
):
364 self
.action
= 'get-dir %s r%d' % (path
, revision
)
366 self
.action
+= ' text'
368 self
.action
+= ' props'
370 def handle_get_file(self
, path
, revision
, text
, props
):
371 self
.action
= 'get-file %s r%d' % (path
, revision
)
373 self
.action
+= ' text'
375 self
.action
+= ' props'
377 def handle_lock(self
, paths
, steal
):
378 self
.action
= 'lock (%s)' % (' '.join(paths
),)
380 self
.action
+= ' steal'
382 def handle_change_rev_prop(self
, revision
, revprop
):
383 self
.action
= 'change-rev-prop r%d %s' % (revision
, revprop
)
385 def handle_rev_prop(self
, revision
, revprop
):
386 self
.action
= 'rev-prop r%d %s' % (revision
, revprop
)
388 def handle_rev_proplist(self
, revision
):
389 self
.action
= 'rev-proplist r%d' % (revision
,)
391 def handle_unlock(self
, paths
, break_lock
):
392 self
.action
= 'unlock (%s)' % (' '.join(paths
),)
394 self
.action
+= ' break'
396 def handle_get_lock(self
, path
):
397 self
.action
= 'get-lock ' + path
399 def handle_get_locks(self
, path
):
400 self
.action
= 'get-locks ' + path
402 def handle_get_locations(self
, path
, revisions
):
403 self
.action
= ('get-locations %s (%s)'
404 % (path
, ' '.join([str(x
) for x
in revisions
])))
406 def handle_get_location_segments(self
, path
, peg
, left
, right
):
407 self
.action
= 'get-location-segments %s@%d r%d:%d' % (path
, peg
,
410 def handle_get_file_revs(self
, path
, left
, right
, include_merged_revisions
):
411 self
.action
= 'get-file-revs %s r%d:%d' % (path
, left
, right
)
412 if include_merged_revisions
:
413 self
.action
+= ' include-merged-revisions'
415 def handle_get_mergeinfo(self
, paths
, inheritance
, include_descendants
):
416 self
.action
= ('get-mergeinfo (%s) %s'
418 svn
.core
.svn_inheritance_to_word(inheritance
)))
419 if include_descendants
:
420 self
.action
+= ' include-descendants'
422 def handle_log(self
, paths
, left
, right
, limit
, discover_changed_paths
,
423 strict
, include_merged_revisions
, revprops
):
424 self
.action
= 'log (%s) r%d:%d' % (' '.join(paths
),
427 self
.action
+= ' limit=%d' % (limit
,)
428 if discover_changed_paths
:
429 self
.action
+= ' discover-changed-paths'
431 self
.action
+= ' strict'
432 if include_merged_revisions
:
433 self
.action
+= ' include-merged-revisions'
435 self
.action
+= ' revprops=all'
436 elif len(revprops
) > 0:
437 self
.action
+= ' revprops=(%s)' % (' '.join(revprops
),)
439 def handle_check_path(self
, path
, revision
):
440 self
.action
= 'check-path %s@%d' % (path
, revision
)
442 def handle_stat(self
, path
, revision
):
443 self
.action
= 'stat %s@%d' % (path
, revision
)
445 def handle_replay(self
, path
, revision
):
446 self
.action
= 'replay %s r%d' % (path
, revision
)
448 def maybe_depth(self
, depth
):
449 if depth
!= svn
.core
.svn_depth_unknown
:
450 self
.action
+= ' depth=%s' % (
451 svn
.core
.svn_depth_to_word(depth
),)
453 def handle_checkout_or_export(self
, path
, revision
, depth
):
454 self
.action
= 'checkout-or-export %s r%d' % (path
, revision
)
455 self
.maybe_depth(depth
)
457 def handle_diff_1path(self
, path
, left
, right
,
458 depth
, ignore_ancestry
):
459 self
.action
= 'diff %s r%d:%d' % (path
, left
, right
)
460 self
.maybe_depth(depth
)
462 self
.action
+= ' ignore-ancestry'
464 def handle_diff_2paths(self
, from_path
, from_rev
,
466 depth
, ignore_ancestry
):
467 self
.action
= ('diff %s@%d %s@%d'
468 % (from_path
, from_rev
, to_path
, to_rev
))
469 self
.maybe_depth(depth
)
471 self
.action
+= ' ignore-ancestry'
473 def handle_status(self
, path
, revision
, depth
):
474 self
.action
= 'status %s r%d' % (path
, revision
)
475 self
.maybe_depth(depth
)
477 def handle_switch(self
, from_path
, to_path
, to_rev
, depth
):
478 self
.action
= ('switch %s %s@%d'
479 % (from_path
, to_path
, to_rev
))
480 self
.maybe_depth(depth
)
482 def handle_update(self
, path
, revision
, depth
, send_copyfrom_args
):
483 self
.action
= 'update %s r%d' % (path
, revision
)
484 self
.maybe_depth(depth
)
485 if send_copyfrom_args
:
486 self
.action
+= ' send-copyfrom-args'
488 tmp
= tempfile
.mktemp()
493 log_file
= sys
.argv
[1]
495 for line
in open(log_file
):
497 # Figure out which log type we have.
498 if re
.match(r
'\d+ \d\d\d\d-', line
):
499 log_type
= 'svnserve'
500 elif re
.match(r
'\[\d\d/', line
):
501 log_type
= 'mod_dav_svn'
503 sys
.stderr
.write("unknown log format in '%s'"
506 sys
.stderr
.write('parsing %s log...\n' % (log_type
,))
510 if log_type
== 'svnserve':
511 # Skip over PID, date, client address, username, and repos.
512 if words
[5].startswith('ERR'):
516 leading
= ' '.join(words
[:5])
517 action
= ' '.join(words
[5:])
519 # Find the SVN-ACTION string from the CustomLog format
520 # davautocheck.sh uses. If that changes, this will need
521 # to as well. Currently it's
522 # %t %u %{SVN-REPOS-NAME}e %{SVN-ACTION}e
523 leading
= ' '.join(words
[:4])
524 action
= ' '.join(words
[4:])
526 # Parse the action and write the reconstructed action to
527 # the temporary file. Ignore the returned trailing text,
528 # as we have none in the davautocheck ops log.
532 except svn_server_log_parse
.Error
:
533 sys
.stderr
.write('error at line %d: %s\n'
534 % (parser
.linenum
, action
))
536 fp
.write(leading
+ ' ' + parser
.action
+ '\n')
538 # Check differences between original and reconstructed files
539 # (should be identical).
540 result
= os
.spawnlp(os
.P_WAIT
, 'diff', 'diff', '-u', log_file
, tmp
)
542 sys
.stderr
.write('OK\n')
548 sys
.stderr
.write('os.unlink(tmp): %s\n' % (e
,))