Skip to content

Commit 3565888

Browse files
committed
Merge remote-tracking branch 'upstream/master' into pr-cmd-raise-with-stderr-on-error
2 parents 08a0fad + e0b21f4 commit 3565888

File tree

13 files changed

+71
-19
lines changed

13 files changed

+71
-19
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ It provides abstractions of git objects for easy access of repository data, and
66

77
The object database implementation is optimized for handling large quantities of objects and large datasets, which is achieved by using low-level structures and data streaming.
88

9+
910
### REQUIREMENTS
1011

1112
GitPython needs the `git` executable to be installed on the system and available in your `PATH` for most operations. If it is not in your `PATH`, you can help GitPython find it by setting the `GIT_PYTHON_GIT_EXECUTABLE=<path/to/git>` environment variable.
1213

1314
* Git (1.7.x or newer)
15+
* Python 2.7 to 3.5, while python 2.6 is supported on a *best-effort basis*.
1416

1517
The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`. The installer takes care of installing them for you.
1618

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.3
1+
2.0.6dev0

doc/source/changes.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,25 @@
22
Changelog
33
=========
44

5+
2.0.6 - Fixes
6+
=============
7+
8+
* Fix: TypeError about passing keyword argument to string decode() on
9+
Python 2.6.
10+
11+
2.0.5 - Fixes
12+
=============
13+
14+
* Fix: parser of fetch info lines choked on some legitimate lines
15+
516
2.0.4 - Fixes
617
=============
718

19+
* Fix: parser of commit object data is now robust against cases where
20+
commit object contains invalid bytes. The invalid characters are now
21+
replaced rather than choked on.
22+
* Fix: non-ASCII paths are now properly decoded and returned in
23+
``.diff()`` output
824
* Fix: `RemoteProgress` will now strip the ', ' prefix or suffix from messages.
925
* API: Remote.[fetch|push|pull](...) methods now allow the ``progress`` argument to
1026
be a callable. This saves you from creating a custom type with usually just one

git/cmd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def __del__(self):
287287
return
288288

289289
# can be that nothing really exists anymore ...
290-
if os is None:
290+
if os is None or os.kill is None:
291291
return
292292

293293
# try to kill it

git/diff.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
PY3
1616
)
1717

18-
1918
__all__ = ('Diffable', 'DiffIndex', 'Diff', 'NULL_TREE')
2019

2120
# Special object to compare against the empty tree in diffs
2221
NULL_TREE = object()
2322

23+
_octal_byte_re = re.compile(b'\\\\([0-9]{3})')
24+
25+
26+
def _octal_repl(matchobj):
27+
value = matchobj.group(1)
28+
value = int(value, 8)
29+
if PY3:
30+
value = bytes(bytearray((value,)))
31+
else:
32+
value = chr(value)
33+
return value
34+
2435

2536
def decode_path(path, has_ab_prefix=True):
2637
if path == b'/dev/null':
@@ -32,6 +43,8 @@ def decode_path(path, has_ab_prefix=True):
3243
.replace(b'\\"', b'"')
3344
.replace(b'\\\\', b'\\'))
3445

46+
path = _octal_byte_re.sub(_octal_repl, path)
47+
3548
if has_ab_prefix:
3649
assert path.startswith(b'a/') or path.startswith(b'b/')
3750
path = path[2:]
@@ -337,7 +350,7 @@ def renamed(self):
337350
:note: This property is deprecated, please use ``renamed_file`` instead.
338351
"""
339352
return self.renamed_file
340-
353+
341354
@property
342355
def renamed_file(self):
343356
""":returns: True if the blob of our diff has been renamed

git/objects/commit.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,14 +501,14 @@ def _deserialize(self, stream):
501501

502502
try:
503503
self.author, self.authored_date, self.author_tz_offset = \
504-
parse_actor_and_date(author_line.decode(self.encoding))
504+
parse_actor_and_date(author_line.decode(self.encoding, 'replace'))
505505
except UnicodeDecodeError:
506506
log.error("Failed to decode author line '%s' using encoding %s", author_line, self.encoding,
507507
exc_info=True)
508508

509509
try:
510510
self.committer, self.committed_date, self.committer_tz_offset = \
511-
parse_actor_and_date(committer_line.decode(self.encoding))
511+
parse_actor_and_date(committer_line.decode(self.encoding, 'replace'))
512512
except UnicodeDecodeError:
513513
log.error("Failed to decode committer line '%s' using encoding %s", committer_line, self.encoding,
514514
exc_info=True)
@@ -518,7 +518,7 @@ def _deserialize(self, stream):
518518
# The end of our message stream is marked with a newline that we strip
519519
self.message = stream.read()
520520
try:
521-
self.message = self.message.decode(self.encoding)
521+
self.message = self.message.decode(self.encoding, 'replace')
522522
except UnicodeDecodeError:
523523
log.error("Failed to decode message '%s' using encoding %s", self.message, self.encoding, exc_info=True)
524524
# END exception handling

git/remote.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class FetchInfo(object):
204204
NEW_TAG, NEW_HEAD, HEAD_UPTODATE, TAG_UPDATE, REJECTED, FORCED_UPDATE, \
205205
FAST_FORWARD, ERROR = [1 << x for x in range(8)]
206206

207-
re_fetch_result = re.compile("^\s*(.) (\[?[\w\s\.$@]+\]?)\s+(.+) -> ([/\w_\+\.\-$@#]+)( \(.*\)?$)?")
207+
re_fetch_result = re.compile("^\s*(.) (\[?[\w\s\.$@]+\]?)\s+(.+) -> ([/\w_\+\.\-$@#()]+)( \(.*\)?$)?")
208208

209209
_flag_map = {'!': ERROR,
210210
'+': FORCED_UPDATE,

git/test/fixtures/commit_invalid_data

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
tree 9f1a495d7d9692d24f5caedaa89f5c2c32d59368
2+
parent 492ace2ffce0e426ebeb55e364e987bcf024dd3b
3+
author E.Azer Ko�o�o�oculu <[email protected]> 1306710073 +0300
4+
committer E.Azer Ko�o�o�oculu <[email protected]> 1306710073 +0300
5+
6+
add environjs

git/test/fixtures/diff_patch_unsafe_paths

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94
6161
+++ "b/path/¯\\_(ツ)_|¯"
6262
@@ -0,0 +1 @@
6363
+dummy content
64+
diff --git "a/path/\360\237\222\251.txt" "b/path/\360\237\222\251.txt"
65+
new file mode 100644
66+
index 0000000000000000000000000000000000000000..eaf5f7510320b6a327fb308379de2f94d8859a54
67+
--- /dev/null
68+
+++ "b/path/\360\237\222\251.txt"
69+
@@ -0,0 +1 @@
70+
+dummy content
6471
diff --git a/a/with spaces b/b/with some spaces
6572
similarity index 100%
6673
rename from a/with spaces

git/test/test_commit.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,13 @@ def test_serialization_unicode_support(self):
306306
# it appears
307307
cmt.author.__repr__()
308308

309+
def test_invalid_commit(self):
310+
cmt = self.rorepo.commit()
311+
cmt._deserialize(open(fixture_path('commit_invalid_data'), 'rb'))
312+
313+
assert cmt.author.name == u'E.Azer Ko�o�o�oculu', cmt.author.name
314+
assert cmt.author.email == '[email protected]', cmt.author.email
315+
309316
def test_gpgsig(self):
310317
cmt = self.rorepo.commit()
311318
cmt._deserialize(open(fixture_path('commit_with_gpgsig'), 'rb'))

0 commit comments

Comments
 (0)