Skip to content

Commit f8fdc8a

Browse files
authored
feat(git): add API to modify repo configuration (#754)
Signed-off-by: Dariusz Duda <[email protected]>
1 parent ceefa4c commit f8fdc8a

File tree

4 files changed

+78
-3
lines changed

4 files changed

+78
-3
lines changed

craft_application/git/_git_repo.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,21 @@ def clone_repository(
710710
) from error
711711
return cls(path)
712712

713+
def get_config_value(self, key: str) -> str | None:
714+
"""Get value for the configuration key if available else return None."""
715+
try:
716+
return cast(str, self._repo.config[key]) # pyright: ignore[reportUnnecessaryCast]
717+
except (KeyError, ValueError):
718+
logger.debug("Config key %r not found in the repository", key)
719+
return None
720+
721+
def set_config_value(self, key: str, value: str) -> None:
722+
"""Set new value for the configuration key.
723+
724+
:raises ValueError: if configuration is incorrect
725+
"""
726+
self._repo.config[key] = value
727+
713728
@classmethod
714729
@lru_cache(maxsize=1)
715730
def get_git_command(cls) -> str:

docs/reference/changelog.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@ Commands
1818

1919
- Reduce spread verbosity level when running the ``test`` command.
2020

21+
Git
22+
===
23+
24+
- Add API to modify repository configuration.
25+
2126
Fixes
2227
======
2328

2429
- Improve test result messages.
2530
- ``InitService`` no longer leaves empty files if rendering template fails.
2631

27-
For a complete list of commits, check out the `5.2.1`_ release on GitHub.
32+
For a complete list of commits, check out the `5.3.0`_ release on GitHub.
2833

2934
5.2.0 (2025-04-25)
3035
------------------
@@ -772,4 +777,4 @@ For a complete list of commits, check out the `2.7.0`_ release on GitHub.
772777
.. _5.0.4: https://github.com/canonical/craft-application/releases/tag/5.0.4
773778
.. _5.1.0: https://github.com/canonical/craft-application/releases/tag/5.1.0
774779
.. _5.2.0: https://github.com/canonical/craft-application/releases/tag/5.2.0
775-
.. _5.2.1: https://github.com/canonical/craft-application/releases/tag/5.2.1
780+
.. _5.3.0: https://github.com/canonical/craft-application/releases/tag/5.3.0

tests/integration/git/test_git.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
"""Git module integration tests."""
1717

1818
import pathlib
19+
import re
1920

2021
import pytest
2122

2223
from craft_application.git import NO_PUSH_URL, Commit, GitError, GitRepo
2324

2425

26+
@pytest.fixture
27+
def git_repo(empty_repository: pathlib.Path) -> GitRepo:
28+
return GitRepo(empty_repository)
29+
30+
2531
@pytest.mark.slow
2632
def test_fetching_hello_repository(
2733
empty_repository: pathlib.Path,
@@ -97,3 +103,49 @@ def test_set_no_push(
97103
git_repo.set_no_push(test_remote)
98104
assert git_repo.get_remote_url(remote_name=test_remote) == hello_repository_lp_url
99105
assert git_repo.get_remote_push_url(remote_name=test_remote) == NO_PUSH_URL
106+
107+
108+
@pytest.mark.parametrize(
109+
("config_key", "expected_value"),
110+
[("core.bare", "false"), ("non_existent.key", None)],
111+
)
112+
def test_get_repo_configuration(
113+
git_repo: GitRepo, config_key: str, expected_value: str | None
114+
) -> None:
115+
assert git_repo.get_config_value(config_key) == expected_value
116+
117+
118+
def test_set_repo_configuration(git_repo: GitRepo) -> None:
119+
new_key = "test.craft"
120+
new_value = "just-testing"
121+
assert git_repo.get_config_value(new_key) is None
122+
git_repo.set_config_value(new_key, new_value)
123+
assert git_repo.get_config_value(new_key) == new_value
124+
125+
126+
def test_update_repo_configuration(git_repo: GitRepo) -> None:
127+
key = "test.craft"
128+
old_value = "just-old"
129+
new_value = "just-new"
130+
git_repo.set_config_value(key, old_value)
131+
assert git_repo.get_config_value(key) == old_value
132+
git_repo.set_config_value(key, new_value)
133+
assert git_repo.get_config_value(key) == new_value
134+
135+
136+
def test_update_boolean_with_string_value(git_repo: GitRepo) -> None:
137+
key = "core.bare"
138+
new_value = "incorrect-boolean"
139+
# this makes repository inaccessible via git CLI client
140+
# fatal: bad boolean config value 'incorrect-boolean' for 'core.bare'
141+
git_repo.set_config_value(key, new_value)
142+
assert git_repo.get_config_value(key) == new_value
143+
144+
145+
def test_incorrect_config_key(git_repo: GitRepo) -> None:
146+
key = "craft.incorrect&test*key"
147+
new_value = "not-important"
148+
with pytest.raises(
149+
ValueError, match=re.escape(f"invalid config item name {key!r}")
150+
):
151+
git_repo.set_config_value(key, new_value)

tests/unit/git/test_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ def write_metadata(snap_path: pathlib.Path, content: str) -> None:
6464
snap_metadata.write_text(content)
6565

6666

67-
def test_import_fallback_in_non_snap_environment() -> None:
67+
def test_import_fallback_in_non_snap_environment(
68+
monkeypatch: pytest.MonkeyPatch,
69+
) -> None:
6870
"""Fallback to previous one if not running as a snap."""
71+
monkeypatch.delenv("SNAP", raising=False)
6972
assert find_ssl_cert_dir() == _FALLBACK_PATH, (
7073
"Use fallback if not installed as a snap."
7174
)

0 commit comments

Comments
 (0)