[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
+
+[![codecov](https://codecov.io/gh/gitpython-developers/GitPython/branch/master/graph/badge.svg)](https://codecov.io/gh/gitpython-developers/GitPython)
+[![Build Status](https://travis-ci.org/gitpython-developers/GitPython.svg)](https://travis-ci.org/gitpython-developers/GitPython)
+[![Build status](https://ci.appveyor.com/api/projects/status/0f3pi3c00hajlrsd/branch/master?svg=true&passingText=windows%20OK&failingText=windows%20failed)](https://ci.appveyor.com/project/Byron/gitpython/branch/master)
+[![Code Climate](https://codeclimate.com/github/gitpython-developers/GitPython/badges/gpa.svg)](https://codeclimate.com/github/gitpython-developers/GitPython)
+[![Documentation Status](https://readthedocs.org/projects/gitpython/badge/?version=stable)](https://readthedocs.org/projects/gitpython/?badge=stable)
+[![Stories in Ready](https://badge.waffle.io/gitpython-developers/GitPython.png?label=ready&title=Ready)](https://waffle.io/gitpython-developers/GitPython)
+[![Throughput Graph](https://graphs.waffle.io/gitpython-developers/GitPython/throughput.svg)](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