Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f3c7760

Browse files
committed
Added isolated kwarg where I think it was relevant
1 parent f7cff58 commit f3c7760

File tree

6 files changed

+55
-32
lines changed

6 files changed

+55
-32
lines changed

git/cmd.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class Git(LazyMixin):
167167
Set its value to 'full' to see details about the returned values.
168168
"""
169169
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
170-
"_git_options", "_persistent_git_options", "_environment")
170+
"_git_options", "_persistent_git_options", "_environment", "isolated")
171171

172172
_excluded_ = ('cat_file_all', 'cat_file_header', '_version_info')
173173

@@ -522,7 +522,7 @@ def __del__(self):
522522
self._stream.read(bytes_left + 1)
523523
# END handle incomplete read
524524

525-
def __init__(self, working_dir=None):
525+
def __init__(self, working_dir=None, isolated=False):
526526
"""Initialize this instance with:
527527
528528
:param working_dir:
@@ -537,6 +537,7 @@ def __init__(self, working_dir=None):
537537

538538
# Extra environment variables to pass to git commands
539539
self._environment = {}
540+
self.isolated = isolated
540541

541542
# cached command slots
542543
self.cat_file_header = None
@@ -696,7 +697,7 @@ def execute(self, command,
696697

697698
# Start the process
698699
inline_env = env
699-
env = os.environ.copy()
700+
env = {} if self.isolated else os.environ.copy()
700701
# Attempt to force all output to plain ascii english, which is what some parsing code
701702
# may expect.
702703
# According to stackoverflow (http://goo.gl/l74GC8), we are setting LANGUAGE as well

git/index/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -945,18 +945,18 @@ def commit(self, message, parent_commits=None, head=True, author=None,
945945
or `--no-verify` on the command line.
946946
:return: Commit object representing the new commit"""
947947
if not skip_hooks:
948-
run_commit_hook('pre-commit', self)
948+
run_commit_hook('pre-commit', self, isolated=self.repo.isolated)
949949

950950
self._write_commit_editmsg(message)
951-
run_commit_hook('commit-msg', self, self._commit_editmsg_filepath())
951+
run_commit_hook('commit-msg', self, self._commit_editmsg_filepath(), isolated=self.repo.isolated)
952952
message = self._read_commit_editmsg()
953953
self._remove_commit_editmsg()
954954
tree = self.write_tree()
955955
rval = Commit.create_from_tree(self.repo, tree, message, parent_commits,
956956
head, author=author, committer=committer,
957957
author_date=author_date, commit_date=commit_date)
958958
if not skip_hooks:
959-
run_commit_hook('post-commit', self)
959+
run_commit_hook('post-commit', self, isolated=self.repo.isolated)
960960
return rval
961961

962962
def _write_commit_editmsg(self, message):

git/index/fun.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,18 @@ def hook_path(name, git_dir):
6262
return osp.join(git_dir, 'hooks', name)
6363

6464

65-
def run_commit_hook(name, index, *args):
65+
def run_commit_hook(name, index, *args, isolated=False):
6666
"""Run the commit hook of the given name. Silently ignores hooks that do not exist.
6767
:param name: name of hook, like 'pre-commit'
6868
:param index: IndexFile instance
6969
:param args: arguments passed to hook file
70+
:param isolated: if true, the parent environment is not passed to the git command.
7071
:raises HookExecutionError: """
7172
hp = hook_path(name, index.repo.git_dir)
7273
if not os.access(hp, os.X_OK):
7374
return
7475

75-
env = os.environ.copy()
76+
env = {} if isolated else os.environ.copy()
7677
env['GIT_INDEX_FILE'] = safe_decode(index.path) if PY3 else safe_encode(index.path)
7778
env['GIT_EDITOR'] = ':'
7879
try:

git/objects/commit.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def _iter_from_process_or_stream(cls, repo, proc_or_stream):
279279

280280
@classmethod
281281
def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False, author=None, committer=None,
282-
author_date=None, commit_date=None):
282+
author_date=None, commit_date=None, isolated=False):
283283
"""Commit the given tree, creating a commit object.
284284
285285
:param repo: Repo object the commit should be part of
@@ -303,6 +303,7 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False,
303303
repository configuration is used to obtain this value.
304304
:param author_date: The timestamp for the author field
305305
:param commit_date: The timestamp for the committer field
306+
:param isolated: if true, the parent environment is not passed to the git command.
306307
307308
:return: Commit object representing the new commit
308309
@@ -332,10 +333,10 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False,
332333

333334
# COMMITER AND AUTHOR INFO
334335
cr = repo.config_reader()
335-
env = os.environ
336+
env = {} if isolated else os.environ
336337

337-
committer = committer or Actor.committer(cr)
338-
author = author or Actor.author(cr)
338+
committer = committer or Actor.committer(cr, isolated=isolated)
339+
author = author or Actor.author(cr, isolated=isolated)
339340

340341
# PARSE THE DATES
341342
unix_time = int(time())

git/repo/base.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class Repo(object):
7272
_working_tree_dir = None
7373
git_dir = None
7474
_common_dir = None
75+
isolated = False
7576

7677
# precompiled regex
7778
re_whitespace = re.compile(r'\s+')
@@ -89,7 +90,8 @@ class Repo(object):
8990
# Subclasses may easily bring in their own custom types by placing a constructor or type here
9091
GitCommandWrapperType = Git
9192

92-
def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=False, expand_vars=True):
93+
def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=False, expand_vars=True,
94+
isolated=False):
9395
"""Create a new Repo instance
9496
9597
:param path:
@@ -113,11 +115,21 @@ def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=Fal
113115
114116
Please note that this was the default behaviour in older versions of GitPython,
115117
which is considered a bug though.
118+
:param isolated:
119+
If True, the current environment variables will be isolated from git as much as possible.
120+
Specifically the GIT_* variables are ignored as much as possible.
121+
116122
:raise InvalidGitRepositoryError:
117123
:raise NoSuchPathError:
118124
:return: git.Repo """
119125

120-
epath = path or os.getenv('GIT_DIR')
126+
self.isolated = isolated
127+
128+
if isolated:
129+
if path is None:
130+
raise ValueError('When isolated, the repo path must be specified.')
131+
132+
epath = path or os.environ.get('GIT_DIR')
121133
if not epath:
122134
epath = os.getcwd()
123135
if Git.is_cygwin():
@@ -152,12 +164,12 @@ def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=Fal
152164
# If GIT_DIR is specified but none of GIT_WORK_TREE and core.worktree is specified,
153165
# the current working directory is regarded as the top level of your working tree.
154166
self._working_tree_dir = os.path.dirname(self.git_dir)
155-
if os.environ.get('GIT_COMMON_DIR') is None:
167+
if isolated or os.environ.get('GIT_COMMON_DIR') is None:
156168
gitconf = self.config_reader("repository")
157169
if gitconf.has_option('core', 'worktree'):
158170
self._working_tree_dir = gitconf.get('core', 'worktree')
159-
if 'GIT_WORK_TREE' in os.environ:
160-
self._working_tree_dir = os.getenv('GIT_WORK_TREE')
171+
if not isolated and 'GIT_WORK_TREE' in os.environ:
172+
self._working_tree_dir = os.environ.get('GIT_WORK_TREE')
161173
break
162174

163175
dotgit = osp.join(curpath, '.git')
@@ -204,7 +216,7 @@ def __init__(self, path=None, odbt=GitCmdObjectDB, search_parent_directories=Fal
204216
# END working dir handling
205217

206218
self.working_dir = self._working_tree_dir or self.common_dir
207-
self.git = self.GitCommandWrapperType(self.working_dir)
219+
self.git = self.GitCommandWrapperType(self.working_dir, isolated=self.isolated)
208220

209221
# special handling, in special times
210222
args = [osp.join(self.common_dir, 'objects')]
@@ -892,7 +904,7 @@ def blame(self, rev, file, incremental=False, **kwargs):
892904
return blames
893905

894906
@classmethod
895-
def init(cls, path=None, mkdir=True, odbt=GitCmdObjectDB, expand_vars=True, **kwargs):
907+
def init(cls, path=None, mkdir=True, odbt=GitCmdObjectDB, expand_vars=True, isolated=False, **kwargs):
896908
"""Initialize a git repository at the given path if specified
897909
898910
:param path:
@@ -915,6 +927,10 @@ def init(cls, path=None, mkdir=True, odbt=GitCmdObjectDB, expand_vars=True, **kw
915927
can lead to information disclosure, allowing attackers to
916928
access the contents of environment variables
917929
930+
:param isolated:
931+
If True, the current environment variables will be isolated from git as much as possible.
932+
Specifically the GIT_* variables are ignored as much as possible.
933+
918934
:param kwargs:
919935
keyword arguments serving as additional options to the git-init command
920936
@@ -925,12 +941,12 @@ def init(cls, path=None, mkdir=True, odbt=GitCmdObjectDB, expand_vars=True, **kw
925941
os.makedirs(path, 0o755)
926942

927943
# git command automatically chdir into the directory
928-
git = Git(path)
944+
git = Git(path, isolated=isolated)
929945
git.init(**kwargs)
930946
return cls(path, odbt=odbt)
931947

932948
@classmethod
933-
def _clone(cls, git, url, path, odb_default_type, progress, multi_options=None, **kwargs):
949+
def _clone(cls, git, url, path, odb_default_type, progress, multi_options=None, isolated=False, **kwargs):
934950
if progress is not None:
935951
progress = to_progress_instance(progress)
936952

@@ -969,7 +985,7 @@ def _clone(cls, git, url, path, odb_default_type, progress, multi_options=None,
969985
if not osp.isabs(path) and git.working_dir:
970986
path = osp.join(git._working_dir, path)
971987

972-
repo = cls(path, odbt=odbt)
988+
repo = cls(path, odbt=odbt, isolated=isolated)
973989

974990
# retain env values that were passed to _clone()
975991
repo.git.update_environment(**git.environment())
@@ -985,7 +1001,7 @@ def _clone(cls, git, url, path, odb_default_type, progress, multi_options=None,
9851001
# END handle remote repo
9861002
return repo
9871003

988-
def clone(self, path, progress=None, multi_options=None, **kwargs):
1004+
def clone(self, path, progress=None, multi_options=None, isolated=False, **kwargs):
9891005
"""Create a clone from this repository.
9901006
9911007
:param path: is the full path of the new repo (traditionally ends with ./<name>.git).
@@ -1000,10 +1016,10 @@ def clone(self, path, progress=None, multi_options=None, **kwargs):
10001016
* All remaining keyword arguments are given to the git-clone command
10011017
10021018
:return: ``git.Repo`` (the newly cloned repo)"""
1003-
return self._clone(self.git, self.common_dir, path, type(self.odb), progress, multi_options, **kwargs)
1019+
return self._clone(self.git, self.common_dir, path, type(self.odb), progress, multi_options, isolated, **kwargs)
10041020

10051021
@classmethod
1006-
def clone_from(cls, url, to_path, progress=None, env=None, multi_options=None, **kwargs):
1022+
def clone_from(cls, url, to_path, progress=None, env=None, multi_options=None, isolated=False, **kwargs):
10071023
"""Create a clone from the given URL
10081024
10091025
:param url: valid git url, see http://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS
@@ -1017,11 +1033,12 @@ def clone_from(cls, url, to_path, progress=None, env=None, multi_options=None, *
10171033
as its value.
10181034
:param multi_options: See ``clone`` method
10191035
:param kwargs: see the ``clone`` method
1036+
:param isolated: see the ``clone`` method
10201037
:return: Repo instance pointing to the cloned directory"""
1021-
git = Git(os.getcwd())
1038+
git = Git(os.getcwd(), isolated=isolated)
10221039
if env is not None:
10231040
git.update_environment(**env)
1024-
return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, **kwargs)
1041+
return cls._clone(git, url, to_path, GitCmdObjectDB, progress, multi_options, isolated, **kwargs)
10251042

10261043
def archive(self, ostream, treeish=None, prefix=None, **kwargs):
10271044
"""Archive the tree at the given revision.

git/util.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -583,19 +583,22 @@ def _from_string(cls, string):
583583
# END handle name/email matching
584584

585585
@classmethod
586-
def _main_actor(cls, env_name, env_email, config_reader=None):
586+
def _main_actor(cls, env_name, env_email, config_reader=None, isolated=False):
587587
actor = Actor('', '')
588588
default_email = get_user_id()
589589
default_name = default_email.split('@')[0]
590590

591591
for attr, evar, cvar, default in (('name', env_name, cls.conf_name, default_name),
592592
('email', env_email, cls.conf_email, default_email)):
593593
try:
594+
if isolated:
595+
raise KeyError("Isolated. No env access.")
594596
val = os.environ[evar]
595597
if not PY3:
596598
val = val.decode(defenc)
597599
# end assure we don't get 'invalid strings'
598600
setattr(actor, attr, val)
601+
continue
599602
except KeyError:
600603
if config_reader is not None:
601604
setattr(actor, attr, config_reader.get_value('user', cvar, default))
@@ -607,21 +610,21 @@ def _main_actor(cls, env_name, env_email, config_reader=None):
607610
return actor
608611

609612
@classmethod
610-
def committer(cls, config_reader=None):
613+
def committer(cls, config_reader=None, isolated=False):
611614
"""
612615
:return: Actor instance corresponding to the configured committer. It behaves
613616
similar to the git implementation, such that the environment will override
614617
configuration values of config_reader. If no value is set at all, it will be
615618
generated
616619
:param config_reader: ConfigReader to use to retrieve the values from in case
617620
they are not set in the environment"""
618-
return cls._main_actor(cls.env_committer_name, cls.env_committer_email, config_reader)
621+
return cls._main_actor(cls.env_committer_name, cls.env_committer_email, config_reader, isolated)
619622

620623
@classmethod
621-
def author(cls, config_reader=None):
624+
def author(cls, config_reader=None, isolated=False):
622625
"""Same as committer(), but defines the main author. It may be specified in the environment,
623626
but defaults to the committer"""
624-
return cls._main_actor(cls.env_author_name, cls.env_author_email, config_reader)
627+
return cls._main_actor(cls.env_author_name, cls.env_author_email, config_reader, isolated)
625628

626629

627630
class Stats(object):

0 commit comments

Comments
 (0)