|
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