[Python-modules-commits] [python-git] 03/06: New upstream version 2.1.8
Takaki Taniguchi
takaki at moszumanska.debian.org
Sun Jan 21 14:42:42 UTC 2018
This is an automated email from the git hooks/post-receive script.
takaki pushed a commit to branch master
in repository python-git.
commit 86263795470d9c7fb8385401950286e50132a7b7
Author: TANIGUCHI Takaki <takaki at asis.media-as.org>
Date: Sat Jan 20 18:47:26 2018 +0900
New upstream version 2.1.8
---
AUTHORS | 4 +
GitPython.egg-info/PKG-INFO | 6 +-
GitPython.egg-info/SOURCES.txt | 2 +
GitPython.egg-info/requires.txt | 2 +-
PKG-INFO | 6 +-
README.md | 199 +++++++++++++++++++++++++++++++++++
VERSION | 2 +-
doc/source/changes.rst | 11 +-
git/__init__.py | 4 +-
git/cmd.py | 4 +-
git/compat.py | 2 +-
git/config.py | 3 +-
git/diff.py | 14 +--
git/exc.py | 2 +-
git/index/base.py | 19 ++++
git/index/fun.py | 7 +-
git/objects/submodule/base.py | 6 +-
git/refs/log.py | 2 +-
git/refs/symbolic.py | 10 +-
git/remote.py | 18 +++-
git/repo/base.py | 38 ++++---
git/test/fixtures/git_config | 18 +++-
git/test/fixtures/git_config-inc.cfg | 5 +
git/test/lib/helper.py | 12 ++-
git/test/test_commit.py | 3 +-
git/test/test_config.py | 16 +++
git/test/test_git.py | 5 +-
git/test/test_index.py | 120 ++++++++++++++++-----
git/test/test_repo.py | 23 ++++
git/test/test_submodule.py | 12 ++-
git/test/test_util.py | 54 +++++-----
git/util.py | 17 ++-
setup.cfg | 1 -
setup.py | 1 +
34 files changed, 524 insertions(+), 124 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index 2b67d6c..b5f0ebd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,5 +22,9 @@ Contributors are:
-Anson Mansfield <anson.mansfield _at_ gmail.com>
-Ken Odegard <ken.odegard _at_ gmail.com>
-Alexis Horgix Chotard
+-Piotr Babij <piotr.babij _at_ gmail.com>
+-Mikuláš Poul <mikulaspoul _at_ gmail.com>
+-Charles Bouchard-Légaré <cblegare.atl _at_ ntis.ca>
+-Yaroslav Halchenko <debian _at_ onerussian.com>
Portions derived from other open source works and are clearly marked.
diff --git a/GitPython.egg-info/PKG-INFO b/GitPython.egg-info/PKG-INFO
index d3126c9..14bbf7e 100644
--- a/GitPython.egg-info/PKG-INFO
+++ b/GitPython.egg-info/PKG-INFO
@@ -1,11 +1,12 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
Name: GitPython
-Version: 2.1.7
+Version: 2.1.8
Summary: Python Git Library
Home-page: https://github.com/gitpython-developers/GitPython
Author: Sebastian Thiel, Michael Trier
Author-email: byronimo at gmail.com, mtrier at gmail.com
License: BSD License
+Description-Content-Type: UNKNOWN
Description: GitPython is a python library used to interact with Git repositories
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
@@ -26,3 +27,4 @@ Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Requires: gitdb2 (>=2.0.0)
+Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
diff --git a/GitPython.egg-info/SOURCES.txt b/GitPython.egg-info/SOURCES.txt
index 1191bc5..cccc380 100644
--- a/GitPython.egg-info/SOURCES.txt
+++ b/GitPython.egg-info/SOURCES.txt
@@ -2,6 +2,7 @@ AUTHORS
CHANGES
LICENSE
MANIFEST.in
+README.md
VERSION
requirements.txt
setup.cfg
@@ -112,6 +113,7 @@ git/test/fixtures/diff_rename_raw
git/test/fixtures/diff_tree_numstat_root
git/test/fixtures/for_each_ref_with_path_component
git/test/fixtures/git_config
+git/test/fixtures/git_config-inc.cfg
git/test/fixtures/git_config_global
git/test/fixtures/git_config_with_comments
git/test/fixtures/git_config_with_empty_value
diff --git a/GitPython.egg-info/requires.txt b/GitPython.egg-info/requires.txt
index 7dd1ffa..5eb87ac 100644
--- a/GitPython.egg-info/requires.txt
+++ b/GitPython.egg-info/requires.txt
@@ -1 +1 @@
-gitdb2 >= 2.0.0
+gitdb2>=2.0.0
diff --git a/PKG-INFO b/PKG-INFO
index d3126c9..14bbf7e 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,11 +1,12 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
Name: GitPython
-Version: 2.1.7
+Version: 2.1.8
Summary: Python Git Library
Home-page: https://github.com/gitpython-developers/GitPython
Author: Sebastian Thiel, Michael Trier
Author-email: byronimo at gmail.com, mtrier at gmail.com
License: BSD License
+Description-Content-Type: UNKNOWN
Description: GitPython is a python library used to interact with Git repositories
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
@@ -26,3 +27,4 @@ Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Requires: gitdb2 (>=2.0.0)
+Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ad428e6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,199 @@
+## GitPython
+
+GitPython is a python library used to interact with git repositories, high-level like git-porcelain,
+or low-level like git-plumbing.
+
+It provides abstractions of git objects for easy access of repository data, and additionally
+allows you to access the git repository more directly using either a pure python implementation,
+or the faster, but more resource intensive *git command* implementation.
+
+The object database implementation is optimized for handling large quantities of objects and large datasets,
+which is achieved by using low-level structures and data streaming.
+
+
+### REQUIREMENTS
+
+GitPython needs the `git` executable to be installed on the system and available
+in your `PATH` for most operations.
+If it is not in your `PATH`, you can help GitPython find it by setting
+the `GIT_PYTHON_GIT_EXECUTABLE=<path/to/git>` environment variable.
+
+* Git (1.7.x or newer)
+* Python 2.7 to 3.6, while python 2.6 is supported on a *best-effort basis*.
+
+The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`.
+The installer takes care of installing them for you.
+
+### INSTALL
+
+If you have downloaded the source code:
+
+ python setup.py install
+
+or if you want to obtain a copy from the Pypi repository:
+
+ pip install GitPython
+
+Both commands will install the required package dependencies.
+
+A distribution package can be obtained for manual installation at:
+
+ http://pypi.python.org/pypi/GitPython
+
+If you like to clone from source, you can do it like so:
+
+```bash
+git clone https://github.com/gitpython-developers/GitPython
+git submodule update --init --recursive
+./init-tests-after-clone.sh
+```
+
+### Limitations
+
+#### Leakage of System Resources
+
+GitPython is not suited for long-running processes (like daemons) as it tends to
+leak system resources. It was written in a time where destructors (as implemented
+in the `__del__` method) still ran deterministically.
+
+In case you still want to use it in such a context, you will want to search the
+codebase for `__del__` implementations and call these yourself when you see fit.
+
+Another way assure proper cleanup of resources is to factor out GitPython into a
+separate process which can be dropped periodically.
+
+#### Windows support
+
+For *Windows*, we do regularly test it on [Appveyor CI](https://www.appveyor.com/)
+but not all test-cases pass - you may help improve them by exploring
+[Issue #525](https://github.com/gitpython-developers/GitPython/issues/525).
+
+#### Python 2.6
+
+Python 2.6 is supported on best-effort basis; which means that it is likely to deteriorate over time.
+
+### RUNNING TESTS
+
+*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.
+
+On *Windows*, make sure you have `git-daemon` in your PATH. For MINGW-git, the `git-daemon.exe`
+exists in `Git\mingw64\libexec\git-core\`; CYGWIN has no daemon, but should get along fine
+with MINGW's.
+
+The easiest way to run tests is by using [tox](https://pypi.python.org/pypi/tox)
+a wrapper around virtualenv. It will take care of setting up environments with the proper
+dependencies installed and execute test commands. To install it simply:
+
+ pip install tox
+
+Then run:
+
+ tox
+
+
+For more fine-grained control, you can use `nose`.
+
+### Contributions
+
+Please have a look at the [contributions file][contributing].
+
+### INFRASTRUCTURE
+
+* [User Documentation](http://gitpython.readthedocs.org)
+* [Questions and Answers](http://stackexchange.com/filters/167317/gitpython)
+ * Please post on stackoverflow and use the `gitpython` tag
+* [Issue Tracker](https://github.com/gitpython-developers/GitPython/issues)
+ * Post reproducible bugs and feature requests as a new issue.
+ Please be sure to provide the following information if posting bugs:
+ * GitPython version (e.g. `import git; git.__version__`)
+ * Python version (e.g. `python --version`)
+ * The encountered stack-trace, if applicable
+ * Enough information to allow reproducing the issue
+
+### How to make a new release
+
+* Update/verify the version in the `VERSION` file
+* Update/verify that the changelog has been updated
+* Commit everything
+* Run `git tag -s <version>` to tag the version in Git
+* Run `make release`
+* Finally, set the upcoming version in the `VERSION` file, usually be
+ incrementing the patch level, and possibly by appending `-dev`. Probably you
+ want to `git push` once more.
+
+### How to verify a release
+
+Please only use releases from `pypi` as you can verify the respective source
+tarballs.
+
+This script shows how to verify the tarball was indeed created by the authors of
+this project:
+
+```
+curl https://pypi.python.org/packages/7e/13/2a556eb97dcf498c915e5e04bb82bf74e07bb8b7337ca2be49bfd9fb6313/GitPython-2.1.5-py2.py3-none-any.whl\#md5\=d3ecb26cb22753f4414f75f721f6f626z > gitpython.whl
+curl https://pypi.python.org/packages/7e/13/2a556eb97dcf498c915e5e04bb82bf74e07bb8b7337ca2be49bfd9fb6313/GitPython-2.1.5-py2.py3-none-any.whl.asc > gitpython-signature.asc
+gpg --verify gitpython-signature.asc gitpython.whl
+```
+
+which outputs
+
+```
+gpg: Signature made Sat Jun 10 20:22:49 2017 CEST using RSA key ID 3B07188F
+gpg: Good signature from "Sebastian Thiel (In Rust I trust!) <byronimo at gmail.com>" [unknown]
+gpg: WARNING: This key is not certified with a trusted signature!
+gpg: There is no indication that the signature belongs to the owner.
+Primary key fingerprint: 4477 ADC5 977D 7C60 D2A7 E378 9FEE 1C6A 3B07 188F
+```
+
+You can verify that the keyid indeed matches the release-signature key provided in this
+repository by looking at the keys details:
+
+```
+gpg --list-packets ./release-verification-key.asc
+```
+
+You can verify that the commit adding it was also signed by it using:
+
+```
+git show --show-signature ./release-verification-key.asc
+```
+
+If you would like to trust it permanently, you can import and sign it:
+
+```
+gpg --import ./release-verification-key.asc
+gpg --edit-key 9FEE1C6A3B07188F
+> sign
+> save
+```
+
+Afterwards verifying the tarball will yield the following:
+```
+$ gpg --verify gitpython-signature.asc gitpython.whl
+gpg: Signature made Sat Jun 10 20:22:49 2017 CEST using RSA key ID 3B07188F
+gpg: Good signature from "Sebastian Thiel (In Rust I trust!) <byronimo at gmail.com>" [ultimate]
+```
+
+### LICENSE
+
+New BSD License. See the LICENSE file.
+
+### DEVELOPMENT STATUS
+
+[](https://codecov.io/gh/gitpython-developers/GitPython)
+[](https://travis-ci.org/gitpython-developers/GitPython)
+[](https://ci.appveyor.com/project/Byron/gitpython/branch/master)
+[](https://codeclimate.com/github/gitpython-developers/GitPython)
+[](https://readthedocs.org/projects/gitpython/?badge=stable)
+[](https://waffle.io/gitpython-developers/GitPython)
+[](https://waffle.io/gitpython-developers/GitPython/metrics/throughput)
+
+Now that there seems to be a massive user base, this should be motivation enough to let git-python
+return to a proper state, which means
+
+* no open pull requests
+* no open issues describing bugs
+
+[contributing]: https://github.com/gitpython-developers/GitPython/blob/master/CONTRIBUTING.md
diff --git a/VERSION b/VERSION
index 04b10b4..ebf14b4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.7
+2.1.8
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
index 4aedf93..70f66a7 100644
--- a/doc/source/changes.rst
+++ b/doc/source/changes.rst
@@ -2,7 +2,16 @@
Changelog
=========
-2.1.6 - Bugfixes
+2.1.8 - bugfixes
+====================================
+
+See the following for (most) details:
+https://github.com/gitpython-developers/GitPython/milestone/23?closed=1
+
+or run have a look at the difference between tags v2.1.7 and v2.1.8:
+https://github.com/gitpython-developers/GitPython/compare/2.1.7...2.1.8
+
+2.1.6 - bugfixes
====================================
* support for worktrees
diff --git a/git/__init__.py b/git/__init__.py
index 4e2dc07..b05ad12 100644
--- a/git/__init__.py
+++ b/git/__init__.py
@@ -12,13 +12,13 @@ import sys
import os.path as osp
-__version__ = '2.1.7'
+__version__ = '2.1.8'
#{ Initialization
def _init_externals():
"""Initialize external projects by putting them into the path"""
- if __version__ == '2.1.7':
+ if __version__ == '2.1.8':
sys.path.insert(0, osp.join(osp.dirname(__file__), 'ext', 'gitdb'))
try:
diff --git a/git/cmd.py b/git/cmd.py
index e0946e4..13c0140 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -780,8 +780,8 @@ class Git(LazyMixin):
if kill_after_timeout:
watchdog.cancel()
if kill_check.isSet():
- stderr_value = 'Timeout: the command "%s" did not complete in %d ' \
- 'secs.' % (" ".join(command), kill_after_timeout)
+ stderr_value = ('Timeout: the command "%s" did not complete in %d '
+ 'secs.' % (" ".join(command), kill_after_timeout)).encode(defenc)
# strip trailing "\n"
if stdout_value.endswith(b"\n"):
stdout_value = stdout_value[:-1]
diff --git a/git/compat.py b/git/compat.py
index b804585..b63768f 100644
--- a/git/compat.py
+++ b/git/compat.py
@@ -309,5 +309,5 @@ def register_surrogateescape():
try:
b"100644 \x9f\0aaa".decode(defenc, "surrogateescape")
-except:
+except Exception:
register_surrogateescape()
diff --git a/git/config.py b/git/config.py
index 7d96227..3310db8 100644
--- a/git/config.py
+++ b/git/config.py
@@ -424,7 +424,8 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
if include_path in seen or not os.access(include_path, os.R_OK):
continue
seen.add(include_path)
- files_to_read.append(include_path)
+ # insert included file to the top to be considered first
+ files_to_read.insert(0, include_path)
num_read_include_files += 1
# each include path in configuration file
# end handle includes
diff --git a/git/diff.py b/git/diff.py
index 16c782f..28c10e4 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -313,20 +313,20 @@ class Diff(object):
h %= self.b_blob.path
msg = ''
- l = None # temp line
- ll = 0 # line length
+ line = None # temp line
+ line_length = 0 # line length
for b, n in zip((self.a_blob, self.b_blob), ('lhs', 'rhs')):
if b:
- l = "\n%s: %o | %s" % (n, b.mode, b.hexsha)
+ line = "\n%s: %o | %s" % (n, b.mode, b.hexsha)
else:
- l = "\n%s: None" % n
+ line = "\n%s: None" % n
# END if blob is not None
- ll = max(len(l), ll)
- msg += l
+ line_length = max(len(line), line_length)
+ msg += line
# END for each blob
# add headline
- h += '\n' + '=' * ll
+ h += '\n' + '=' * line_length
if self.deleted_file:
msg += '\nfile deleted in rhs'
diff --git a/git/exc.py b/git/exc.py
index a737110..4865da9 100644
--- a/git/exc.py
+++ b/git/exc.py
@@ -48,7 +48,7 @@ class CommandError(UnicodeMixin, GitError):
else:
try:
status = u'exit code(%s)' % int(status)
- except:
+ except (ValueError, TypeError):
s = safe_decode(str(status))
status = u"'%s'" % s if isinstance(status, string_types) else s
diff --git a/git/index/base.py b/git/index/base.py
index 4fee2aa..a9e3a3c 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -948,6 +948,11 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
:return: Commit object representing the new commit"""
if not skip_hooks:
run_commit_hook('pre-commit', self)
+
+ self._write_commit_editmsg(message)
+ run_commit_hook('commit-msg', self, self._commit_editmsg_filepath())
+ message = self._read_commit_editmsg()
+ self._remove_commit_editmsg()
tree = self.write_tree()
rval = Commit.create_from_tree(self.repo, tree, message, parent_commits,
head, author=author, committer=committer,
@@ -955,6 +960,20 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable):
if not skip_hooks:
run_commit_hook('post-commit', self)
return rval
+
+ def _write_commit_editmsg(self, message):
+ with open(self._commit_editmsg_filepath(), "wb") as commit_editmsg_file:
+ commit_editmsg_file.write(message.encode(defenc))
+
+ def _remove_commit_editmsg(self):
+ os.remove(self._commit_editmsg_filepath())
+
+ def _read_commit_editmsg(self):
+ with open(self._commit_editmsg_filepath(), "rb") as commit_editmsg_file:
+ return commit_editmsg_file.read().decode(defenc)
+
+ def _commit_editmsg_filepath(self):
+ return osp.join(self.repo.common_dir, "COMMIT_EDITMSG")
@classmethod
def _flush_stdin_and_wait(cls, proc, ignore_stdout=False):
diff --git a/git/index/fun.py b/git/index/fun.py
index 7f7518e..c01a32b 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -62,10 +62,11 @@ def hook_path(name, git_dir):
return osp.join(git_dir, 'hooks', name)
-def run_commit_hook(name, index):
+def run_commit_hook(name, index, *args):
"""Run the commit hook of the given name. Silently ignores hooks that do not exist.
:param name: name of hook, like 'pre-commit'
:param index: IndexFile instance
+ :param args: arguments passed to hook file
:raises HookExecutionError: """
hp = hook_path(name, index.repo.git_dir)
if not os.access(hp, os.X_OK):
@@ -75,7 +76,7 @@ def run_commit_hook(name, index):
env['GIT_INDEX_FILE'] = safe_decode(index.path) if PY3 else safe_encode(index.path)
env['GIT_EDITOR'] = ':'
try:
- cmd = subprocess.Popen(hp,
+ cmd = subprocess.Popen([hp] + list(args),
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
@@ -93,7 +94,7 @@ def run_commit_hook(name, index):
if cmd.returncode != 0:
stdout = force_text(stdout, defenc)
stderr = force_text(stderr, defenc)
- raise HookExecutionError(hp, cmd.returncode, stdout, stderr)
+ raise HookExecutionError(hp, cmd.returncode, stderr, stdout)
# end handle return code
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
index a6b4cae..3315121 100644
--- a/git/objects/submodule/base.py
+++ b/git/objects/submodule/base.py
@@ -278,7 +278,7 @@ class Submodule(IndexObject, Iterable, Traversable):
if not path.startswith(working_tree_linux):
raise ValueError("Submodule checkout path '%s' needs to be within the parents repository at '%s'"
% (working_tree_linux, path))
- path = path[len(working_tree_linux) + 1:]
+ path = path[len(working_tree_linux.rstrip('/')) + 1:]
if not path:
raise ValueError("Absolute submodule path '%s' didn't yield a valid relative path" % path)
# end verify converted relative path makes sense
@@ -358,7 +358,9 @@ class Submodule(IndexObject, Iterable, Traversable):
if sm.exists():
# reretrieve submodule from tree
try:
- return repo.head.commit.tree[path]
+ sm = repo.head.commit.tree[path]
+ sm._name = name
+ return sm
except KeyError:
# could only be in index
index = repo.index
diff --git a/git/refs/log.py b/git/refs/log.py
index 623a63d..1c085ef 100644
--- a/git/refs/log.py
+++ b/git/refs/log.py
@@ -246,7 +246,7 @@ class RefLog(list, Serializable):
try:
self._serialize(fp)
lfd.commit()
- except:
+ except Exception:
# on failure it rolls back automatically, but we make it clear
lfd.rollback()
raise
diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py
index bef6ba3..8efeafc 100644
--- a/git/refs/symbolic.py
+++ b/git/refs/symbolic.py
@@ -96,7 +96,15 @@ class SymbolicReference(object):
if not line:
continue
if line.startswith('#'):
- if line.startswith('# pack-refs with:') and not line.endswith('peeled'):
+ # "# pack-refs with: peeled fully-peeled sorted"
+ # the git source code shows "peeled",
+ # "fully-peeled" and "sorted" as the keywords
+ # that can go on this line, as per comments in git file
+ # refs/packed-backend.c
+ # I looked at master on 2017-10-11,
+ # commit 111ef79afe, after tag v2.15.0-rc1
+ # from repo https://github.com/git/git.git
+ if line.startswith('# pack-refs with:') and 'peeled' not in line:
raise TypeError("PackingType of packed-Refs not understood: %r" % line)
# END abort if we do not understand the packing scheme
continue
diff --git a/git/remote.py b/git/remote.py
index 7261be8..813566a 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -536,10 +536,20 @@ class Remote(LazyMixin, Iterable):
# and: http://stackoverflow.com/a/32991784/548792
#
if 'Unknown subcommand: get-url' in str(ex):
- remote_details = self.repo.git.remote("show", self.name)
- for line in remote_details.split('\n'):
- if ' Push URL:' in line:
- yield line.split(': ')[-1]
+ try:
+ remote_details = self.repo.git.remote("show", self.name)
+ for line in remote_details.split('\n'):
+ if ' Push URL:' in line:
+ yield line.split(': ')[-1]
+ except GitCommandError as ex:
+ if any([msg in str(ex) for msg in ['correct access rights', 'cannot run ssh']]):
+ # If ssh is not setup to access this repository, see issue 694
+ result = Git().execute(
+ ['git', 'config', '--get', 'remote.%s.url' % self.name]
+ )
+ yield result
+ else:
+ raise ex
else:
raise ex
diff --git a/git/repo/base.py b/git/repo/base.py
index d3bdc98..a477bf3 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -8,7 +8,6 @@ from collections import namedtuple
import logging
import os
import re
-import sys
import warnings
from git.cmd import (
@@ -40,11 +39,6 @@ import gitdb
log = logging.getLogger(__name__)
-DefaultDBType = GitCmdObjectDB
-if sys.version_info[:2] < (2, 5): # python 2.4 compatibility
- DefaultDBType = GitCmdObjectDB
-# END handle python 2.4
-
BlameEntry = namedtuple('BlameEntry', ['commit', 'linenos', 'orig_path', 'orig_linenos'])
@@ -88,7 +82,7 @@ class Repo(object):
# Subclasses may easily bring in their own custom types by placing a constructor or type here
GitCommandWrapperType = Git
- def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=False, expand_vars=True):
+ def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=False, expand_vars=True):
"""Create a new Repo instance
:param path:
@@ -203,15 +197,23 @@ class Repo(object):
def __del__(self):
try:
self.close()
- except:
+ except Exception:
pass
def close(self):
if self.git:
self.git.clear_cache()
- gc.collect()
+ # Tempfiles objects on Windows are holding references to
+ # open files until they are collected by the garbage
+ # collector, thus preventing deletion.
+ # TODO: Find these references and ensure they are closed
+ # and deleted synchronously rather than forcing a gc
+ # collection.
+ if is_win:
+ gc.collect()
gitdb.util.mman.collect()
- gc.collect()
+ if is_win:
+ gc.collect()
def __eq__(self, rhs):
if isinstance(rhs, Repo):
@@ -861,7 +863,7 @@ class Repo(object):
return blames
@classmethod
- def init(cls, path=None, mkdir=True, odbt=DefaultDBType, expand_vars=True, **kwargs):
+ def init(cls, path=None, mkdir=True, odbt=GitCmdObjectDB, expand_vars=True, **kwargs):
"""Initialize a git repository at the given path if specified
:param path:
@@ -905,6 +907,10 @@ class Repo(object):
odbt = kwargs.pop('odbt', odb_default_type)
+ # when pathlib.Path or other classbased path is passed
+ if not isinstance(path, str):
+ path = str(path)
+
## A bug win cygwin's Git, when `--bare` or `--separate-git-dir`
# it prepends the cwd or(?) the `url` into the `path, so::
# git clone --bare /cygwin/d/foo.git C:\\Work
@@ -918,9 +924,9 @@ class Repo(object):
if sep_dir:
kwargs['separate_git_dir'] = Git.polish_url(sep_dir)
proc = git.clone(Git.polish_url(url), clone_path, with_extended_output=True, as_process=True,
- v=True, **add_progress(kwargs, git, progress))
+ v=True, universal_newlines=True, **add_progress(kwargs, git, progress))
if progress:
- handle_process_output(proc, None, progress.new_message_handler(), finalize_process)
+ handle_process_output(proc, None, progress.new_message_handler(), finalize_process, decode_streams=False)
else:
(stdout, stderr) = proc.communicate()
log.debug("Cmd(%s)'s unused stdout: %s", getattr(proc, 'args', ''), stdout)
@@ -931,12 +937,16 @@ class Repo(object):
if not osp.isabs(path) and git.working_dir:
path = osp.join(git._working_dir, path)
+ repo = cls(path, odbt=odbt)
+
+ # retain env values that were passed to _clone()
+ repo.git.update_environment(**git.environment())
+
# adjust remotes - there may be operating systems which use backslashes,
# These might be given as initial paths, but when handling the config file
# that contains the remote from which we were clones, git stops liking it
# as it will escape the backslashes. Hence we undo the escaping just to be
# sure
- repo = cls(path, odbt=odbt)
if repo.remotes:
with repo.remotes[0].config_writer as writer:
writer.set_value('url', Git.polish_url(repo.remotes[0].url))
diff --git a/git/test/fixtures/git_config b/git/test/fixtures/git_config
index c9945cd..b8c178e 100644
--- a/git/test/fixtures/git_config
+++ b/git/test/fixtures/git_config
@@ -22,11 +22,25 @@
url = git://gitorious.org/~martin.marcher/git-python/serverhorror.git
fetch = +refs/heads/*:refs/remotes/MartinMarcher/*
# can handle comments - the section name is supposed to be stripped
+# causes stock git-config puke
[ gui ]
geometry = 1316x820+219+243 207 192
[branch "mainline_performance"]
remote = mainline
merge = refs/heads/master
+# section with value defined before include to be overriden
+[sec]
+ var0 = value0_main
[include]
- path = doesntexist.cfg
- abspath = /usr/bin/foodoesntexist.bar
\ No newline at end of file
+ path = doesntexist.cfg
+ # field should be 'path' so abspath should be ignored
+ abspath = /usr/bin/foodoesntexist.bar
+ path = /usr/bin/foodoesntexist.bar
+ # should be relative to the path of this config file
+ path = ./git_config-inc.cfg
+# and defined after include. According to the documentation
+# and behavior of git config, this should be the value since
+# inclusions should be processed immediately
+[sec]
+ var1 = value1_main
+
diff --git a/git/test/fixtures/git_config-inc.cfg b/git/test/fixtures/git_config-inc.cfg
new file mode 100644
index 0000000..2368ec2
--- /dev/null
+++ b/git/test/fixtures/git_config-inc.cfg
@@ -0,0 +1,5 @@
+[sec]
+ var0 = value0_included
+ var1 = value1_included
+[diff]
+ tool = diff_included
diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py
index 729c76a..cb46173 100644
--- a/git/test/lib/helper.py
+++ b/git/test/lib/helper.py
@@ -29,6 +29,8 @@ else:
import unittest
TestCase = unittest.TestCase
+SkipTest = unittest.SkipTest
+skipIf = unittest.skipIf
ospd = osp.dirname
@@ -37,7 +39,9 @@ GIT_DAEMON_PORT = os.environ.get("GIT_PYTHON_TEST_GIT_DAEMON_PORT", "19418")
__all__ = (
'fixture_path', 'fixture', 'StringProcessAdapter',
- 'with_rw_directory', 'with_rw_repo', 'with_rw_and_rw_remote_repo', 'TestBase', 'TestCase',
+ 'with_rw_directory', 'with_rw_repo', 'with_rw_and_rw_remote_repo',
+ 'TestBase', 'TestCase',
+ 'SkipTest', 'skipIf',
'GIT_REPO', 'GIT_DAEMON_PORT'
)
@@ -139,7 +143,7 @@ def with_rw_repo(working_tree_ref, bare=False):
try:
try:
return func(self, rw_repo)
- except:
+ except: # noqa E722
log.info("Keeping repo after failure: %s", repo_dir)
repo_dir = None
raise
@@ -227,7 +231,7 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
Same as with_rw_repo, but also provides a writable remote repository from which the
rw_repo has been forked as well as a handle for a git-daemon that may be started to
run the remote_repo.
- The remote repository was cloned as bare repository from the rorepo, whereas
+ The remote repository was cloned as bare repository from the ro repo, whereas
the rw repo has a working tree and was cloned from the remote repository.
remote_repo has two remotes: origin and daemon_origin. One uses a local url,
@@ -296,7 +300,7 @@ def with_rw_and_rw_remote_repo(working_tree_ref):
with cwd(rw_repo.working_dir):
try:
return func(self, rw_repo, rw_daemon_repo)
- except:
+ except: # noqa E722
log.info("Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s",
rw_repo_dir, rw_daemon_repo_dir)
rw_repo_dir = rw_daemon_repo_dir = None
diff --git a/git/test/test_commit.py b/git/test/test_commit.py
index fbb1c24..cd6c5d5 100644
--- a/git/test/test_commit.py
+++ b/git/test/test_commit.py
@@ -169,8 +169,7 @@ class TestCommit(TestBase):
# at some point, both iterations should stop
self.assertEqual(list(bfirst)[-1], first)
stoptraverse = self.rorepo.commit("254d04aa3180eb8b8daf7b7ff25f010cd69b4e7d").traverse(as_edge=True)
- l = list(stoptraverse)
- self.assertEqual(len(l[0]), 2)
+ self.assertEqual(len(next(stoptraverse)), 2)
# ignore self
self.assertEqual(next(start.traverse(ignore_self=False)), start)
diff --git a/git/test/test_config.py b/git/test/test_config.py
index 7cf9d31..4d6c823 100644
--- a/git/test/test_config.py
+++ b/git/test/test_config.py
@@ -15,6 +15,7 @@ from git.config import cp
from git.test.lib import (
TestCase,
fixture_path,
+ SkipTest,
)
from git.test.lib import with_rw_directory
@@ -88,6 +89,21 @@ class TestBase(TestCase):
assert r_config.get(sname, oname) == val
# END for each filename
+ def test_includes_order(self):
+ with GitConfigParser(list(map(fixture_path, ("git_config", "git_config_global")))) as r_config:
+ r_config.read() # enforce reading
+ # Simple inclusions, again checking them taking precedence
+ assert r_config.get_value('sec', 'var0') == "value0_included"
+ # This one should take the git_config_global value since included
+ # values must be considered as soon as they get them
+ assert r_config.get_value('diff', 'tool') == "meld"
+ try:
+ assert r_config.get_value('sec', 'var1') == "value1_main"
+ except AssertionError:
+ raise SkipTest(
+ 'Known failure -- included values are not in effect right away'
+ )
+
@with_rw_directory
def test_lock_reentry(self, rw_dir):
fpl = osp.join(rw_dir, 'l')
diff --git a/git/test/test_git.py b/git/test/test_git.py
index 0a0d7ef..059f90c 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -37,6 +37,8 @@ try:
except ImportError:
import mock
+from git.compat import is_win
+
class TestGit(TestBase):
@@ -177,7 +179,8 @@ class TestGit(TestBase):
self.assertRaises(GitCommandNotFound, refresh, "yada")
# test a good path refresh
- path = os.popen("which git").read().strip()
+ which_cmd = "where" if is_win else "which"
+ path = os.popen("{0} git".format(which_cmd)).read().strip().split('\n')[0]
refresh(path)
def test_options_are_passed_to_git(self):
diff --git a/git/test/test_index.py b/git/test/test_index.py
index e8d38a0..757bec9 100644
--- a/git/test/test_index.py
+++ b/git/test/test_index.py
@@ -54,6 +54,22 @@ from gitdb.base import IStream
import os.path as osp
from git.cmd import Git
+HOOKS_SHEBANG = "#!/usr/bin/env sh\n"
+
+
+ at skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "TODO: fix hooks execution on Windows: #703")
+def _make_hook(git_dir, name, content, make_exec=True):
+ """A helper to create a hook"""
+ hp = hook_path(name, git_dir)
+ hpd = osp.dirname(hp)
+ if not osp.isdir(hpd):
+ os.mkdir(hpd)
+ with open(hp, "wt") as fp:
+ fp.write(HOOKS_SHEBANG + content)
+ if make_exec:
+ os.chmod(hp, 0o744)
+ return hp
+
class TestIndex(TestBase):
@@ -729,35 +745,6 @@ class TestIndex(TestBase):
assert fkey not in index.entries
index.add(files, write=True)
- if is_win:
- hp = hook_path('pre-commit', index.repo.git_dir)
- hpd = osp.dirname(hp)
- if not osp.isdir(hpd):
- os.mkdir(hpd)
- with open(hp, "wt") as fp:
- fp.write("#!/usr/bin/env sh\necho stdout; echo stderr 1>&2; exit 1")
- # end
- os.chmod(hp, 0o744)
- try:
- index.commit("This should fail")
- except HookExecutionError as err:
- if is_win:
- self.assertIsInstance(err.status, OSError)
- self.assertEqual(err.command, [hp])
- self.assertEqual(err.stdout, '')
- self.assertEqual(err.stderr, '')
- assert str(err)
- else:
- self.assertEqual(err.status, 1)
- self.assertEqual(err.command, hp)
- self.assertEqual(err.stdout, 'stdout\n')
- self.assertEqual(err.stderr, 'stderr\n')
- assert str(err)
- else:
- raise AssertionError("Should have cought a HookExecutionError")
- # end exception handling
- os.remove(hp)
- # end hook testing
nc = index.commit("2 files committed", head=False)
for fkey in keys:
@@ -859,3 +846,78 @@ class TestIndex(TestBase):
r = Repo.init(rw_dir)
r.index.add([fp])
r.index.commit('Added [.exe')
+
+ @with_rw_repo('HEAD', bare=True)
+ def test_pre_commit_hook_success(self, rw_repo):
+ index = rw_repo.index
+ _make_hook(
+ index.repo.git_dir,
+ 'pre-commit',
+ "exit 0"
+ )
+ index.commit("This should not fail")
+
+ @with_rw_repo('HEAD', bare=True)
+ def test_pre_commit_hook_fail(self, rw_repo):
+ index = rw_repo.index
+ hp = _make_hook(
+ index.repo.git_dir,
+ 'pre-commit',
+ "echo stdout; echo stderr 1>&2; exit 1"
+ )
+ try:
+ index.commit("This should fail")
+ except HookExecutionError as err:
+ if is_win:
+ self.assertIsInstance(err.status, OSError)
+ self.assertEqual(err.command, [hp])
+ self.assertEqual(err.stdout, '')
+ self.assertEqual(err.stderr, '')
+ assert str(err)
... 257 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-git.git
More information about the Python-modules-commits
mailing list