Codebase list python-git / upstream/3.0.3
New upstream version 3.0.3 TANIGUCHI Takaki 4 years ago
17 changed file(s) with 135 addition(s) and 116 deletion(s). Raw diff Collapse all Expand all
00 Metadata-Version: 1.2
11 Name: GitPython
2 Version: 3.0.1
2 Version: 3.0.3
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
00 gitdb2>=2.0.0
1 ddt>=1.1.1
00 Metadata-Version: 1.2
11 Name: GitPython
2 Version: 3.0.1
2 Version: 3.0.3
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
0 3.0.1
0 3.0.3
00 =========
11 Changelog
22 =========
3
4 3.0.3 - Bugfixes
5 =============================================
6
7 see the following for (most) details:
8 https://github.com/gitpython-developers/gitpython/milestone/30?closed=1
9
10 3.0.2 - Bugfixes
11 =============================================
12
13 * fixes an issue with installation
314
415 3.0.1 - Bugfixes and performance improvements
516 =============================================
1111 import os.path as osp
1212
1313
14 __version__ = '3.0.1'
14 __version__ = '3.0.3'
1515
1616
1717 #{ Initialization
1818 def _init_externals():
1919 """Initialize external projects by putting them into the path"""
20 if __version__ == '3.0.1':
20 if __version__ == '3.0.3':
2121 sys.path.insert(0, osp.join(osp.dirname(__file__), 'ext', 'gitdb'))
2222
2323 try:
483483 buf = enc.strip()
484484 while buf:
485485 if buf[0:10] == b"encoding ":
486 self.encoding = buf[buf.find(' ') + 1:].decode('ascii')
486 self.encoding = buf[buf.find(' ') + 1:].decode(
487 self.encoding, 'ignore')
487488 elif buf[0:7] == b"gpgsig ":
488489 sig = buf[buf.find(b' ') + 1:] + b"\n"
489490 is_next_header = False
497498 break
498499 sig += sigbuf[1:]
499500 # end read all signature
500 self.gpgsig = sig.rstrip(b"\n").decode('ascii')
501 self.gpgsig = sig.rstrip(b"\n").decode(self.encoding, 'ignore')
501502 if is_next_header:
502503 continue
503504 buf = readline().strip()
863863 rmtree(wtd)
864864 except Exception as ex:
865865 if HIDE_WINDOWS_KNOWN_ERRORS:
866 raise SkipTest("FIXME: fails with: PermissionError\n %s", ex)
867 else:
868 raise
866 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex))
867 raise
869868 # END delete tree if possible
870869 # END handle force
871870
155155 if flags & cls.DELETED:
156156 from_ref = None
157157 else:
158 from_ref = Reference.from_path(remote.repo, from_ref_string)
158 if from_ref_string == "(delete)":
159 from_ref = None
160 else:
161 from_ref = Reference.from_path(remote.repo, from_ref_string)
159162
160163 # commit handling, could be message or commit info
161164 old_commit = None
447450 return '<git.%s "%s">' % (self.__class__.__name__, self.name)
448451
449452 def __eq__(self, other):
450 return self.name == other.name
453 return isinstance(other, type(self)) and self.name == other.name
451454
452455 def __ne__(self, other):
453456 return not (self == other)
10111011 :param to_path: Path to which the repository should be cloned to
10121012 :param progress: See 'git.remote.Remote.push'.
10131013 :param env: Optional dictionary containing the desired environment variables.
1014 Note: Provided variables will be used to update the execution
1015 environment for `git`. If some variable is not specified in `env`
1016 and is defined in `os.environ`, value from `os.environ` will be used.
1017 If you want to unset some variable, consider providing empty string
1018 as its value.
10141019 :param multi_options: See ``clone`` method
10151020 :param kwargs: see the ``clone`` method
10161021 :return: Repo instance pointing to the cloned directory"""
3737 def tearDown(self):
3838 for lfp in glob.glob(_tc_lock_fpaths):
3939 if osp.isfile(lfp):
40 raise AssertionError('Previous TC left hanging git-lock file: %s', lfp)
40 raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
4141
4242 def _to_memcache(self, file_path):
4343 with open(file_path, "rb") as fp:
133133
134134 def test_persistent_cat_file_command(self):
135135 # read header only
136 import subprocess as sp
137136 hexsha = "b2339455342180c7cc1e9bba3e9f181f7baa5167"
138 g = self.git.cat_file(batch_check=True, istream=sp.PIPE, as_process=True)
137 g = self.git.cat_file(
138 batch_check=True, istream=subprocess.PIPE, as_process=True
139 )
139140 g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
140141 g.stdin.flush()
141142 obj_info = g.stdout.readline()
142143
143144 # read header + data
144 g = self.git.cat_file(batch=True, istream=sp.PIPE, as_process=True)
145 g = self.git.cat_file(
146 batch=True, istream=subprocess.PIPE, as_process=True
147 )
145148 g.stdin.write(b"b2339455342180c7cc1e9bba3e9f181f7baa5167\n")
146149 g.stdin.flush()
147150 obj_info_two = g.stdout.readline()
159162
160163 # same can be achieved using the respective command functions
161164 hexsha, typename, size = self.git.get_object_header(hexsha)
162 hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha) # @UnusedVariable
165 hexsha, typename_two, size_two, _ = self.git.get_object_data(hexsha)
163166 self.assertEqual(typename, typename_two)
164167 self.assertEqual(size, size_two)
165168
263266 remote.fetch()
264267 except GitCommandError as err:
265268 if sys.version_info[0] < 3 and is_darwin:
266 self.assertIn('ssh-orig, ' in str(err))
269 self.assertIn('ssh-orig', str(err))
267270 self.assertEqual(err.status, 128)
268271 else:
269272 self.assertIn('FOO', str(err))
896896 _make_hook(
897897 index.repo.git_dir,
898898 'commit-msg',
899 'echo -n " {}" >> "$1"'.format(from_hook_message)
899 'printf " {}" >> "$1"'.format(from_hook_message)
900900 )
901901 new_commit = index.commit(commit_message)
902902 self.assertEqual(new_commit.message, u"{} {}".format(commit_message, from_hook_message))
5252 # Keep it for debugging
5353 self._seen_lines.append(line)
5454 rval = super(TestRemoteProgress, self)._parse_progress_line(line)
55 assert len(line) > 1, "line %r too short" % line
5655 return rval
5756
5857 def line_dropped(self, line):
385384 progress.make_assertion()
386385 self._do_test_push_result(res, remote)
387386
387 # rejected stale delete
388 force_with_lease = "%s:0000000000000000000000000000000000000000" % new_head.path
389 res = remote.push(":%s" % new_head.path, force_with_lease=force_with_lease)
390 self.assertTrue(res[0].flags & PushInfo.ERROR)
391 self.assertTrue(res[0].flags & PushInfo.REJECTED)
392 self.assertIsNone(res[0].local_ref)
393 self._do_test_push_result(res, remote)
394
388395 # delete new branch on the remote end and locally
389396 res = remote.push(":%s" % new_head.path)
390397 self._do_test_push_result(res, remote)
8989 def tearDown(self):
9090 for lfp in glob.glob(_tc_lock_fpaths):
9191 if osp.isfile(lfp):
92 raise AssertionError('Previous TC left hanging git-lock file: %s', lfp)
92 raise AssertionError('Previous TC left hanging git-lock file: {}'.format(lfp))
9393 import gc
9494 gc.collect()
9595
9797 func(path) # Will scream if still not possible to delete.
9898 except Exception as ex:
9999 if HIDE_WINDOWS_KNOWN_ERRORS:
100 raise SkipTest("FIXME: fails with: PermissionError\n %s", ex)
101 else:
102 raise
100 raise SkipTest("FIXME: fails with: PermissionError\n {}".format(ex))
101 raise
103102
104103 return shutil.rmtree(path, False, onerror)
105104
379378
380379 - Lines that do not contain progress info are stored in :attr:`other_lines`.
381380 - Lines that seem to contain an error (i.e. start with error: or fatal:) are stored
382 in :attr:`error_lines`.
383
384 :return: list(line, ...) list of lines that could not be processed"""
381 in :attr:`error_lines`."""
385382 # handle
386383 # Counting objects: 4, done.
387 # Compressing objects: 50% (1/2) \rCompressing objects: 100% (2/2) \rCompressing objects: 100% (2/2), done.
384 # Compressing objects: 50% (1/2)
385 # Compressing objects: 100% (2/2)
386 # Compressing objects: 100% (2/2), done.
388387 self._cur_line = line = line.decode('utf-8') if isinstance(line, bytes) else line
389388 if len(self.error_lines) > 0 or self._cur_line.startswith(('error:', 'fatal:')):
390389 self.error_lines.append(self._cur_line)
391 return []
392
393 sub_lines = line.split('\r')
394 failed_lines = []
395 for sline in sub_lines:
396 # find escape characters and cut them away - regex will not work with
397 # them as they are non-ascii. As git might expect a tty, it will send them
398 last_valid_index = None
399 for i, c in enumerate(reversed(sline)):
400 if ord(c) < 32:
401 # its a slice index
402 last_valid_index = -i - 1
403 # END character was non-ascii
404 # END for each character in sline
405 if last_valid_index is not None:
406 sline = sline[:last_valid_index]
407 # END cut away invalid part
408 sline = sline.rstrip()
409
410 cur_count, max_count = None, None
411 match = self.re_op_relative.match(sline)
412 if match is None:
413 match = self.re_op_absolute.match(sline)
414
415 if not match:
416 self.line_dropped(sline)
417 failed_lines.append(sline)
418 continue
419 # END could not get match
420
421 op_code = 0
422 remote, op_name, percent, cur_count, max_count, message = match.groups() # @UnusedVariable
423
424 # get operation id
425 if op_name == "Counting objects":
426 op_code |= self.COUNTING
427 elif op_name == "Compressing objects":
428 op_code |= self.COMPRESSING
429 elif op_name == "Writing objects":
430 op_code |= self.WRITING
431 elif op_name == 'Receiving objects':
432 op_code |= self.RECEIVING
433 elif op_name == 'Resolving deltas':
434 op_code |= self.RESOLVING
435 elif op_name == 'Finding sources':
436 op_code |= self.FINDING_SOURCES
437 elif op_name == 'Checking out files':
438 op_code |= self.CHECKING_OUT
439 else:
440 # Note: On windows it can happen that partial lines are sent
441 # Hence we get something like "CompreReceiving objects", which is
442 # a blend of "Compressing objects" and "Receiving objects".
443 # This can't really be prevented, so we drop the line verbosely
444 # to make sure we get informed in case the process spits out new
445 # commands at some point.
446 self.line_dropped(sline)
447 # Note: Don't add this line to the failed lines, as we have to silently
448 # drop it
449 self.other_lines.extend(failed_lines)
450 return failed_lines
451 # END handle op code
452
453 # figure out stage
454 if op_code not in self._seen_ops:
455 self._seen_ops.append(op_code)
456 op_code |= self.BEGIN
457 # END begin opcode
458
459 if message is None:
460 message = ''
461 # END message handling
462
463 message = message.strip()
464 if message.endswith(self.DONE_TOKEN):
465 op_code |= self.END
466 message = message[:-len(self.DONE_TOKEN)]
467 # END end message handling
468 message = message.strip(self.TOKEN_SEPARATOR)
469
470 self.update(op_code,
471 cur_count and float(cur_count),
472 max_count and float(max_count),
473 message)
474 # END for each sub line
475 self.other_lines.extend(failed_lines)
476 return failed_lines
390 return
391
392 # find escape characters and cut them away - regex will not work with
393 # them as they are non-ascii. As git might expect a tty, it will send them
394 last_valid_index = None
395 for i, c in enumerate(reversed(line)):
396 if ord(c) < 32:
397 # its a slice index
398 last_valid_index = -i - 1
399 # END character was non-ascii
400 # END for each character in line
401 if last_valid_index is not None:
402 line = line[:last_valid_index]
403 # END cut away invalid part
404 line = line.rstrip()
405
406 cur_count, max_count = None, None
407 match = self.re_op_relative.match(line)
408 if match is None:
409 match = self.re_op_absolute.match(line)
410
411 if not match:
412 self.line_dropped(line)
413 self.other_lines.append(line)
414 return
415 # END could not get match
416
417 op_code = 0
418 remote, op_name, percent, cur_count, max_count, message = match.groups() # @UnusedVariable
419
420 # get operation id
421 if op_name == "Counting objects":
422 op_code |= self.COUNTING
423 elif op_name == "Compressing objects":
424 op_code |= self.COMPRESSING
425 elif op_name == "Writing objects":
426 op_code |= self.WRITING
427 elif op_name == 'Receiving objects':
428 op_code |= self.RECEIVING
429 elif op_name == 'Resolving deltas':
430 op_code |= self.RESOLVING
431 elif op_name == 'Finding sources':
432 op_code |= self.FINDING_SOURCES
433 elif op_name == 'Checking out files':
434 op_code |= self.CHECKING_OUT
435 else:
436 # Note: On windows it can happen that partial lines are sent
437 # Hence we get something like "CompreReceiving objects", which is
438 # a blend of "Compressing objects" and "Receiving objects".
439 # This can't really be prevented, so we drop the line verbosely
440 # to make sure we get informed in case the process spits out new
441 # commands at some point.
442 self.line_dropped(line)
443 # Note: Don't add this line to the other lines, as we have to silently
444 # drop it
445 return
446 # END handle op code
447
448 # figure out stage
449 if op_code not in self._seen_ops:
450 self._seen_ops.append(op_code)
451 op_code |= self.BEGIN
452 # END begin opcode
453
454 if message is None:
455 message = ''
456 # END message handling
457
458 message = message.strip()
459 if message.endswith(self.DONE_TOKEN):
460 op_code |= self.END
461 message = message[:-len(self.DONE_TOKEN)]
462 # END end message handling
463 message = message.strip(self.TOKEN_SEPARATOR)
464
465 self.update(op_code,
466 cur_count and float(cur_count),
467 max_count and float(max_count),
468 message)
477469
478470 def new_message_handler(self):
479471 """
00 gitdb2 (>=2.0.0)
1 ddt>=1.1.1