From ff5ac9a9dce166215cc5303dc9057da322b5ebdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuna=20Alika=C5=9Fifo=C4=9Flu?= Date: Thu, 8 May 2025 22:55:24 +0300 Subject: [PATCH 1/4] feat(providers): add support for `Cargo.lock` If `Cargo.lock` file is present in the same path as the `Cargo.toml`, the version of the package will also be updated in the `Cargo.lock` file. The implementation is similar to the one used for `UvProvider`, which extends the `CargoProvider` to handle lock files. The change does not break any existing functionality, if the `Cargo.lock` file is not present, since it checks for the existence of the file before attempting a lock file update. --- commitizen/providers/cargo_provider.py | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/commitizen/providers/cargo_provider.py b/commitizen/providers/cargo_provider.py index cee687c15..2e73ff35a 100644 --- a/commitizen/providers/cargo_provider.py +++ b/commitizen/providers/cargo_provider.py @@ -1,5 +1,7 @@ from __future__ import annotations +from pathlib import Path + import tomlkit from commitizen.providers.base_provider import TomlProvider @@ -13,6 +15,11 @@ class CargoProvider(TomlProvider): """ filename = "Cargo.toml" + lock_filename = "Cargo.lock" + + @property + def lock_file(self) -> Path: + return Path() / self.lock_filename def get(self, document: tomlkit.TOMLDocument) -> str: try: @@ -28,3 +35,23 @@ def set(self, document: tomlkit.TOMLDocument, version: str): except tomlkit.exceptions.NonExistentKey: ... document["package"]["version"] = version # type: ignore + + def set_version(self, version: str) -> None: + super().set_version(version) + if self.lock_file.exists(): + self.set_lock_version(version) + + def set_lock_version(self, version: str) -> None: + cargo_toml_content = tomlkit.parse(self.file.read_text()) + try: + package_name = cargo_toml_content["package"]["name"] # type: ignore + except tomlkit.exceptions.NonExistentKey: + package_name = cargo_toml_content["workspace"]["package"]["name"] # type: ignore + + cargo_lock_content = tomlkit.parse(self.lock_file.read_text()) + packages: tomlkit.items.AoT = cargo_lock_content["package"] # type: ignore[assignment] + for i, package in enumerate(packages): + if package["name"] == package_name: + cargo_lock_content["package"][i]["version"] = version # type: ignore[index] + break + self.lock_file.write_text(tomlkit.dumps(cargo_lock_content)) From 4871b36583e8060218f6a2757f9978eb3662d362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuna=20Alika=C5=9Fifo=C4=9Flu?= Date: Thu, 8 May 2025 23:07:24 +0300 Subject: [PATCH 2/4] refactor(tests): increase verbosity of variables To add more test variables, increase the verbosity of current ones and make them more clear. --- tests/providers/test_cargo_provider.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index 646ef3a53..2144a145a 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -15,7 +15,7 @@ version = "0.1.0" """ -CARGO_EXPECTED = """\ +CARGO_TOML_EXPECTED = """\ [package] name = "whatever" version = "42.1" @@ -27,7 +27,7 @@ version = "0.1.0" """ -CARGO_WORKSPACE_EXPECTED = """\ +CARGO_WORKSPACE_TOML_EXPECTED = """\ [workspace.package] name = "whatever" version = "42.1" @@ -37,8 +37,8 @@ @pytest.mark.parametrize( "content, expected", ( - (CARGO_TOML, CARGO_EXPECTED), - (CARGO_WORKSPACE_TOML, CARGO_WORKSPACE_EXPECTED), + (CARGO_TOML, CARGO_TOML_EXPECTED), + (CARGO_WORKSPACE_TOML, CARGO_WORKSPACE_TOML_EXPECTED), ), ) def test_cargo_provider( From 5a8ac4d30ee778a3fa77058e10e10c357912a506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuna=20Alika=C5=9Fifo=C4=9Flu?= Date: Thu, 8 May 2025 23:08:12 +0300 Subject: [PATCH 3/4] test: add test for cargo provider with lock files Add a test to check the behavior of the cargo provider when a `Cargo.lock` file is present. This test ensures that the `CargoProvider` behaves correctly when the lock file is present, and updates both the `Cargo.lock` and `Cargo.toml` files accordingly. --- tests/providers/test_cargo_provider.py | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tests/providers/test_cargo_provider.py b/tests/providers/test_cargo_provider.py index 2144a145a..4b20c6ea5 100644 --- a/tests/providers/test_cargo_provider.py +++ b/tests/providers/test_cargo_provider.py @@ -33,6 +33,32 @@ version = "42.1" """ +CARGO_LOCK = """\ +[[package]] +name = "whatever" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] +""" + +CARGO_LOCK_EXPECTED = """\ +[[package]] +name = "whatever" +version = "42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123abc" +dependencies = [ + "packageA", + "packageB", + "packageC", +] +""" + @pytest.mark.parametrize( "content, expected", @@ -58,3 +84,46 @@ def test_cargo_provider( provider.set_version("42.1") assert file.read_text() == dedent(expected) + + +@pytest.mark.parametrize( + "toml_content, lock_content, toml_expected, lock_expected", + ( + ( + CARGO_TOML, + CARGO_LOCK, + CARGO_TOML_EXPECTED, + CARGO_LOCK_EXPECTED, + ), + ( + CARGO_WORKSPACE_TOML, + CARGO_LOCK, + CARGO_WORKSPACE_TOML_EXPECTED, + CARGO_LOCK_EXPECTED, + ), + ), +) +def test_cargo_provider_with_lock( + config: BaseConfig, + chdir: Path, + toml_content: str, + lock_content: str, + toml_expected: str, + lock_expected: str, +): + filename = CargoProvider.filename + file = chdir / filename + file.write_text(dedent(toml_content)) + + lock_filename = CargoProvider.lock_filename + lock_file = chdir / lock_filename + lock_file.write_text(dedent(lock_content)) + config.settings["version_provider"] = "cargo" + + provider = get_provider(config) + assert isinstance(provider, CargoProvider) + assert provider.get_version() == "0.1.0" + + provider.set_version("42.1") + assert file.read_text() == dedent(toml_expected) + assert lock_file.read_text() == dedent(lock_expected) From 4501f85854c759eb3eef752e7aeda93abe2156c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tuna=20Alika=C5=9Fifo=C4=9Flu?= Date: Thu, 8 May 2025 23:22:17 +0300 Subject: [PATCH 4/4] docs(providers): update `cargo` explanation Add `Cargo.lock` update information to the documentation. --- docs/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.md b/docs/config.md index d1ae90b29..a52231274 100644 --- a/docs/config.md +++ b/docs/config.md @@ -353,7 +353,7 @@ Commitizen provides some version providers for some well known formats: | `pep621` | Get and set version from `pyproject.toml` `project.version` field | | `poetry` | Get and set version from `pyproject.toml` `tool.poetry.version` field | | `uv` | Get and set version from `pyproject.toml` `project.version` field and `uv.lock` `package.version` field whose `package.name` field is the same as `pyproject.toml` `project.name` field | -| `cargo` | Get and set version from `Cargo.toml` `project.version` field | +| `cargo` | Get and set version from `Cargo.toml` `package.version` field and `Cargo.lock` `package.version` field whose `package.name` field is the same as `Cargo.toml` `package.name` field | | `npm` | Get and set version from `package.json` `version` field, `package-lock.json` `version,packages.''.version` fields if the file exists, and `npm-shrinkwrap.json` `version,packages.''.version` fields if the file exists | | `composer` | Get and set version from `composer.json` `project.version` field |