@@ -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.
0 commit comments