Skip to content

Commit

Permalink
fix: fix trimming on publish
Browse files Browse the repository at this point in the history
  • Loading branch information
nevse committed Aug 27, 2023
1 parent 205504b commit 300cf35
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 112 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Set up .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'
- name: Install dependencies
run: dotnet restore ConvA/ConvA.csproj
- name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Set up .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: '7.0.x'
dotnet-version: '8.0.x'
- name: Install dependencies
run: dotnet restore ConvA/ConvA.csproj
- name: Build osx-arm64
Expand Down
11 changes: 11 additions & 0 deletions ConvA/Config.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
using System.Text.Json.Serialization;

namespace ConvA;

public class Config {
public string? RepositoryPath { get; set; }
public ConversionType? ConversionType { get; set; }
}

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Config))]
[JsonSerializable(typeof(ConversionType))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(int))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
16 changes: 13 additions & 3 deletions ConvA/ConvA.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<NoWarn>CA1861</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!--x-release-please-start-version-->
<Version>1.0.0</Version>
<!--x-release-please-end-->
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<PublishTrimmed>true</PublishTrimmed>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<IncludeSymbolsInSingleFile>false</IncludeSymbolsInSingleFile>
<EnableCompressionInSingleFile>false</EnableCompressionInSingleFile>
<DebugType>embedded</DebugType>
<UseAppHost>true</UseAppHost>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>
</Project>
8 changes: 4 additions & 4 deletions ConvA/Converters/DllReferenceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ protected override void ConvertCore(Project project, HashSet<PackageInfo> packag
}
string referenceCondition = reference.Condition.ToLower();
if (referenceCondition.Contains("-android")) {
if (androidReferences.ContainsKey(reference.Name!)) {
if (project.UpdateDllReference(reference.Name!, androidReferences[reference.Name!], reference.Condition))
if (androidReferences.TryGetValue(reference.Name!, out string? value)) {
if (project.UpdateDllReference(reference.Name!, value, reference.Condition))
androidReferences.Remove(reference.Name!);
}
} else if (referenceCondition.Contains("-ios")) {
if (iosReferences.ContainsKey(reference.Name!)) {
if (project.UpdateDllReference(reference.Name!, iosReferences[reference.Name!], reference.Condition))
if (iosReferences.TryGetValue(reference.Name!, out string? value)) {
if (project.UpdateDllReference(reference.Name!, value, reference.Condition))
iosReferences.Remove(reference.Name!);
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions ConvA/Converters/ProjectReferenceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected override void ConvertCore(Project project, HashSet<PackageInfo> packag
projectReferencesToRemove.Add(projectReference);
}
}
} else if (projectReference.Condition.ToLower().Contains("android")) {
} else if (projectReference.Condition.Contains("android", StringComparison.CurrentCultureIgnoreCase)) {
if (androidProjectReferences.Contains(dllReferenceName)) {
if (project.UpdateProjectReference(projectReference.Path, RepoInfo.GetProjectPath(dllReferenceName),
projectReference.Condition))
Expand All @@ -53,7 +53,7 @@ protected override void ConvertCore(Project project, HashSet<PackageInfo> packag
projectReferencesToRemove.Add(projectReference);
}
}
} else if (projectReference.Condition.ToLower().Contains("ios")) {
} else if (projectReference.Condition.Contains("ios", StringComparison.CurrentCultureIgnoreCase)) {
if (iosProjectReferences.Contains(dllReferenceName)) {
if (project.UpdateProjectReference(projectReference.Path, RepoInfo.GetProjectPath(dllReferenceName),
projectReference.Condition))
Expand Down
2 changes: 1 addition & 1 deletion ConvA/Models/ConversionType.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace ConvA;

public enum ConversionType {
public enum ConversionType: int {
Proj,
Proj2,
Package,
Expand Down
162 changes: 73 additions & 89 deletions ConvA/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Diagnostics.CodeAnalysis;
using CommandLine;
using System.CommandLine;
using System.CommandLine.Parsing;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using CommandLine.Text;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace ConvA;

Expand All @@ -12,94 +14,76 @@ class Program {

[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Program))]
public static async Task<int> Main(string[] args) {
var parser = new Parser(with => {
with.CaseInsensitiveEnumValues = true;
});

ParserResult<Program>? parserResults = parser.ParseArguments<Program>(args);

await parserResults.WithParsedAsync(async p => await p.Run());
await parserResults.WithNotParsedAsync(async errors => await ShowErrors(errors));
return ((parserResults is Parsed<Program>) || IsHelpOrVersionRequested ) ? 0 : -1;
var repositoryPathArgument = new Argument<string>
("path to repo", () => "" , "Path to working repository.");

var fileOption = new Option<ConversionType?>(
aliases: new[] { "-t", "--type" },
description: "Project conversion type",
getDefaultValue: () => ConversionType.Proj);

var projectPathOption = new Option<string>(
aliases: new[] { "-p", "--path" },
description: "Path to project to convert");

var patchVersionOption = new Option<string>(
name: "--patch-version",
description: "Version of package reference");

var rootCommand = new RootCommand();
rootCommand.AddArgument(repositoryPathArgument);
rootCommand.AddOption(fileOption);
rootCommand.AddOption(projectPathOption);
rootCommand.AddOption(patchVersionOption);

rootCommand.SetHandler(Run, repositoryPathArgument, fileOption, projectPathOption, patchVersionOption);
return await rootCommand.InvokeAsync(args);
}
static async Task ShowErrors(IEnumerable<Error> errors) {
foreach (var error in errors) {
if (error is HelpRequestedError) {
Parser.Default.ParseArguments<Program>(new[] { "--help" });
IsHelpOrVersionRequested = true;
continue;
} else if (error is VersionRequestedError) {
Parser.Default.ParseArguments<Program>(new[] { "--version" });
IsHelpOrVersionRequested = true;
continue;
} else if (error is UnknownOptionError unknownOptionError) {
Console.WriteLine($"Unknown option: {unknownOptionError.Token}");
Parser.Default.ParseArguments<Program>(new[] { "--help" });
continue;
}
}
await Task.CompletedTask;
}

public Config? Config { get; private set; }

// Options
[Value(0, MetaName = "input", HelpText = "Path to working repository.")]
public string? RepositoryPath { get; set; }

[Option('t', "type", Required = false, Default = ConversionType.Proj, HelpText = "Project conversion type (package|dll|proj|proj2)")]
public ConversionType Type { get; set; } = ConversionType.Proj;

[Option('p', "path", Required = false, Default = null, HelpText = "Path to project to convert")]
public string? ProjectPath { get; set; }

[Option("patch-version", Required = false, Default = "", HelpText = "Version of package reference")]
public string? PatchVersion { get; set; }

//usage example
[Usage(ApplicationAlias = "conva")]
public static IEnumerable<Example> Examples {
get {
return new List<Example>() {
new("Convert project in current dir to project references",
new Program { RepositoryPath = "~/work/my-repo", Type = ConversionType.Proj }),
new("Convert project in current dir to dll references",
new Program { RepositoryPath = "~/work/my-repo", Type = ConversionType.Dll }),
new("Convert project in current dir to package references with version 10.2.7",
new Program {
RepositoryPath = "~/work/my-repo",
Type = ConversionType.Package,
PatchVersion = "10.2.7"
}),
};
}
}

async Task Run() {
Instance = this;
string actualProjectPath = ProjectPath ?? Directory.GetCurrentDirectory();
Config = await GetConfig(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(ConvA), ConfigFileName)) ?? new Config();
RepositoryPath ??= Config.RepositoryPath;
// [Usage(ApplicationAlias = "conva")]
// public static IEnumerable<Example> Examples {
// get {
// return new List<Example>() {
// new("Convert project in current dir to project references",
// new Program { RepositoryPath = "~/work/my-repo", Type = ConversionType.Proj }),
// new("Convert project in current dir to dll references",
// new Program { RepositoryPath = "~/work/my-repo", Type = ConversionType.Dll }),
// new("Convert project in current dir to package references with version 10.2.7",
// new Program {
// RepositoryPath = "~/work/my-repo",
// Type = ConversionType.Package,
// PatchVersion = "10.2.7"
// }),
// };
// }
// }

static async Task<int> Run(string? repositoryPath, ConversionType? type, string? projectPath, string? packageVersion) {
string actualProjectPath = projectPath ?? Directory.GetCurrentDirectory();
var config = await GetConfig(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(ConvA), ConfigFileName)) ?? new Config();
if (String.IsNullOrEmpty(repositoryPath))
repositoryPath = null;
repositoryPath ??= config.RepositoryPath;
Config? localConfig = FindLocalConfig(actualProjectPath);
RepositoryPath ??= localConfig?.RepositoryPath;
RepositoryPath ??= GetRepositoryPathFromProject(actualProjectPath);
if (String.IsNullOrEmpty(RepositoryPath) || !Directory.Exists(RepositoryPath)) {
repositoryPath ??= localConfig?.RepositoryPath;
repositoryPath ??= GetRepositoryPathFromProject(actualProjectPath);
if (String.IsNullOrEmpty(repositoryPath) || !Directory.Exists(repositoryPath)) {
Console.WriteLine("Path to working repository is not specified.");
Parser.Default.ParseArguments<Program>(new[] { "--help" });
return;
//Parser.Default.ParseArguments<Program>(new[] { "--help" });
return -1;
}

RepositoryPath = PathHelper.ExpandPath(RepositoryPath);
repositoryPath = PathHelper.ExpandPath(repositoryPath);
string projectDir = File.Exists(actualProjectPath) ? Path.GetDirectoryName(actualProjectPath)! : actualProjectPath;
RepoInfo repoInfo = new(RepositoryPath);
RepoInfo repoInfo = new(repositoryPath);
repoInfo.Build();
string actualVersion = String.IsNullOrEmpty(PatchVersion) ? repoInfo.GetVersion() : PatchVersion;
ProjectConverterBase converter = Type switch {
string actualVersion = String.IsNullOrEmpty(packageVersion) ? repoInfo.GetVersion() : packageVersion;
ProjectConverterBase converter = type switch {
ConversionType.Proj => new ProjectReferenceConverter(repoInfo, false),
ConversionType.Proj2 => new ProjectReferenceConverter(repoInfo, true),
ConversionType.Dll => new DllReferenceConverter(repoInfo),
ConversionType.Package => new PackageReferenceConverter(repoInfo, actualVersion),
_ => throw new NotSupportedException($"Conversion type {Type} is not supported")
_ => throw new NotSupportedException($"Conversion type {type} is not supported")
};
IEnumerable<string> projectFiles = File.Exists(actualProjectPath) ? new[] { actualProjectPath } : Directory.EnumerateFiles(actualProjectPath, "*.csproj");
foreach (var projectFileName in projectFiles) {
Expand All @@ -108,7 +92,8 @@ async Task Run() {
project.SaveBackup();
project.Save();
}
await SaveConfig(RepositoryPath, Type, Path.Combine(projectDir, ConfigFileName));
await SaveConfig(repositoryPath, type, Path.Combine(projectDir, ConfigFileName));
return 0;
}

static string? GetRepositoryPathFromProject(string actualProjectPath) {
Expand Down Expand Up @@ -153,7 +138,8 @@ async Task Run() {
} while (directoryInfo != null);
return null;
}
Config? FindLocalConfig(string path) {

static Config? FindLocalConfig(string path) {
if (String.IsNullOrEmpty(path))
return null;
if (File.Exists(path))
Expand All @@ -163,7 +149,7 @@ async Task Run() {
var configFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, ConfigFileName));
if (configFileInfo.Exists) {
using var configStream = configFileInfo.OpenRead();
return JsonSerializer.Deserialize<Config>(configStream) ?? new Config();
return JsonSerializer.Deserialize<Config>(configStream, SourceGenerationContext.Default.Config) ?? new Config();
}
directoryInfo = directoryInfo.Parent;
if (directoryInfo == null)
Expand All @@ -173,22 +159,20 @@ async Task Run() {
return null;
}

[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
async Task<Config?> GetConfig(string path) {
static async Task<Config?> GetConfig(string path) {
var configFileInfo = new FileInfo(path);
if (!configFileInfo.Exists)
return new Config();
await using var configStream = configFileInfo.OpenRead();
return await JsonSerializer.DeserializeAsync<Config>(configStream);
return await JsonSerializer.DeserializeAsync<Config>(configStream, SourceGenerationContext.Default.Config);
}

[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
public async Task SaveConfig(string repoPath, ConversionType conversionType, string path) {
static async Task SaveConfig(string repoPath, ConversionType? conversionType, string path) {
var configFileInfo = new FileInfo(path);
if (!configFileInfo.Directory!.Exists)
configFileInfo.Directory.Create();
Config = new Config { RepositoryPath = repoPath, ConversionType = conversionType };
var config = new Config { RepositoryPath = repoPath, ConversionType = conversionType };
await using var configStream = configFileInfo.OpenWrite();
await JsonSerializer.SerializeAsync(configStream, Config);
await JsonSerializer.SerializeAsync(configStream, config, SourceGenerationContext.Default.Config);
}
}
7 changes: 5 additions & 2 deletions ConvA/RepoInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace ConvA;

public class RepoInfo {
public partial class RepoInfo {
const string ProjectsBasePath = "xamarin/maui";
const string NuspecBasePath = "nuspec";

Expand Down Expand Up @@ -126,7 +126,7 @@ static bool HasCommonPath(string path, string projectPath) {
}

public string GetVersion() {
Regex regex = new(@"(\d+\.\d+\.\d+)-.*");
Regex regex = VersionRegex();
if (DevExpressDataVersion is not null) {
Match match = regex.Match(DevExpressDataVersion);
if (match.Success)
Expand All @@ -138,4 +138,7 @@ public string GetVersion() {
public bool CanConvertPackage(string packageName) {
return PackagesByNameDictionary.ContainsKey(packageName);
}

[GeneratedRegex(@"(\d+\.\d+\.\d+)-.*")]
private static partial Regex VersionRegex();
}
2 changes: 1 addition & 1 deletion ConvA/Workspace/PackageInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void Parse() {
defaultNamespace.AddNamespace("ns", nuspecRoot.GetNamespaceOfPrefix(""));
Id = nuspecRoot.SelectSingleNode("//ns:package/ns:metadata/ns:id", defaultNamespace)?.InnerText ??
throw new InvalidDataException("Package id is null");
if (Id == null || !Id.ToLower().Contains("maui")) {
if (Id == null || !Id.Contains("maui", StringComparison.CurrentCultureIgnoreCase)) {
throw new NotSupportedException($"Package {Id} is not a maui package");
}

Expand Down
Loading

0 comments on commit 300cf35

Please sign in to comment.