2 # Copyright (C) 2008 Michael Trier (mtrier@gmail.com) and contributors
4 # This module is part of GitPython and is released under
5 # the BSD License: http://www.opensource.org/licenses/bsd-license.php
10 from cola
import utils
11 from cola
.exception
import GitCommandError
14 return string
.replace('_', '-')
16 # Enables debugging of GitPython's git commands
17 GIT_PYTHON_TRACE
= os
.environ
.get("GIT_PYTHON_TRACE", False)
19 execute_kwargs
= ('istream', 'with_keep_cwd', 'with_extended_output',
20 'with_exceptions', 'with_raw_output')
24 The Git class manages communication with the Git binary
29 def set_cwd(self
, path
):
32 def __getattr__(self
, name
):
34 raise AttributeError(name
)
35 return lambda *args
, **kwargs
: self
._call
_process
(name
, *args
, **kwargs
)
37 def execute(self
, command
,
40 with_extended_output
=False,
42 with_raw_output
=False):
44 Handles executing the command on the shell and consumes and returns
45 the returned information (stdout)
48 The command argument list to execute
51 Standard input filehandle passed to subprocess.Popen.
54 Whether to use the current working directory from os.getcwd().
55 GitPython uses the cwd set by set_cwd() by default.
57 ``with_extended_output``
58 Whether to return a (status, stdout, stderr) tuple.
61 Whether to raise an exception when git returns a non-zero status.
64 Whether to avoid stripping off trailing whitespace.
67 str(output) # extended_output = False (Default)
68 tuple(int(status), str(output)) # extended_output = True
71 if GIT_PYTHON_TRACE
and not GIT_PYTHON_TRACE
== 'full':
72 print ' '.join(command
)
74 # Allow the user to have the command executed in their working dir.
75 if with_keep_cwd
or not self
._git
_cwd
:
81 if sys
.platform
== 'win32':
82 command
= utils
.shell_quote(*command
)
84 proc
= subprocess
.Popen(command
,
86 shell
=sys
.platform
== 'win32',
88 stderr
=subprocess
.PIPE
,
89 stdout
=subprocess
.PIPE
)
90 # Wait for the process to return
91 stdout_value
, stderr_value
= proc
.communicate()
96 status
= proc
.returncode
98 # Strip off trailing whitespace by default
99 if not with_raw_output
:
100 stdout_value
= stdout_value
.rstrip()
101 stderr_value
= stderr_value
.rstrip()
103 if with_exceptions
and status
:
104 raise GitCommandError(command
, status
, stderr_value
)
106 if GIT_PYTHON_TRACE
== 'full':
108 print "%s -> %d: '%s' !! '%s'" % (command
, status
, stdout_value
, stderr_value
)
110 print "%s -> %d: '%s'" % (command
, status
, stdout_value
)
112 print "%s -> %d" % (command
, status
)
114 # Allow access to the command's status code
115 if with_extended_output
:
116 return (status
, stdout_value
, stderr_value
)
118 if stdout_value
and stderr_value
:
119 return stderr_value
+ '\n' + stdout_value
125 def transform_kwargs(self
, **kwargs
):
127 Transforms Python style kwargs into git command line options.
130 for k
, v
in kwargs
.items():
133 args
.append("-%s" % k
)
134 elif type(v
) is not bool:
135 args
.append("-%s%s" % (k
, v
))
138 args
.append("--%s" % dashify(k
))
139 elif type(v
) is not bool:
140 args
.append("--%s=%s" % (dashify(k
), v
))
143 def _call_process(self
, method
, *args
, **kwargs
):
145 Run the given git command with the specified arguments and return
146 the result as a String
152 is the list of arguments
155 is a dict of keyword arguments.
156 This function accepts the same optional keyword arguments
160 git.rev_list('master', max_count=10, header=True)
166 # Handle optional arguments prior to calling transform_kwargs
167 # otherwise these'll end up in args, which is bad.
169 for kwarg
in execute_kwargs
:
171 _kwargs
[kwarg
] = kwargs
.pop(kwarg
)
175 # Prepare the argument list
176 opt_args
= self
.transform_kwargs(**kwargs
)
177 ext_args
= [a
.encode('utf-8') for a
in args
]
178 args
= opt_args
+ ext_args
180 call
= ['git', dashify(method
)]
183 return self
.execute(call
, **_kwargs
)