summaryrefslogtreecommitdiff
path: root/git
diff options
context:
space:
mode:
Diffstat (limited to 'git')
-rw-r--r--git/cmd.py1
-rw-r--r--git/objects/commit.py17
-rw-r--r--git/objects/fun.py11
-rw-r--r--git/objects/util.py9
-rw-r--r--git/remote.py17
-rw-r--r--git/repo/base.py7
-rw-r--r--git/test/lib/helper.py2
-rw-r--r--git/test/test_fun.py7
-rw-r--r--git/test/test_git.py4
-rw-r--r--git/util.py14
10 files changed, 62 insertions, 27 deletions
diff --git a/git/cmd.py b/git/cmd.py
index 5425d8ff..a1780de7 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -88,6 +88,7 @@ class Git(LazyMixin):
# try to kill it
try:
os.kill(self.proc.pid, 2) # interrupt signal
+ self.proc.wait() # ensure process goes away
except OSError:
pass # ignore error when process already died
except AttributeError:
diff --git a/git/objects/commit.py b/git/objects/commit.py
index 4380f472..bc437e8b 100644
--- a/git/objects/commit.py
+++ b/git/objects/commit.py
@@ -8,6 +8,7 @@ from git.util import (
Actor,
Iterable,
Stats,
+ finalize_process
)
from git.diff import Diffable
from tree import Tree
@@ -65,7 +66,6 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
message=None, parents=None, encoding=None, gpgsig=None):
"""Instantiate a new Commit. All keyword arguments taking None as default will
be implicitly set on first query.
-
:param binsha: 20 byte sha1
:param parents: tuple( Commit, ... )
is a tuple of commit ids or actual Commits
@@ -252,6 +252,10 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
assert len(hexsha) == 40, "Invalid line: %s" % hexsha
yield Commit(repo, hex_to_bin(hexsha))
# END for each line in stream
+ # TODO: Review this - it seems process handling got a bit out of control
+ # due to many developers trying to fix the open file handles issue
+ if hasattr(proc_or_stream, 'wait'):
+ finalize_process(proc_or_stream)
@classmethod
@@ -430,14 +434,21 @@ class Commit(base.Object, Iterable, Diffable, Traversable, Serializable):
self.author, self.authored_date, self.author_tz_offset = parse_actor_and_date(next_line)
self.committer, self.committed_date, self.committer_tz_offset = parse_actor_and_date(readline())
-
+
+ # we might run into one or more mergetag blocks, skip those for now
+ next_line = readline()
+ while next_line.startswith('mergetag '):
+ next_line = readline()
+ while next_line.startswith(' '):
+ next_line = readline()
# now we can have the encoding line, or an empty line followed by the optional
# message.
self.encoding = self.default_encoding
# read headers
- buf = readline().strip()
+ enc = next_line
+ buf = enc.strip()
while buf != "":
if buf[0:10] == "encoding ":
self.encoding = buf[buf.find(' ')+1:]
diff --git a/git/objects/fun.py b/git/objects/fun.py
index f73be542..66b7998e 100644
--- a/git/objects/fun.py
+++ b/git/objects/fun.py
@@ -70,9 +70,13 @@ def tree_entries_from_data(data):
# default encoding for strings in git is utf8
# Only use the respective unicode object if the byte stream was encoded
name = data[ns:i]
- name_enc = name.decode("utf-8")
- if len(name) > len(name_enc):
- name = name_enc
+ try:
+ name_enc = name.decode("utf-8")
+ except UnicodeDecodeError:
+ pass
+ else:
+ if len(name) > len(name_enc):
+ name = name_enc
# END handle encoding
# byte is NULL, get next 20
@@ -84,6 +88,7 @@ def tree_entries_from_data(data):
return out
+
def _find_by_name(tree_data, name, is_dir, start_at):
"""return data entry matching the given name and tree mode
or None.
diff --git a/git/objects/util.py b/git/objects/util.py
index 2e44c9c0..cdf72bed 100644
--- a/git/objects/util.py
+++ b/git/objects/util.py
@@ -167,6 +167,7 @@ def parse_date(string_date):
# precompiled regex
_re_actor_epoch = re.compile(r'^.+? (.*) (\d+) ([+-]\d+).*$')
+_re_only_actor = re.compile(r'^.+? (.*)$')
def parse_actor_and_date(line):
"""Parse out the actor (author or committer) info from a line like::
@@ -174,10 +175,14 @@ def parse_actor_and_date(line):
author Tom Preston-Werner <tom@mojombo.com> 1191999972 -0700
:return: [Actor, int_seconds_since_epoch, int_timezone_offset]"""
+ actor, epoch, offset = '', 0, 0
m = _re_actor_epoch.search(line)
- actor, epoch, offset = m.groups()
+ if m:
+ actor, epoch, offset = m.groups()
+ else:
+ m = _re_only_actor.search(line)
+ actor = m.group(1) if m else line or ''
return (Actor._from_string(actor), int(epoch), utctz_to_altz(offset))
-
#} END functions
diff --git a/git/remote.py b/git/remote.py
index b06c0686..75e88e43 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -24,7 +24,10 @@ from refs import (
TagReference
)
-from git.util import join_path
+from git.util import (
+ join_path,
+ finalize_process
+ )
from gitdb.util import join
import re
@@ -58,18 +61,6 @@ def digest_process_messages(fh, progress):
# END while file is not done reading
return dropped_lines
-def finalize_process(proc):
- """Wait for the process (clone, fetch, pull or push) and handle its errors accordingly"""
- try:
- proc.wait()
- except GitCommandError,e:
- # if a push has rejected items, the command has non-zero return status
- # a return status of 128 indicates a connection error - reraise the previous one
- if proc.poll() == 128:
- raise
- pass
- # END exception handling
-
def add_progress(kwargs, git, progress):
"""Add the --progress flag to the given kwargs dict if supported by the
git command. If the actual progress in the given progress instance is not
diff --git a/git/repo/base.py b/git/repo/base.py
index 933c8c82..6a311f0b 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -6,7 +6,10 @@
from git.exc import InvalidGitRepositoryError, NoSuchPathError
from git.cmd import Git
-from git.util import Actor
+from git.util import (
+ Actor,
+ finalize_process
+ )
from git.refs import *
from git.index import IndexFile
from git.objects import *
@@ -14,7 +17,6 @@ from git.config import GitConfigParser
from git.remote import (
Remote,
digest_process_messages,
- finalize_process,
add_progress
)
@@ -540,6 +542,7 @@ class Repo(object):
if filename[0] == filename[-1] == '"':
filename = filename[1:-1].decode('string_escape')
untracked_files.append(filename)
+ finalize_process(proc)
return untracked_files
@property
diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py
index 2634ecdb..a76f1a15 100644
--- a/git/test/lib/helper.py
+++ b/git/test/lib/helper.py
@@ -227,7 +227,7 @@ class TestBase(TestCase):
"""
@classmethod
- def setUp(cls):
+ def setUpClass(cls):
"""
Dynamically add a read-only repository to our actual type. This way
each test type has its own repository
diff --git a/git/test/test_fun.py b/git/test/test_fun.py
index 530988ef..096cd368 100644
--- a/git/test/test_fun.py
+++ b/git/test/test_fun.py
@@ -2,7 +2,8 @@ from git.test.lib import *
from git.objects.fun import (
traverse_tree_recursive,
traverse_trees_recursive,
- tree_to_stream
+ tree_to_stream,
+ tree_entries_from_data
)
from git.index.fun import (
@@ -249,3 +250,7 @@ class TestFun(TestBase):
entries = traverse_tree_recursive(odb, commit.tree.binsha, '')
assert entries
# END for each commit
+
+ def test_tree_entries_from_data(self):
+ r = tree_entries_from_data(b'100644 \x9f\0aaa')
+ assert r == [('aaa', 33188, '\x9f')], r
diff --git a/git/test/test_git.py b/git/test/test_git.py
index cdea1d3e..7132aa83 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -18,8 +18,8 @@ from git import ( Git,
class TestGit(TestBase):
@classmethod
- def setUp(cls):
- super(TestGit, cls).setUp()
+ def setUpClass(cls):
+ super(TestGit, cls).setUpClass()
cls.git = Git(cls.rorepo.working_dir)
@patch.object(Git, 'execute')
diff --git a/git/util.py b/git/util.py
index 30ccfa66..955d23de 100644
--- a/git/util.py
+++ b/git/util.py
@@ -15,6 +15,8 @@ import getpass
# NOTE: Some of the unused imports might be used/imported by others.
# Handle once test-cases are back up and running.
+from exc import GitCommandError
+
from gitdb.util import (
make_sha,
LockedFD,
@@ -117,6 +119,18 @@ def get_user_id():
""":return: string identifying the currently active system user as name@node"""
return "%s@%s" % (getpass.getuser(), platform.node())
+def finalize_process(proc):
+ """Wait for the process (clone, fetch, pull or push) and handle its errors accordingly"""
+ try:
+ proc.wait()
+ except GitCommandError,e:
+ # if a push has rejected items, the command has non-zero return status
+ # a return status of 128 indicates a connection error - reraise the previous one
+ if proc.poll() == 128:
+ raise
+ pass
+ # END exception handling
+
#} END utilities
#{ Classes