浏览代码

Add support for GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM environment variables (#1699)

These variables allow overriding the default global and system
configuration paths.

Fixes #1193
Jelmer Vernooij 1 月之前
父节点
当前提交
aa769ead29
共有 3 个文件被更改,包括 93 次插入6 次删除
  1. 4 0
      NEWS
  2. 15 6
      dulwich/config.py
  3. 74 0
      tests/test_config.py

+ 4 - 0
NEWS

@@ -3,6 +3,10 @@
  * Add support for merge drivers.
    (Jelmer Vernooij)
 
+ * Add support for ``GIT_CONFIG_GLOBAL`` and ``GIT_CONFIG_SYSTEM``
+   environment variables to override global and system configuration
+   paths. (Jelmer Vernooij, #1193)
+
  * ``dulwich.porcelain.diff``: Support diffing two commits
    and diffing cached and working tree. (Jelmer Vernooij)
 

+ 15 - 6
dulwich/config.py

@@ -1212,13 +1212,22 @@ class StackedConfig(Config):
         See git-config(1) for details on the files searched.
         """
         paths = []
-        paths.append(os.path.expanduser("~/.gitconfig"))
-        paths.append(get_xdg_config_home_path("git", "config"))
 
-        if "GIT_CONFIG_NOSYSTEM" not in os.environ:
-            paths.append("/etc/gitconfig")
-            if sys.platform == "win32":
-                paths.extend(get_win_system_paths())
+        # Handle GIT_CONFIG_GLOBAL - overrides user config paths
+        try:
+            paths.append(os.environ["GIT_CONFIG_GLOBAL"])
+        except KeyError:
+            paths.append(os.path.expanduser("~/.gitconfig"))
+            paths.append(get_xdg_config_home_path("git", "config"))
+
+        # Handle GIT_CONFIG_SYSTEM and GIT_CONFIG_NOSYSTEM
+        try:
+            paths.append(os.environ["GIT_CONFIG_SYSTEM"])
+        except KeyError:
+            if "GIT_CONFIG_NOSYSTEM" not in os.environ:
+                paths.append("/etc/gitconfig")
+                if sys.platform == "win32":
+                    paths.extend(get_win_system_paths())
 
         backends = []
         for path in paths:

+ 74 - 0
tests/test_config.py

@@ -851,6 +851,80 @@ class StackedConfigTests(TestCase):
             paths,
         )
 
+    def test_git_config_global(self) -> None:
+        with tempfile.NamedTemporaryFile(
+            suffix=".gitconfig", delete=False
+        ) as global_config:
+            # Write test config
+            global_config.write(b"[user]\n\tname = Test User\n")
+            global_config.flush()
+            config_path = global_config.name
+
+        try:
+            self.overrideEnv("GIT_CONFIG_GLOBAL", config_path)
+            backends = StackedConfig.default_backends()
+
+            # Should have at least one backend (the global config)
+            self.assertGreater(len(backends), 0)
+
+            # Check that the custom global config is loaded
+            paths = [backend.path for backend in backends if hasattr(backend, "path")]
+            self.assertIn(
+                config_path.encode() if isinstance(paths[0], bytes) else config_path,
+                paths,
+            )
+        finally:
+            os.unlink(config_path)
+
+    def test_git_config_system(self) -> None:
+        with tempfile.NamedTemporaryFile(
+            suffix=".gitconfig", delete=False
+        ) as system_config:
+            # Write test config
+            system_config.write(b"[core]\n\tautocrlf = true\n")
+            system_config.flush()
+            config_path = system_config.name
+
+        try:
+            self.overrideEnv("GIT_CONFIG_SYSTEM", config_path)
+            self.overrideEnv("GIT_CONFIG_NOSYSTEM", None)  # Ensure it's not set
+            backends = StackedConfig.default_backends()
+
+            # Should have at least one backend (the system config)
+            self.assertGreater(len(backends), 0)
+
+            # Check that the custom system config is loaded
+            paths = [backend.path for backend in backends if hasattr(backend, "path")]
+            self.assertIn(
+                config_path.encode() if isinstance(paths[0], bytes) else config_path,
+                paths,
+            )
+        finally:
+            os.unlink(config_path)
+
+    def test_git_config_nosystem_precedence(self) -> None:
+        # GIT_CONFIG_SYSTEM should take precedence over GIT_CONFIG_NOSYSTEM
+        with tempfile.NamedTemporaryFile(
+            suffix=".gitconfig", delete=False
+        ) as system_config:
+            system_config.write(b"[core]\n\ttest = value\n")
+            system_config.flush()
+            config_path = system_config.name
+
+        try:
+            self.overrideEnv("GIT_CONFIG_SYSTEM", config_path)
+            self.overrideEnv("GIT_CONFIG_NOSYSTEM", "1")  # This should be ignored
+            backends = StackedConfig.default_backends()
+
+            # Check that the custom system config is still loaded
+            paths = [backend.path for backend in backends if hasattr(backend, "path")]
+            self.assertIn(
+                config_path.encode() if isinstance(paths[0], bytes) else config_path,
+                paths,
+            )
+        finally:
+            os.unlink(config_path)
+
 
 class EscapeValueTests(TestCase):
     def test_nothing(self) -> None: