Skip to content

Commit 76ac61a

Browse files
committed
Merge with latest branch 'exp_git_dir'
Conflicts: git/repo/base.py git/repo/fun.py git/test/test_submodule.py
2 parents cc77e6b + 9d5d143 commit 76ac61a

File tree

5 files changed

+74
-46
lines changed

5 files changed

+74
-46
lines changed

‎git/cmd.py‎

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class Git(LazyMixin):
162162
Set its value to 'full' to see details about the returned values.
163163
"""
164164
__slots__= ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
165-
"_git_options", "_environment")
165+
"_git_options", "_persistent_git_options", "_environment")
166166

167167
_excluded_= ('cat_file_all', 'cat_file_header', '_version_info')
168168

@@ -405,6 +405,7 @@ def __init__(self, working_dir=None):
405405
super(Git, self).__init__()
406406
self._working_dir=working_dir
407407
self._git_options= ()
408+
self._persistent_git_options= []
408409

409410
# Extra environment variables to pass to git commands
410411
self._environment={}
@@ -421,6 +422,20 @@ def __getattr__(self, name):
421422
returnLazyMixin.__getattr__(self, name)
422423
returnlambda*args, **kwargs: self._call_process(name, *args, **kwargs)
423424

425+
defset_persistent_git_options(self, **kwargs):
426+
"""Specify command line options to the git executable
427+
for subsequent subcommand calls
428+
429+
:param kwargs:
430+
is a dict of keyword arguments.
431+
these arguments are passed as in _call_process
432+
but will be passed to the git command rather than
433+
the subcommand.
434+
"""
435+
436+
self._persistent_git_options=self.transform_kwargs(
437+
split_single_char_options=True, **kwargs)
438+
424439
def_set_cache_(self, attr):
425440
ifattr=='_version_info':
426441
# We only use the first 4 numbers, as everthing else could be strings in fact (on windows)
@@ -839,7 +854,10 @@ def _call_process(self, method, *args, **kwargs):
839854

840855
call= [self.GIT_PYTHON_GIT_EXECUTABLE]
841856

842-
# add the git options, the reset to empty
857+
# add persistent git options
858+
call.extend(self._persistent_git_options)
859+
860+
# add the git options, then reset to empty
843861
# to avoid side_effects
844862
call.extend(self._git_options)
845863
self._git_options= ()

‎git/repo/base.py‎

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@
3030
fromgit.refsimportHEAD, Head, Reference, TagReference
3131
fromgit.remoteimportRemote, add_progress, to_progress_instance
3232
fromgit.utilimportActor, finalize_process, decygpath, hex_to_bin
33-
3433
importos.pathasosp
3534

36-
from .funimportrev_parse, is_git_dir, find_git_dir, touch
35+
from .funimportrev_parse, is_git_dir, find_submodule_git_dir, touch
3736

3837

3938
log=logging.getLogger(__name__)
@@ -50,7 +49,7 @@
5049

5150

5251
def_expand_path(p):
53-
returnosp.abspath(osp.expandvars(osp.expanduser(p)))
52+
returnosp.normpath(osp.abspath(osp.expandvars(osp.expanduser(p))))
5453

5554

5655
classRepo(object):
@@ -69,6 +68,11 @@ class Repo(object):
6968
'git_dir' is the .git repository directory, which is always set."""
7069
DAEMON_EXPORT_FILE='git-daemon-export-ok'
7170

71+
git=None# Must exist, or __del__ will fail in case we raise on `__init__()`
72+
working_dir=None
73+
_working_tree_dir=None
74+
git_dir=None
75+
7276
# precompiled regex
7377
re_whitespace=re.compile(r'\s+')
7478
re_hexsha_only=re.compile('^[0-9A-Fa-f]{40}$')
@@ -95,8 +99,9 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
9599
repo = Repo("~/Development/git-python.git")
96100
repo = Repo("$REPOSITORIES/Development/git-python.git")
97101
98-
In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
99-
102+
- In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
103+
- If `None, current-directory is used.
104+
- The :envvar:`GIT_DIR` if set and not empty takes precendance over this parameter.
100105
:param odbt:
101106
Object DataBase type - a type which is constructed by providing
102107
the directory containing the database objects, i.e. .git/objects. It will
@@ -109,40 +114,39 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
109114
:raise InvalidGitRepositoryError:
110115
:raise NoSuchPathError:
111116
:return: git.Repo """
117+
epath=os.getenv('GIT_DIR') orpathoros.getcwd()
112118
ifGit.is_cygwin():
113-
path=decygpath(path)
114-
115-
epath=_expand_path(pathoros.getcwd())
116-
self.git=None# should be set for __del__ not to fail in case we raise
117-
ifnotosp.exists(epath):
119+
epath=decygpath(epath)
120+
epath=_expand_path(epathorpathoros.getcwd())
121+
ifnotos.path.exists(epath):
118122
raiseNoSuchPathError(epath)
119123

120-
self.working_dir=None
121-
self._working_tree_dir=None
122-
self.git_dir=None
123-
curpath=os.getenv('GIT_DIR', epath)
124-
125-
# walk up the path to find the .git dir
124+
## Walk up the path to find the `.git` dir.
125+
#
126+
curpath=epath
126127
whilecurpath:
127128
# ABOUT osp.NORMPATH
128129
# It's important to normalize the paths, as submodules will otherwise initialize their
129130
# repo instances with paths that depend on path-portions that will not exist after being
130131
# removed. It's just cleaner.
131132
ifis_git_dir(curpath):
132-
self.git_dir=osp.normpath(curpath)
133-
self._working_tree_dir=osp.dirname(self.git_dir)
133+
self.git_dir=curpath
134+
self._working_tree_dir=os.path.dirname(self.git_dir)
134135
break
135136

136-
gitpath=find_git_dir(osp.join(curpath, '.git'))
137-
ifgitpathisnotNone:
138-
self.git_dir=osp.normpath(gitpath)
137+
sm_gitpath=find_submodule_git_dir(osp.join(curpath, '.git'))
138+
ifsm_gitpathisnotNone:
139+
self.git_dir=osp.normpath(sm_gitpath)
140+
sm_gitpath=find_submodule_git_dir(osp.join(curpath, '.git'))
141+
ifsm_gitpathisnotNone:
142+
self.git_dir=_expand_path(sm_gitpath)
139143
self._working_tree_dir=curpath
140144
break
141145

142146
ifnotsearch_parent_directories:
143147
break
144-
curpath, dummy=osp.split(curpath)
145-
ifnotdummy:
148+
curpath, tail=osp.split(curpath)
149+
ifnottail:
146150
break
147151
# END while curpath
148152

‎git/repo/fun.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
fromgit.cmdimportGit
1717

1818

19-
__all__= ('rev_parse', 'is_git_dir', 'touch', 'find_git_dir', 'name_to_object', 'short_to_long', 'deref_tag',
19+
__all__= ('rev_parse', 'is_git_dir', 'touch', 'find_submodule_git_dir', 'name_to_object', 'short_to_long', 'deref_tag',
2020
'to_commit')
2121

2222

@@ -47,7 +47,8 @@ def is_git_dir(d):
4747
returnFalse
4848

4949

50-
deffind_git_dir(d):
50+
deffind_submodule_git_dir(d):
51+
"""Search for a submodule repo."""
5152
ifis_git_dir(d):
5253
returnd
5354

@@ -60,12 +61,13 @@ def find_git_dir(d):
6061
else:
6162
ifcontent.startswith('gitdir: '):
6263
path=content[8:]
64+
6365
ifGit.is_cygwin():
6466
## Cygwin creates submodules prefixed with `/cygdrive/...` suffixes.
6567
path=decygpath(path)
6668
ifnotosp.isabs(path):
6769
path=osp.join(osp.dirname(d), path)
68-
returnfind_git_dir(path)
70+
returnfind_submodule_git_dir(path)
6971
# end handle exception
7072
returnNone
7173

‎git/test/test_git.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,20 @@ def test_options_are_passed_to_git(self):
162162
git_command_version=self.git.version()
163163
self.assertEquals(git_version, git_command_version)
164164

165+
deftest_persistent_options(self):
166+
git_command_version=self.git.version()
167+
# analog to test_options_are_passed_to_git
168+
self.git.set_persistent_git_options(version=True)
169+
git_version=self.git.NoOp()
170+
self.assertEquals(git_version, git_command_version)
171+
# subsequent calls keep this option:
172+
git_version_2=self.git.NoOp()
173+
self.assertEquals(git_version_2, git_command_version)
174+
175+
# reset to empty:
176+
self.git.set_persistent_git_options()
177+
self.assertRaises(GitCommandError, self.git.NoOp)
178+
165179
deftest_single_char_git_options_are_passed_to_git(self):
166180
input_value='TestValue'
167181
output_value=self.git(c='user.name=%s'%input_value).config('--get', 'user.name')

‎git/test/test_submodule.py‎

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,24 @@
77

88
importgit
99
fromgit.cmdimportGit
10-
fromgit.compatimport (
11-
string_types,
12-
is_win,
13-
)
10+
fromgit.compatimportstring_types, is_win
1411
fromgit.excimport (
1512
InvalidGitRepositoryError,
1613
RepositoryDirtyError
1714
)
1815
fromgit.objects.submodule.baseimportSubmodule
19-
fromgit.objects.submodule.rootimport (
20-
RootModule,
21-
RootUpdateProgress,
22-
)
16+
fromgit.objects.submodule.rootimportRootModule, RootUpdateProgress
2317
fromgit.repo.funimport (
24-
find_git_dir,
25-
touch,
18+
find_submodule_git_dir,
19+
touch
2620
)
2721
fromgit.test.libimport (
2822
TestBase,
29-
with_rw_repo,
23+
with_rw_repo
3024
)
3125
fromgit.test.libimportwith_rw_directory
32-
fromgit.utilimport (
33-
to_native_path_linux,
34-
join_path_native,
35-
HIDE_WINDOWS_KNOWN_ERRORS,
36-
)
37-
26+
fromgit.utilimportHIDE_WINDOWS_KNOWN_ERRORS
27+
fromgit.utilimportto_native_path_linux, join_path_native
3828
importos.pathasosp
3929

4030

@@ -775,7 +765,7 @@ def assert_exists(sm, value=True):
775765
else:
776766
assertosp.isfile(module_repo_path)
777767
assertsm.module().has_separate_working_tree()
778-
assertfind_git_dir(module_repo_path) isnotNone, "module pointed to by .git file must be valid"
768+
assertfind_submodule_git_dir(module_repo_path) isnotNone, "module pointed to by .git file must be valid"
779769
# end verify submodule 'style'
780770

781771
# test move

0 commit comments

Comments
(0)