Merge branch 'master' into fix/deepsource-issues · gitpython-developers/GitPython@abb1896 · GitHub
Skip to content

Commit abb1896

Browse files
authored
Merge branch 'master' into fix/deepsource-issues
2 parents 284f89d + dfa0eac commit abb1896

12 files changed

Lines changed: 148 additions & 21 deletions

File tree

AUTHORS

Lines changed: 1 addition & 0 deletions

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,13 @@ Please have a look at the [contributions file][contributing].
110110

111111
### How to make a new release
112112

113-
* Update/verify the version in the `VERSION` file
114-
* Update/verify that the changelog has been updated
113+
* Update/verify the **version** in the `VERSION` file
114+
* Update/verify that the `doc/source/changes.rst` changelog file was updated
115115
* Commit everything
116116
* Run `git tag -s <version>` to tag the version in Git
117117
* Run `make release`
118-
* Finally, set the upcoming version in the `VERSION` file, usually be
118+
* Close the milestone mentioned in the _changelog_ and create a new one. _Do not reuse milestones by renaming them_.
119+
* set the upcoming version in the `VERSION` file, usually be
119120
incrementing the patch level, and possibly by appending `-dev`. Probably you
120121
want to `git push` once more.
121122

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.3
1+
3.0.4

doc/source/changes.rst

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

5+
3.0.4 - Bugfixes
6+
=============================================
7+
8+
see the following for details:
9+
https://github.com/gitpython-developers/gitpython/milestone/31?closed=1
10+
511
3.0.3 - Bugfixes
612
=============================================
713

git/cmd.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767

6868
def handle_process_output(process, stdout_handler, stderr_handler,
6969
finalizer=None, decode_streams=True):
70-
"""Registers for notifications to lean that process output is ready to read, and dispatches lines to
70+
"""Registers for notifications to learn that process output is ready to read, and dispatches lines to
7171
the respective line handlers.
7272
This function returns once the finalizer returns
7373
@@ -330,6 +330,9 @@ def polish_url(cls, url, is_cygwin=None):
330330
but git stops liking them as it will escape the backslashes.
331331
Hence we undo the escaping just to be sure.
332332
"""
333+
url = os.path.expandvars(url)
334+
if url.startswith('~'):
335+
url = os.path.expanduser(url)
333336
url = url.replace("\\\\", "\\").replace("\\", "/")
334337

335338
return url
@@ -362,8 +365,11 @@ def __del__(self):
362365
proc.stderr.close()
363366

364367
# did the process finish already so we have a return code ?
365-
if proc.poll() is not None:
366-
return
368+
try:
369+
if proc.poll() is not None:
370+
return
371+
except OSError as ex:
372+
log.info("Ignored error after process had died: %r", ex)
367373

368374
# can be that nothing really exists anymore ...
369375
if os is None or getattr(os, 'kill', None) is None:

git/diff.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class DiffIndex(list):
167167
# R = Renamed
168168
# M = Modified
169169
# T = Changed in the type
170-
change_type = ("A", "D", "R", "M", "T")
170+
change_type = ("A", "C", "D", "R", "M", "T")
171171

172172
def iter_change_type(self, change_type):
173173
"""
@@ -193,6 +193,8 @@ def iter_change_type(self, change_type):
193193
yield diff
194194
elif change_type == "D" and diff.deleted_file:
195195
yield diff
196+
elif change_type == "C" and diff.copied_file:
197+
yield diff
196198
elif change_type == "R" and diff.renamed:
197199
yield diff
198200
elif change_type == "M" and diff.a_blob and diff.b_blob and diff.a_blob != diff.b_blob:
@@ -235,14 +237,17 @@ class Diff(object):
235237
# precompiled regex
236238
re_header = re.compile(br"""
237239
^diff[ ]--git
238-
[ ](?P<a_path_fallback>"?a/.+?"?)[ ](?P<b_path_fallback>"?b/.+?"?)\n
240+
[ ](?P<a_path_fallback>"?[ab]/.+?"?)[ ](?P<b_path_fallback>"?[ab]/.+?"?)\n
239241
(?:^old[ ]mode[ ](?P<old_mode>\d+)\n
240242
^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
241243
(?:^similarity[ ]index[ ]\d+%\n
242244
^rename[ ]from[ ](?P<rename_from>.*)\n
243245
^rename[ ]to[ ](?P<rename_to>.*)(?:\n|$))?
244246
(?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))?
245247
(?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))?
248+
(?:^similarity[ ]index[ ]\d+%\n
249+
^copy[ ]from[ ].*\n
250+
^copy[ ]to[ ](?P<copied_file_name>.*)(?:\n|$))?
246251
(?:^index[ ](?P<a_blob_id>[0-9A-Fa-f]+)
247252
\.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
248253
(?:^---[ ](?P<a_path>[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))?
@@ -253,11 +258,11 @@ class Diff(object):
253258
NULL_BIN_SHA = b"\0" * 20
254259

255260
__slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "a_rawpath", "b_rawpath",
256-
"new_file", "deleted_file", "raw_rename_from", "raw_rename_to",
257-
"diff", "change_type", "score")
261+
"new_file", "deleted_file", "copied_file", "raw_rename_from",
262+
"raw_rename_to", "diff", "change_type", "score")
258263

259264
def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,
260-
b_mode, new_file, deleted_file, raw_rename_from,
265+
b_mode, new_file, deleted_file, copied_file, raw_rename_from,
261266
raw_rename_to, diff, change_type, score):
262267

263268
self.a_mode = a_mode
@@ -273,6 +278,14 @@ def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,
273278
if self.b_mode:
274279
self.b_mode = mode_str_to_int(self.b_mode)
275280

281+
# Determine whether this diff references a submodule, if it does then
282+
# we need to overwrite "repo" to the corresponding submodule's repo instead
283+
if repo and a_rawpath:
284+
for submodule in repo.submodules:
285+
if submodule.path == a_rawpath.decode("utf-8"):
286+
repo = submodule.module()
287+
break
288+
276289
if a_blob_id is None or a_blob_id == self.NULL_HEX_SHA:
277290
self.a_blob = None
278291
else:
@@ -285,6 +298,7 @@ def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,
285298

286299
self.new_file = new_file
287300
self.deleted_file = deleted_file
301+
self.copied_file = copied_file
288302

289303
# be clear and use None instead of empty strings
290304
assert raw_rename_from is None or isinstance(raw_rename_from, binary_type)
@@ -336,6 +350,8 @@ def __str__(self):
336350
msg += '\nfile deleted in rhs'
337351
if self.new_file:
338352
msg += '\nfile added in rhs'
353+
if self.copied_file:
354+
msg += '\nfile %r copied from %r' % (self.b_path, self.a_path)
339355
if self.rename_from:
340356
msg += '\nfile renamed from %r' % self.rename_from
341357
if self.rename_to:
@@ -420,11 +436,12 @@ def _index_from_patch_format(cls, repo, proc):
420436
a_path_fallback, b_path_fallback, \
421437
old_mode, new_mode, \
422438
rename_from, rename_to, \
423-
new_file_mode, deleted_file_mode, \
439+
new_file_mode, deleted_file_mode, copied_file_name, \
424440
a_blob_id, b_blob_id, b_mode, \
425441
a_path, b_path = _header.groups()
426442

427-
new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode)
443+
new_file, deleted_file, copied_file = \
444+
bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_name)
428445

429446
a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback)
430447
b_path = cls._pick_best_path(b_path, rename_to, b_path_fallback)
@@ -446,7 +463,7 @@ def _index_from_patch_format(cls, repo, proc):
446463
b_blob_id and b_blob_id.decode(defenc),
447464
a_mode and a_mode.decode(defenc),
448465
b_mode and b_mode.decode(defenc),
449-
new_file, deleted_file,
466+
new_file, deleted_file, copied_file,
450467
rename_from,
451468
rename_to,
452469
None, None, None))
@@ -487,6 +504,7 @@ def handle_diff_line(line):
487504
b_path = path.encode(defenc)
488505
deleted_file = False
489506
new_file = False
507+
copied_file = False
490508
rename_from = None
491509
rename_to = None
492510

@@ -498,6 +516,11 @@ def handle_diff_line(line):
498516
elif change_type == 'A':
499517
a_blob_id = None
500518
new_file = True
519+
elif change_type == 'C':
520+
copied_file = True
521+
a_path, b_path = path.split('\t', 1)
522+
a_path = a_path.encode(defenc)
523+
b_path = b_path.encode(defenc)
501524
elif change_type == 'R':
502525
a_path, b_path = path.split('\t', 1)
503526
a_path = a_path.encode(defenc)
@@ -509,8 +532,8 @@ def handle_diff_line(line):
509532
# END add/remove handling
510533

511534
diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode,
512-
new_file, deleted_file, rename_from, rename_to, '',
513-
change_type, score)
535+
new_file, deleted_file, copied_file, rename_from, rename_to,
536+
'', change_type, score)
514537
index.append(diff)
515538

516539
handle_process_output(proc, handle_diff_line, None, finalize_process, decode_streams=False)

git/objects/util.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def __init__(self, secs_west_of_utc, name=None):
105105
self._offset = timedelta(seconds=-secs_west_of_utc)
106106
self._name = name or 'fixed'
107107

108+
def __reduce__(self):
109+
return tzoffset, (-self._offset.total_seconds(), self._name)
110+
108111
def utcoffset(self, dt):
109112
return self._offset
110113

git/test/fixtures/diff_copied_mode

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
diff --git a/test1.txt b/test2.txt
2+
similarity index 100%
3+
copy from test1.txt
4+
copy to test2.txt
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:100644 100644 cfe9deac6e10683917e80f877566b58644aa21df cfe9deac6e10683917e80f877566b58644aa21df C100 test1.txt test2.txt

git/test/test_diff.py

Lines changed: 77 additions & 3 deletions

0 commit comments

Comments
 (0)