| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ccc4811 commit 447c8bf
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -361,6 +361,21 @@ def _module_abspath( | |||
| 361 | 361 | ) | |
| 362 | 362 | raise NotADirectoryError() | |
| 363 | 363 | ||
| 364 | + @classmethod | ||
| 365 | + def _transport_env(cls, allow_unsafe_protocols: bool = False) -> Dict[str, str]: | ||
| 366 | + """ | ||
| 367 | + :return: | ||
| 368 | + Environment for clones and fetches whose URL comes from ``.gitmodules``. | ||
| 369 | + | ||
| 370 | + :manpage:`git-submodule(1)` runs those with ``GIT_PROTOCOL_FROM_USER=0``, so | ||
| 371 | + that git refuses every transport whose ``protocol.<name>.allow`` policy is | ||
| 372 | + ``user``, which it is for ``file`` since git 2.38.1, unless the user | ||
| 373 | + configured ``protocol.<name>.allow=always``. | ||
| 374 | + """ | ||
| 375 | + if allow_unsafe_protocols: | ||
| 376 | + return {} | ||
| 377 | + return {"GIT_PROTOCOL_FROM_USER": "0"} | ||
| 378 | + | ||
| 364 | 379 | @classmethod | |
| 365 | 380 | def _clone_repo( | |
| 366 | 381 | cls, | |
@@ -849,7 +864,10 @@ def update( | |||
| 849 | 864 | They only take effect with the `init` option. | |
| 850 | 865 | ||
| 851 | 866 | :param allow_unsafe_protocols: | |
| 852 | - Allow unsafe protocols to be used, like ``ext``. | ||
| 867 | + Allow unsafe protocols to be used, like ``ext``. This also runs the clone | ||
| 868 | + and the fetches as if their URL came from the user, so that git accepts a | ||
| 869 | + transport whose ``protocol.<name>.allow`` policy is ``user``, such as | ||
| 870 | + ``file``, without ``protocol.<name>.allow=always`` being configured. | ||
| 853 | 871 | ||
| 854 | 872 | :param allow_unsafe_options: | |
| 855 | 873 | Allow unsafe options to be used, like ``--upload-pack``. | |
@@ -900,7 +918,8 @@ def fetch_remotes(module_repo: "Repo") -> None: | |||
| 900 | 918 | ) | |
| 901 | 919 | # =============================== | |
| 902 | 920 | if not dry_run: | |
| 903 | - remote.fetch(progress=progress) | ||
| 921 | + with module_repo.git.custom_environment(**self._transport_env(allow_unsafe_protocols)): | ||
| 922 | + remote.fetch(progress=progress) | ||
| 904 | 923 | # END handle dry-run | |
| 905 | 924 | # =============================== | |
| 906 | 925 | if i == len_rmts - 1: | |
@@ -987,7 +1006,7 @@ def fetch_remotes(module_repo: "Repo") -> None: | |||
| 987 | 1006 | self.path, | |
| 988 | 1007 | self.name, | |
| 989 | 1008 | n=True, | |
| 990 | - env=env, | ||
| 1009 | + env={**self._transport_env(allow_unsafe_protocols), **(env or {})}, | ||
| 991 | 1010 | multi_options=clone_multi_options, | |
| 992 | 1011 | allow_unsafe_options=allow_unsafe_options, | |
| 993 | 1012 | allow_unsafe_protocols=allow_unsafe_protocols, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -305,7 +305,8 @@ def update( # type: ignore[override] | |||
| 305 | 305 | else: | |
| 306 | 306 | assert nn not in [r.name for r in rmts] | |
| 307 | 307 | smr = smm.create_remote(nn, sm_url) | |
| 308 | - smr.fetch(progress=progress) | ||
| 308 | + with smm.git.custom_environment(**sm._transport_env()): | ||
| 309 | + smr.fetch(progress=progress) | ||
| 309 | 310 | ||
| 310 | 311 | # If we have a tracking branch, it should be available | |
| 311 | 312 | # in the new remote as well. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,7 @@ | |||
| 10 | 10 | "with_rw_directory", | |
| 11 | 11 | "with_rw_repo", | |
| 12 | 12 | "with_rw_and_rw_remote_repo", | |
| 13 | + "patch_git_config", | ||
| 13 | 14 | "PathLikeMock", | |
| 14 | 15 | "TestBase", | |
| 15 | 16 | "VirtualEnvironment", | |
@@ -39,6 +40,7 @@ | |||
| 39 | 40 | import textwrap | |
| 40 | 41 | import time | |
| 41 | 42 | import unittest | |
| 43 | + from unittest import mock | ||
| 42 | 44 | import venv | |
| 43 | 45 | from typing import Union, Type, Tuple | |
| 44 | 46 | ||
@@ -84,6 +86,26 @@ def fixture(name): | |||
| 84 | 86 | # { Adapters | |
| 85 | 87 | ||
| 86 | 88 | ||
| 89 | + @contextlib.contextmanager | ||
| 90 | + def patch_git_config(name, value): | ||
| 91 | + """Temporarily add a git config name-value pair, using environment variables.""" | ||
| 92 | + pair_index = int(os.getenv("GIT_CONFIG_COUNT", "0")) | ||
| 93 | + | ||
| 94 | + # This is recomputed each time the context is entered, for compatibility with | ||
| 95 | + # existing GIT_CONFIG_* environment variables, even if changed in this process. | ||
| 96 | + patcher = mock.patch.dict( | ||
| 97 | + os.environ, | ||
| 98 | + { | ||
| 99 | + "GIT_CONFIG_COUNT": str(pair_index + 1), | ||
| 100 | + f"GIT_CONFIG_KEY_{pair_index}": name, | ||
| 101 | + f"GIT_CONFIG_VALUE_{pair_index}": value, | ||
| 102 | + }, | ||
| 103 | + ) | ||
| 104 | + | ||
| 105 | + with patcher: | ||
| 106 | + yield | ||
| 107 | + | ||
| 108 | + | ||
| 87 | 109 | class StringProcessAdapter: | |
| 88 | 110 | """Allows strings to be used as process objects returned by subprocess.Popen. | |
| 89 | 111 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,7 @@ | |||
| 8 | 8 | import os.path | |
| 9 | 9 | ||
| 10 | 10 | from test.lib import TestBase | |
| 11 | - from test.lib.helper import with_rw_directory, with_rw_repo | ||
| 11 | + from test.lib.helper import patch_git_config, with_rw_directory, with_rw_repo | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | class Tutorials(TestBase): | |
@@ -479,6 +479,7 @@ def test_references_and_objects(self, rw_dir): | |||
| 479 | 479 | repo.git.clear_cache() | |
| 480 | 480 | ||
| 481 | 481 | @with_rw_repo("c15a6e1923a14bc760851913858a3942a4193cdb") | |
| 482 | + @patch_git_config("protocol.file.allow", "always") | ||
| 482 | 483 | def test_submodules(self, repo): | |
| 483 | 484 | # [1-test_submodules] | |
| 484 | 485 | sms = repo.submodules | |
| Back | FazBrowse Home | New Git URL |
0 commit comments