Codebase list python-git / 7c63b9c
New upstream version 2.1.5 TANIGUCHI Takaki 6 years ago
28 changed file(s) with 101 addition(s) and 58 deletion(s). Raw diff Collapse all Expand all
1616 -Phil Elson <pelson _dot_ pub _at_ gmail.com>
1717 -Bernard `Guyzmo` Pratz <guyzmo+gitpython+pub@m0g.net>
1818 -Timothy B. Hartman <tbhartman _at_ gmail.com>
19 -Konstantin Popov <konstantin.popov.89 _at_ yandex.ru>
1920
2021 Portions derived from other open source works and are clearly marked.
00 Metadata-Version: 1.1
11 Name: GitPython
2 Version: 2.1.3
2 Version: 2.1.5
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
2323 Classifier: Programming Language :: Python :: 3.3
2424 Classifier: Programming Language :: Python :: 3.4
2525 Classifier: Programming Language :: Python :: 3.5
26 Classifier: Programming Language :: Python :: 3.6
2627 Requires: gitdb2 (>=2.0.0)
00 Metadata-Version: 1.1
11 Name: GitPython
2 Version: 2.1.3
2 Version: 2.1.5
33 Summary: Python Git Library
44 Home-page: https://github.com/gitpython-developers/GitPython
55 Author: Sebastian Thiel, Michael Trier
2323 Classifier: Programming Language :: Python :: 3.3
2424 Classifier: Programming Language :: Python :: 3.4
2525 Classifier: Programming Language :: Python :: 3.5
26 Classifier: Programming Language :: Python :: 3.6
2627 Requires: gitdb2 (>=2.0.0)
0 2.1.3
0 2.1.5
1111 import os.path as osp
1212
1313
14 __version__ = '2.1.3'
14 __version__ = '2.1.5'
1515
1616
1717 #{ Initialization
1818 def _init_externals():
1919 """Initialize external projects by putting them into the path"""
20 if __version__ == '2.1.3':
20 if __version__ == '2.1.5':
2121 sys.path.insert(0, osp.join(osp.dirname(__file__), 'ext', 'gitdb'))
2222
2323 try:
539539 * str(output) if extended_output = False (Default)
540540 * tuple(int(status), str(stdout), str(stderr)) if extended_output = True
541541
542 if ouput_stream is True, the stdout value will be your output stream:
542 if output_stream is True, the stdout value will be your output stream:
543543 * output_stream if extended_output = False
544544 * tuple(int(status), output_stream, str(stderr)) if extended_output = True
545545
168168 # They must be compatible to the LockFile interface.
169169 # A suitable alternative would be the BlockingLockFile
170170 t_lock = LockFile
171 re_comment = re.compile('^\s*[#;]')
171 re_comment = re.compile(r'^\s*[#;]')
172172
173173 #} END configuration
174174
211211 self._is_initialized = False
212212 self._merge_includes = merge_includes
213213 self._lock = None
214 self._aquire_lock()
215
216 def _aquire_lock(self):
214 self._acquire_lock()
215
216 def _acquire_lock(self):
217217 if not self._read_only:
218218 if not self._lock:
219219 if isinstance(self._file_or_files, (tuple, list)):
238238 self.release()
239239
240240 def __enter__(self):
241 self._aquire_lock()
241 self._acquire_lock()
242242 return self
243243
244244 def __exit__(self, exception_type, exception_value, traceback):
88 from git.compat import UnicodeMixin, safe_decode, string_types
99
1010
11 class InvalidGitRepositoryError(Exception):
11 class GitError(Exception):
12 """ Base class for all package exceptions """
13
14
15 class InvalidGitRepositoryError(GitError):
1216 """ Thrown if the given repository appears to have an invalid format. """
1317
1418
1620 """ Thrown to indicate we can't handle work tree repositories """
1721
1822
19 class NoSuchPathError(OSError):
23 class NoSuchPathError(GitError, OSError):
2024 """ Thrown if a path could not be access by the system. """
2125
2226
23 class CommandError(UnicodeMixin, Exception):
27 class CommandError(UnicodeMixin, GitError):
2428 """Base class for exceptions thrown at every stage of `Popen()` execution.
2529
2630 :param command:
7377 super(GitCommandError, self).__init__(command, status, stderr, stdout)
7478
7579
76 class CheckoutError(Exception):
80 class CheckoutError(GitError):
7781 """Thrown if a file could not be checked out from the index as it contained
7882 changes.
7983
97101 return Exception.__str__(self) + ":%s" % self.failed_files
98102
99103
100 class CacheError(Exception):
104 class CacheError(GitError):
101105
102106 """Base for all errors related to the git index, which is called cache internally"""
103107
116120 self._msg = u"Hook('%s') failed%s"
117121
118122
119 class RepositoryDirtyError(Exception):
120 """Thrown whenever an operation on a repository fails as it has uncommited changes that would be overwritten"""
123 class RepositoryDirtyError(GitError):
124 """Thrown whenever an operation on a repository fails as it has uncommitted changes that would be overwritten"""
121125
122126 def __init__(self, repo, message):
123127 self.repo = repo
432432 try:
433433 proc.stdin.write(("%s\n" % filepath).encode(defenc))
434434 except IOError:
435 # pipe broke, usually because some error happend
435 # pipe broke, usually because some error happened
436436 raise fmakeexc()
437437 # END write exception handling
438438 proc.stdin.flush()
845845
846846 :param working_tree:
847847 If True, the entry will also be removed from the working tree, physically
848 removing the respective file. This may fail if there are uncommited changes
848 removing the respective file. This may fail if there are uncommitted changes
849849 in it.
850850
851851 :param kwargs:
5050 class BaseIndexEntry(tuple):
5151
5252 """Small Brother of an index entry which can be created to describe changes
53 done to the index in which case plenty of additional information is not requried.
53 done to the index in which case plenty of additional information is not required.
5454
5555 As the first 4 data members match exactly to the IndexEntry type, methods
5656 expecting a BaseIndexEntry can also handle full IndexEntries even if they
151151 def __hash__(self):
152152 """
153153 :return:
154 Hash of our path as index items are uniquely identifyable by path, not
154 Hash of our path as index items are uniquely identifiable by path, not
155155 by their data !"""
156156 return hash(self.path)
157157
167167
168168 :param kwargs:
169169 Additional options to be passed to git-rev-list. They must not alter
170 the ouput style of the command, or parsing will yield incorrect results
170 the output style of the command, or parsing will yield incorrect results
171171 :return: int defining the number of reachable commits"""
172172 # yes, it makes a difference whether empty paths are given or not in our case
173173 # as the empty paths version will ignore merge commits for some reason.
9191 k_head_default = 'master'
9292 k_default_mode = stat.S_IFDIR | stat.S_IFLNK # submodules are directories with link-status
9393
94 # this is a bogus type for base class compatability
94 # this is a bogus type for base class compatibility
9595 type = 'submodule'
9696
9797 __slots__ = ('_parent_commit', '_url', '_branch_path', '_name', '__weakref__')
422422 writer.set_value(cls.k_head_option, br.path)
423423 sm._branch_path = br.path
424424
425 # we deliberatly assume that our head matches our index !
425 # we deliberately assume that our head matches our index !
426426 sm.binsha = mrepo.head.commit.binsha
427427 index.add([sm], write=True)
428428
550550 with self.repo.config_writer() as writer:
551551 writer.set_value(sm_section(self.name), 'url', self.url)
552552 # END handle dry_run
553 # END handle initalization
553 # END handle initialization
554554
555555 # DETERMINE SHAS TO CHECKOUT
556556 ############################
132132 of the head in question. Custom query methods allow to retrieve log entries
133133 by date or by other criteria.
134134
135 Reflog entries are orded, the first added entry is first in the list, the last
135 Reflog entries are ordered, the first added entry is first in the list, the last
136136 entry, i.e. the last change of the head or reference, is last in the list."""
137137
138138 __slots__ = ('_path', )
208208 """:return: RefLogEntry at the given index
209209 :param filepath: full path to the index file from which to read the entry
210210 :param index: python list compatible index, i.e. it may be negative to
211 specifiy an entry counted from the end of the list
211 specify an entry counted from the end of the list
212212
213213 :raise IndexError: If the entry didn't exist
214214
207207 NEW_TAG, NEW_HEAD, HEAD_UPTODATE, TAG_UPDATE, REJECTED, FORCED_UPDATE, \
208208 FAST_FORWARD, ERROR = [1 << x for x in range(8)]
209209
210 re_fetch_result = re.compile('^\s*(.) (\[?[\w\s\.$@]+\]?)\s+(.+) -> ([^\s]+)( \(.*\)?$)?')
210 re_fetch_result = re.compile(r'^\s*(.) (\[?[\w\s\.$@]+\]?)\s+(.+) -> ([^\s]+)( \(.*\)?$)?')
211211
212212 _flag_map = {'!': ERROR,
213213 '+': FORCED_UPDATE,
214 '-': TAG_UPDATE,
215214 '*': 0,
216215 '=': HEAD_UPTODATE,
217216 ' ': FAST_FORWARD}
217
218 v = Git().version_info[:2]
219 if v >= (2, 10):
220 _flag_map['t'] = TAG_UPDATE
221 else:
222 _flag_map['-'] = TAG_UPDATE
218223
219224 def __init__(self, ref, flags, note='', old_commit=None, remote_ref_path=None):
220225 """
390395
391396 def __getattr__(self, attr):
392397 """Allows to call this instance like
393 remote.special( \*args, \*\*kwargs) to call git-remote special self.name"""
398 remote.special( \\*args, \\*\\*kwargs) to call git-remote special self.name"""
394399 if attr == "_config_reader":
395400 return super(Remote, self).__getattr__(attr)
396401
628633 fetch_info_lines = list()
629634 # Basically we want all fetch info lines which appear to be in regular form, and thus have a
630635 # command character. Everything else we ignore,
631 cmds = set(PushInfo._flag_map.keys()) & set(FetchInfo._flag_map.keys())
636 cmds = set(FetchInfo._flag_map.keys())
632637
633638 progress_handler = progress.new_message_handler()
634639 handle_process_output(proc, None, progress_handler, finalizer=None, decode_streams=False)
3939 log = logging.getLogger(__name__)
4040
4141 DefaultDBType = GitCmdObjectDB
42 if sys.version_info[:2] < (2, 5): # python 2.4 compatiblity
42 if sys.version_info[:2] < (2, 5): # python 2.4 compatibility
4343 DefaultDBType = GitCmdObjectDB
4444 # END handle python 2.4
4545
185185 self.close()
186186
187187 def __del__(self):
188 self.close()
188 try:
189 self.close()
190 except:
191 pass
189192
190193 def close(self):
191194 if self.git:
417420
418421 :param config_level:
419422 One of the following values
420 system = sytem wide configuration file
423 system = system wide configuration file
421424 global = user level configuration file
422425 repository = configuration file for this repostory only"""
423426 return GitConfigParser(self._get_config_path(config_level), read_only=False)
563566
564567 :raise NoSuchPathError:
565568 :note:
566 The method does not check for the existance of the paths in alts
569 The method does not check for the existence of the paths in alts
567570 as the caller is responsible."""
568571 alternates_path = osp.join(self.git_dir, 'objects', 'info', 'alternates')
569572 if not alts:
628631 return self._get_untracked_files()
629632
630633 def _get_untracked_files(self, *args, **kwargs):
631 # make sure we get all files, no only untracked directores
634 # make sure we get all files, not only untracked directories
632635 proc = self.git.status(*args,
633636 porcelain=True,
634637 untracked_files=True,
680683
681684 stream = (line for line in data.split(b'\n') if line)
682685 while True:
683 line = next(stream) # when exhausted, casues a StopIteration, terminating this function
686 line = next(stream) # when exhausted, causes a StopIteration, terminating this function
684687 hexsha, orig_lineno, lineno, num_lines = line.split()
685688 lineno = int(lineno)
686689 num_lines = int(num_lines)
881884 # git clone --bare /cygwin/d/foo.git /cygwin/d/C:\\Work
882885 #
883886 clone_path = (Git.polish_url(path)
884 if Git.is_cygwin() and 'bare'in kwargs
887 if Git.is_cygwin() and 'bare' in kwargs
885888 else path)
886889 sep_dir = kwargs.get('separate_git_dir')
887890 if sep_dir:
951954 * Use the 'format' argument to define the kind of format. Use
952955 specialized ostreams to write any format supported by python.
953956 * You may specify the special **path** keyword, which may either be a repository-relative
954 path to a directory or file to place into the archive, or a list or tuple of multipe paths.
957 path to a directory or file to place into the archive, or a list or tuple of multiple paths.
955958
956959 :raise GitCommandError: in case something went wrong
957960 :return: self"""
971974 def has_separate_working_tree(self):
972975 """
973976 :return: True if our git_dir is not at the root of our working_tree_dir, but a .git file with a
974 platform agnositic symbolic link. Our git_dir will be whereever the .git file points to
977 platform agnositic symbolic link. Our git_dir will be wherever the .git file points to
975978 :note: bare repositories will always return False here
976979 """
977980 if self.bare:
199199 and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>
200200 """)
201201 if is_win:
202 msg += textwrap.dedent("""
202 msg += textwrap.dedent(r"""
203203
204204 On Windows,
205205 the `git-daemon.exe` must be in PATH.
226226 Same as with_rw_repo, but also provides a writable remote repository from which the
227227 rw_repo has been forked as well as a handle for a git-daemon that may be started to
228228 run the remote_repo.
229 The remote repository was cloned as bare repository from the rorepo, wheras
229 The remote repository was cloned as bare repository from the rorepo, whereas
230230 the rw repo has a working tree and was cloned from the remote repository.
231231
232232 remote_repo has two remotes: origin and daemon_origin. One uses a local url,
215215 with self.assertRaises(cp.NoSectionError):
216216 check_test_value(cr, tv)
217217
218 # But can make it skip includes alltogether, and thus allow write-backs
218 # But can make it skip includes altogether, and thus allow write-backs
219219 with GitConfigParser(fpa, read_only=False, merge_includes=False) as cw:
220220 write_test_value(cw, tv)
221221
432432 # reset the index and working tree to match the pointed-to commit
433433 repo.head.reset(index=True, working_tree=True)
434434
435 # To detach your head, you have to point to a commit directy
435 # To detach your head, you have to point to a commit directly
436436 repo.head.reference = repo.commit('HEAD~5')
437437 assert repo.head.is_detached
438438 # now our head points 15 commits into the past, whereas the working tree
99
1010 import ddt
1111 from git.exc import (
12 InvalidGitRepositoryError,
13 WorkTreeRepositoryUnsupported,
14 NoSuchPathError,
1215 CommandError,
1316 GitCommandNotFound,
1417 GitCommandError,
18 CheckoutError,
19 CacheError,
20 UnmergedEntriesError,
1521 HookExecutionError,
22 RepositoryDirtyError,
1623 )
1724 from git.test.lib import TestBase
1825
4249
4350 @ddt.ddt
4451 class TExc(TestBase):
52
53 def test_ExceptionsHaveBaseClass(self):
54 from git.exc import GitError
55 self.assertIsInstance(GitError(), Exception)
56
57 exception_classes = [
58 InvalidGitRepositoryError,
59 WorkTreeRepositoryUnsupported,
60 NoSuchPathError,
61 CommandError,
62 GitCommandNotFound,
63 GitCommandError,
64 CheckoutError,
65 CacheError,
66 UnmergedEntriesError,
67 HookExecutionError,
68 RepositoryDirtyError,
69 ]
70 for ex_class in exception_classes:
71 self.assertTrue(issubclass(ex_class, GitError))
4572
4673 @ddt.data(*list(itt.product(_cmd_argvs, _causes_n_substrings, _streams_n_substrings)))
4774 def test_CommandError_unicode(self, case):
9090 self.assertEqual(set(['-s', '-t']), set(res))
9191
9292 def test_it_executes_git_to_shell_and_returns_result(self):
93 assert_match('^git version [\d\.]{2}.*$', self.git.execute(["git", "version"]))
93 assert_match(r'^git version [\d\.]{2}.*$', self.git.execute(["git", "version"]))
9494
9595 def test_it_accepts_stdin(self):
9696 filename = fixture_path("cat_file_blob")
130130 g.stdin.flush()
131131 self.assertEqual(g.stdout.readline(), obj_info)
132132
133 # same can be achived using the respective command functions
133 # same can be achieved using the respective command functions
134134 hexsha, typename, size = self.git.get_object_header(hexsha)
135135 hexsha, typename_two, size_two, data = self.git.get_object_data(hexsha) # @UnusedVariable
136136 self.assertEqual(typename, typename_two)
188188 self.failUnlessRaises(ValueError, self.git.remote, 'add', insert_kwargs_after='foo')
189189
190190 def test_env_vars_passed_to_git(self):
191 editor = 'non_existant_editor'
191 editor = 'non_existent_editor'
192192 with mock.patch.dict('os.environ', {'GIT_EDITOR': editor}): # @UndefinedVariable
193193 self.assertEqual(self.git.var("GIT_EDITOR"), editor)
194194
410410 # END num existing helper
411411
412412 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
413 """FIXME: File "C:\projects\gitpython\git\test\test_index.py", line 642, in test_index_mutation
413 """FIXME: File "C:\\projects\\gitpython\\git\\test\\test_index.py", line 642, in test_index_mutation
414414 self.assertEqual(fd.read(), link_target)
415415 AssertionError: '!<symlink>\xff\xfe/\x00e\x00t\x00c\x00/\x00t\x00h\x00a\x00t\x00\x00\x00'
416416 != '/etc/that'
162162
163163 def _commit_random_file(self, repo):
164164 # Create a file with a random name and random data and commit it to repo.
165 # Return the commited absolute file path
165 # Return the committed absolute file path
166166 index = repo.index
167167 new_file = self._make_file(osp.basename(tempfile.mktemp()), str(random.random()), repo)
168168 index.add([new_file])
9595 Repo(tempfile.gettempdir())
9696
9797 @raises(NoSuchPathError)
98 def test_new_should_raise_on_non_existant_path(self):
98 def test_new_should_raise_on_non_existent_path(self):
9999 Repo("repos/foobar")
100100
101101 @with_rw_repo('0.3.2.1')
415415 self.assertEqual(len(res[0][1]), 83, "Unexpected amount of parsed blame lines")
416416
417417 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
418 """FIXME: File "C:\projects\gitpython\git\cmd.py", line 671, in execute
418 """FIXME: File "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
419419 raise GitCommandError(command, status, stderr_value, stdout_value)
420420 GitCommandError: Cmd('git') failed due to: exit code(128)
421421 cmdline: git add 1__��ava verb��ten 1_test _myfile 1_test_other_file
422422 self._do_base_tests(rwrepo)
423423
424424 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
425 File "C:\projects\gitpython\git\cmd.py", line 559, in execute
425 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
426426 raise GitCommandNotFound(command, err)
427427 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
428 cmdline: git clone -n --shared -v C:\projects\gitpython\.git Users\appveyor\AppData\Local\Temp\1\tmplyp6kr_rnon_bare_test_root_module""") # noqa E501
428 cmdline: git clone -n --shared -v C:\\projects\\gitpython\\.git Users\\appveyor\\AppData\\Local\\Temp\\1\\tmplyp6kr_rnon_bare_test_root_module""") # noqa E501
429429 @with_rw_repo(k_subm_current, bare=False)
430430 def test_root_module(self, rwrepo):
431431 # Can query everything without problems
663663 # end for each checkout mode
664664
665665 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and Git.is_cygwin(),
666 """FIXME: ile "C:\projects\gitpython\git\cmd.py", line 671, in execute
666 """FIXME: ile "C:\\projects\\gitpython\\git\\cmd.py", line 671, in execute
667667 raise GitCommandError(command, status, stderr_value, stdout_value)
668668 GitCommandError: Cmd('git') failed due to: exit code(128)
669669 cmdline: git add 1__Xava verbXXten 1_test _myfile 1_test_other_file 1_XXava-----verbXXten
2323 class TestTree(TestBase):
2424
2525 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
26 File "C:\projects\gitpython\git\cmd.py", line 559, in execute
26 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
2727 raise GitCommandNotFound(command, err)
2828 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
2929 cmdline: git cat-file --batch-check""")
5656 # END for each item in tree
5757
5858 @skipIf(HIDE_WINDOWS_KNOWN_ERRORS and sys.version_info[:2] == (3, 5), """
59 File "C:\projects\gitpython\git\cmd.py", line 559, in execute
59 File "C:\\projects\\gitpython\\git\\cmd.py", line 559, in execute
6060 raise GitCommandNotFound(command, err)
6161 git.exc.GitCommandNotFound: Cmd('git') not found due to: OSError('[WinError 6] The handle is invalid')
6262 cmdline: git cat-file --batch-check""")
808808 def _obtain_lock(self):
809809 """This method blocks until it obtained the lock, or raises IOError if
810810 it ran out of time or if the parent directory was not available anymore.
811 If this method returns, you are guranteed to own the lock"""
811 If this method returns, you are guaranteed to own the lock"""
812812 starttime = time.time()
813813 maxtime = starttime + float(self._max_block_time)
814814 while True:
130130 "Programming Language :: Python :: 3.3",
131131 "Programming Language :: Python :: 3.4",
132132 "Programming Language :: Python :: 3.5",
133 "Programming Language :: Python :: 3.6",
133134 ]
134135 )