| 
17 | 17 | import subprocess  | 
18 | 18 | import sys  | 
19 | 19 | import threading  | 
 | 20 | +from textwrap import dedent  | 
20 | 21 | 
 
  | 
21 | 22 | from git.compat import (  | 
22 | 23 |     string_types,  | 
@@ -182,16 +183,141 @@ def __setstate__(self, d):  | 
182 | 183 |     # Enables debugging of GitPython's git commands  | 
183 | 184 |     GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False)  | 
184 | 185 | 
 
  | 
185 |  | -    # Provide the full path to the git executable. Otherwise it assumes git is in the path  | 
186 |  | -    _git_exec_env_var = "GIT_PYTHON_GIT_EXECUTABLE"  | 
187 |  | -    GIT_PYTHON_GIT_EXECUTABLE = os.environ.get(_git_exec_env_var, git_exec_name)  | 
188 |  | - | 
189 | 186 |     # If True, a shell will be used when executing git commands.  | 
190 | 187 |     # This should only be desirable on Windows, see https://github.com/gitpython-developers/GitPython/pull/126  | 
191 | 188 |     # and check `git/test_repo.py:TestRepo.test_untracked_files()` TC for an example where it is required.  | 
192 | 189 |     # Override this value using `Git.USE_SHELL = True`  | 
193 | 190 |     USE_SHELL = False  | 
194 | 191 | 
 
  | 
 | 192 | +    # Provide the full path to the git executable. Otherwise it assumes git is in the path  | 
 | 193 | +    _git_exec_env_var = "GIT_PYTHON_GIT_EXECUTABLE"  | 
 | 194 | +    _refresh_env_var = "GIT_PYTHON_REFRESH"  | 
 | 195 | +    GIT_PYTHON_GIT_EXECUTABLE = None  | 
 | 196 | +    # note that the git executable is actually found during the refresh step in  | 
 | 197 | +    # the top level __init__  | 
 | 198 | + | 
 | 199 | +    @classmethod  | 
 | 200 | +    def refresh(cls, path=None):  | 
 | 201 | +        """This gets called by the refresh function (see the top level  | 
 | 202 | +        __init__).  | 
 | 203 | +        """  | 
 | 204 | +        # discern which path to refresh with  | 
 | 205 | +        if path is not None:  | 
 | 206 | +            new_git = os.path.expanduser(path)  | 
 | 207 | +            new_git = os.path.abspath(new_git)  | 
 | 208 | +        else:  | 
 | 209 | +            new_git = os.environ.get(cls._git_exec_env_var, cls.git_exec_name)  | 
 | 210 | + | 
 | 211 | +        # keep track of the old and new git executable path  | 
 | 212 | +        old_git = cls.GIT_PYTHON_GIT_EXECUTABLE  | 
 | 213 | +        cls.GIT_PYTHON_GIT_EXECUTABLE = new_git  | 
 | 214 | + | 
 | 215 | +        # test if the new git executable path is valid  | 
 | 216 | + | 
 | 217 | +        if sys.version_info < (3,):  | 
 | 218 | +            # - a GitCommandNotFound error is spawned by ourselves  | 
 | 219 | +            # - a OSError is spawned if the git executable provided  | 
 | 220 | +            #   cannot be executed for whatever reason  | 
 | 221 | +            exceptions = (GitCommandNotFound, OSError)  | 
 | 222 | +        else:  | 
 | 223 | +            # - a GitCommandNotFound error is spawned by ourselves  | 
 | 224 | +            # - a PermissionError is spawned if the git executable provided  | 
 | 225 | +            #   cannot be executed for whatever reason  | 
 | 226 | +            exceptions = (GitCommandNotFound, PermissionError)  | 
 | 227 | + | 
 | 228 | +        has_git = False  | 
 | 229 | +        try:  | 
 | 230 | +            cls().version()  | 
 | 231 | +            has_git = True  | 
 | 232 | +        except exceptions:  | 
 | 233 | +            pass  | 
 | 234 | + | 
 | 235 | +        # warn or raise exception if test failed  | 
 | 236 | +        if not has_git:  | 
 | 237 | +            err = dedent("""\  | 
 | 238 | +                Bad git executable.  | 
 | 239 | +                The git executable must be specified in one of the following ways:  | 
 | 240 | +                    - be included in your $PATH  | 
 | 241 | +                    - be set via $%s  | 
 | 242 | +                    - explicitly set via git.refresh()  | 
 | 243 | +                """) % cls._git_exec_env_var  | 
 | 244 | + | 
 | 245 | +            # revert to whatever the old_git was  | 
 | 246 | +            cls.GIT_PYTHON_GIT_EXECUTABLE = old_git  | 
 | 247 | + | 
 | 248 | +            if old_git is None:  | 
 | 249 | +                # on the first refresh (when GIT_PYTHON_GIT_EXECUTABLE is  | 
 | 250 | +                # None) we only are quiet, warn, or error depending on the  | 
 | 251 | +                # GIT_PYTHON_REFRESH value  | 
 | 252 | + | 
 | 253 | +                # determine what the user wants to happen during the initial  | 
 | 254 | +                # refresh we expect GIT_PYTHON_REFRESH to either be unset or  | 
 | 255 | +                # be one of the following values:  | 
 | 256 | +                #   0|q|quiet|s|silence  | 
 | 257 | +                #   1|w|warn|warning  | 
 | 258 | +                #   2|r|raise|e|error  | 
 | 259 | + | 
 | 260 | +                mode = os.environ.get(cls._refresh_env_var, "raise").lower()  | 
 | 261 | + | 
 | 262 | +                quiet = ["quiet", "q", "silence", "s", "none", "n", "0"]  | 
 | 263 | +                warn = ["warn", "w", "warning", "1"]  | 
 | 264 | +                error = ["error", "e", "raise", "r", "2"]  | 
 | 265 | + | 
 | 266 | +                if mode in quiet:  | 
 | 267 | +                    pass  | 
 | 268 | +                elif mode in warn or mode in error:  | 
 | 269 | +                    err = dedent("""\  | 
 | 270 | +                        %s  | 
 | 271 | +                        All git commands will error until this is rectified.  | 
 | 272 | +
  | 
 | 273 | +                        This initial warning can be silenced or aggravated in the future by setting the  | 
 | 274 | +                        $%s environment variable. Use one of the following values:  | 
 | 275 | +                            - %s: for no warning or exception  | 
 | 276 | +                            - %s: for a printed warning  | 
 | 277 | +                            - %s: for a raised exception  | 
 | 278 | +
  | 
 | 279 | +                        Example:  | 
 | 280 | +                            export %s=%s  | 
 | 281 | +                        """) % (  | 
 | 282 | +                        err,  | 
 | 283 | +                        cls._refresh_env_var,  | 
 | 284 | +                        "|".join(quiet),  | 
 | 285 | +                        "|".join(warn),  | 
 | 286 | +                        "|".join(error),  | 
 | 287 | +                        cls._refresh_env_var,  | 
 | 288 | +                        quiet[0])  | 
 | 289 | + | 
 | 290 | +                    if mode in warn:  | 
 | 291 | +                        print("WARNING: %s" % err)  | 
 | 292 | +                    else:  | 
 | 293 | +                        raise ImportError(err)  | 
 | 294 | +                else:  | 
 | 295 | +                    err = dedent("""\  | 
 | 296 | +                        %s environment variable has been set but it has been set with an invalid value.  | 
 | 297 | +
  | 
 | 298 | +                        Use only the following values:  | 
 | 299 | +                            - %s: for no warning or exception  | 
 | 300 | +                            - %s: for a printed warning  | 
 | 301 | +                            - %s: for a raised exception  | 
 | 302 | +                        """) % (  | 
 | 303 | +                        cls._refresh_env_var,  | 
 | 304 | +                        "|".join(quiet),  | 
 | 305 | +                        "|".join(warn),  | 
 | 306 | +                        "|".join(error))  | 
 | 307 | +                    raise ImportError(err)  | 
 | 308 | + | 
 | 309 | +                # we get here if this was the init refresh and the refresh mode  | 
 | 310 | +                # was not error, go ahead and set the GIT_PYTHON_GIT_EXECUTABLE  | 
 | 311 | +                # such that we discern the difference between a first import  | 
 | 312 | +                # and a second import  | 
 | 313 | +                cls.GIT_PYTHON_GIT_EXECUTABLE = cls.git_exec_name  | 
 | 314 | +            else:  | 
 | 315 | +                # after the first refresh (when GIT_PYTHON_GIT_EXECUTABLE  | 
 | 316 | +                # is no longer None) we raise an exception  | 
 | 317 | +                raise GitCommandNotFound("git", err)  | 
 | 318 | + | 
 | 319 | +        return has_git  | 
 | 320 | + | 
195 | 321 |     @classmethod  | 
196 | 322 |     def is_cygwin(cls):  | 
197 | 323 |         return is_cygwin_git(cls.GIT_PYTHON_GIT_EXECUTABLE)  | 
@@ -828,13 +954,13 @@ def _call_process(self, method, *args, **kwargs):  | 
828 | 954 |             - "command options" to be converted by :meth:`transform_kwargs()`;  | 
829 | 955 |             - the `'insert_kwargs_after'` key which its value must match one of ``*args``,  | 
830 | 956 |               and any cmd-options will be appended after the matched arg.  | 
831 |  | -          | 
 | 957 | +
  | 
832 | 958 |         Examples::  | 
833 |  | -          | 
 | 959 | +
  | 
834 | 960 |             git.rev_list('master', max_count=10, header=True)  | 
835 |  | -          | 
 | 961 | +
  | 
836 | 962 |         turns into::  | 
837 |  | -          | 
 | 963 | +
  | 
838 | 964 |            git rev-list max-count 10 --header master  | 
839 | 965 | 
  | 
840 | 966 |         :return: Same as ``execute``"""  | 
 | 
0 commit comments