diff options
author | Kostis Anagnostopoulos <ankostis@gmail.com> | 2016-10-19 16:16:24 +0200 |
---|---|---|
committer | Kostis Anagnostopoulos <ankostis@gmail.com> | 2016-10-19 17:02:35 +0200 |
commit | 76ac61a2b4bb10c8434a7d6fc798b115b4b7934d (patch) | |
tree | 763993b8d2c46a425db36e12d941db79866f7de7 | |
parent | cc77e6b2862733a211c55cf29cc7a83c36c27919 (diff) | |
parent | 9d5d143f72e4d588e3a0abb2ab82fa5a2c35e8aa (diff) | |
download | gitpython-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.py | 22 | ||||
-rw-r--r-- | git/repo/base.py | 50 | ||||
-rw-r--r-- | git/repo/fun.py | 8 | ||||
-rw-r--r-- | git/test/test_git.py | 14 | ||||
-rw-r--r-- | git/test/test_submodule.py | 26 |
5 files changed, 74 insertions, 46 deletions
@@ -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 |