public static bool AddPathToArchivePlan(ArchivePlan plan, string sourcePath, string destinationPath) { var basePath = plan.Config.GetProjectRelativePath(sourcePath); if (Directory.Exists(basePath)) { var destDirectory = FormatArchivePath(destinationPath, false); if (!destDirectory.EndsWith('/')) { destDirectory = $"{destDirectory}/"; } foreach (string filename in Directory.EnumerateFiles(basePath, "*.*", SearchOption.AllDirectories)) { var targetPath = FormatArchivePath($"{destDirectory}{filename[(basePath.Length + 1)..]}");
public static int DoBuild(Config.Config config) { var packageId = config.GetPackageId(); Write.WithNL($"Building {Cyan(packageId)}", after: true); var readmePath = config.GetPackageReadmePath(); if (!File.Exists(readmePath)) { Write.ErrorExit($"Readme not found from the declared path: {White(Dim(readmePath))}"); return(1); } var iconPath = config.GetPackageIconPath(); if (!File.Exists(iconPath)) { Write.ErrorExit($"Icon not found from the declared path: {White(Dim(iconPath))}"); return(1); } var outDir = config.GetBuildOutputDir(); if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } var filename = config.GetBuildOutputFile(); Write.Line($"Output path {Cyan(filename)}"); var encounteredIssues = false; var plan = new ArchivePlan(config); Write.Header("Planning for files to include in build"); plan.AddPlan("icon.png", () => File.ReadAllBytes(iconPath)); plan.AddPlan("README.md", () => File.ReadAllBytes(readmePath)); plan.AddPlan("manifest.json", () => Encoding.UTF8.GetBytes(SerializeManifest(config))); if (config.BuildConfig.CopyPaths is not null) { foreach (var pathMap in config.BuildConfig.CopyPaths) { Write.WithNL($"Mapping {Dim(pathMap.From)} to {Dim($"/{pathMap.To}")}", before: true); encounteredIssues |= !AddPathToArchivePlan(plan, pathMap.From, pathMap.To); } } if (plan.HasErrors) { Write.Empty(); Write.ErrorExit( "Build was aborted due to errors identified in planning phase", "Adjust your configuration so no issues are present" ); return(1); } Write.Header("Writing configured files"); using (var outputFile = File.Open(filename, FileMode.Create)) { using (var archive = new ZipArchive(outputFile, ZipArchiveMode.Create)) { var isWindows = OperatingSystem.IsWindows(); foreach (var entry in plan) { Write.Light($"Writing /{entry.Key}"); var archiveEntry = archive.CreateEntry(entry.Key, CompressionLevel.Optimal); if (!isWindows) { // https://github.com/dotnet/runtime/issues/17912#issuecomment-641594638 // modifed solution to use a constant instead of a string conversion archiveEntry.ExternalAttributes |= 0b110110100 << 16; // rw-rw-r-- permissions } using (var writer = new BinaryWriter(archiveEntry.Open())) { writer.Write(entry.Value()); } } } } Write.Empty(); if (encounteredIssues || plan.HasWarnings) { Write.Note("Some issues were encountered when building, see output for more details"); return(1); } else { Write.Success($"Successfully built {Cyan(packageId)}"); return(0); } }