| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,5 +19,9 @@ Contributors are: | |||
| 19 | 19 | -Timothy B. Hartman <tbhartman _at_ gmail.com> | |
| 20 | 20 | -Konstantin Popov <konstantin.popov.89 _at_ yandex.ru> | |
| 21 | 21 | -Peter Jones <pjones _at_ redhat.com> | |
| 22 | + -Anson Mansfield <anson.mansfield _at_ gmail.com> | ||
| 23 | + -Ken Odegard <ken.odegard _at_ gmail.com> | ||
| 24 | + -Alexis Horgix Chotard | ||
| 25 | + -Piotr Babij <piotr.babij _at_ gmail.com> | ||
| 22 | 26 | ||
| 23 | 27 | Portions derived from other open source works and are clearly marked. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,5 +14,5 @@ release: clean | |||
| 14 | 14 | ||
| 15 | 15 | force_release: clean | |
| 16 | 16 | git push --tags | |
| 17 | - python setup.py sdist bdist_wheel | ||
| 17 | + python3 setup.py sdist bdist_wheel | ||
| 18 | 18 | twine upload -s -i byronimo@gmail.com dist/* | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1 +1 @@ | |||
| 1 | - 2.1.5 | ||
| 1 | + 2.1.6 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -35,25 +35,49 @@ def _init_externals(): | |||
| 35 | 35 | ||
| 36 | 36 | #{ Imports | |
| 37 | 37 | ||
| 38 | - from git.config import GitConfigParser # @NoMove @IgnorePep8 | ||
| 39 | - from git.objects import * # @NoMove @IgnorePep8 | ||
| 40 | - from git.refs import * # @NoMove @IgnorePep8 | ||
| 41 | - from git.diff import * # @NoMove @IgnorePep8 | ||
| 42 | - from git.exc import * # @NoMove @IgnorePep8 | ||
| 43 | - from git.db import * # @NoMove @IgnorePep8 | ||
| 44 | - from git.cmd import Git # @NoMove @IgnorePep8 | ||
| 45 | - from git.repo import Repo # @NoMove @IgnorePep8 | ||
| 46 | - from git.remote import * # @NoMove @IgnorePep8 | ||
| 47 | - from git.index import * # @NoMove @IgnorePep8 | ||
| 48 | - from git.util import ( # @NoMove @IgnorePep8 | ||
| 49 | - LockFile, | ||
| 50 | - BlockingLockFile, | ||
| 51 | - Stats, | ||
| 52 | - Actor, | ||
| 53 | - rmtree, | ||
| 54 | - ) | ||
| 38 | + from git.exc import * # @NoMove @IgnorePep8 | ||
| 39 | + try: | ||
| 40 | + from git.config import GitConfigParser # @NoMove @IgnorePep8 | ||
| 41 | + from git.objects import * # @NoMove @IgnorePep8 | ||
| 42 | + from git.refs import * # @NoMove @IgnorePep8 | ||
| 43 | + from git.diff import * # @NoMove @IgnorePep8 | ||
| 44 | + from git.db import * # @NoMove @IgnorePep8 | ||
| 45 | + from git.cmd import Git # @NoMove @IgnorePep8 | ||
| 46 | + from git.repo import Repo # @NoMove @IgnorePep8 | ||
| 47 | + from git.remote import * # @NoMove @IgnorePep8 | ||
| 48 | + from git.index import * # @NoMove @IgnorePep8 | ||
| 49 | + from git.util import ( # @NoMove @IgnorePep8 | ||
| 50 | + LockFile, | ||
| 51 | + BlockingLockFile, | ||
| 52 | + Stats, | ||
| 53 | + Actor, | ||
| 54 | + rmtree, | ||
| 55 | + ) | ||
| 56 | + except GitError as exc: | ||
| 57 | + raise ImportError('%s: %s' % (exc.__class__.__name__, exc)) | ||
| 55 | 58 | ||
| 56 | 59 | #} END imports | |
| 57 | 60 | ||
| 58 | 61 | __all__ = [name for name, obj in locals().items() | |
| 59 | 62 | if not (name.startswith('_') or inspect.ismodule(obj))] | |
| 63 | + | ||
| 64 | + | ||
| 65 | + #{ Initialize git executable path | ||
| 66 | + GIT_OK = None | ||
| 67 | + | ||
| 68 | + def refresh(path=None): | ||
| 69 | + """Convenience method for setting the git executable path.""" | ||
| 70 | + global GIT_OK | ||
| 71 | + GIT_OK = False | ||
| 72 | + | ||
| 73 | + if not Git.refresh(path=path): | ||
| 74 | + return | ||
| 75 | + if not FetchInfo.refresh(): | ||
| 76 | + return | ||
| 77 | + | ||
| 78 | + GIT_OK = True | ||
| 79 | + #} END initialize git executable path | ||
| 80 | + | ||
| 81 | + ################# | ||
| 82 | + refresh() | ||
| 83 | + ################# | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,6 +17,7 @@ | |||
| 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, | |
@@ -31,7 +32,7 @@ | |||
| 31 | 32 | ) | |
| 32 | 33 | from git.exc import CommandError | |
| 33 | 34 | from git.odict import OrderedDict | |
| 34 | - from git.util import is_cygwin_git, cygpath | ||
| 35 | + from git.util import is_cygwin_git, cygpath, expand_path | ||
| 35 | 36 | ||
| 36 | 37 | from .exc import ( | |
| 37 | 38 | GitCommandError, | |
@@ -46,7 +47,7 @@ | |||
| 46 | 47 | execute_kwargs = set(('istream', 'with_extended_output', | |
| 47 | 48 | 'with_exceptions', 'as_process', 'stdout_as_string', | |
| 48 | 49 | 'output_stream', 'with_stdout', 'kill_after_timeout', | |
| 49 | - 'universal_newlines', 'shell')) | ||
| 50 | + 'universal_newlines', 'shell', 'env')) | ||
| 50 | 51 | ||
| 51 | 52 | log = logging.getLogger(__name__) | |
| 52 | 53 | log.addHandler(logging.NullHandler()) | |
@@ -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) | |
@@ -405,7 +531,7 @@ def __init__(self, working_dir=None): | |||
| 405 | 531 | It is meant to be the working tree directory if available, or the | |
| 406 | 532 | .git directory in case of bare repositories.""" | |
| 407 | 533 | super(Git, self).__init__() | |
| 408 | - self._working_dir = working_dir | ||
| 534 | + self._working_dir = expand_path(working_dir) | ||
| 409 | 535 | self._git_options = () | |
| 410 | 536 | self._persistent_git_options = [] | |
| 411 | 537 | ||
@@ -471,6 +597,7 @@ def execute(self, command, | |||
| 471 | 597 | with_stdout=True, | |
| 472 | 598 | universal_newlines=False, | |
| 473 | 599 | shell=None, | |
| 600 | + env=None, | ||
| 474 | 601 | **subprocess_kwargs | |
| 475 | 602 | ): | |
| 476 | 603 | """Handles executing the command on the shell and consumes and returns | |
@@ -514,6 +641,9 @@ def execute(self, command, | |||
| 514 | 641 | decoded into a string using the default encoding (usually utf-8). | |
| 515 | 642 | The latter can fail, if the output contains binary data. | |
| 516 | 643 | ||
| 644 | + :param env: | ||
| 645 | + A dictionary of environment variables to be passed to `subprocess.Popen`. | ||
| 646 | + | ||
| 517 | 647 | :param subprocess_kwargs: | |
| 518 | 648 | Keyword arguments to be passed to subprocess.Popen. Please note that | |
| 519 | 649 | some of the valid kwargs are already set by this method, the ones you | |
@@ -559,6 +689,7 @@ def execute(self, command, | |||
| 559 | 689 | cwd = self._working_dir or os.getcwd() | |
| 560 | 690 | ||
| 561 | 691 | # Start the process | |
| 692 | + inline_env = env | ||
| 562 | 693 | env = os.environ.copy() | |
| 563 | 694 | # Attempt to force all output to plain ascii english, which is what some parsing code | |
| 564 | 695 | # may expect. | |
@@ -567,6 +698,8 @@ def execute(self, command, | |||
| 567 | 698 | env["LANGUAGE"] = "C" | |
| 568 | 699 | env["LC_ALL"] = "C" | |
| 569 | 700 | env.update(self._environment) | |
| 701 | + if inline_env is not None: | ||
| 702 | + env.update(inline_env) | ||
| 570 | 703 | ||
| 571 | 704 | if is_win: | |
| 572 | 705 | cmd_not_found_exception = OSError | |
@@ -828,13 +961,13 @@ def _call_process(self, method, *args, **kwargs): | |||
| 828 | 961 | - "command options" to be converted by :meth:`transform_kwargs()`; | |
| 829 | 962 | - the `'insert_kwargs_after'` key which its value must match one of ``*args``, | |
| 830 | 963 | and any cmd-options will be appended after the matched arg. | |
| 831 | - | ||
| 964 | + | ||
| 832 | 965 | Examples:: | |
| 833 | - | ||
| 966 | + | ||
| 834 | 967 | git.rev_list('master', max_count=10, header=True) | |
| 835 | - | ||
| 968 | + | ||
| 836 | 969 | turns into:: | |
| 837 | - | ||
| 970 | + | ||
| 838 | 971 | git rev-list max-count 10 --header master | |
| 839 | 972 | ||
| 840 | 973 | :return: Same as ``execute``""" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -123,12 +123,12 @@ def _set_cache_(self, attr): | |||
| 123 | 123 | reader = self.config_reader() | |
| 124 | 124 | # default submodule values | |
| 125 | 125 | try: | |
| 126 | - self.path = reader.get_value('path') | ||
| 126 | + self.path = reader.get('path') | ||
| 127 | 127 | except cp.NoSectionError: | |
| 128 | 128 | raise ValueError("This submodule instance does not exist anymore in '%s' file" | |
| 129 | 129 | % osp.join(self.repo.working_tree_dir, '.gitmodules')) | |
| 130 | 130 | # end | |
| 131 | - self._url = reader.get_value('url') | ||
| 131 | + self._url = reader.get('url') | ||
| 132 | 132 | # git-python extension values - optional | |
| 133 | 133 | self._branch_path = reader.get_value(self.k_head_option, git.Head.to_full_path(self.k_head_default)) | |
| 134 | 134 | elif attr == '_name': | |
@@ -358,7 +358,9 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False): | |||
| 358 | 358 | if sm.exists(): | |
| 359 | 359 | # reretrieve submodule from tree | |
| 360 | 360 | try: | |
| 361 | - return repo.head.commit.tree[path] | ||
| 361 | + sm = repo.head.commit.tree[path] | ||
| 362 | + sm._name = name | ||
| 363 | + return sm | ||
| 362 | 364 | except KeyError: | |
| 363 | 365 | # could only be in index | |
| 364 | 366 | index = repo.index | |
@@ -1168,11 +1170,11 @@ def iter_items(cls, repo, parent_commit='HEAD'): | |||
| 1168 | 1170 | ||
| 1169 | 1171 | for sms in parser.sections(): | |
| 1170 | 1172 | n = sm_name(sms) | |
| 1171 | - p = parser.get_value(sms, 'path') | ||
| 1172 | - u = parser.get_value(sms, 'url') | ||
| 1173 | + p = parser.get(sms, 'path') | ||
| 1174 | + u = parser.get(sms, 'url') | ||
| 1173 | 1175 | b = cls.k_head_default | |
| 1174 | 1176 | if parser.has_option(sms, cls.k_head_option): | |
| 1175 | - b = str(parser.get_value(sms, cls.k_head_option)) | ||
| 1177 | + b = str(parser.get(sms, cls.k_head_option)) | ||
| 1176 | 1178 | # END handle optional information | |
| 1177 | 1179 | ||
| 1178 | 1180 | # get the binsha | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,6 +36,10 @@ def delete(cls, repo, *refs, **kwargs): | |||
| 36 | 36 | # are generally ignored in the refs/ folder. We don't though | |
| 37 | 37 | # and delete remainders manually | |
| 38 | 38 | for ref in refs: | |
| 39 | + try: | ||
| 40 | + os.remove(osp.join(repo.common_dir, ref.path)) | ||
| 41 | + except OSError: | ||
| 42 | + pass | ||
| 39 | 43 | try: | |
| 40 | 44 | os.remove(osp.join(repo.git_dir, ref.path)) | |
| 41 | 45 | except OSError: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments