summaryrefslogtreecommitdiff
path: root/git
diff options
context:
space:
mode:
Diffstat (limited to 'git')
-rw-r--r--git/cmd.py22
-rw-r--r--git/exc.py10
m---------git/ext/gitdb0
-rw-r--r--git/repo/base.py8
-rw-r--r--git/test/test_git.py30
5 files changed, 50 insertions, 20 deletions
diff --git a/git/cmd.py b/git/cmd.py
index b3274dd8..bd7d5b92 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -74,6 +74,9 @@ class Git(LazyMixin):
self.args = args
def __del__(self):
+ self.proc.stdout.close()
+ self.proc.stderr.close()
+
# did the process finish already so we have a return code ?
if self.proc.poll() is not None:
return
@@ -85,6 +88,8 @@ class Git(LazyMixin):
# try to kill it
try:
os.kill(self.proc.pid, 2) # interrupt signal
+ except OSError:
+ pass # ignore error when process already died
except AttributeError:
# try windows
# for some reason, providing None for stdout/stderr still prints something. This is why
@@ -101,6 +106,8 @@ class Git(LazyMixin):
:raise GitCommandError: if the return status is not 0"""
status = self.proc.wait()
+ self.proc.stdout.close()
+ self.proc.stderr.close()
if status != 0:
raise GitCommandError(self.args, status, self.proc.stderr.read())
# END status handling
@@ -236,7 +243,7 @@ class Git(LazyMixin):
if attr == '_version_info':
# We only use the first 4 numbers, as everthing else could be strings in fact (on windows)
version_numbers = self._call_process('version').split(' ')[2]
- self._version_info = tuple(int(n) for n in version_numbers.split('.')[:4])
+ self._version_info = tuple(int(n) for n in version_numbers.split('.')[:4] if n.isdigit())
else:
super(Git, self)._set_cache_(attr)
#END handle version info
@@ -316,6 +323,9 @@ class Git(LazyMixin):
if ouput_stream is True, the stdout value will be your output stream:
* output_stream if extended_output = False
* tuple(int(status), output_stream, str(stderr)) if extended_output = True
+
+ Note git is executed with LC_MESSAGES="C" to ensure consitent
+ output regardless of system language.
:raise GitCommandError:
@@ -333,6 +343,7 @@ class Git(LazyMixin):
# Start the process
proc = Popen(command,
+ env={"LC_MESSAGES": "C"},
cwd=cwd,
stdin=istream,
stderr=PIPE,
@@ -380,7 +391,10 @@ class Git(LazyMixin):
# END handle debug printing
if with_exceptions and status != 0:
- raise GitCommandError(command, status, stderr_value)
+ if with_extended_output:
+ raise GitCommandError(command, status, stderr_value, stdout_value)
+ else:
+ raise GitCommandError(command, status, stderr_value)
# Allow access to the command's status code
if with_extended_output:
@@ -410,12 +424,16 @@ class Git(LazyMixin):
@classmethod
def __unpack_args(cls, arg_list):
if not isinstance(arg_list, (list,tuple)):
+ if isinstance(arg_list, unicode):
+ return [arg_list.encode('utf-8')]
return [ str(arg_list) ]
outlist = list()
for arg in arg_list:
if isinstance(arg_list, (list, tuple)):
outlist.extend(cls.__unpack_args( arg ))
+ elif isinstance(arg_list, unicode):
+ outlist.append(arg_list.encode('utf-8'))
# END recursion
else:
outlist.append(str(arg))
diff --git a/git/exc.py b/git/exc.py
index 3b3091e2..76d3d486 100644
--- a/git/exc.py
+++ b/git/exc.py
@@ -17,14 +17,18 @@ class NoSuchPathError(OSError):
class GitCommandError(Exception):
""" Thrown if execution of the git command fails with non-zero status code. """
- def __init__(self, command, status, stderr=None):
+ def __init__(self, command, status, stderr=None, stdout=None):
self.stderr = stderr
+ self.stdout = stdout
self.status = status
self.command = command
def __str__(self):
- return ("'%s' returned exit status %i: %s" %
- (' '.join(str(i) for i in self.command), self.status, self.stderr))
+ ret = "'%s' returned exit status %i: %s" % \
+ (' '.join(str(i) for i in self.command), self.status, self.stderr)
+ if self.stdout is not None:
+ ret += "\nstdout: %s" % self.stdout
+ return ret
class CheckoutError( Exception ):
diff --git a/git/ext/gitdb b/git/ext/gitdb
-Subproject 39de1127459b73b862f2b779bb4565ad6b4bd62
+Subproject 2f2fe4eea8ba4f47e63a7392a1f27f74f5ee925
diff --git a/git/repo/base.py b/git/repo/base.py
index 71492fe8..933c8c82 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -376,7 +376,7 @@ class Repo(object):
if rev is None:
return self.head.commit
else:
- return self.rev_parse(str(rev)+"^0")
+ return self.rev_parse(unicode(rev)+"^0")
def iter_trees(self, *args, **kwargs):
""":return: Iterator yielding Tree objects
@@ -399,7 +399,7 @@ class Repo(object):
if rev is None:
return self.head.commit.tree
else:
- return self.rev_parse(str(rev)+"^{tree}")
+ return self.rev_parse(unicode(rev)+"^{tree}")
def iter_commits(self, rev=None, paths='', **kwargs):
"""A list of Commit objects representing the history of a given ref/commit
@@ -499,8 +499,8 @@ class Repo(object):
default_args = ('--abbrev=40', '--full-index', '--raw')
if index:
# diff index against HEAD
- if isfile(self.index.path) and self.head.is_valid() and \
- len(self.git.diff('HEAD', '--cached', *default_args)):
+ if isfile(self.index.path) and \
+ len(self.git.diff('--cached', *default_args)):
return True
# END index handling
if working_tree:
diff --git a/git/test/test_git.py b/git/test/test_git.py
index e67cb92b..cdea1d3e 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -4,7 +4,7 @@
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
-import os, sys
+import os
from git.test.lib import ( TestBase,
patch,
raises,
@@ -16,7 +16,7 @@ from git import ( Git,
GitCommandError )
class TestGit(TestBase):
-
+
@classmethod
def setUp(cls):
super(TestGit, cls).setUp()
@@ -29,6 +29,14 @@ class TestGit(TestBase):
assert_true(git.called)
assert_equal(git.call_args, ((['git', 'version'],), {}))
+ def test_call_unpack_args_unicode(self):
+ args = Git._Git__unpack_args(u'Unicode' + unichr(40960))
+ assert_equal(args, ['Unicode\xea\x80\x80'])
+
+ def test_call_unpack_args(self):
+ args = Git._Git__unpack_args(['git', 'log', '--', u'Unicode' + unichr(40960)])
+ assert_equal(args, ['git', 'log', '--', 'Unicode\xea\x80\x80'])
+
@raises(GitCommandError)
def test_it_raises_errors(self):
self.git.this_does_not_exist()
@@ -56,9 +64,9 @@ class TestGit(TestBase):
@patch.object(Git, 'execute')
def test_it_ignores_false_kwargs(self, git):
# this_should_not_be_ignored=False implies it *should* be ignored
- output = self.git.version(pass_this_kwarg=False)
+ self.git.version(pass_this_kwarg=False)
assert_true("pass_this_kwarg" not in git.call_args[1])
-
+
def test_persistent_cat_file_command(self):
# read header only
import subprocess as sp
@@ -67,37 +75,37 @@ class TestGit(TestBase):
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
g.stdin.flush()
obj_info = g.stdout.readline()
-
+
# read header + data
g = self.git.cat_file(batch=True, istream=sp.PIPE,as_process=True)
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
g.stdin.flush()
obj_info_two = g.stdout.readline()
assert obj_info == obj_info_two
-
+
# read data - have to read it in one large chunk
size = int(obj_info.split()[2])
data = g.stdout.read(size)
- terminating_newline = g.stdout.read(1)
+ g.stdout.read(1)
# now we should be able to read a new object
g.stdin.write("b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
g.stdin.flush()
assert g.stdout.readline() == obj_info
-
-
+
+
# same can be achived using the respective command functions
hexsha, typename, size = self.git.get_object_header(hexsha)
hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha)
assert typename == typename_two and size == size_two
-
+
def test_version(self):
v = self.git.version_info
assert isinstance(v, tuple)
for n in v:
assert isinstance(n, int)
#END verify number types
-
+
def test_cmd_override(self):
prev_cmd = self.git.GIT_PYTHON_GIT_EXECUTABLE
try: