dependable check on a *.csproj whose PackageReference carries a bare
Version="13.0.1" reports UpToDate no matter what NuGet publishes. It cannot
ever report an available update for that shape, which is the ordinary shape of a
C# manifest.
Mechanism
nuget_constraint_to_semver (crates/dependable-core/src/semver/nuget.rs) reads a
bare version as an inclusive minimum:
// A bare version is an inclusive minimum in NuGet.
nuget_to_semver(c).map_or_else(String::new, |v| format!(">={v}"))
So Version="13.0.1" becomes >=13.0.1. That string is what
evaluate_item hands to check_version
(crates/dependable-fetch/src/check.rs, the to_semver_constraint(&item.version_constraint, ecosystem)
call). Inside check_version
(crates/dependable-core/src/semver/checker.rs):
latest_compatible is the newest published version the requirement matches. A
>= lower bound matches every later release, so latest_compatible == latest_available.
- There is no NuGet lockfile reader in the tree at all (no
packages.lock.json
parser, no LockfileKind for one), so locked_at is always None for a C#
item and current falls back to latest_compatible.
- The status arm is then
Some(cur) if *cur >= latest_available => DependencyStatus::UpToDate, and it is taken unconditionally.
The result does not depend on the registry: whatever Newtonsoft.Json publishes,
the answer is UpToDate. --fix correspondingly never has anything to offer, and
the JSON/SARIF/report surfaces inherit the same verdict.
Why this is a defect and not a reading of NuGet
Maven's translator makes the opposite call for the identical shape.
crates/dependable-core/src/semver/maven.rs:
// A bare version is read as exact, as Hex's is.
maven_to_semver(c).map_or_else(String::new, |v| format!("={v}"))
with the stated rationale that reading a bare version as an open >= bound would
report every project as already up to date. That is exactly the outcome NuGet has
today. The argument was made in maven.rs and was never made in nuget.rs.
Either reading is defensible as NuGet resolution semantics — MSBuild does treat
a bare Version as a floor and picks the lowest release at or above it. But the
question this tool answers is "is there a newer release you could move to", and
under >= that question is unanswerable by construction.
Blast radius, and why it was not folded into #107
Changing nuget_constraint_to_semver changes check, list, fix, report, and
SARIF output for every C# user in one step:
- every bare-
Version PackageReference flips from UpToDate to whatever the
registry actually says, which for most real projects means UpdateAvailable;
--fix starts offering rewrites of lines it has never touched;
- exit codes on existing CI pipelines change accordingly.
That is a deliberate, user-visible behaviour change and wants its own PR and its
own note. #107 was about what a tree node reports, so it took the narrow route
instead: it recognizes an exact pin only where the ecosystem's existing
translator already reads one (Cargo =1.2.3, PEP 440 ==2.28.1, NuGet [1.2.3],
a bare Maven or Hex version), and deliberately leaves a bare NuGet Version
reporting an unknown version so that tree and check cannot disagree about the
same line of the same file. Closing this issue is what would let a bare
<PackageReference Version="1.2.3" /> report its version in tree as well.
Suggested shape
- Make
nuget_constraint_to_semver translate a fully specified bare version to
={v}, keeping >= only where the bare version is partial (1, 1.2), if
that distinction is wanted.
- Cover it with a
check_version test that fails on the current behaviour: a bare
13.0.1 against a published 13.0.3 must not be UpToDate.
- Re-check the
fix.rs wildcard guard alongside it — issue 92 records the same
bare-version-is-exact question from the rewrite side and states NuGet's current
reading as settled, so the two need to agree afterwards.
dependable checkon a*.csprojwhosePackageReferencecarries a bareVersion="13.0.1"reports UpToDate no matter what NuGet publishes. It cannotever report an available update for that shape, which is the ordinary shape of a
C# manifest.
Mechanism
nuget_constraint_to_semver(crates/dependable-core/src/semver/nuget.rs) reads abare version as an inclusive minimum:
So
Version="13.0.1"becomes>=13.0.1. That string is whatevaluate_itemhands tocheck_version(
crates/dependable-fetch/src/check.rs, theto_semver_constraint(&item.version_constraint, ecosystem)call). Inside
check_version(
crates/dependable-core/src/semver/checker.rs):latest_compatibleis the newest published version the requirement matches. A>=lower bound matches every later release, solatest_compatible == latest_available.packages.lock.jsonparser, no
LockfileKindfor one), solocked_atis alwaysNonefor a C#item and
currentfalls back tolatest_compatible.Some(cur) if *cur >= latest_available => DependencyStatus::UpToDate, and it is taken unconditionally.The result does not depend on the registry: whatever Newtonsoft.Json publishes,
the answer is UpToDate.
--fixcorrespondingly never has anything to offer, andthe JSON/SARIF/report surfaces inherit the same verdict.
Why this is a defect and not a reading of NuGet
Maven's translator makes the opposite call for the identical shape.
crates/dependable-core/src/semver/maven.rs:with the stated rationale that reading a bare version as an open
>=bound wouldreport every project as already up to date. That is exactly the outcome NuGet has
today. The argument was made in
maven.rsand was never made innuget.rs.Either reading is defensible as NuGet resolution semantics — MSBuild does treat
a bare
Versionas a floor and picks the lowest release at or above it. But thequestion this tool answers is "is there a newer release you could move to", and
under
>=that question is unanswerable by construction.Blast radius, and why it was not folded into #107
Changing
nuget_constraint_to_semverchangescheck,list,fix,report, andSARIF output for every C# user in one step:
VersionPackageReferenceflips from UpToDate to whatever theregistry actually says, which for most real projects means UpdateAvailable;
--fixstarts offering rewrites of lines it has never touched;That is a deliberate, user-visible behaviour change and wants its own PR and its
own note. #107 was about what a
treenode reports, so it took the narrow routeinstead: it recognizes an exact pin only where the ecosystem's existing
translator already reads one (Cargo
=1.2.3, PEP 440==2.28.1, NuGet[1.2.3],a bare Maven or Hex version), and deliberately leaves a bare NuGet
Versionreporting an unknown version so that
treeandcheckcannot disagree about thesame line of the same file. Closing this issue is what would let a bare
<PackageReference Version="1.2.3" />report its version intreeas well.Suggested shape
nuget_constraint_to_semvertranslate a fully specified bare version to={v}, keeping>=only where the bare version is partial (1,1.2), ifthat distinction is wanted.
check_versiontest that fails on the current behaviour: a bare13.0.1against a published13.0.3must not be UpToDate.fix.rswildcard guard alongside it — issue 92 records the samebare-version-is-exact question from the rewrite side and states NuGet's current
reading as settled, so the two need to agree afterwards.