Skip to content

Commit b4b5ecc

Browse files
committed
2 parents a7f403b + 4896fa2 commit b4b5ecc

File tree

15 files changed

+223
-53
lines changed

15 files changed

+223
-53
lines changed

.travis.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ install:
1919
- pip install coveralls flake8 sphinx
2020

2121
# generate some reflog as git-python tests need it (in master)
22-
- git tag __testing_point__
23-
- git checkout master || git checkout -b master
24-
- git reset --hard HEAD~1
25-
- git reset --hard HEAD~1
26-
- git reset --hard HEAD~1
27-
- git reset --hard __testing_point__
22+
- ./init-tests-after-clone.sh
2823

2924
# as commits are performed with the default user, it needs to be set for travis too
3025
- git config --global user.email "travis@ci.com"

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,29 @@ Both commands will install the required package dependencies.
3434
A distribution package can be obtained for manual installation at:
3535

3636
http://pypi.python.org/pypi/GitPython
37+
38+
If you like to clone from source, you can do it like so:
39+
40+
```bash
41+
git clone https://github.com/gitpython-developers/GitPython
42+
git submodule update --init --recursive
43+
./init-tests-after-clone.sh
44+
```
3745

3846
### RUNNING TESTS
3947

48+
*Important*: Right after cloning this repository, please be sure to have executed the `init-tests-after-clone.sh` script in the repository root. Otherwise you will encounter test failures.
49+
4050
The easiest way to run test is by using [tox](https://pypi.python.org/pypi/tox) a wrapper around virtualenv. It will take care of setting up environnements with the proper dependencies installed and execute test commands. To install it simply:
4151

4252
pip install tox
4353

4454
Then run:
4555

4656
tox
57+
58+
59+
For more fine-grained control, you can use `nose`.
4760

4861
### Contributions
4962

VERSION

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

doc/source/changes.rst

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
Changelog
33
=========
44

5-
2.0.6 - Fixes
6-
=============
7-
5+
2.0.6 - Fixes and Features
6+
==========================
7+
8+
* Fix: remote output parser now correctly matches refs with non-ASCII
9+
chars in them
10+
* API: Diffs now have `a_rawpath`, `b_rawpath`, `raw_rename_from`,
11+
`raw_rename_to` properties, which are the raw-bytes equivalents of their
12+
unicode path counterparts.
813
* Fix: TypeError about passing keyword argument to string decode() on
914
Python 2.6.
15+
* Feature: `setUrl API on Remotes <https://github.com/gitpython-developers/GitPython/pull/446#issuecomment-224670539>`_
1016

1117
2.0.5 - Fixes
1218
=============

git/cmd.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import mmap
1515

1616
from git.odict import OrderedDict
17-
1817
from contextlib import contextmanager
1918
import signal
2019
from subprocess import (
@@ -40,7 +39,8 @@
4039
PY3,
4140
bchr,
4241
# just to satisfy flake8 on py3
43-
unicode
42+
unicode,
43+
safe_decode,
4444
)
4545

4646
execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output',
@@ -694,12 +694,12 @@ def _kill_process(pid):
694694
cmdstr = " ".join(command)
695695

696696
def as_text(stdout_value):
697-
return not output_stream and stdout_value.decode(defenc) or '<OUTPUT_STREAM>'
697+
return not output_stream and safe_decode(stdout_value) or '<OUTPUT_STREAM>'
698698
# end
699699

700700
if stderr_value:
701701
log.info("%s -> %d; stdout: '%s'; stderr: '%s'",
702-
cmdstr, status, as_text(stdout_value), stderr_value.decode(defenc))
702+
cmdstr, status, as_text(stdout_value), safe_decode(stderr_value))
703703
elif stdout_value:
704704
log.info("%s -> %d; stdout: '%s'", cmdstr, status, as_text(stdout_value))
705705
else:
@@ -713,11 +713,11 @@ def as_text(stdout_value):
713713
raise GitCommandError(command, status, stderr_value)
714714

715715
if isinstance(stdout_value, bytes) and stdout_as_string: # could also be output_stream
716-
stdout_value = stdout_value.decode(defenc)
716+
stdout_value = safe_decode(stdout_value)
717717

718718
# Allow access to the command's status code
719719
if with_extended_output:
720-
return (status, stdout_value, stderr_value.decode(defenc))
720+
return (status, stdout_value, safe_decode(stderr_value))
721721
else:
722722
return stdout_value
723723

git/compat.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def mviter(d):
3535
return d.values()
3636
range = xrange
3737
unicode = str
38+
binary_type = bytes
3839
else:
3940
FileType = file
4041
# usually, this is just ascii, which might not enough for our encoding needs
@@ -44,6 +45,7 @@ def mviter(d):
4445
byte_ord = ord
4546
bchr = chr
4647
unicode = unicode
48+
binary_type = str
4749
range = xrange
4850
def mviter(d):
4951
return d.itervalues()
@@ -54,7 +56,7 @@ def safe_decode(s):
5456
if isinstance(s, unicode):
5557
return s
5658
elif isinstance(s, bytes):
57-
return s.decode(defenc, errors='replace')
59+
return s.decode(defenc, 'replace')
5860
raise TypeError('Expected bytes or text, but got %r' % (s,))
5961

6062

git/diff.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from gitdb.util import hex_to_bin
99

10+
from .compat import binary_type
1011
from .objects.blob import Blob
1112
from .objects.util import mode_str_to_int
1213

@@ -245,18 +246,20 @@ class Diff(object):
245246
NULL_HEX_SHA = "0" * 40
246247
NULL_BIN_SHA = b"\0" * 20
247248

248-
__slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "a_path", "b_path",
249-
"new_file", "deleted_file", "rename_from", "rename_to", "diff")
249+
__slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "a_rawpath", "b_rawpath",
250+
"new_file", "deleted_file", "raw_rename_from", "raw_rename_to", "diff")
250251

251-
def __init__(self, repo, a_path, b_path, a_blob_id, b_blob_id, a_mode,
252-
b_mode, new_file, deleted_file, rename_from,
253-
rename_to, diff):
252+
def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,
253+
b_mode, new_file, deleted_file, raw_rename_from,
254+
raw_rename_to, diff):
254255

255256
self.a_mode = a_mode
256257
self.b_mode = b_mode
257258

258-
self.a_path = a_path
259-
self.b_path = b_path
259+
assert a_rawpath is None or isinstance(a_rawpath, binary_type)
260+
assert b_rawpath is None or isinstance(b_rawpath, binary_type)
261+
self.a_rawpath = a_rawpath
262+
self.b_rawpath = b_rawpath
260263

261264
if self.a_mode:
262265
self.a_mode = mode_str_to_int(self.a_mode)
@@ -266,19 +269,21 @@ def __init__(self, repo, a_path, b_path, a_blob_id, b_blob_id, a_mode,
266269
if a_blob_id is None or a_blob_id == self.NULL_HEX_SHA:
267270
self.a_blob = None
268271
else:
269-
self.a_blob = Blob(repo, hex_to_bin(a_blob_id), mode=self.a_mode, path=a_path)
272+
self.a_blob = Blob(repo, hex_to_bin(a_blob_id), mode=self.a_mode, path=self.a_path)
270273

271274
if b_blob_id is None or b_blob_id == self.NULL_HEX_SHA:
272275
self.b_blob = None
273276
else:
274-
self.b_blob = Blob(repo, hex_to_bin(b_blob_id), mode=self.b_mode, path=b_path)
277+
self.b_blob = Blob(repo, hex_to_bin(b_blob_id), mode=self.b_mode, path=self.b_path)
275278

276279
self.new_file = new_file
277280
self.deleted_file = deleted_file
278281

279282
# be clear and use None instead of empty strings
280-
self.rename_from = rename_from or None
281-
self.rename_to = rename_to or None
283+
assert raw_rename_from is None or isinstance(raw_rename_from, binary_type)
284+
assert raw_rename_to is None or isinstance(raw_rename_to, binary_type)
285+
self.raw_rename_from = raw_rename_from or None
286+
self.raw_rename_to = raw_rename_to or None
282287

283288
self.diff = diff
284289

@@ -344,6 +349,22 @@ def __str__(self):
344349
# end
345350
return res
346351

352+
@property
353+
def a_path(self):
354+
return self.a_rawpath.decode(defenc, 'replace') if self.a_rawpath else None
355+
356+
@property
357+
def b_path(self):
358+
return self.b_rawpath.decode(defenc, 'replace') if self.b_rawpath else None
359+
360+
@property
361+
def rename_from(self):
362+
return self.raw_rename_from.decode(defenc, 'replace') if self.raw_rename_from else None
363+
364+
@property
365+
def rename_to(self):
366+
return self.raw_rename_to.decode(defenc, 'replace') if self.raw_rename_to else None
367+
347368
@property
348369
def renamed(self):
349370
""":returns: True if the blob of our diff has been renamed
@@ -388,6 +409,7 @@ def _index_from_patch_format(cls, repo, stream):
388409
new_file_mode, deleted_file_mode, \
389410
a_blob_id, b_blob_id, b_mode, \
390411
a_path, b_path = header.groups()
412+
391413
new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode)
392414

393415
a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback)
@@ -404,15 +426,15 @@ def _index_from_patch_format(cls, repo, stream):
404426
a_mode = old_mode or deleted_file_mode or (a_path and (b_mode or new_mode or new_file_mode))
405427
b_mode = b_mode or new_mode or new_file_mode or (b_path and a_mode)
406428
index.append(Diff(repo,
407-
a_path and a_path.decode(defenc),
408-
b_path and b_path.decode(defenc),
429+
a_path,
430+
b_path,
409431
a_blob_id and a_blob_id.decode(defenc),
410432
b_blob_id and b_blob_id.decode(defenc),
411433
a_mode and a_mode.decode(defenc),
412434
b_mode and b_mode.decode(defenc),
413435
new_file, deleted_file,
414-
rename_from and rename_from.decode(defenc),
415-
rename_to and rename_to.decode(defenc),
436+
rename_from,
437+
rename_to,
416438
None))
417439

418440
previous_header = header
@@ -438,8 +460,8 @@ def _index_from_raw_format(cls, repo, stream):
438460
meta, _, path = line[1:].partition('\t')
439461
old_mode, new_mode, a_blob_id, b_blob_id, change_type = meta.split(None, 4)
440462
path = path.strip()
441-
a_path = path
442-
b_path = path
463+
a_path = path.encode(defenc)
464+
b_path = path.encode(defenc)
443465
deleted_file = False
444466
new_file = False
445467
rename_from = None
@@ -455,6 +477,8 @@ def _index_from_raw_format(cls, repo, stream):
455477
new_file = True
456478
elif change_type[0] == 'R': # parses RXXX, where XXX is a confidence value
457479
a_path, b_path = path.split('\t', 1)
480+
a_path = a_path.encode(defenc)
481+
b_path = b_path.encode(defenc)
458482
rename_from, rename_to = a_path, b_path
459483
# END add/remove handling
460484

git/ext/gitdb

git/index/base.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -931,19 +931,24 @@ def move(self, items, skip_errors=False, **kwargs):
931931
return out
932932

933933
def commit(self, message, parent_commits=None, head=True, author=None,
934-
committer=None, author_date=None, commit_date=None):
934+
committer=None, author_date=None, commit_date=None,
935+
skip_hooks=False):
935936
"""Commit the current default index file, creating a commit object.
936937
For more information on the arguments, see tree.commit.
937938
938939
:note: If you have manually altered the .entries member of this instance,
939940
don't forget to write() your changes to disk beforehand.
941+
Passing skip_hooks=True is the equivalent of using `-n`
942+
or `--no-verify` on the command line.
940943
:return: Commit object representing the new commit"""
941-
run_commit_hook('pre-commit', self)
944+
if not skip_hooks:
945+
run_commit_hook('pre-commit', self)
942946
tree = self.write_tree()
943947
rval = Commit.create_from_tree(self.repo, tree, message, parent_commits,
944948
head, author=author, committer=committer,
945949
author_date=author_date, commit_date=commit_date)
946-
run_commit_hook('post-commit', self)
950+
if not skip_hooks:
951+
run_commit_hook('post-commit', self)
947952
return rval
948953

949954
@classmethod

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy