diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index c998ac67c..bd54a1fbe 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,9 +1,8 @@ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.202.1/containers/dotnet/.devcontainer/base.Dockerfile # [Choice] .NET version: 6.0, 5.0, 3.1, 2.1 -ARG VARIANT="6.0" -#FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT} -FROM mcr.microsoft.com/vscode/devcontainers/dotnet:dev-6.0 +ARG VARIANT="3.1" +FROM mcr.microsoft.com/vscode/devcontainers/dotnet:dev-${VARIANT} # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 ARG NODE_VERSION="none" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index bb7f2ca8d..dd0f8e36f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,30 +2,28 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.202.1/containers/dotnet { "name": "C# (.NET)", - "runArgs": ["--init"], + "runArgs": [ + "--init" + ], "build": { "dockerfile": "Dockerfile", - "args": { + "args": { // Update 'VARIANT' to pick a .NET Core version: 2.1, 3.1, 5.0, 6.0 - "VARIANT": "6.0", + "VARIANT": "3.1", // Options "NODE_VERSION": "lts/*", "INSTALL_AZURE_CLI": "false" } }, - // Set *default* container specific settings.json values on container create. "settings": {}, - // Add the IDs of extensions you want installed when the container is created. "extensions": [ "ms-dotnettools.csharp", "vsls-contrib.codetour" ], - // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [5000, 5001], - // [Optional] To reuse of your local HTTPS dev cert: // // 1. Export it locally using this command: @@ -48,10 +46,8 @@ // // * If only using Remote - Containers with a local container, uncomment this line instead: // "mounts": [ "source=${env:HOME}${env:USERPROFILE}/.aspnet/https,target=/home/vscode/.aspnet/https,type=bind" ], - // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "dotnet restore", - // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode", "features": { diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateDetector.cs b/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateDetector.cs index 3eb86cdbe..6f9e31b8a 100644 --- a/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateDetector.cs @@ -21,7 +21,7 @@ public class RustCrateDetector : FileComponentDetector public override IEnumerable SupportedComponentTypes => new[] { ComponentType.Cargo }; - public override int Version { get; } = 4; + public override int Version { get; } = 5; public override IEnumerable Categories => new List { "Rust" }; diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateV2Detector.cs b/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateV2Detector.cs index 577191fbb..3fa2d34d1 100644 --- a/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateV2Detector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/rust/RustCrateV2Detector.cs @@ -21,7 +21,7 @@ public class RustCrateV2Detector : FileComponentDetector public override IEnumerable SupportedComponentTypes => new[] { ComponentType.Cargo }; - public override int Version { get; } = 3; + public override int Version { get; } = 4; public override IEnumerable Categories => new List { "Rust" }; diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs index b7f0bcc90..e91dd7cad 100644 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs +++ b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs @@ -17,12 +17,17 @@ internal static class Desugarer { private const string VersionChars = @"[0-9a-zA-Z\-\+\.\*]"; + // tilde and caret requirements can't also have wildcards in them + private const string VersionCharsNoWildcard = @"[0-9a-zA-Z\-\+\.]"; + private static readonly Regex TildePatternRegex = new Regex( - $@"^\s*~\s*({VersionChars}+)\s*", + $@"^\s*~\s*({VersionCharsNoWildcard}+)\s*$", RegexOptions.Compiled); + // The caret is optional, as Cargo treats "x.y.z" like "^x.y.z": + // https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio private static readonly Regex CaretPatternRegex = new Regex( - $@"^\s*\^\s*({VersionChars}+)\s*", + $@"^\s*\^?\s*({VersionCharsNoWildcard}+)\s*$", RegexOptions.Compiled); private static readonly Regex HyphenPatternRegex = new Regex( @@ -241,4 +246,4 @@ private static Comparator[] MinMaxComparators(SemVersion minVersion, SemVersion } } } -} \ No newline at end of file +} diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/RustCrateDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/RustCrateDetectorTests.cs index 3e7505063..832176d8f 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/RustCrateDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/RustCrateDetectorTests.cs @@ -729,6 +729,64 @@ public async Task TestRustV2Detector_WorkspacesWithSubDirectories() componentRecorder.ForAllComponents(x => x.AllFileLocations.Count().Should().Be(4)); } + [TestMethod] + public async Task TestRustDetector_UnequalButSemverCompatibleRoot() + { + var testTomlString = @" +[package] +name = ""test"" +version = ""0.1.0"" +edition = ""2021"" + +[dependencies] +c-ares = ""7.1.0"" +"; + var testLockString = @" +[[package]] +name = ""c-ares"" +version = ""7.5.2"" +source = ""registry+https://github.com/rust-lang/crates.io-index"" +checksum = ""a8554820e0b20a1b58b4626a3477fa4bccb1f8ee75c61ef547d50523a517126f"" +dependencies = [ + ""c-ares-sys"", +] + +[[package]] +name = ""c-ares-sys"" +version = ""5.3.3"" +source = ""registry+https://github.com/rust-lang/crates.io-index"" +checksum = ""067403b940b1320de22c347323f2cfd20b7c64b5709ab47928f5eb000e585fe0"" + +[[package]] +name = ""test"" +version = ""0.1.0"" +dependencies = [ + ""c-ares"", +] +"; + var (result, componentRecorder) = await detectorV2TestUtility + .WithFile("Cargo.lock", testLockString) + .WithFile("Cargo.toml", testTomlString, new List { "Cargo.toml" }) + .ExecuteDetector(); + + Assert.AreEqual(ProcessingResultCode.Success, result.ResultCode); + Assert.AreEqual(2, componentRecorder.GetDetectedComponents().Count()); + + var graph = componentRecorder.GetDependencyGraphsByLocation().Values.First(); // There should only be 1 + + // Verify explicitly referenced roots + var rootComponents = new List + { + "c-ares 7.5.2 - Cargo", + }; + + rootComponents.ForEach(rootComponentId => graph.IsComponentExplicitlyReferenced(rootComponentId).Should().BeTrue()); + + // Verify dependencies for other_dependency + var cAresDependencies = new List { "c-ares-sys 5.3.3 - Cargo" }; + graph.GetDependenciesForComponent("c-ares 7.5.2 - Cargo").Should().BeEquivalentTo(cAresDependencies); + } + /// /// (my_dependency, 1.0, root) /// (my_other_dependency, 0.1.0, root)