From e794d7c8335127a824dcec0b3ed3cefeb1804ca6 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Mar 2026 23:18:46 +0200 Subject: [PATCH] Replace `Publish-MacOSBundle.ps1` with a .NET 10 single-file C# script (#1515) Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .../DiscordChatExporter.Gui.csproj | 2 +- .../Publish-MacOSBundle.csx | 128 ++++++++++++++++++ .../Publish-MacOSBundle.ps1 | 87 ------------ 3 files changed, 129 insertions(+), 88 deletions(-) create mode 100644 DiscordChatExporter.Gui/Publish-MacOSBundle.csx delete mode 100644 DiscordChatExporter.Gui/Publish-MacOSBundle.ps1 diff --git a/DiscordChatExporter.Gui/DiscordChatExporter.Gui.csproj b/DiscordChatExporter.Gui/DiscordChatExporter.Gui.csproj index e5e27df3..73ed4d1d 100644 --- a/DiscordChatExporter.Gui/DiscordChatExporter.Gui.csproj +++ b/DiscordChatExporter.Gui/DiscordChatExporter.Gui.csproj @@ -56,7 +56,7 @@ diff --git a/DiscordChatExporter.Gui/Publish-MacOSBundle.csx b/DiscordChatExporter.Gui/Publish-MacOSBundle.csx new file mode 100644 index 00000000..ab6fc635 --- /dev/null +++ b/DiscordChatExporter.Gui/Publish-MacOSBundle.csx @@ -0,0 +1,128 @@ +#!/usr/bin/env -S dotnet run -- +#:package CliFx + +using CliFx; +using CliFx.Attributes; +using CliFx.Infrastructure; + +return await new CliApplicationBuilder() + .AddCommand() + .Build() + .RunAsync(args); + +[Command(Description = "Publishes the GUI app as a macOS .app bundle.")] +public class PublishMacOSBundleCommand : ICommand +{ + private const string BundleName = "DiscordChatExporter.app"; + private const string AppName = "DiscordChatExporter"; + private const string AppCopyright = "© Oleksii Holub"; + private const string AppIdentifier = "me.Tyrrrz.DiscordChatExporter"; + private const string AppSpokenName = "Discord Chat Exporter"; + private const string AppIconName = "AppIcon"; + + [CommandOption("publish-dir", Description = "Path to the publish output directory.")] + public required string PublishDirPath { get; init; } + + [CommandOption("icons-file", Description = "Path to the .icns icons file.")] + public required string IconsFilePath { get; init; } + + [CommandOption("full-version", Description = "Full version string (e.g. '1.2.3.4').")] + public required string FullVersion { get; init; } + + [CommandOption("short-version", Description = "Short version string (e.g. '1.2.3').")] + public required string ShortVersion { get; init; } + + public async ValueTask ExecuteAsync(IConsole console) + { + // Set up paths + var publishDirPath = Path.GetFullPath(PublishDirPath); + var tempDirPath = Path.GetFullPath( + Path.Combine(publishDirPath, "../publish-macos-app-temp") + ); + + // Ensure the temporary directory is clean before use in case a previous run crashed + if (Directory.Exists(tempDirPath)) + Directory.Delete(tempDirPath, true); + + var bundleDirPath = Path.Combine(tempDirPath, BundleName); + var contentsDirPath = Path.Combine(bundleDirPath, "Contents"); + + try + { + // Copy icons into the .app's Resources folder + Directory.CreateDirectory(Path.Combine(contentsDirPath, "Resources")); + File.Copy( + IconsFilePath, + Path.Combine(contentsDirPath, "Resources", "AppIcon.icns"), + true + ); + + // Generate the Info.plist metadata file with the app information + // lang=xml + var plistContent = $""" + + + + + CFBundleDisplayName + {AppName} + CFBundleName + {AppName} + CFBundleExecutable + {AppName} + NSHumanReadableCopyright + {AppCopyright} + CFBundleIdentifier + {AppIdentifier} + CFBundleSpokenName + {AppSpokenName} + CFBundleIconFile + {AppIconName} + CFBundleIconName + {AppIconName} + CFBundleVersion + {FullVersion} + CFBundleShortVersionString + {ShortVersion} + NSHighResolutionCapable + + CFBundlePackageType + APPL + + + """; + + await File.WriteAllTextAsync(Path.Combine(contentsDirPath, "Info.plist"), plistContent); + + // Delete the previous bundle if it exists + var existingBundlePath = Path.Combine(publishDirPath, BundleName); + if (Directory.Exists(existingBundlePath)) + Directory.Delete(existingBundlePath, true); + + // Move all files from the publish directory into the MacOS directory + Directory.CreateDirectory(Path.Combine(contentsDirPath, "MacOS")); + foreach (var entryPath in Directory.GetFileSystemEntries(publishDirPath)) + { + var destinationPath = Path.Combine( + contentsDirPath, + "MacOS", + Path.GetFileName(entryPath) + ); + + if (Directory.Exists(entryPath)) + Directory.Move(entryPath, destinationPath); + else + File.Move(entryPath, destinationPath); + } + + // Move the final bundle into the publish directory for upload + Directory.Move(bundleDirPath, Path.Combine(publishDirPath, BundleName)); + } + finally + { + // Clean up the temporary directory + if (Directory.Exists(tempDirPath)) + Directory.Delete(tempDirPath, true); + } + } +} diff --git a/DiscordChatExporter.Gui/Publish-MacOSBundle.ps1 b/DiscordChatExporter.Gui/Publish-MacOSBundle.ps1 deleted file mode 100644 index fd08ea22..00000000 --- a/DiscordChatExporter.Gui/Publish-MacOSBundle.ps1 +++ /dev/null @@ -1,87 +0,0 @@ -param( - [Parameter(Mandatory=$true)] - [string]$PublishDirPath, - - [Parameter(Mandatory=$true)] - [string]$IconsFilePath, - - [Parameter(Mandatory=$true)] - [string]$FullVersion, - - [Parameter(Mandatory=$true)] - [string]$ShortVersion -) - -$ErrorActionPreference = "Stop" - -# Setup paths -$tempDirPath = Join-Path $PublishDirPath "../publish-macos-app-temp" -$bundleName = "DiscordChatExporter.app" -$bundleDirPath = Join-Path $tempDirPath $bundleName -$contentsDirPath = Join-Path $bundleDirPath "Contents" -$macosDirPath = Join-Path $contentsDirPath "MacOS" -$resourcesDirPath = Join-Path $contentsDirPath "Resources" - -try { - # Initialize the bundle's directory structure - New-Item -Path $bundleDirPath -ItemType Directory -Force - New-Item -Path $contentsDirPath -ItemType Directory -Force - New-Item -Path $macosDirPath -ItemType Directory -Force - New-Item -Path $resourcesDirPath -ItemType Directory -Force - - # Copy icons into the .app's Resources folder - Copy-Item -Path $IconsFilePath -Destination (Join-Path $resourcesDirPath "AppIcon.icns") -Force - - # Generate the Info.plist metadata file with the app information - $plistContent = @" - - - - - CFBundleDisplayName - DiscordChatExporter - CFBundleName - DiscordChatExporter - CFBundleExecutable - DiscordChatExporter - NSHumanReadableCopyright - © Oleksii Holub - CFBundleIdentifier - me.Tyrrrz.DiscordChatExporter - CFBundleSpokenName - Discord Chat Exporter - CFBundleIconFile - AppIcon - CFBundleIconName - AppIcon - CFBundleVersion - $FullVersion - CFBundleShortVersionString - $ShortVersion - NSHighResolutionCapable - - CFBundlePackageType - APPL - - -"@ - - Set-Content -Path (Join-Path $contentsDirPath "Info.plist") -Value $plistContent - - # Delete the previous bundle if it exists - if (Test-Path (Join-Path $PublishDirPath $bundleName)) { - Remove-Item -Path (Join-Path $PublishDirPath $bundleName) -Recurse -Force - } - - # Move all files from the publish directory into the MacOS directory - Get-ChildItem -Path $PublishDirPath | ForEach-Object { - Move-Item -Path $_.FullName -Destination $macosDirPath -Force - } - - # Move the final bundle into the publish directory for upload - Move-Item -Path $bundleDirPath -Destination $PublishDirPath -Force -} -finally { - # Clean up the temporary directory - Remove-Item -Path $tempDirPath -Recurse -Force -} \ No newline at end of file