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
24 from cvs2svn_lib
.log
import logger
27 def call_command(command
, **kw
):
28 """Call the specified command, checking that it exits successfully.
30 Raise a FatalError if the command cannot be executed, or if it exits
31 with a non-zero exit code. Pass KW as keyword arguments to
34 logger
.debug('Running command %r' % (command
,))
36 retcode
= subprocess
.call(command
, **kw
)
39 'Command terminated by signal %d: "%s"'
40 % (-retcode
, ' '.join(command
),)
44 'Command failed with return code %d: "%s"'
45 % (retcode
, ' '.join(command
),)
49 'Command execution failed (%s): "%s"'
50 % (e
, ' '.join(command
),)
54 class CommandFailedException(Exception):
55 """Exception raised if check_command_runs() fails."""
60 def check_command_runs(command
, commandname
):
61 """Check whether the command CMD can be executed without errors.
63 CMD is a list or string, as accepted by subprocess.Popen(). CMDNAME
64 is the name of the command as it should be included in exception
67 This function checks three things: (1) the command can be run
68 without throwing an OSError; (2) it exits with status=0; (3) it
69 doesn't output anything to stderr. If any of these conditions is
70 not met, raise a CommandFailedException describing the problem."""
72 logger
.debug('Running command %r' % (command
,))
74 pipe
= subprocess
.Popen(
76 stdin
=subprocess
.PIPE
,
77 stdout
=subprocess
.PIPE
,
78 stderr
=subprocess
.PIPE
,
81 raise CommandFailedException('error executing %s: %s' % (commandname
, e
,))
82 (stdout
, stderr
) = pipe
.communicate()
83 if pipe
.returncode
or stderr
:
84 msg
= 'error executing %s; returncode=%s' % (commandname
, pipe
.returncode
,)
86 msg
+= ', error output:\n%s' % (stderr
,)
87 raise CommandFailedException(msg
)
90 def get_command_output(command
):
91 """Run COMMAND and return its stdout.
93 COMMAND is a list of strings. Run the command and return its stdout
94 as a string. If the command exits with a nonzero return code or
95 writes something to stderr, raise a CommandError."""
97 """A file-like object from which revision contents can be read."""
99 logger
.debug('Running command %r' % (command
,))
100 pipe
= subprocess
.Popen(
102 stdin
=subprocess
.PIPE
,
103 stdout
=subprocess
.PIPE
,
104 stderr
=subprocess
.PIPE
,
106 (stdout
, stderr
) = pipe
.communicate()
107 if pipe
.returncode
or stderr
:
108 raise CommandError(' '.join(command
), pipe
.returncode
, stderr
)