Binary tooling (#18726)

This commit is contained in:
Ella Hathaway 2024-03-12 10:30:23 -06:00 committed by GitHub
parent 15f666742c
commit b76440930b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 753 additions and 41 deletions

View file

@ -386,6 +386,7 @@ jobs:
find artifacts/ -type f -name "*.diff" -exec rsync -R {} -t ${targetFolder} \;
if [[ "${{ parameters.buildSourceOnly }}" == "True" ]]; then
find artifacts/prebuilt-report/ -exec rsync -R {} -t ${targetFolder} \;
find artifacts/log/binary-report/ -exec rsync -R {} -t ${targetFolder} \;
fi
find src/ -type f -name "*.binlog" -exec rsync -R {} -t ${targetFolder} \;
find src/ -type f -name "*.log" -exec rsync -R {} -t ${targetFolder} \;

View file

@ -2,8 +2,9 @@
### Usage: $0
###
### Prepares the environment for a source build by downloading Private.SourceBuilt.Artifacts.*.tar.gz and
### installing the version of dotnet referenced in global.json
### Prepares the environment for a source build by downloading Private.SourceBuilt.Artifacts.*.tar.gz,
### installing the version of dotnet referenced in global.json,
### and detecting binaries and removing any non-SB allowed binaries.
###
### Options:
### --no-artifacts Exclude the download of the previously source-built artifacts archive
@ -15,6 +16,21 @@
### --runtime-source-feed URL of a remote server or a local directory, from which SDKs and
### runtimes can be downloaded
### --runtime-source-feed-key Key for accessing the above server, if necessary
###
### Binary-Tooling options:
### --no-binary-tooling Don't run the binary tooling
### --allowed-binaries Path to the file containing the list of known binaries that are allowed
### in the VMR and can be kept for source-building.
### Default is src/installer/src/VirtualMonoRepo/allowed-binaries.txt
### --disallowed-sb-binaries Path to the file containing the list of known binaries that are allowed
### in the VMR but cannot be kept for source-building.
### Default is null.
### --with-sdk Use the SDK in the specified directory
### Default is the .NET SDK
### --with-packages URL or specified directory to use as the source feed for packages
### Default is the previously source-built artifacts archive
### --no-validate Do not run validation. Only remove the binaries.
### --no-clean Do not remove the binaries. Only run the validation.
set -euo pipefail
IFS=$'\n\t'
@ -26,8 +42,16 @@ function print_help () {
sed -n '/^### /,/^$/p' "$source" | cut -b 5-
}
# SB prep default arguments
defaultArtifactsRid='centos.8-x64'
# Binary Tooling default arguments
defaultAllowedBinaries="$REPO_ROOT/src/installer/src/VirtualMonoRepo/allowed-binaries.txt"
defaultDotnetSdk="$REPO_ROOT/.dotnet"
defaultPackagesDir="$REPO_ROOT/prereqs/packages"
defaultMode="All"
# SB prep arguments
buildBootstrap=true
downloadArtifacts=true
downloadPrebuilts=true
@ -35,6 +59,15 @@ installDotnet=true
artifactsRid=$defaultArtifactsRid
runtime_source_feed='' # IBM requested these to support s390x scenarios
runtime_source_feed_key='' # IBM requested these to support s390x scenarios
# Binary Tooling arguments
runBinaryTool=true
allowedBinaries=$defaultAllowedBinaries
disallowedSbBinaries=''
dotnetSdk=$defaultDotnetSdk
packagesSourceFeed=$defaultPackagesDir
mode=$defaultMode
positional_args=()
while :; do
if [ $# -le 0 ]; then
@ -69,6 +102,47 @@ while :; do
runtime_source_feed_key=$2
shift
;;
--no-binary-tooling)
runBinaryTool=false
;;
--allowed-binaries)
allowedBinaries=$2
if [ ! -f "$allowedBinaries" ]; then
echo "Allowed binaries file '$allowedBinaries' does not exist"
exit 1
fi
shift
;;
--disallowed-sb-binaries)
disallowedSbBinaries=$2
if [ ! -f "$disallowedSbBinaries" ]; then
echo "Disallowed source build binaries file '$disallowedSbBinaries' does not exist"
exit 1
fi
shift
;;
--with-sdk)
dotnetSdk=$2
if [ ! -d "$dotnetSdk" ]; then
echo "Custom SDK directory '$dotnetSdk' does not exist"
exit 1
fi
if [ ! -x "$dotnetSdk/dotnet" ]; then
echo "Custom SDK '$dotnetSdk/dotnet' does not exist or is not executable"
exit 1
fi
shift
;;
--with-packages)
packagesSourceFeed=$2
shift
;;
--no-clean)
mode="Validate"
;;
--no-validate)
mode="Clean"
;;
*)
positional_args+=("$1")
;;
@ -112,6 +186,56 @@ if [ "$installDotnet" == true ] && [ -d "$REPO_ROOT/.dotnet" ]; then
installDotnet=false;
fi
function ParseBinaryArgs {
# Attempting to run the binary tooling without an SDK will fail. So either the --with-sdk flag must be passed
# or a pre-existing .dotnet SDK directory must exist.
if [ "$dotnetSdk" == "$defaultDotnetSdk" ] && [ ! -d "$dotnetSdk" ]; then
echo " ERROR: A pre-existing .dotnet SDK directory is needed if --with-sdk is not provided. \
Please either supply an SDK using --with-sdk or execute ./eng/prep-source-build.sh before proceeding. Exiting..."
exit 1
fi
## Attemping to run the binary tooling without a packages directory or source-feed will fail. So either the
## --with-packages flag must be passed with a valid directory or a pre-existing packages directory must exist.
if [ "$packagesSourceFeed" == "$defaultPackagesDir" ] && [ ! -d "$packagesSourceFeed" ]; then
echo " ERROR: A pre-existing packages directory is needed if --with-packages is not provided. \
Please either supply a packages directory using --with-packages or \
execute ./eng/prep-source-build.sh with download artifacts enabled before proceeding. Exiting..."
exit 1
fi
# Attempting to run the binary tooling with a custom packages feed that does not
# have PackageVersions.props in the packages directory or source-feed will fail.
if [ "$packagesSourceFeed" != "$defaultPackagesDir" ] && [ ! -f "$packagesSourceFeed/PackageVersions.props" ]; then
echo " ERROR: PackageVersions.props is needed in the packages directory or source-feed. Exiting..."
exit 1
fi
# Set up the packages source feed if we're using the default artifacts
previouslyBuiltPackagesDir="$defaultPackagesDir/previously-source-built"
packageArtifacts="$defaultPackagesDir/archive/Private.SourceBuilt.Artifacts.*.tar.gz"
if [ "$packagesSourceFeed" == "$defaultPackagesDir" ]; then
if [ -d "$previouslyBuiltPackagesDir" ]; then
echo " Previously source built packages directory exists..."
echo " Using $previouslyBuiltPackagesDir as the source-feed for the binary tooling..."
packagesSourceFeed="$previouslyBuiltPackagesDir"
elif [ -f ${packageArtifacts} ]; then
echo " Unpacking Private.SourceBuilt.Artifacts.*.tar.gz to $previouslyBuiltPackagesDir..."
mkdir -p "$previouslyBuiltPackagesDir"
tar -xzf ${packageArtifacts} -C "$previouslyBuiltPackagesDir"
tar -xzf ${packageArtifacts} -C "$previouslyBuiltPackagesDir" PackageVersions.props
echo " Using $previouslyBuiltPackagesDir as the source-feed for the binary tooling..."
packagesSourceFeed="$previouslyBuiltPackagesDir"
else
echo " ERROR: A pre-existing package archive is needed if --with-packages is not provided. \
Please either supply a source-feed using --with-packages or execute ./eng/prep-source-build.sh \
with download artifacts enabled before proceeding. Exiting..."
exit 1
fi
fi
}
function DownloadArchive {
archiveType="$1"
isRequired="$2"
@ -171,6 +295,18 @@ function BootstrapArtifacts {
rm -rf "$workingDir"
}
function RunBinaryTool {
BinaryTool="$REPO_ROOT/eng/tools/BinaryToolKit"
TargetDir="$REPO_ROOT"
OutputDir="$REPO_ROOT/artifacts/log/binary-report"
# Set the environment variable for the packages source feed
export ARTIFACTS_PATH="$packagesSourceFeed"
# Run the BinaryDetection tool
"$dotnetSdk/dotnet" run --project "$BinaryTool" -c Release -p PackagesPropsDirectory="$packagesSourceFeed" "$TargetDir" "$OutputDir" -ab "$allowedBinaries" -db "$disallowedSbBinaries" -m $mode -l Debug
}
# Check for the version of dotnet to install
if [ "$installDotnet" == true ]; then
echo " Installing dotnet..."
@ -189,3 +325,8 @@ fi
if [ "$downloadPrebuilts" == true ]; then
DownloadArchive Prebuilts false $artifactsRid
fi
if [ "$runBinaryTool" == true ]; then
ParseBinaryArgs
RunBinaryTool
fi

View file

@ -0,0 +1,100 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace BinaryToolKit;
public class BinaryTool
{
public async Task ExecuteAsync(
string targetDirectory,
string outputReportDirectory,
string? allowedBinariesFile,
string? disallowedSbBinariesFile,
Modes mode)
{
DateTime startTime = DateTime.Now;
Log.LogInformation($"Starting binary tool at {startTime} in {mode} mode");
// Parse args
targetDirectory = GetAndValidateFullPath(
"TargetDirectory",
targetDirectory,
isDirectory: true,
createIfNotExist: false,
isRequired: true)!;
outputReportDirectory = GetAndValidateFullPath(
"OutputReportDirectory",
outputReportDirectory,
isDirectory: true,
createIfNotExist: true,
isRequired: true)!;
allowedBinariesFile = GetAndValidateFullPath(
"AllowedBinariesFile",
allowedBinariesFile,
isDirectory: false,
createIfNotExist: false,
isRequired: false);
disallowedSbBinariesFile = GetAndValidateFullPath(
"DisallowedSbBinariesFile",
disallowedSbBinariesFile,
isDirectory: false,
createIfNotExist: false,
isRequired: false);
// Run the tooling
var detectedBinaries = await DetectBinaries.ExecuteAsync(targetDirectory);
var comparedBinaries = CompareBinariesAgainstBaselines
.Execute(
detectedBinaries,
allowedBinariesFile,
disallowedSbBinariesFile,
outputReportDirectory,
targetDirectory,
mode);
if (mode.HasFlag(Modes.Clean))
{
RemoveBinaries.Execute(comparedBinaries, targetDirectory);
}
Log.LogInformation("Finished all binary tasks. Took " + (DateTime.Now - startTime).TotalSeconds + " seconds.");
}
private string? GetAndValidateFullPath(
string parameterName,
string? path,
bool isDirectory,
bool createIfNotExist,
bool isRequired)
{
if (string.IsNullOrWhiteSpace(path))
{
if (isRequired)
{
Log.LogError($"Required path for '{parameterName}' is empty or contains whitespace.");
Environment.Exit(1);
}
return null;
}
string fullPath = Path.GetFullPath(path);
bool exists = isDirectory ? Directory.Exists(fullPath) : File.Exists(fullPath);
if (!exists)
{
if (createIfNotExist && isDirectory)
{
Log.LogInformation($"Creating directory '{fullPath}' for '{parameterName}'.");
Directory.CreateDirectory(fullPath);
}
else
{
Log.LogError($"{(isDirectory ? "Directory" : "File")} '{fullPath}' for '{parameterName}' does not exist.");
Environment.Exit(1);
}
}
return fullPath;
}
}

View file

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="CheckPackagesPropsDirectory">
<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PackagesPropsDirectory></PackagesPropsDirectory>
<OutputType>Exe</OutputType>
</PropertyGroup>
<Target Name="CheckPackagesPropsDirectory">
<Error Condition="'$(PackagesPropsDirectory)' == ''" Text="PackagesPropsDirectory is not set. Please pass as an MSBuild Property" />
<Error Condition="!Exists('$(PackagesPropsDirectory)/PackageVersions.props')" Text="PackageVersions.props does not exist in $(PackagesPropsDirectory)." />
</Target>
<!-- Need to condition this import because msbuild will complain about the project not being valid otherwise. -->
<!-- With the condition, the CheckPackagesPropsDirectory will run as expected and show the respective errors. -->
<Import Project="$(PackagesPropsDirectory)/PackageVersions.props" Condition="'$(PackagesPropsDirectory)' != ''" />
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MicrosoftExtensionsFileSystemGlobbingVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsoleVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingVersion)" />
<PackageReference Include="System.CommandLine" Version="$(SystemCommandLineVersion)" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,134 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Extensions.FileSystemGlobbing;
namespace BinaryToolKit;
public static class CompareBinariesAgainstBaselines
{
public static List<string> Execute(
IEnumerable<string> detectedBinaries,
string? allowedBinariesFile,
string? disallowedSbBinariesFile,
string outputReportDirectory,
string targetDirectory,
Modes mode)
{
Log.LogInformation("Comparing detected binaries to baseline(s).");
var binariesToRemove = GetUnmatchedBinaries(
detectedBinaries,
allowedBinariesFile,
outputReportDirectory,
targetDirectory,
mode).ToList();
if (mode.HasFlag(Modes.Validate))
{
var nonSbBinariesToRemove = GetUnmatchedBinaries(
detectedBinaries,
disallowedSbBinariesFile,
outputReportDirectory,
targetDirectory,
mode).ToList();
var newBinaries = binariesToRemove.Intersect(nonSbBinariesToRemove);
if (newBinaries.Any())
{
string newBinariesFile = Path.Combine(outputReportDirectory, "NewBinaries.txt");
File.WriteAllLines(newBinariesFile, newBinaries);
Log.LogWarning($" {newBinaries.Count()} new binaries detected. Check '{newBinariesFile}' for details.");
}
}
Log.LogInformation("Finished comparing binaries.");
return binariesToRemove;
}
private static IEnumerable<string> GetUnmatchedBinaries(
IEnumerable<string> searchFiles,
string? baselineFile,
string outputReportDirectory,
string targetDirectory,
Modes mode)
{
var patterns = ParseBaselineFile(baselineFile);
if (mode.HasFlag(Modes.Validate))
{
// If validating in any mode (Mode == Validate or Mode == All),
// we need to detect both unused patterns and unmatched files.
// We simultaneously detect unused patterns and unmatched files for efficiency.
HashSet<string> unusedPatterns = new HashSet<string>(patterns);
HashSet<string> unmatchedFiles = new HashSet<string>(searchFiles);
foreach (string pattern in patterns)
{
Matcher matcher = new Matcher(StringComparison.Ordinal);
matcher.AddInclude(pattern);
var matches = matcher.Match(targetDirectory, searchFiles);
if (matches.HasMatches)
{
unusedPatterns.Remove(pattern);
unmatchedFiles.ExceptWith(matches.Files.Select(file => file.Path));
}
}
UpdateBaselineFile(baselineFile, outputReportDirectory, unusedPatterns);
return unmatchedFiles;
}
else if (mode == Modes.Clean)
{
// If only cleaning and not validating (Mode == Clean),
// we don't need to update the baseline files with unused patterns
// so we can just detect unmatched files.
Matcher matcher = new Matcher(StringComparison.Ordinal);
matcher.AddInclude("**/*");
matcher.AddExcludePatterns(patterns);
return matcher.Match(targetDirectory, searchFiles).Files.Select(file => file.Path);
}
else
{
// Unhandled mode
throw new ArgumentException($"Unhandled mode: {mode}");
}
}
private static IEnumerable<string> ParseBaselineFile(string? file) {
if (!File.Exists(file))
{
return Enumerable.Empty<string>();
}
// Read the baseline file and parse the patterns, ignoring comments and empty lines
return File.ReadLines(file)
.Select(line => line.Trim())
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith("#"))
.Select(line => line.Split('#')[0].Trim());
}
private static void UpdateBaselineFile(string? file, string outputReportDirectory, HashSet<string> unusedPatterns)
{
if(File.Exists(file))
{
var lines = File.ReadAllLines(file);
var newLines = lines.Where(line => !unusedPatterns.Contains(line)).ToList();
string updatedFile = Path.Combine(outputReportDirectory, "Updated" + Path.GetFileName(file));
File.WriteAllLines(updatedFile, newLines);
Log.LogInformation($" Updated baseline file '{file}' written to '{updatedFile}'");
}
}
}

View file

@ -0,0 +1,143 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using Microsoft.Extensions.FileSystemGlobbing;
using System.Text.RegularExpressions;
namespace BinaryToolKit;
public static class DetectBinaries
{
private const string Utf16Marker = "UTF-16";
private const int ChunkSize = 4096;
private static readonly Regex GitCleanRegex = new Regex(@"Would (remove|skip)( repository)? (.*)");
public static async Task<List<string>> ExecuteAsync(string targetDirectory)
{
Log.LogInformation($"Detecting binaries in '{targetDirectory}'...");
var matcher = new Matcher(StringComparison.Ordinal);
matcher.AddInclude("**/*");
matcher.AddExcludePatterns(await GetIgnoredPatternsAsync(targetDirectory));
IEnumerable<string> matchingFiles = matcher.GetResultsInFullPath(targetDirectory);
var tasks = matchingFiles
.Select(async file =>
{
return await IsBinaryAsync(file) ? file.Substring(targetDirectory.Length + 1) : null;
});
var binaryFiles = (await Task.WhenAll(tasks)).OfType<string>().ToList();
Log.LogInformation($"Finished binary detection.");
return binaryFiles;
}
private static async Task<List<string>> GetIgnoredPatternsAsync(string targetDirectory)
{
string gitDirectory = Path.Combine(targetDirectory, ".git");
bool isGitRepo = Directory.Exists(gitDirectory);
try
{
if (!isGitRepo)
{
// Configure a fake git repo to use so that we can run git clean -ndx
await ExecuteProcessAsync("git", $"-C {targetDirectory} init -q");
}
await ExecuteProcessAsync("git", $"-C {targetDirectory} config --global safe.directory {targetDirectory}");
string output = await ExecuteProcessAsync("git", $"-C {targetDirectory} clean -ndx");
List<string> ignoredPaths = output.Split(Environment.NewLine)
.Select(line => GitCleanRegex.Match(line))
.Where(match => match.Success)
.Select(match => match.Groups[3].Value)
.ToList();
if (isGitRepo)
{
ignoredPaths.Add(".git");
}
return ignoredPaths;
}
finally
{
// Ensure .git directory is deleted if it wasn't originally a git repo
if (!isGitRepo && Directory.Exists(gitDirectory))
{
Directory.Delete(gitDirectory, true);
}
}
}
private static async Task<bool> IsBinaryAsync(string filePath)
{
// Using the GNU diff heuristic to determine if a file is binary or not.
// For more details, refer to the GNU diff manual:
// https://www.gnu.org/software/diffutils/manual/html_node/Binary.html
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (BinaryReader br = new BinaryReader(fs))
{
byte[] buffer = new byte[ChunkSize];
int bytesRead = br.Read(buffer, 0, ChunkSize);
for (int i = 0; i < bytesRead; i++)
{
if (buffer[i] == 0)
{
// Need to check that the file is not UTF-16 encoded
// because heuristic can return false positives
return await IsNotUTF16Async(filePath);
}
}
}
return false;
}
private static async Task<bool> IsNotUTF16Async(string file)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
string output = await ExecuteProcessAsync("file", $"\"{file}\"");
output = output.Split(":")[1].Trim();
if (output.Contains(Utf16Marker))
{
return false;
}
}
return true;
}
private static async Task<string> ExecuteProcessAsync(string executable, string arguments)
{
ProcessStartInfo psi = new ()
{
FileName = executable,
Arguments = arguments,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var proc = Process.Start(psi)!;
string output = await proc.StandardOutput.ReadToEndAsync();
string error = await proc.StandardError.ReadToEndAsync();
await proc.WaitForExitAsync();
if (!string.IsNullOrEmpty(error))
{
Log.LogError(error);
}
return output;
}
}

View file

@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Extensions.Logging;
namespace BinaryToolKit;
public static class Log
{
public static LogLevel Level = LogLevel.Information;
private static readonly Lazy<ILogger> _logger = new Lazy<ILogger>(ConfigureLogger);
public static void LogDebug(string message)
{
_logger.Value.LogDebug(message);
}
public static void LogInformation(string message)
{
_logger.Value.LogInformation(message);
}
public static void LogWarning(string message)
{
_logger.Value.LogWarning(message);
}
public static void LogError(string message)
{
_logger.Value.LogError(message);
}
private static ILogger ConfigureLogger()
{
using ILoggerFactory loggerFactory =
LoggerFactory.Create(builder =>
builder.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.TimestampFormat = "HH:mm:ss ";
options.UseUtcTimestamp = true;
})
.SetMinimumLevel(Level));
return loggerFactory.CreateLogger("BinaryTool");
}
}

View file

@ -0,0 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace BinaryToolKit;
[Flags]
public enum Modes
{
Validate = 1,
Clean = 2,
All = Validate | Clean
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<!-- %ARTIFACTS_PATH% must be set via an environment variable (export ARTIFACTS_PATH=<path-to-sources>). -->
<add key="artifactsPath" value="%ARTIFACTS_PATH%" />
</packageSources>
</configuration>

View file

@ -0,0 +1,76 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.CommandLine;
using Microsoft.Extensions.Logging;
namespace BinaryToolKit;
public class Program
{
public static async Task<int> Main(string[] args)
{
CliArgument<string> TargetDirectory = new("target-directory")
{
Description = "The directory to run the binary tooling on."
};
CliArgument<string> OutputReportDirectory = new("output-report-directory")
{
Description = "The directory to output the report to."
};
CliOption<string> AllowedBinariesFile = new("--allowed-binaries", "-ab")
{
Description = "The file containing the list of known binaries " +
"that are allowed in the VMR and can be kept for source-building."
};
CliOption<string> DisallowedSbBinariesFile = new("--disallowed-sb-binaries", "-db")
{
Description = "The file containing the list of known binaries " +
"that are allowed in the VMR but cannot be kept for source-building."
};
CliOption<Modes> Mode = new("--mode", "-m")
{
Description = "The mode to run the tool in.",
Arity = ArgumentArity.ZeroOrOne,
DefaultValueFactory = _ => Modes.All
};
CliOption<LogLevel> Level = new("--log-level", "-l")
{
Description = "The log level to run the tool in.",
Arity = ArgumentArity.ZeroOrOne,
DefaultValueFactory = _ => LogLevel.Information
};
var rootCommand = new CliRootCommand("Tool for detecting, validating, and cleaning binaries in the target directory.")
{
TargetDirectory,
OutputReportDirectory,
AllowedBinariesFile,
DisallowedSbBinariesFile,
Mode,
Level
};
rootCommand.SetAction(async (result, CancellationToken) =>
{
Log.Level = result.GetValue(Level);
var binaryTool = new BinaryTool();
await binaryTool.ExecuteAsync(
result.GetValue(TargetDirectory)!,
result.GetValue(OutputReportDirectory)!,
result.GetValue(AllowedBinariesFile),
result.GetValue(DisallowedSbBinariesFile),
result.GetValue(Mode));
});
return await rootCommand.Parse(args).InvokeAsync();
}
}

View file

@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Extensions.Logging;
namespace BinaryToolKit;
public static class RemoveBinaries
{
public static void Execute(IEnumerable<string> binariesToRemove, string targetDirectory)
{
Log.LogInformation($"Removing binaries from '{targetDirectory}'...");
foreach (var binary in binariesToRemove)
{
File.Delete(Path.Combine(targetDirectory, binary));
Log.LogDebug($" Removed '{binary}'");
}
Log.LogInformation($"Finished binary removal. Removed {binariesToRemove.Count()} binaries.");
}
}

View file

@ -1,64 +1,65 @@
*.bmp
*.doc
*.docx
*.gif
*.ico
*.jpg
*.JPG
*.pdf
*.png
*.PNG
*.rtf
*.snk
*.vsd
*.vsdx
*.xlsx
*.ttf
*.cur
*.icm
*.reg
**/*.bmp
**/*.doc
**/*.docx
**/*.gif
**/*.ico
**/*.jpg
**/*.JPG
**/*.pdf
**/*.png
**/*.PNG
**/*.rtf
**/*.snk
**/*.vsd
**/*.vsdx
**/*.xlsx
**/*.ttf
**/*.cur
**/*.icm
**/*.reg
**/test/*
**/Test/*
**/Test/*
**/test/**/*
**/Test/**/*
**/Test/**/*
**/testCert*.pfx
**/TestCert*.pfx
**/tests/*
**/tests/**/*
eng/common/loc/*.lss # UTF16-LE text files
**/eng/common/loc/*.lss # UTF16-LE text files
src/aspnetcore/**/samples/*
src/aspnetcore/**/TestCertificates/*
src/aspnetcore/src/*.eot
src/aspnetcore/src/*.otf
src/aspnetcore/src/*.woff
src/aspnetcore/src/*.woff2
src/aspnetcore/**/samples/**/*
src/aspnetcore/**/TestCertificates/**/*
src/aspnetcore/src/**/*.eot
src/aspnetcore/src/**/*.otf
src/aspnetcore/src/**/*.woff
src/aspnetcore/src/**/*.woff2
src/aspnetcore/src/Components/Web.JS/dist/Release/blazor.*.js # JavaScript files with a null bytes
src/aspnetcore/src/ProjectTemplates/Web.ProjectTemplates/**/app.db
src/aspnetcore/src/submodules/spa-templates/**/app.db
src/aspnetcore/src/submodules/Node-Externals/cache/**/* # https://github.com/dotnet/source-build/issues/4161
src/fsharp/**/signedtests/*
src/fsharp/**/signedtests/**/*
src/fsharp/src/fsi/fsi.res # Icon
src/msbuild/src/Tasks.UnitTests/*
src/msbuild/src/Tasks.UnitTests/**/*
src/razor/**/SampleApp/**/fonts/*
src/razor/**/SampleApp/**/fonts/**/*
src/roslyn/**/CodeAnalysisTest/*
src/roslyn/**/CodeAnalysisTest/**/*
src/roslyn/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/Resources/WindowsProxy.winmd # https://github.com/dotnet/roslyn/issues/66718
src/runtime/src/*.woff
src/runtime/src/*.woff2
src/runtime/src/**/*.woff
src/runtime/src/**/*.woff2
src/runtime/src/libraries/System.Diagnostics.EventLog/src/Messages/EventLogMessages.res # Icon
src/runtime/src/libraries/System.Speech/src/*.upsmap # https://github.com/dotnet/runtime/issues/81692
src/runtime/src/libraries/System.Speech/src/**/*.upsmap # https://github.com/dotnet/runtime/issues/81692
src/runtime/src/libraries/System.Text.Encoding.CodePages/src/Data/codepages.nlp # https://github.com/dotnet/runtime/issues/81693
src/runtime/src/mono/wasm/testassets/*
src/runtime/src/mono/wasm/testassets/**/*
src/runtime/src/native/external/brotli/common/dictionary.bin.br
src/sdk/src/Assets/TestProjects/*
src/sdk/src/Assets/TestProjects/**/*
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/build/strongNameBypass.reg # UTF16-LE text file
src/source-build-externals/src/azure-activedirectory-identitymodel-extensions-for-dotnet/build/strongNameBypass2.reg # UTF16-LE text file
src/source-build-externals/src/humanizer/src/Humanizer.Tests*
src/source-build-externals/src/humanizer/src/Humanizer.Tests**/*
src/source-build-externals/src/newtonsoft-json/Src/Newtonsoft.Json.Tests/SpaceShipV2.bson