Skip to content

Commit 2b824d2

Browse files
Add Supplier/License info to RustCli Cargo Components. (#940)
* Add Supplier/License info to RustCli Cargo Components. * Address feedback. * Fix input for test * Add extra check for empty array of authors. --------- Co-authored-by: Sebastian Gomez <segomez@microsoft.com>
1 parent 0923d09 commit 2b824d2

File tree

3 files changed

+428
-4
lines changed

3 files changed

+428
-4
lines changed

src/Microsoft.ComponentDetection.Contracts/TypedComponent/CargoComponent.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace Microsoft.ComponentDetection.Contracts.TypedComponent;
22

3+
using Newtonsoft.Json;
34
using PackageUrl;
45

56
public class CargoComponent : TypedComponent
@@ -9,16 +10,26 @@ private CargoComponent()
910
// reserved for deserialization
1011
}
1112

12-
public CargoComponent(string name, string version)
13+
public CargoComponent(string name, string version, string author = null, string license = null)
1314
{
1415
this.Name = this.ValidateRequiredInput(name, nameof(this.Name), nameof(ComponentType.Cargo));
1516
this.Version = this.ValidateRequiredInput(version, nameof(this.Version), nameof(ComponentType.Cargo));
17+
this.Author = author;
18+
this.License = license;
1619
}
1720

1821
public string Name { get; set; }
1922

2023
public string Version { get; set; }
2124

25+
#nullable enable
26+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
27+
public string? Author { get; set; }
28+
29+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
30+
public string? License { get; set; }
31+
#nullable disable
32+
2233
public override ComponentType Type => ComponentType.Cargo;
2334

2435
public override string Id => $"{this.Name} {this.Version} - {this.Type}";

src/Microsoft.ComponentDetection.Detectors/rust/RustCliDetector.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
8484

8585
var metadata = CargoMetadata.FromJson(cliResult.StdOut);
8686
var graph = BuildGraph(metadata);
87+
88+
var packages = metadata.Packages.ToDictionary(
89+
x => $"{x.Name} {x.Version}",
90+
x => (
91+
(x.Authors == null || x.Authors.Any(a => string.IsNullOrWhiteSpace(a)) || !x.Authors.Any()) ? null : string.Join(", ", x.Authors),
92+
string.IsNullOrWhiteSpace(x.License) ? null : x.License));
93+
8794
var root = metadata.Resolve.Root;
8895

8996
// A cargo.toml can be used to declare a workspace and not a package (A Virtual Manifest).
@@ -95,7 +102,7 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID
95102
return;
96103
}
97104

98-
this.TraverseAndRecordComponents(processRequest.SingleFileComponentRecorder, componentStream.Location, graph, root, null, null);
105+
this.TraverseAndRecordComponents(processRequest.SingleFileComponentRecorder, componentStream.Location, graph, root, null, null, packages);
99106
}
100107
catch (InvalidOperationException e)
101108
{
@@ -118,13 +125,19 @@ private void TraverseAndRecordComponents(
118125
string id,
119126
DetectedComponent parent,
120127
Dep depInfo,
128+
IReadOnlyDictionary<string, (string Authors, string License)> packagesMetadata,
121129
bool explicitlyReferencedDependency = false)
122130
{
123131
try
124132
{
125133
var isDevelopmentDependency = depInfo?.DepKinds.Any(x => x.Kind is Kind.Dev) ?? false;
126134
var (name, version) = ParseNameAndVersion(id);
127-
var detectedComponent = new DetectedComponent(new CargoComponent(name, version));
135+
136+
var (authors, license) = packagesMetadata.TryGetValue($"{name} {version}", out var package)
137+
? package
138+
: (null, null);
139+
140+
var detectedComponent = new DetectedComponent(new CargoComponent(name, version, authors, license));
128141

129142
recorder.RegisterUsage(
130143
detectedComponent,
@@ -140,7 +153,7 @@ private void TraverseAndRecordComponents(
140153

141154
foreach (var dep in node.Deps)
142155
{
143-
this.TraverseAndRecordComponents(recorder, location, graph, dep.Pkg, detectedComponent, dep, parent == null);
156+
this.TraverseAndRecordComponents(recorder, location, graph, dep.Pkg, detectedComponent, dep, packagesMetadata, parent == null);
144157
}
145158
}
146159
catch (IndexOutOfRangeException e)

0 commit comments

Comments
 (0)