Skip to content

Commit

Permalink
Handle edge cases and version constraints when processing conan.lock …
Browse files Browse the repository at this point in the history
…files. Add docs and verification test sample files.
  • Loading branch information
ashokgowtham committed Aug 2, 2023
1 parent f2f92c2 commit d9583c0
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 9 deletions.
11 changes: 11 additions & 0 deletions docs/detectors/conan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Conan Detection
## Requirements
Conan detection relies on a conan.lock file being present.

## Detection strategy
Conan detection is performed by parsing every <em>conan.lock</em> found under the scan directory.

## Known limitations
Conan detection will not work if lock files are not being used or not yet generated. So ensure to run the conan build to generate the lock file(s) before running the scan.

Full dependency graph generation is not supported. However, dependency relationships identified/present in the <em>conan.lock</em> file is captured.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
{
var conanLock = JsonSerializer.Deserialize<ConanLock>(conanLockFile.Stream);
this.RecordLockfileVersion(conanLock.Version);
if (conanLock.Version != "0.4")
{
this.Logger.LogWarning("Unsupported conan.lock file version '{ConanLockVersion}'. Failed to process conan.lock file '{ConanLockLocation}'", conanLock.Version, conanLockFile.Location);
return;
}

if (!conanLock.HasNodes())
{
Expand All @@ -58,8 +63,8 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
if (packagesDictionary.ContainsKey("0"))
{
packagesDictionary.Remove("0", out var rootNode);
explicitReferencedDependencies = rootNode.Requires;
developmentDependencies = rootNode.BuildRequires;
explicitReferencedDependencies = rootNode.Requires ?? Array.Empty<string>();
developmentDependencies = rootNode.BuildRequires ?? Array.Empty<string>();
}

foreach (var (packageIndex, package) in packagesDictionary)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ namespace Microsoft.ComponentDetection.Detectors.Conan.Contracts;

public class ConanLockNode
{
private string[] requires;
private string[] buildRequires;

[JsonPropertyName("context")]
public string Context { get; set; }

Expand All @@ -32,18 +29,18 @@ public class ConanLockNode
public string Reference { get; set; }

[JsonPropertyName("requires")]
public string[] Requires { get => this.requires; set => this.requires = value ?? Array.Empty<string>(); }
public string[] Requires { get; set; }

[JsonPropertyName("build_requires")]
public string[] BuildRequires { get => this.buildRequires; set => this.buildRequires = value ?? Array.Empty<string>(); }
public string[] BuildRequires { get; set; }

public override bool Equals(object obj) => obj is ConanLockNode node && this.Context == node.Context && this.Modified == node.Modified && this.Options == node.Options && this.PackageId == node.PackageId && this.Path == node.Path && this.Previous == node.Previous && this.Reference == node.Reference && Enumerable.SequenceEqual(this.Requires, node.Requires);

public override int GetHashCode() => HashCode.Combine(this.Context, this.Modified, this.Options, this.PackageId, this.Path, this.Previous, this.Reference, this.Requires);

internal string Name() => this.Reference.Split('/', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).FirstOrDefault("Unknown");
internal string Name() => this.Reference == null ? string.Empty : this.Reference.Split('/', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).FirstOrDefault("Unknown");

internal TypedComponent ToComponent() => new ConanComponent(this.Name(), this.Version());

internal string Version() => this.Reference.Split('/', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Skip(1).FirstOrDefault("None");
internal string Version() => this.Reference == null ? string.Empty : this.Reference.Split('/', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Skip(1).FirstOrDefault("None");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"graph_lock": {
"nodes": {
"0": {
"ref": "MyAwesomeConanProject/1.2.5",
"options": "",
"requires": [
"1"
],
"build_requires": [
"6"
],
"path": "conanfile.py",
"context": "host"
},
"1": {
"ref": "boost/1.82.0",
"options": "",
"package_id": "dd7f5f958c7381cfd81e611a16062de0c827160a",
"prev": "0",
"modified": true,
"requires": [
"2",
"3",
"4"
],
"build_requires": [
"5"
],
"context": "host"
},
"2": {
"ref": "zlib/1.2.13",
"options": "",
"package_id": "240c2182163325b213ca6886a7614c8ed2bf1738",
"prev": "0",
"modified": true,
"context": "host"
},
"3": {
"ref": "bzip2/1.0.8",
"options": "",
"package_id": "238a93dc813ca1550968399f1f8925565feeff8e",
"prev": "0",
"modified": true,
"context": "host"
},
"4": {
"ref": "libbacktrace/cci.20210118",
"options": "",
"package_id": "240c2182163325b213ca6886a7614c8ed2bf1738",
"prev": "0",
"modified": true,
"context": "host"
},
"5": {
"ref": "b2/4.9.6",
"options": "",
"package_id": "a5ad5696abf650a25eea8f377806b3d5fe234e6e",
"prev": "0",
"modified": true,
"context": "host"
},
"6": {
"ref": "gtest/1.8.1",
"options": "",
"package_id": "fb16a498e820fb09d04ff9374a782b5b21da0601",
"prev": "0",
"modified": true,
"context": "host"
}
},
"revisions_enabled": false
},
"version": "0.4",
"profile_host": "\n"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from conans import ConanFile

class MyAwesome(ConanFile):
name = "MyAwesomeConanProject"
version = "1.2.5"

def requirements(self):
self.requires("boost/1.82.0")

def build_requirements(self):
self.tool_requires("gtest/1.8.1")
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"graph_lock": {
"nodes": {
"0": {
"options": "",
"requires": [
"1"
],
"build_requires": [
"5"
],
"path": "conanfile.txt",
"context": "host"
},
"1": {
"ref": "boost/1.82.0",
"options": "",
"package_id": "dd7f5f958c7381cfd81e611a16062de0c827160a",
"prev": "0",
"requires": [
"2",
"3",
"4"
],
"context": "host"
},
"2": {
"ref": "zlib/1.2.13",
"options": "",
"package_id": "240c2182163325b213ca6886a7614c8ed2bf1738",
"prev": "0",
"context": "host"
},
"3": {
"ref": "bzip2/1.0.8",
"options": "",
"package_id": "238a93dc813ca1550968399f1f8925565feeff8e",
"prev": "0",
"context": "host"
},
"4": {
"ref": "libbacktrace/cci.20210118",
"options": "",
"package_id": "240c2182163325b213ca6886a7614c8ed2bf1738",
"prev": "0",
"context": "host"
},
"5": {
"ref": "gtest/1.8.1",
"options": "",
"package_id": "fb16a498e820fb09d04ff9374a782b5b21da0601",
"prev": "0",
"context": "host"
}
},
"revisions_enabled": false
},
"version": "0.4",
"profile_host": "\n"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[requires]
boost/1.82.0

[tool_requires]
gtest/1.8.1

0 comments on commit d9583c0

Please sign in to comment.