From 5b4f92c8eea41f20b95f9e62a39b210400f4d2a9 Mon Sep 17 00:00:00 2001 From: Benjamin Poldrack Date: Tue, 18 Oct 2016 15:10:11 +0200 Subject: Allow for setting git options, that are persistent across subcommand calls --- git/cmd.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'git') diff --git a/git/cmd.py b/git/cmd.py index f0757301..3d455546 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -161,7 +161,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') @@ -386,6 +386,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 = {} @@ -402,6 +403,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) @@ -820,7 +835,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 = () -- cgit v1.2.1 From f1b8d0c92e4b5797b95948bdb95bec7756f5189f Mon Sep 17 00:00:00 2001 From: Benjamin Poldrack Date: Tue, 18 Oct 2016 16:07:54 +0200 Subject: Add a test for persistent git options --- git/cmd.py | 2 +- git/test/test_git.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'git') diff --git a/git/cmd.py b/git/cmd.py index 3d455546..1481ac81 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -415,7 +415,7 @@ class Git(LazyMixin): """ self._persistent_git_options = self.transform_kwargs( - split_single_char_options=True, **kwargs) + split_single_char_options=True, **kwargs) def _set_cache_(self, attr): if attr == '_version_info': diff --git a/git/test/test_git.py b/git/test/test_git.py index bd8ebee2..ef327c6d 100644 --- a/git/test/test_git.py +++ b/git/test/test_git.py @@ -160,6 +160,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') -- cgit v1.2.1 From bf8ce9464987c7b0dbe6acbc2cc2653e98ec739a Mon Sep 17 00:00:00 2001 From: Benjamin Poldrack Date: Wed, 19 Oct 2016 12:56:57 +0200 Subject: Fix flake8 error --- git/test/test_git.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git') diff --git a/git/test/test_git.py b/git/test/test_git.py index ef327c6d..14c70e18 100644 --- a/git/test/test_git.py +++ b/git/test/test_git.py @@ -172,7 +172,7 @@ class TestGit(TestBase): # reset to empty: self.git.set_persistent_git_options() - self.assertRaises(GitCommandError, self.git.NoOp) + self.assertRaises(GitCommandError, self.git.NoOp) def test_single_char_git_options_are_passed_to_git(self): input_value = 'TestValue' -- cgit v1.2.1 From b29388a8f9cf3522e5f52b47572af7d8f61862a1 Mon Sep 17 00:00:00 2001 From: Kostis Anagnostopoulos Date: Wed, 19 Oct 2016 15:49:13 +0200 Subject: FIX #535: expand also GIT_DIR var on Repo-construct + Ignore "empty" GIT_DIR vars. + Improve documentation on the constructor `path` parameter. --- git/repo/base.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'git') diff --git a/git/repo/base.py b/git/repo/base.py index c5cdce7c..d36864bb 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -124,6 +124,8 @@ class Repo(object): repo = Repo("~/Development/git-python.git") repo = Repo("$REPOSITORIES/Development/git-python.git") + 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 @@ -136,17 +138,19 @@ class Repo(object): :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ - epath = _expand_path(path or os.getcwd()) self.git = None # should be set for __del__ not to fail in case we raise + epath = os.getenv('GIT_DIR') + 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 os.path.NORMPATH # It's important to normalize the paths, as submodules will otherwise initialize their -- cgit v1.2.1 From 9d5d143f72e4d588e3a0abb2ab82fa5a2c35e8aa Mon Sep 17 00:00:00 2001 From: Kostis Anagnostopoulos Date: Wed, 19 Oct 2016 16:01:47 +0200 Subject: repo: minor code and doc correcions. + Expansion of paths also `osp.normalize()` them. + Make Repo-fields --> class-fields to avoid initializations on construct. + Explain and rename `git.repo.fun.find_git_dir()` is for submodules (`find_submodule_git_dir()`). --- git/repo/base.py | 26 +++++++++++++------------- git/repo/fun.py | 7 ++++--- git/test/test_submodule.py | 4 ++-- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'git') diff --git a/git/repo/base.py b/git/repo/base.py index d36864bb..bde9b936 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -47,7 +47,7 @@ from gitdb.util import ( from .fun import ( rev_parse, is_git_dir, - find_git_dir, + find_submodule_git_dir, touch, ) from git.compat import ( @@ -79,7 +79,7 @@ __all__ = ('Repo',) def _expand_path(p): - return os.path.abspath(os.path.expandvars(os.path.expanduser(p))) + return os.path.normpath(os.path.abspath(os.path.expandvars(os.path.expanduser(p)))) class Repo(object): @@ -98,6 +98,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}$') @@ -138,16 +143,11 @@ class Repo(object): :raise InvalidGitRepositoryError: :raise NoSuchPathError: :return: git.Repo """ - self.git = None # should be set for __del__ not to fail in case we raise epath = os.getenv('GIT_DIR') 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 - ## Walk up the path to find the `.git` dir. # curpath = epath @@ -157,20 +157,20 @@ class Repo(object): # 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 = os.path.normpath(curpath) + self.git_dir = curpath self._working_tree_dir = os.path.dirname(self.git_dir) break - gitpath = find_git_dir(join(curpath, '.git')) - if gitpath is not None: - self.git_dir = os.path.normpath(gitpath) + sm_gitpath = find_submodule_git_dir(join(curpath, '.git')) + if sm_gitpath is not None: + self.git_dir = os.path.normpath(sm_gitpath) self._working_tree_dir = curpath break if not search_parent_directories: break - curpath, dummy = os.path.split(curpath) - if not dummy: + curpath, tail = os.path.split(curpath) + if not tail: break # END while curpath diff --git a/git/repo/fun.py b/git/repo/fun.py index 320eb1c8..fe0896a9 100644 --- a/git/repo/fun.py +++ b/git/repo/fun.py @@ -20,7 +20,7 @@ from git.exc import WorkTreeRepositoryUnsupported from git.compat import xrange -__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') @@ -49,7 +49,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 @@ -64,7 +65,7 @@ def find_git_dir(d): path = content[8:] if not os.path.isabs(path): path = join(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_submodule.py b/git/test/test_submodule.py index 9db4f9c9..39040ced 100644 --- a/git/test/test_submodule.py +++ b/git/test/test_submodule.py @@ -14,7 +14,7 @@ from git.exc import ( from git.objects.submodule.base import Submodule from git.objects.submodule.root import RootModule, RootUpdateProgress from git.repo.fun import ( - find_git_dir, + find_submodule_git_dir, touch ) from git.test.lib import ( @@ -757,7 +757,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 -- cgit v1.2.1