1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2000-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://cvs2svn.tigris.org/.
15 # ====================================================================
17 """This module contains generic utilities used by cvs2svn."""
22 from cvs2svn_lib
.common
import FatalError
23 from cvs2svn_lib
.common
import CommandError
26 def call_command(command
, **kw
):
27 """Call the specified command, checking that it exits successfully.
29 Raise a FatalError if the command cannot be executed, or if it exits
30 with a non-zero exit code. Pass KW as keyword arguments to
34 retcode
= subprocess
.call(command
, **kw
)
37 'Command terminated by signal %d: "%s"'
38 % (-retcode
, ' '.join(command
),)
42 'Command failed with return code %d: "%s"'
43 % (retcode
, ' '.join(command
),)
47 'Command execution failed (%s): "%s"'
48 % (e
, ' '.join(command
),)
52 class CommandFailedException(Exception):
53 """Exception raised if check_command_runs() fails."""
58 def check_command_runs(cmd
, cmdname
):
59 """Check whether the command CMD can be executed without errors.
61 CMD is a list or string, as accepted by subprocess.Popen(). CMDNAME
62 is the name of the command as it should be included in exception
65 This function checks three things: (1) the command can be run
66 without throwing an OSError; (2) it exits with status=0; (3) it
67 doesn't output anything to stderr. If any of these conditions is
68 not met, raise a CommandFailedException describing the problem."""
71 pipe
= subprocess
.Popen(
73 stdin
=subprocess
.PIPE
,
74 stdout
=subprocess
.PIPE
,
75 stderr
=subprocess
.PIPE
,
78 raise CommandFailedException('error executing %s: %s' % (cmdname
, e
,))
81 errmsg
= pipe
.stderr
.read()
84 msg
= 'error executing %s: status %s' % (cmdname
, status
,)
86 msg
+= ', error output:\n%s' % (errmsg
,)
87 raise CommandFailedException(msg
)
90 class PipeStream(object):
91 """A file-like object from which revision contents can be read."""
93 def __init__(self
, pipe_command
):
94 self
._pipe
_command
_str
= ' '.join(pipe_command
)
95 self
.pipe
= subprocess
.Popen(
97 stdin
=subprocess
.PIPE
,
98 stdout
=subprocess
.PIPE
,
99 stderr
=subprocess
.PIPE
,
101 self
.pipe
.stdin
.close()
103 def read(self
, size
=None):
105 return self
.pipe
.stdout
.read()
107 return self
.pipe
.stdout
.read(size
)
110 self
.pipe
.stdout
.close()
111 error_output
= self
.pipe
.stderr
.read()
112 exit_status
= self
.pipe
.wait()
113 if exit_status
or error_output
:
114 raise CommandError(self
._pipe
_command
_str
, exit_status
, error_output
)