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 "[email protected]"

‎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
importmmap
1515

1616
fromgit.odictimportOrderedDict
17-
1817
fromcontextlibimportcontextmanager
1918
importsignal
2019
fromsubprocessimport (
@@ -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
defas_text(stdout_value):
697-
returnnotoutput_streamandstdout_value.decode(defenc) or'<OUTPUT_STREAM>'
697+
returnnotoutput_streamandsafe_decode(stdout_value) or'<OUTPUT_STREAM>'
698698
# end
699699

700700
ifstderr_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
elifstdout_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
raiseGitCommandError(command, status, stderr_value)
714714

715715
ifisinstance(stdout_value, bytes) andstdout_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
ifwith_extended_output:
720-
return (status, stdout_value, stderr_value.decode(defenc))
720+
return (status, stdout_value, safe_decode(stderr_value))
721721
else:
722722
returnstdout_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
returnd.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
defmviter(d):
4951
returnd.itervalues()
@@ -54,7 +56,7 @@ def safe_decode(s):
5456
ifisinstance(s, unicode):
5557
returns
5658
elifisinstance(s, bytes):
57-
returns.decode(defenc, errors='replace')
59+
returns.decode(defenc, 'replace')
5860
raiseTypeError('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
fromgitdb.utilimporthex_to_bin
99

10+
from .compatimportbinary_type
1011
from .objects.blobimportBlob
1112
from .objects.utilimportmode_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+
asserta_rawpathisNoneorisinstance(a_rawpath, binary_type)
260+
assertb_rawpathisNoneorisinstance(b_rawpath, binary_type)
261+
self.a_rawpath=a_rawpath
262+
self.b_rawpath=b_rawpath
260263

261264
ifself.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
ifa_blob_idisNoneora_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
ifb_blob_idisNoneorb_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_fromorNone
281-
self.rename_to=rename_toorNone
283+
assertraw_rename_fromisNoneorisinstance(raw_rename_from, binary_type)
284+
assertraw_rename_toisNoneorisinstance(raw_rename_to, binary_type)
285+
self.raw_rename_from=raw_rename_fromorNone
286+
self.raw_rename_to=raw_rename_toorNone
282287

283288
self.diff=diff
284289

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

352+
@property
353+
defa_path(self):
354+
returnself.a_rawpath.decode(defenc, 'replace') ifself.a_rawpathelseNone
355+
356+
@property
357+
defb_path(self):
358+
returnself.b_rawpath.decode(defenc, 'replace') ifself.b_rawpathelseNone
359+
360+
@property
361+
defrename_from(self):
362+
returnself.raw_rename_from.decode(defenc, 'replace') ifself.raw_rename_fromelseNone
363+
364+
@property
365+
defrename_to(self):
366+
returnself.raw_rename_to.decode(defenc, 'replace') ifself.raw_rename_toelseNone
367+
347368
@property
348369
defrenamed(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_modeordeleted_file_modeor (a_pathand (b_modeornew_modeornew_file_mode))
405427
b_mode=b_modeornew_modeornew_file_modeor (b_pathanda_mode)
406428
index.append(Diff(repo,
407-
a_pathanda_path.decode(defenc),
408-
b_pathandb_path.decode(defenc),
429+
a_path,
430+
b_path,
409431
a_blob_idanda_blob_id.decode(defenc),
410432
b_blob_idandb_blob_id.decode(defenc),
411433
a_modeanda_mode.decode(defenc),
412434
b_modeandb_mode.decode(defenc),
413435
new_file, deleted_file,
414-
rename_fromandrename_from.decode(defenc),
415-
rename_toandrename_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
elifchange_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
returnout
932932

933933
defcommit(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+
ifnotskip_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+
ifnotskip_hooks:
951+
run_commit_hook('post-commit', self)
947952
returnrval
948953

949954
@classmethod

0 commit comments

Comments
(0)