summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostis Anagnostopoulos <ankostis@gmail.com>2016-10-19 16:16:24 +0200
committerKostis Anagnostopoulos <ankostis@gmail.com>2016-10-19 17:02:35 +0200
commit76ac61a2b4bb10c8434a7d6fc798b115b4b7934d (patch)
tree763993b8d2c46a425db36e12d941db79866f7de7
parentcc77e6b2862733a211c55cf29cc7a83c36c27919 (diff)
parent9d5d143f72e4d588e3a0abb2ab82fa5a2c35e8aa (diff)
downloadgitpython-76ac61a2b4bb10c8434a7d6fc798b115b4b7934d.tar.gz
Merge with latest branch 'exp_git_dir'
Conflicts: git/repo/base.py git/repo/fun.py git/test/test_submodule.py
-rw-r--r--git/cmd.py22
-rw-r--r--git/repo/base.py50
-rw-r--r--git/repo/fun.py8
-rw-r--r--git/test/test_git.py14
-rw-r--r--git/test/test_submodule.py26
5 files changed, 74 insertions, 46 deletions
diff --git a/git/cmd.py b/git/cmd.py
index c43fac56..2d244036 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -162,7 +162,7 @@ class Git(LazyMixin):
Set its value to 'full' to see details about the returned values.
"""
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
- "_git_options", "_environment")
+ "_git_options", "_persistent_git_options", "_environment")
_excluded_ = ('cat_file_all', 'cat_file_header', '_version_info')
@@ -405,6 +405,7 @@ class Git(LazyMixin):
super(Git, self).__init__()
self._working_dir = working_dir
self._git_options = ()
+ self._persistent_git_options = []
# Extra environment variables to pass to git commands
self._environment = {}
@@ -421,6 +422,20 @@ class Git(LazyMixin):
return LazyMixin.__getattr__(self, name)
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
+ def set_persistent_git_options(self, **kwargs):
+ """Specify command line options to the git executable
+ for subsequent subcommand calls
+
+ :param kwargs:
+ is a dict of keyword arguments.
+ these arguments are passed as in _call_process
+ but will be passed to the git command rather than
+ the subcommand.
+ """
+
+ self._persistent_git_options = self.transform_kwargs(
+ split_single_char_options=True, **kwargs)
+
def _set_cache_(self, attr):
if attr == '_version_info':
# We only use the first 4 numbers, as everthing else could be strings in fact (on windows)
@@ -839,7 +854,10 @@ class Git(LazyMixin):
call = [self.GIT_PYTHON_GIT_EXECUTABLE]
- # add the git options, the reset to empty
+ # add persistent git options
+ call.extend(self._persistent_git_options)
+
+ # add the git options, then reset to empty
# to avoid side_effects
call.extend(self._git_options)
self._git_options = ()
diff --git a/git/repo/base.py b/git/repo/base.py
index 21d129e9..f3a04cf4 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -30,10 +30,9 @@ from git.objects import Submodule, RootModule, Commit
from git.refs import HEAD, Head, Reference, TagReference
from git.remote import Remote, add_progress, to_progress_instance
from git.util import Actor, finalize_process, decygpath, hex_to_bin
-
import os.path as osp
-from .fun import rev_parse, is_git_dir, find_git_dir, touch
+from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch
log = logging.getLogger(__name__)
@@ -50,7 +49,7 @@ __all__ = ('Repo',)
def _expand_path(p):
- return osp.abspath(osp.expandvars(osp.expanduser(p)))
+ return osp.normpath(osp.abspath(osp.expandvars(osp.expanduser(p))))
class Repo(object):
@@ -69,6 +68,11 @@ class Repo(object):
'git_dir' is the .git repository directory, which is always set."""
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
+ git = None # Must exist, or __del__ will fail in case we raise on `__init__()`
+ working_dir = None
+ _working_tree_dir = None
+ git_dir = None
+
# precompiled regex
re_whitespace = re.compile(r'\s+')
re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
@@ -95,8 +99,9 @@ class Repo(object):
repo = Repo("~/Development/git-python.git")
repo = Repo("$REPOSITORIES/Development/git-python.git")
- In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
-
+ - In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
+ - If `None, current-directory is used.
+ - The :envvar:`GIT_DIR` if set and not empty takes precendance over this parameter.
:param odbt:
Object DataBase type - a type which is constructed by providing
the directory containing the database objects, i.e. .git/objects. It will
@@ -109,40 +114,39 @@ class Repo(object):
:raise InvalidGitRepositoryError:
:raise NoSuchPathError:
:return: git.Repo """
+ epath = os.getenv('GIT_DIR') or path or os.getcwd()
if Git.is_cygwin():
- path = decygpath(path)
-
- epath = _expand_path(path or os.getcwd())
- self.git = None # should be set for __del__ not to fail in case we raise
- if not osp.exists(epath):
+ epath = decygpath(epath)
+ epath = _expand_path(epath or path or os.getcwd())
+ if not os.path.exists(epath):
raise NoSuchPathError(epath)
- self.working_dir = None
- self._working_tree_dir = None
- self.git_dir = None
- curpath = os.getenv('GIT_DIR', epath)
-
- # walk up the path to find the .git dir
+ ## Walk up the path to find the `.git` dir.
+ #
+ curpath = epath
while curpath:
# ABOUT osp.NORMPATH
# It's important to normalize the paths, as submodules will otherwise initialize their
# repo instances with paths that depend on path-portions that will not exist after being
# removed. It's just cleaner.
if is_git_dir(curpath):
- self.git_dir = osp.normpath(curpath)
- self._working_tree_dir = osp.dirname(self.git_dir)
+ self.git_dir = curpath
+ self._working_tree_dir = os.path.dirname(self.git_dir)
break
- gitpath = find_git_dir(osp.join(curpath, '.git'))
- if gitpath is not None:
- self.git_dir = osp.normpath(gitpath)
+ sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git'))
+ if sm_gitpath is not None:
+ self.git_dir = osp.normpath(sm_gitpath)
+ sm_gitpath = find_submodule_git_dir(osp.join(curpath, '.git'))
+ if sm_gitpath is not None:
+ self.git_dir = _expand_path(sm_gitpath)
self._working_tree_dir = curpath
break
if not search_parent_directories:
break
- curpath, dummy = osp.split(curpath)
- if not dummy:
+ curpath, tail = osp.split(curpath)
+ if not tail:
break
# END while curpath
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 7ea45e6b..41e7ad3f 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -16,7 +16,7 @@ import os.path as osp
from git.cmd import Git
-__all__ = ('rev_parse', 'is_git_dir', 'touch', 'find_git_dir', 'name_to_object', 'short_to_long', 'deref_tag',
+__all__ = ('rev_parse', 'is_git_dir', 'touch', 'find_submodule_git_dir', 'name_to_object', 'short_to_long', 'deref_tag',
'to_commit')
@@ -47,7 +47,8 @@ def is_git_dir(d):
return False
-def find_git_dir(d):
+def find_submodule_git_dir(d):
+ """Search for a submodule repo."""
if is_git_dir(d):
return d
@@ -60,12 +61,13 @@ def find_git_dir(d):
else:
if content.startswith('gitdir: '):
path = content[8:]
+
if Git.is_cygwin():
## Cygwin creates submodules prefixed with `/cygdrive/...` suffixes.
path = decygpath(path)
if not osp.isabs(path):
path = osp.join(osp.dirname(d), path)
- return find_git_dir(path)
+ return find_submodule_git_dir(path)
# end handle exception
return None
diff --git a/git/test/test_git.py b/git/test/test_git.py
index 7d713022..f97f8130 100644
--- a/git/test/test_git.py
+++ b/git/test/test_git.py
@@ -162,6 +162,20 @@ class TestGit(TestBase):
git_command_version = self.git.version()
self.assertEquals(git_version, git_command_version)
+ def test_persistent_options(self):
+ git_command_version = self.git.version()
+ # analog to test_options_are_passed_to_git
+ self.git.set_persistent_git_options(version=True)
+ git_version = self.git.NoOp()
+ self.assertEquals(git_version, git_command_version)
+ # subsequent calls keep this option:
+ git_version_2 = self.git.NoOp()
+ self.assertEquals(git_version_2, git_command_version)
+
+ # reset to empty:
+ self.git.set_persistent_git_options()
+ self.assertRaises(GitCommandError, self.git.NoOp)
+
def test_single_char_git_options_are_passed_to_git(self):
input_value = 'TestValue'
output_value = self.git(c='user.name=%s' % input_value).config('--get', 'user.name')
diff --git a/git/test/test_submodule.py b/git/test/test_submodule.py
index fcaad04b..0ebd9ec7 100644
--- a/git/test/test_submodule.py
+++ b/git/test/test_submodule.py
@@ -7,34 +7,24 @@ from unittest.case import skipIf
import git
from git.cmd import Git
-from git.compat import (
- string_types,
- is_win,
-)
+from git.compat import string_types, is_win
from git.exc import (
InvalidGitRepositoryError,
RepositoryDirtyError
)
from git.objects.submodule.base import Submodule
-from git.objects.submodule.root import (
- RootModule,
- RootUpdateProgress,
-)
+from git.objects.submodule.root import RootModule, RootUpdateProgress
from git.repo.fun import (
- find_git_dir,
- touch,
+ find_submodule_git_dir,
+ touch
)
from git.test.lib import (
TestBase,
- with_rw_repo,
+ with_rw_repo
)
from git.test.lib import with_rw_directory
-from git.util import (
- to_native_path_linux,
- join_path_native,
- HIDE_WINDOWS_KNOWN_ERRORS,
-)
-
+from git.util import HIDE_WINDOWS_KNOWN_ERRORS
+from git.util import to_native_path_linux, join_path_native
import os.path as osp
@@ -775,7 +765,7 @@ class TestSubmodule(TestBase):
else:
assert osp.isfile(module_repo_path)
assert sm.module().has_separate_working_tree()
- assert find_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid"
+ assert find_submodule_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid"
# end verify submodule 'style'
# test move