up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
This commit is contained in:
@@ -1,234 +1,234 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Go.Internal;
|
||||
|
||||
internal static class GoBuildInfoParser
|
||||
{
|
||||
private const string PathPrefix = "path\t";
|
||||
private const string ModulePrefix = "mod\t";
|
||||
private const string DependencyPrefix = "dep\t";
|
||||
private const string ReplacementPrefix = "=>\t";
|
||||
private const string BuildPrefix = "build\t";
|
||||
|
||||
public static bool TryParse(string goVersion, string absoluteBinaryPath, string rawModuleData, out GoBuildInfo? info)
|
||||
{
|
||||
info = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(goVersion) || string.IsNullOrWhiteSpace(rawModuleData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string? modulePath = null;
|
||||
GoModule? mainModule = null;
|
||||
var dependencies = new List<GoModule>();
|
||||
var settings = new SortedDictionary<string, string?>(StringComparer.Ordinal);
|
||||
|
||||
GoModule? lastModule = null;
|
||||
using var reader = new StringReader(rawModuleData);
|
||||
|
||||
while (reader.ReadLine() is { } line)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(PathPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
modulePath = line[PathPrefix.Length..].Trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(ModulePrefix, StringComparison.Ordinal))
|
||||
{
|
||||
mainModule = ParseModule(line.AsSpan(ModulePrefix.Length), isMain: true);
|
||||
lastModule = mainModule;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(DependencyPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
var dependency = ParseModule(line.AsSpan(DependencyPrefix.Length), isMain: false);
|
||||
if (dependency is not null)
|
||||
{
|
||||
dependencies.Add(dependency);
|
||||
lastModule = dependency;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(ReplacementPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
if (lastModule is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var replacement = ParseReplacement(line.AsSpan(ReplacementPrefix.Length));
|
||||
if (replacement is not null)
|
||||
{
|
||||
lastModule.SetReplacement(replacement);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(BuildPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
var pair = ParseBuildSetting(line.AsSpan(BuildPrefix.Length));
|
||||
if (!string.IsNullOrEmpty(pair.Key))
|
||||
{
|
||||
settings[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mainModule is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(modulePath))
|
||||
{
|
||||
modulePath = mainModule.Path;
|
||||
}
|
||||
|
||||
info = new GoBuildInfo(
|
||||
goVersion,
|
||||
absoluteBinaryPath,
|
||||
modulePath,
|
||||
mainModule,
|
||||
dependencies,
|
||||
settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static GoModule? ParseModule(ReadOnlySpan<char> span, bool isMain)
|
||||
{
|
||||
var fields = SplitFields(span, expected: 4);
|
||||
if (fields.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = fields[0];
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var version = fields.Count > 1 ? fields[1] : null;
|
||||
var sum = fields.Count > 2 ? fields[2] : null;
|
||||
|
||||
return new GoModule(path, version, sum, isMain);
|
||||
}
|
||||
|
||||
private static GoModuleReplacement? ParseReplacement(ReadOnlySpan<char> span)
|
||||
{
|
||||
var fields = SplitFields(span, expected: 3);
|
||||
if (fields.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = fields[0];
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var version = fields.Count > 1 ? fields[1] : null;
|
||||
var sum = fields.Count > 2 ? fields[2] : null;
|
||||
|
||||
return new GoModuleReplacement(path, version, sum);
|
||||
}
|
||||
|
||||
private static KeyValuePair<string, string?> ParseBuildSetting(ReadOnlySpan<char> span)
|
||||
{
|
||||
span = span.Trim();
|
||||
if (span.IsEmpty)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var separatorIndex = span.IndexOf('=');
|
||||
if (separatorIndex <= 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var rawKey = span[..separatorIndex].Trim();
|
||||
var rawValue = span[(separatorIndex + 1)..].Trim();
|
||||
|
||||
var key = Unquote(rawKey.ToString());
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var value = Unquote(rawValue.ToString());
|
||||
return new KeyValuePair<string, string?>(key, value);
|
||||
}
|
||||
|
||||
private static List<string> SplitFields(ReadOnlySpan<char> span, int expected)
|
||||
{
|
||||
var fields = new List<string>(expected);
|
||||
var builder = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < span.Length; i++)
|
||||
{
|
||||
var current = span[i];
|
||||
if (current == '\t')
|
||||
{
|
||||
fields.Add(builder.ToString());
|
||||
builder.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append(current);
|
||||
}
|
||||
|
||||
fields.Add(builder.ToString());
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static string Unquote(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
value = value.Trim();
|
||||
if (value.Length < 2)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value[0] == '"' && value[^1] == '"')
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<string>(value) ?? value;
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if (value[0] == '`' && value[^1] == '`')
|
||||
{
|
||||
return value[1..^1];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Go.Internal;
|
||||
|
||||
internal static class GoBuildInfoParser
|
||||
{
|
||||
private const string PathPrefix = "path\t";
|
||||
private const string ModulePrefix = "mod\t";
|
||||
private const string DependencyPrefix = "dep\t";
|
||||
private const string ReplacementPrefix = "=>\t";
|
||||
private const string BuildPrefix = "build\t";
|
||||
|
||||
public static bool TryParse(string goVersion, string absoluteBinaryPath, string rawModuleData, out GoBuildInfo? info)
|
||||
{
|
||||
info = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(goVersion) || string.IsNullOrWhiteSpace(rawModuleData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string? modulePath = null;
|
||||
GoModule? mainModule = null;
|
||||
var dependencies = new List<GoModule>();
|
||||
var settings = new SortedDictionary<string, string?>(StringComparer.Ordinal);
|
||||
|
||||
GoModule? lastModule = null;
|
||||
using var reader = new StringReader(rawModuleData);
|
||||
|
||||
while (reader.ReadLine() is { } line)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(PathPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
modulePath = line[PathPrefix.Length..].Trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(ModulePrefix, StringComparison.Ordinal))
|
||||
{
|
||||
mainModule = ParseModule(line.AsSpan(ModulePrefix.Length), isMain: true);
|
||||
lastModule = mainModule;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(DependencyPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
var dependency = ParseModule(line.AsSpan(DependencyPrefix.Length), isMain: false);
|
||||
if (dependency is not null)
|
||||
{
|
||||
dependencies.Add(dependency);
|
||||
lastModule = dependency;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(ReplacementPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
if (lastModule is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var replacement = ParseReplacement(line.AsSpan(ReplacementPrefix.Length));
|
||||
if (replacement is not null)
|
||||
{
|
||||
lastModule.SetReplacement(replacement);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.StartsWith(BuildPrefix, StringComparison.Ordinal))
|
||||
{
|
||||
var pair = ParseBuildSetting(line.AsSpan(BuildPrefix.Length));
|
||||
if (!string.IsNullOrEmpty(pair.Key))
|
||||
{
|
||||
settings[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mainModule is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(modulePath))
|
||||
{
|
||||
modulePath = mainModule.Path;
|
||||
}
|
||||
|
||||
info = new GoBuildInfo(
|
||||
goVersion,
|
||||
absoluteBinaryPath,
|
||||
modulePath,
|
||||
mainModule,
|
||||
dependencies,
|
||||
settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static GoModule? ParseModule(ReadOnlySpan<char> span, bool isMain)
|
||||
{
|
||||
var fields = SplitFields(span, expected: 4);
|
||||
if (fields.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = fields[0];
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var version = fields.Count > 1 ? fields[1] : null;
|
||||
var sum = fields.Count > 2 ? fields[2] : null;
|
||||
|
||||
return new GoModule(path, version, sum, isMain);
|
||||
}
|
||||
|
||||
private static GoModuleReplacement? ParseReplacement(ReadOnlySpan<char> span)
|
||||
{
|
||||
var fields = SplitFields(span, expected: 3);
|
||||
if (fields.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = fields[0];
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var version = fields.Count > 1 ? fields[1] : null;
|
||||
var sum = fields.Count > 2 ? fields[2] : null;
|
||||
|
||||
return new GoModuleReplacement(path, version, sum);
|
||||
}
|
||||
|
||||
private static KeyValuePair<string, string?> ParseBuildSetting(ReadOnlySpan<char> span)
|
||||
{
|
||||
span = span.Trim();
|
||||
if (span.IsEmpty)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var separatorIndex = span.IndexOf('=');
|
||||
if (separatorIndex <= 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var rawKey = span[..separatorIndex].Trim();
|
||||
var rawValue = span[(separatorIndex + 1)..].Trim();
|
||||
|
||||
var key = Unquote(rawKey.ToString());
|
||||
if (string.IsNullOrWhiteSpace(key))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var value = Unquote(rawValue.ToString());
|
||||
return new KeyValuePair<string, string?>(key, value);
|
||||
}
|
||||
|
||||
private static List<string> SplitFields(ReadOnlySpan<char> span, int expected)
|
||||
{
|
||||
var fields = new List<string>(expected);
|
||||
var builder = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < span.Length; i++)
|
||||
{
|
||||
var current = span[i];
|
||||
if (current == '\t')
|
||||
{
|
||||
fields.Add(builder.ToString());
|
||||
builder.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append(current);
|
||||
}
|
||||
|
||||
fields.Add(builder.ToString());
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static string Unquote(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
value = value.Trim();
|
||||
if (value.Length < 2)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value[0] == '"' && value[^1] == '"')
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<string>(value) ?? value;
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if (value[0] == '`' && value[^1] == '`')
|
||||
{
|
||||
return value[1..^1];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user