Skip to content

Commit a933a55

Browse files
committed
fix(provider): harden cargo version parsing and lockfile updates
- prefer [workspace.package] version with safe fallback to [package] - handle virtual workspace + version.workspace=true members when updating Cargo.lock - add regression tests for error/continue branches and workspace edge cases
1 parent e5e464a commit a933a55

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

tests/providers/test_cargo_provider.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from typing import TYPE_CHECKING
77

88
import pytest
9+
from tomlkit.exceptions import NonExistentKey
910

1011
from commitizen.providers import get_provider
1112
from commitizen.providers.cargo_provider import CargoProvider
@@ -451,3 +452,145 @@ def test_cargo_provider_workspace_member_without_workspace_key(
451452
assert file.read_text() == dedent(expected_workspace_toml)
452453
# The lock file should remain unchanged since the member doesn't inherit workspace version
453454
assert lock_file.read_text() == dedent(expected_lock_content)
455+
456+
457+
def test_cargo_provider_get_raises_when_version_is_not_string(
458+
config: BaseConfig,
459+
chdir: Path,
460+
) -> None:
461+
"""CargoProvider.get should raise when root version is not a string."""
462+
(chdir / CargoProvider.filename).write_text(
463+
dedent(
464+
"""\
465+
[package]
466+
name = "whatever"
467+
version = 1
468+
"""
469+
)
470+
)
471+
config.settings["version_provider"] = "cargo"
472+
473+
provider = get_provider(config)
474+
assert isinstance(provider, CargoProvider)
475+
476+
with pytest.raises(TypeError, match=r"expected root version to be a string"):
477+
provider.get_version()
478+
479+
480+
def test_cargo_provider_get_raises_when_no_package_tables(
481+
config: BaseConfig,
482+
chdir: Path,
483+
) -> None:
484+
"""_root_version_table should raise when neither [workspace.package] nor [package] exists."""
485+
(chdir / CargoProvider.filename).write_text(
486+
dedent(
487+
"""\
488+
[workspace]
489+
members = []
490+
"""
491+
)
492+
)
493+
config.settings["version_provider"] = "cargo"
494+
495+
provider = get_provider(config)
496+
assert isinstance(provider, CargoProvider)
497+
498+
with pytest.raises(
499+
NonExistentKey, match=r"expected either \[workspace\.package\] or \[package\]"
500+
):
501+
provider.get_version()
502+
503+
504+
def test_workspace_member_dir_without_cargo_toml_is_ignored(
505+
config: BaseConfig,
506+
chdir: Path,
507+
) -> None:
508+
"""Cover: if not cargo_file.exists(): continue"""
509+
workspace_toml = """\
510+
[workspace]
511+
members = ["missing_manifest"]
512+
513+
[workspace.package]
514+
version = "0.1.0"
515+
"""
516+
lock_content = """\
517+
[[package]]
518+
name = "missing_manifest"
519+
version = "0.1.0"
520+
source = "registry+https://github.com/rust-lang/crates.io-index"
521+
checksum = "123abc"
522+
"""
523+
expected_workspace_toml = """\
524+
[workspace]
525+
members = ["missing_manifest"]
526+
527+
[workspace.package]
528+
version = "42.1"
529+
"""
530+
531+
(chdir / CargoProvider.filename).write_text(dedent(workspace_toml))
532+
os.mkdir(chdir / "missing_manifest") # directory exists, but Cargo.toml does NOT
533+
534+
(chdir / CargoProvider.lock_filename).write_text(dedent(lock_content))
535+
536+
config.settings["version_provider"] = "cargo"
537+
provider = get_provider(config)
538+
assert isinstance(provider, CargoProvider)
539+
540+
provider.set_version("42.1")
541+
assert (chdir / CargoProvider.filename).read_text() == dedent(
542+
expected_workspace_toml
543+
)
544+
# lock should remain unchanged since member cannot be inspected => not inheriting
545+
assert (chdir / CargoProvider.lock_filename).read_text() == dedent(lock_content)
546+
547+
548+
def test_workspace_member_with_non_table_package_is_ignored(
549+
config: BaseConfig,
550+
chdir: Path,
551+
) -> None:
552+
"""Cover: if not hasattr(pkg, "get"): continue"""
553+
workspace_toml = """\
554+
[workspace]
555+
members = ["bad_package"]
556+
557+
[workspace.package]
558+
version = "0.1.0"
559+
"""
560+
member_toml = """\
561+
package = "oops"
562+
"""
563+
lock_content = """\
564+
[[package]]
565+
name = "bad_package"
566+
version = "0.1.0"
567+
source = "registry+https://github.com/rust-lang/crates.io-index"
568+
checksum = "123abc"
569+
"""
570+
expected_workspace_toml = """\
571+
[workspace]
572+
members = ["bad_package"]
573+
574+
[workspace.package]
575+
version = "42.1"
576+
"""
577+
578+
(chdir / CargoProvider.filename).write_text(dedent(workspace_toml))
579+
580+
os.mkdir(chdir / "bad_package")
581+
(chdir / "bad_package" / "Cargo.toml").write_text(
582+
dedent(member_toml)
583+
) # package is str, not table
584+
585+
(chdir / CargoProvider.lock_filename).write_text(dedent(lock_content))
586+
587+
config.settings["version_provider"] = "cargo"
588+
provider = get_provider(config)
589+
assert isinstance(provider, CargoProvider)
590+
591+
provider.set_version("42.1")
592+
assert (chdir / CargoProvider.filename).read_text() == dedent(
593+
expected_workspace_toml
594+
)
595+
# lock should remain unchanged since package is not a table => not inheriting
596+
assert (chdir / CargoProvider.lock_filename).read_text() == dedent(lock_content)

0 commit comments

Comments
 (0)