Skip to content

Commit 40203f4

Browse files
author
Amitla Vannikumar
committed
move goreplace from experiments to prod
1 parent ed4488a commit 40203f4

File tree

6 files changed

+588
-1604
lines changed

6 files changed

+588
-1604
lines changed

src/Microsoft.ComponentDetection.Detectors/go/GoComponentDetector.cs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,22 @@ public class GoComponentDetector : FileComponentDetector
2727

2828
private readonly ICommandLineInvocationService commandLineInvocationService;
2929
private readonly IEnvironmentVariableService envVarService;
30+
private readonly IFileUtilityService fileUtilityService;
3031

3132
public GoComponentDetector(
3233
IComponentStreamEnumerableFactory componentStreamEnumerableFactory,
3334
IObservableDirectoryWalkerFactory walkerFactory,
3435
ICommandLineInvocationService commandLineInvocationService,
3536
IEnvironmentVariableService envVarService,
36-
ILogger<GoComponentDetector> logger)
37+
ILogger<GoComponentDetector> logger,
38+
IFileUtilityService fileUtilityService)
3739
{
3840
this.ComponentStreamEnumerableFactory = componentStreamEnumerableFactory;
3941
this.Scanner = walkerFactory;
4042
this.commandLineInvocationService = commandLineInvocationService;
4143
this.envVarService = envVarService;
4244
this.Logger = logger;
45+
this.fileUtilityService = fileUtilityService;
4346
}
4447

4548
public override string Id => "Go";
@@ -50,7 +53,7 @@ public GoComponentDetector(
5053

5154
public override IEnumerable<ComponentType> SupportedComponentTypes { get; } = [ComponentType.Go];
5255

53-
public override int Version => 7;
56+
public override int Version => 8;
5457

5558
protected override Task<IObservable<ProcessRequest>> OnPrepareDetectionAsync(
5659
IObservable<ProcessRequest> processRequests,
@@ -246,7 +249,7 @@ private async Task<bool> UseGoCliToScanAsync(string location, ISingleFileCompone
246249
return false;
247250
}
248251

249-
this.RecordBuildDependencies(goDependenciesProcess.StdOut, singleFileComponentRecorder);
252+
this.RecordBuildDependencies(goDependenciesProcess.StdOut, singleFileComponentRecorder, projectRootDirectory.FullName);
250253

251254
var generateGraphProcess = await this.commandLineInvocationService.ExecuteCommandAsync("go", null, workingDirectory: projectRootDirectory, new List<string> { "mod", "graph" }.ToArray());
252255
if (generateGraphProcess.ExitCode == 0)
@@ -284,6 +287,7 @@ private async Task ParseGoModFileAsync(
284287
GoGraphTelemetryRecord goGraphTelemetryRecord)
285288
{
286289
using var reader = new StreamReader(file.Stream);
290+
var startString = "require ";
287291

288292
// There can be multiple require( ) sections in go 1.17+. loop over all of them.
289293
while (!reader.EndOfStream)
@@ -299,9 +303,9 @@ private async Task ParseGoModFileAsync(
299303

300304
// In go >= 1.17, direct dependencies are listed as "require x/y v1.2.3", and transitive dependencies
301305
// are listed in the require () section
302-
if (line.StartsWith("require "))
306+
if (line.StartsWith(startString))
303307
{
304-
this.TryRegisterDependencyFromModLine(line[8..], singleFileComponentRecorder);
308+
this.TryRegisterDependencyFromModLine(line[startString.Length..], singleFileComponentRecorder);
305309
}
306310

307311
line = await reader.ReadLineAsync();
@@ -421,14 +425,16 @@ private bool IsModuleInBuildList(ISingleFileComponentRecorder singleFileComponen
421425
return singleFileComponentRecorder.GetComponent(component.Id) != null;
422426
}
423427

424-
private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRecorder singleFileComponentRecorder)
428+
private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRecorder singleFileComponentRecorder, string projectRootDirectoryFullName)
425429
{
426430
var goBuildModules = new List<GoBuildModule>();
427431
var reader = new JsonTextReader(new StringReader(goListOutput))
428432
{
429433
SupportMultipleContent = true,
430434
};
431435

436+
using var record = new GoReplaceTelemetryRecord();
437+
432438
while (reader.Read())
433439
{
434440
var serializer = new JsonSerializer();
@@ -439,13 +445,45 @@ private void RecordBuildDependencies(string goListOutput, ISingleFileComponentRe
439445

440446
foreach (var dependency in goBuildModules)
441447
{
448+
var dependencyName = $"{dependency.Path} {dependency.Version}";
449+
442450
if (dependency.Main)
443451
{
444452
// main is the entry point module (superfluous as we already have the file location)
445453
continue;
446454
}
447455

448-
var goComponent = new GoComponent(dependency.Path, dependency.Version);
456+
if (dependency.Replace?.Path != null && dependency.Replace.Version == null)
457+
{
458+
var dirName = projectRootDirectoryFullName;
459+
var combinedPath = Path.Combine(dirName, dependency.Replace.Path, "go.mod");
460+
var goModFilePath = Path.GetFullPath(combinedPath);
461+
if (this.fileUtilityService.Exists(goModFilePath))
462+
{
463+
this.Logger.LogInformation("go Module {GoModule} is being replaced with module at path {GoModFilePath}", dependencyName, goModFilePath);
464+
record.GoModPathAndVersion = dependencyName;
465+
record.GoModReplacement = goModFilePath;
466+
continue;
467+
}
468+
469+
this.Logger.LogWarning("go.mod file {GoModFilePath} does not exist in the relative path given for replacement", goModFilePath);
470+
record.GoModPathAndVersion = goModFilePath;
471+
record.GoModReplacement = null;
472+
}
473+
474+
GoComponent goComponent;
475+
if (dependency.Replace?.Path != null && dependency.Replace.Version != null)
476+
{
477+
var dependencyReplacementName = $"{dependency.Replace.Path} {dependency.Replace.Version}";
478+
goComponent = new GoComponent(dependency.Replace.Path, dependency.Replace.Version);
479+
this.Logger.LogInformation("go Module {GoModule} being replaced with module {GoModuleReplacement}", dependencyName, dependencyReplacementName);
480+
record.GoModPathAndVersion = dependencyName;
481+
record.GoModReplacement = dependencyReplacementName;
482+
}
483+
else
484+
{
485+
goComponent = new GoComponent(dependency.Path, dependency.Version);
486+
}
449487

450488
if (dependency.Indirect)
451489
{
@@ -485,5 +523,7 @@ private class GoBuildModule
485523
public string Version { get; set; }
486524

487525
public bool Indirect { get; set; }
526+
527+
public GoBuildModule Replace { get; set; }
488528
}
489529
}

0 commit comments

Comments
 (0)