From a0bc2b14a30bef631b91a2ca37c5254d9af44718 Mon Sep 17 00:00:00 2001 From: Insaf Latypov Date: Tue, 13 Oct 2026 16:41:12 +0000 Subject: [PATCH] git_config: Fix bugs in processing RepoConfig. - Automatically create all the parent directories for `git confing --file ...` - Prevent `RepoConfig` from inheriting caches from `GitConfig`. These two are different files. Bug: 569927750 Test: ./run_tests Change-Id: I9c60cecff75c1fb62be3ff63425d9618c0f56b06 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/643263 Reviewed-by: Mike Frysinger Tested-by: Insaf Latypov Commit-Queue: Insaf Latypov --- git_config.py | 12 ++++++++++++ tests/test_git_config.py | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/git_config.py b/git_config.py index 84d347b1a..4facccda6 100644 --- a/git_config.py +++ b/git_config.py @@ -266,6 +266,13 @@ class GitConfig: except KeyError: old = [] + if self.file != self._SYSTEM_CONFIG: + # `git config --file` does not create missing parent directories + # (e.g. ~/.repoconfig/ on first use). + parent_dir = os.path.dirname(self.file) + if parent_dir: + os.makedirs(parent_dir, exist_ok=True) + if value is None: if old: del self._cache[key] @@ -444,6 +451,11 @@ class GitConfig: class RepoConfig(GitConfig): """User settings for repo itself.""" + # Keep separate caches from GitConfig, otherwise ForUser()/ForSystem() + # would return the already-cached ~/.gitconfig instance of the parent. + _ForUser = None + _ForSystem = None + @staticmethod def _getUserConfig(): repo_config_dir = os.getenv("REPO_CONFIG_DIR", os.path.expanduser("~")) diff --git a/tests/test_git_config.py b/tests/test_git_config.py index 4b4e4cabb..33b0466fa 100644 --- a/tests/test_git_config.py +++ b/tests/test_git_config.py @@ -268,3 +268,23 @@ def test_remote_save_with_push_url_without_projectname( def test_is_id(rev: str, expected: bool) -> None: """Test IsId identifies both SHA-1 and SHA-256 hashes.""" assert git_config.IsId(rev) == expected + + +def test_repo_config_for_user_is_not_shared_with_git_config( + monkeypatch: pytest.MonkeyPatch, tmp_home_dir: Path +) -> None: + """RepoConfig.ForUser() must not reuse GitConfig.ForUser()'s cache.""" + monkeypatch.setattr(git_config.GitConfig, "_ForUser", None) + monkeypatch.setattr(git_config.RepoConfig, "_ForUser", None) + monkeypatch.delenv("REPO_CONFIG_DIR", raising=False) + + # Populate the GitConfig cache first, as manifest loading does. + git_cfg = git_config.GitConfig.ForUser() + repo_cfg = git_config.RepoConfig.ForUser() + + assert repo_cfg is not git_cfg + assert git_cfg.file == str(tmp_home_dir / ".gitconfig") + assert repo_cfg.file == str(tmp_home_dir / ".repoconfig" / "config") + # And the RepoConfig instance is cached on its own class. + assert git_config.RepoConfig.ForUser() is repo_cfg + assert git_config.GitConfig.ForUser() is git_cfg