Esempio n. 1
0
        private static void Publish()
        {
            if (Directory.Exists(BinDistDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(BinDistDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {BinDistDirectory}");
            }

            StartProcessAndWaitForExit("cmd", DesktopProjectDirectory, "dotnet clean --configuration Release && exit");

            var desktopBinReleaseDirectory = Path.GetFullPath(Path.Combine(DesktopProjectDirectory, "bin", "Release"));
            var libraryBinReleaseDirectory = Path.GetFullPath(Path.Combine(LibraryProjectDirectory, "bin", "Release"));

            if (Directory.Exists(desktopBinReleaseDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(desktopBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {desktopBinReleaseDirectory}");
            }
            if (Directory.Exists(libraryBinReleaseDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(libraryBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {libraryBinReleaseDirectory}");
            }

            var deterministicFileNameTag = IsContinuousDelivery ? $"{DateTimeOffset.UtcNow:ddMMyyyy}{DateTimeOffset.UtcNow.TimeOfDay.TotalSeconds}" : VersionPrefix;
            var deliveryPath             = IsContinuousDelivery ? Path.Combine(BinDistDirectory, "cdelivery") : BinDistDirectory;

            IoHelpers.EnsureDirectoryExists(deliveryPath);
            Console.WriteLine($"Binaries will be delivered here: {deliveryPath}");

            foreach (string target in Targets)
            {
                string publishedFolder         = Path.Combine(BinDistDirectory, target);
                string currentBinDistDirectory = publishedFolder;

                Console.WriteLine();
                Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

                Console.WriteLine();
                if (!Directory.Exists(currentBinDistDirectory))
                {
                    Directory.CreateDirectory(currentBinDistDirectory);
                    Console.WriteLine($"Created {currentBinDistDirectory}");
                }

                StartProcessAndWaitForExit("dotnet", DesktopProjectDirectory, arguments: "clean");

                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21
                // -c|--configuration {Debug|Release}
                //		Defines the build configuration. The default value is Debug.
                // --force
                //		Forces all dependencies to be resolved even if the last restore was successful. Specifying this flag is the same as deleting the project.assets.json file.
                // -o|--output <OUTPUT_DIRECTORY>
                //		Specifies the path for the output directory.
                //		If not specified, it defaults to ./bin/[configuration]/[framework]/publish/ for a framework-dependent deployment or
                //		./bin/[configuration]/[framework]/[runtime]/publish/ for a self-contained deployment.
                //		If the path is relative, the output directory generated is relative to the project file location, not to the current working directory.
                // --self-contained
                //		Publishes the .NET Core runtime with your application so the runtime does not need to be installed on the target machine.
                //		If a runtime identifier is specified, its default value is true. For more information about the different deployment types, see .NET Core application deployment.
                // -r|--runtime <RUNTIME_IDENTIFIER>
                //		Publishes the application for a given runtime. This is used when creating a self-contained deployment (SCD).
                //		For a list of Runtime Identifiers (RIDs), see the RID catalog. Default is to publish a framework-dependent deployment (FDD).
                // --version-suffix <VERSION_SUFFIX>
                //		Defines the version suffix to replace the asterisk (*) in the version field of the project file.
                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore?tabs=netcore2x
                // --disable-parallel
                //		Disables restoring multiple projects in parallel.
                // --no-cache
                //		Specifies to not cache packages and HTTP requests.
                // https://github.com/dotnet/docs/issues/7568
                // /p:Version=1.2.3.4
                //		"dotnet publish" supports msbuild command line options like /p:Version=1.2.3.4

                string dotnetProcessArgs = string.Join(
                    " ",
                    $"publish",
                    $"--configuration Release",
                    $"--force",
                    $"--output \"{currentBinDistDirectory}\"",
                    $"--self-contained true",
                    $"--runtime \"{target}\"",
                    $"--disable-parallel",
                    $"--no-cache",
                    $"/p:VersionPrefix={VersionPrefix}",
                    $"/p:DebugType=none",
                    $"/p:DebugSymbols=false",
                    $"/p:ErrorReport=none",
                    $"/p:DocumentationFile=\"\"",
                    $"/p:Deterministic=true",
                    $"/p:RestoreLockedMode=true");

                StartProcessAndWaitForExit(
                    "dotnet",
                    DesktopProjectDirectory,
                    arguments: dotnetProcessArgs,
                    redirectStandardOutput: true);

                Tools.ClearSha512Tags(currentBinDistDirectory);

                // Remove Tor binaries that are not relevant to the platform.
                var toNotRemove = "";
                if (target.StartsWith("win"))
                {
                    toNotRemove = "win";
                }
                else if (target.StartsWith("linux"))
                {
                    toNotRemove = "lin";
                }
                else if (target.StartsWith("osx"))
                {
                    toNotRemove = "osx";
                }

                // Remove binaries that are not relevant to the platform.
                var binaryFolder = new DirectoryInfo(Path.Combine(currentBinDistDirectory, "Microservices", "Binaries"));

                foreach (var dir in binaryFolder.EnumerateDirectories())
                {
                    if (!dir.Name.Contains(toNotRemove, StringComparison.OrdinalIgnoreCase))
                    {
                        IoHelpers.TryDeleteDirectoryAsync(dir.FullName).GetAwaiter().GetResult();
                    }
                }

                // Rename the final exe.
                string oldExecutablePath;
                string newExecutablePath;
                if (target.StartsWith("win"))
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Fluent.Desktop.exe");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, $"{ExecutableName}.exe");

                    // Delete unused executables.
                    File.Delete(Path.Combine(currentBinDistDirectory, "WalletWasabi.Fluent.exe"));
                }
                else                 // Linux & OSX
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Fluent.Desktop");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, ExecutableName);

                    // Delete unused executables.
                    File.Delete(Path.Combine(currentBinDistDirectory, "WalletWasabi.Fluent"));
                }
                File.Move(oldExecutablePath, newExecutablePath);

                long installedSizeKb = Tools.DirSize(new DirectoryInfo(publishedFolder)) / 1000;

                if (target.StartsWith("win"))
                {
                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;                         // In Windows build at this moment it does not matter though.
                    }

                    ZipFile.CreateFromDirectory(currentBinDistDirectory, Path.Combine(deliveryPath, $"Wasabi-{deterministicFileNameTag}-{target}.zip"));

                    if (IsContinuousDelivery)
                    {
                        continue;
                    }
                }
                else if (target.StartsWith("osx"))
                {
                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;
                    }

                    ZipFile.CreateFromDirectory(currentBinDistDirectory, Path.Combine(deliveryPath, $"Wasabi-{deterministicFileNameTag}-{target}.zip"));

                    if (IsContinuousDelivery)
                    {
                        continue;
                    }

                    ZipFile.CreateFromDirectory(currentBinDistDirectory, Path.Combine(BinDistDirectory, $"Wasabi-osx-{VersionPrefix}.zip"));

                    IoHelpers.TryDeleteDirectoryAsync(currentBinDistDirectory).GetAwaiter().GetResult();
                    Console.WriteLine($"Deleted {currentBinDistDirectory}");
                }
                else if (target.StartsWith("linux"))
                {
                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;
                    }

                    ZipFile.CreateFromDirectory(currentBinDistDirectory, Path.Combine(deliveryPath, $"Wasabi-{deterministicFileNameTag}-{target}.zip"));

                    if (IsContinuousDelivery)
                    {
                        continue;
                    }

                    Console.WriteLine("Create Linux .tar.gz");
                    if (!Directory.Exists(publishedFolder))
                    {
                        throw new Exception($"{publishedFolder} does not exist.");
                    }
                    var newFolderName = $"Wasabi-{VersionPrefix}";
                    var newFolderPath = Path.Combine(BinDistDirectory, newFolderName);
                    Directory.Move(publishedFolder, newFolderPath);
                    publishedFolder = newFolderPath;

                    var driveLetterUpper = BinDistDirectory[0];
                    var driveLetterLower = char.ToLower(driveLetterUpper);

                    var linuxPath = $"/mnt/{driveLetterLower}/{Tools.LinuxPath(BinDistDirectory[3..])}";
Esempio n. 2
0
        private static void Publish()
        {
            if (Directory.Exists(BinDistDirectory))
            {
                IoHelpers.DeleteRecursivelyWithMagicDustAsync(BinDistDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {BinDistDirectory}");
            }

            using (var process = Process.Start(new ProcessStartInfo
            {
                FileName = "cmd",
                RedirectStandardInput = true,
                WorkingDirectory = SolutionDirectory
            }))
            {
                process.StandardInput.WriteLine("git submodule update --init --recursive && exit");
                process.WaitForExit();
            }

            using (var process = Process.Start(new ProcessStartInfo
            {
                FileName = "cmd",
                RedirectStandardInput = true,
                WorkingDirectory = GuiProjectDirectory
            }))
            {
                process.StandardInput.WriteLine("dotnet clean --configuration Release && exit");
                process.WaitForExit();
            }

            var guiBinReleaseDirectory     = Path.GetFullPath(Path.Combine(GuiProjectDirectory, "bin\\Release"));
            var libraryBinReleaseDirectory = Path.GetFullPath(Path.Combine(LibraryProjectDirectory, "bin\\Release"));

            if (Directory.Exists(guiBinReleaseDirectory))
            {
                IoHelpers.DeleteRecursivelyWithMagicDustAsync(guiBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {guiBinReleaseDirectory}");
            }
            if (Directory.Exists(libraryBinReleaseDirectory))
            {
                IoHelpers.DeleteRecursivelyWithMagicDustAsync(libraryBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {libraryBinReleaseDirectory}");
            }

            foreach (string target in Targets)
            {
                string publishedFolder         = Path.Combine(BinDistDirectory, target);
                string currentBinDistDirectory = publishedFolder;

                Console.WriteLine();
                Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

                Console.WriteLine();
                if (!Directory.Exists(currentBinDistDirectory))
                {
                    Directory.CreateDirectory(currentBinDistDirectory);
                    Console.WriteLine($"Created {currentBinDistDirectory}");
                }

                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = $"clean",
                    WorkingDirectory = GuiProjectDirectory
                }))
                {
                    process.WaitForExit();
                }

                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21
                // -c|--configuration {Debug|Release}
                //		Defines the build configuration. The default value is Debug.
                // --force
                //		Forces all dependencies to be resolved even if the last restore was successful. Specifying this flag is the same as deleting the project.assets.json file.
                // -o|--output <OUTPUT_DIRECTORY>
                //		Specifies the path for the output directory.
                //		If not specified, it defaults to ./bin/[configuration]/[framework]/publish/ for a framework-dependent deployment or
                //		./bin/[configuration]/[framework]/[runtime]/publish/ for a self-contained deployment.
                //		If the path is relative, the output directory generated is relative to the project file location, not to the current working directory.
                // --self-contained
                //		Publishes the .NET Core runtime with your application so the runtime doesn't need to be installed on the target machine.
                //		If a runtime identifier is specified, its default value is true. For more information about the different deployment types, see .NET Core application deployment.
                // -r|--runtime <RUNTIME_IDENTIFIER>
                //		Publishes the application for a given runtime. This is used when creating a self-contained deployment (SCD).
                //		For a list of Runtime Identifiers (RIDs), see the RID catalog. Default is to publish a framework-dependent deployment (FDD).
                // --version-suffix <VERSION_SUFFIX>
                //		Defines the version suffix to replace the asterisk (*) in the version field of the project file.
                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore?tabs=netcore2x
                // --disable-parallel
                //		Disables restoring multiple projects in parallel.
                // --no-cache
                //		Specifies to not cache packages and HTTP requests.
                // https://github.com/dotnet/docs/issues/7568
                // /p:Version=1.2.3.4
                //		"dotnet publish" supports msbuild command line options like /p:Version=1.2.3.4
                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = $"publish --configuration Release --force --output \"{currentBinDistDirectory}\" --self-contained true --runtime \"{target}\" /p:VersionPrefix={VersionPrefix} --disable-parallel --no-cache /p:DebugType=none /p:DebugSymbols=false /p:ErrorReport=none /p:DocumentationFile=\"\" /p:Deterministic=true",
                    WorkingDirectory = GuiProjectDirectory
                }))
                {
                    process.WaitForExit();
                }

                Tools.ClearSha512Tags(currentBinDistDirectory);
                Tools.RemoveSosDocsUnix(currentBinDistDirectory);

                // Remove Tor binaries those are not relevant to the platform.
                var torFolder   = new DirectoryInfo(Path.Combine(currentBinDistDirectory, "TorDaemons"));
                var toNotremove = "";
                if (target.StartsWith("win"))
                {
                    toNotremove = "win";
                }
                else if (target.StartsWith("linux"))
                {
                    toNotremove = "linux";
                }
                else if (target.StartsWith("osx"))
                {
                    toNotremove = "osx";
                }
                foreach (var file in torFolder.EnumerateFiles())
                {
                    if (!file.Name.Contains("data", StringComparison.OrdinalIgnoreCase) && !file.Name.Contains(toNotremove, StringComparison.OrdinalIgnoreCase))
                    {
                        File.Delete(file.FullName);
                    }
                }

                // Rename the final exe.
                string oldExecutablePath;
                string newExecutablePath;
                if (target.StartsWith("win"))
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Gui.exe");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, $"{ExecutableName}.exe");
                }
                else                 // Linux & OSX
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Gui");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, ExecutableName);
                }
                File.Move(oldExecutablePath, newExecutablePath);

                long installedSizeKb = Tools.DirSize(new DirectoryInfo(publishedFolder)) / 1000;

                if (target.StartsWith("win"))
                {
                    // Don't open console.
                    if (!NSubsysUtil.ProcessFile(newExecutablePath))
                    {
                        Console.WriteLine("ERROR: Couldn't remove console from exe.");
                    }

                    var icoPath = Path.Combine(GuiProjectDirectory, "Assets", "WasabiLogo.ico");
                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "rcedit",                         // https://github.com/electron/rcedit/
                        Arguments = $"\"{newExecutablePath}\" --set-icon \"{icoPath}\" --set-file-version \"{VersionPrefix}\" --set-product-version \"{VersionPrefix}\" --set-version-string \"LegalCopyright\" \"MIT\" --set-version-string \"CompanyName\" \"zkSNACKs\" --set-version-string \"FileDescription\" \"Privacy focused, ZeroLink compliant Bitcoin wallet.\" --set-version-string \"ProductName\" \"Wasabi Wallet\"",
                        WorkingDirectory = currentBinDistDirectory
                    }))
                    {
                        process.WaitForExit();
                    }

                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;                                   // In Windows build at this moment it doesn't matter though.
                    }
                }
                else if (target.StartsWith("osx"))
                {
                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;
                    }

                    var tempName = Path.Combine(BinDistDirectory, $"temp-{target}");
                    Directory.Move(currentBinDistDirectory, tempName);
                    currentBinDistDirectory = tempName;

                    string macWasabiAppDir = Path.Combine(publishedFolder, "Wasabi Wallet.App");                     // This should be lowercase .app, but MAC will prevent people from upgrading if we change it.
                    string macContentsDir  = Path.Combine(macWasabiAppDir, "Contents");
                    string newName         = Path.GetFullPath(Path.Combine(macContentsDir, "MacOS"));
                    Directory.CreateDirectory(macContentsDir);
                    Directory.Move(currentBinDistDirectory, newName);
                    currentBinDistDirectory = newName;

                    string resourcesDir = Path.Combine(macContentsDir, "Resources");
                    string infoFilePath = Path.Combine(macContentsDir, "Info.plist");

                    Directory.CreateDirectory(resourcesDir);
                    var iconpath = Path.Combine(GuiProjectDirectory, "Assets", "WasabiLogo.icns");
                    File.Copy(iconpath, Path.Combine(resourcesDir, "WasabiLogo.icns"));

                    string infoContent = $@"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version = ""1.0"">
<dict>
	<key>LSMinimumSystemVersion</key>
	<string>10.12</string>

	<key>LSArchitecturePriority</key>
	<array>
		<string>x86_64</string>
	</array>

	<key>CFBundleIconFile</key>
	<string>WasabiLogo.icns</string>

	<key>CFBundlePackageType</key>
	<string>APPL</string>

	<key>CFBundleShortVersionString</key>
	<string>{VersionPrefix}</string>

	<key>CFBundleVersion</key>
	<string>{VersionPrefix}</string>

	<key>CFBundleExecutable</key>
	<string>{ExecutableName}</string>

	<key>CFBundleName</key>
	<string>Wasabi Wallet</string>

	<key>CFBundleIdentifier</key>
	<string>zksnacks.wasabiwallet</string>

	<key>NSHighResolutionCapable</key>
	<true/>

	<key>NSAppleScriptEnabled</key>
	<true/>

	<key>LSApplicationCategoryType</key>
	<string>public.app-category.finance</string>

	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
</dict>
</plist>
";
                    File.WriteAllText(infoFilePath, infoContent);

                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory = publishedFolder
                    }))
                    {
                        process.StandardInput.WriteLine($"wsl ln -s /Applications && exit");
                        process.WaitForExit();
                    }

                    //how to generate .DS_Store file - https://github.com/zkSNACKs/WalletWasabi/pull/928/commits/e38ed672dee25f6e45a3eb16584887cc6d48c4e6
                    var dmgContentDir = Path.Combine(PackagerProjectDirectory, "Content", "Osx");
                    IoHelpers.CopyFilesRecursively(new DirectoryInfo(dmgContentDir), new DirectoryInfo(publishedFolder));

                    string uncompressedDmgFileName = $"Wasabi-uncompressed.dmg";
                    string uncompressedDmgFilePath = Path.Combine(BinDistDirectory, uncompressedDmgFileName);
                    string dmgFileName             = $"Wasabi-{VersionPrefix}.dmg";
                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory = BinDistDirectory
                    }))
                    {
                        // http://www.nathancoulson.com/proj_cross_tools.php
                        // -D: Do not use deep directory relocation, and instead just pack them in the way we see them
                        // -V: Volume Label
                        // -no-pad: Do not pad the end by 150 sectors (300kb). As it is not a cd image, not required
                        // -apple -r: Creates a .dmg image
                        process.StandardInput.WriteLine($"wsl genisoimage -D -V \"Wasabi Wallet\" -no-pad -apple -r -dir-mode 755 -o \"{uncompressedDmgFileName}\" \"{new DirectoryInfo(publishedFolder).Name}\" && exit");
                        process.WaitForExit();
                    }
                    // cd ~
                    // git clone https://github.com/planetbeing/libdmg-hfsplus.git && cd libdmg-hfsplus
                    // https://github.com/planetbeing/libdmg-hfsplus/issues/14
                    // mkdir build && cd build
                    // sudo apt-get install zlib1g-dev
                    // cmake ..
                    // cd build
                    // sudo apt-get install libssl1.0-dev
                    // cmake ..
                    // cd ~/libdmg-hfsplus/build/
                    // make
                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory = BinDistDirectory
                    }))
                    {
                        process.StandardInput.WriteLine($"wsl ~/libdmg-hfsplus/build/dmg/./dmg dmg \"{uncompressedDmgFileName}\" \"{dmgFileName}\" && exit");
                        process.WaitForExit();
                    }

                    IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                    File.Delete(uncompressedDmgFilePath);

                    IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                    Console.WriteLine($"Deleted {publishedFolder}");
                }
                else if (target.StartsWith("linux"))
                {
                    // IF IT'S IN ONLYBINARIES MODE DON'T DO ANYTHING FANCY PACKAGING AFTER THIS!!!
                    if (OnlyBinaries)
                    {
                        continue;
                    }

                    Console.WriteLine("Create Linux .tar.gz");
                    if (!Directory.Exists(publishedFolder))
                    {
                        throw new Exception($"{publishedFolder} doesn't exist.");
                    }
                    var newFolderName = $"WasabiLinux-{VersionPrefix}";
                    var newFolderPath = Path.Combine(BinDistDirectory, newFolderName);
                    Directory.Move(publishedFolder, newFolderPath);
                    publishedFolder = newFolderPath;

                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory = BinDistDirectory
                    }))
                    {
                        process.StandardInput.WriteLine($"wsl tar -pczvf {newFolderName}.tar.gz {newFolderName} && exit");
                        process.WaitForExit();
                    }

                    Console.WriteLine("Create Linux .deb");

                    var debFolderRelativePath            = "deb";
                    var debFolderPath                    = Path.Combine(BinDistDirectory, debFolderRelativePath);
                    var linuxUsrLocalBinFolder           = "/usr/local/bin/";
                    var debUsrLocalBinFolderRelativePath = Path.Combine(debFolderRelativePath, "usr", "local", "bin");
                    var debUsrLocalBinFolderPath         = Path.Combine(BinDistDirectory, debUsrLocalBinFolderRelativePath);
                    Directory.CreateDirectory(debUsrLocalBinFolderPath);
                    var debUsrAppFolderRelativePath = Path.Combine(debFolderRelativePath, "usr", "share", "applications");
                    var debUsrAppFolderPath         = Path.Combine(BinDistDirectory, debUsrAppFolderRelativePath);
                    Directory.CreateDirectory(debUsrAppFolderPath);
                    var debUsrShareIconsFolderRelativePath = Path.Combine(debFolderRelativePath, "usr", "share", "icons", "hicolor");
                    var debUsrShareIconsFolderPath         = Path.Combine(BinDistDirectory, debUsrShareIconsFolderRelativePath);
                    var debianFolderRelativePath           = Path.Combine(debFolderRelativePath, "DEBIAN");
                    var debianFolderPath = Path.Combine(BinDistDirectory, debianFolderRelativePath);
                    Directory.CreateDirectory(debianFolderPath);
                    newFolderName = "wasabiwallet";
                    var linuxWasabiWalletFolder = Tools.LinuxPathCombine(linuxUsrLocalBinFolder, newFolderName);
                    var newFolderRelativePath   = Path.Combine(debUsrLocalBinFolderRelativePath, newFolderName);
                    newFolderPath = Path.Combine(BinDistDirectory, newFolderRelativePath);
                    Directory.Move(publishedFolder, newFolderPath);

                    var assetsFolder = Path.Combine(GuiProjectDirectory, "Assets");
                    var assetsInfo   = new DirectoryInfo(assetsFolder);

                    foreach (var file in assetsInfo.EnumerateFiles())
                    {
                        var number = file.Name.Split(new string[] { "WasabiLogo", ".png" }, StringSplitOptions.RemoveEmptyEntries);
                        if (number.Count() == 1 && int.TryParse(number.First(), out int size))
                        {
                            string destFolder = Path.Combine(debUsrShareIconsFolderPath, $"{size}x{size}", "apps");
                            Directory.CreateDirectory(destFolder);
                            file.CopyTo(Path.Combine(destFolder, $"{ExecutableName}.png"));
                        }
                    }

                    var controlFilePath = Path.Combine(debianFolderPath, "control");
                    // License format doesn't yet work, but should work in the future, it's work in progress: https://bugs.launchpad.net/ubuntu/+source/software-center/+bug/435183
                    var controlFileContent = $"Package: {ExecutableName}\n" +
                                             $"Priority: optional\n" +
                                             $"Section: utils\n" +
                                             $"Maintainer: nopara73 <*****@*****.**>\n" +
                                             $"Version: {VersionPrefix}\n" +
                                             $"Homepage: http://wasabiwallet.io\n" +
                                             $"Vcs-Git: git://github.com/zkSNACKs/WalletWasabi.git\n" +
                                             $"Vcs-Browser: https://github.com/zkSNACKs/WalletWasabi\n" +
                                             $"Architecture: amd64\n" +
                                             $"License: Open Source (MIT)\n" +
                                             $"Installed-Size: {installedSizeKb}\n" +
                                             $"Description: open-source, non-custodial, privacy focused Bitcoin wallet\n" +
                                             $"  Built-in Tor, CoinJoin and Coin Control features.\n";

                    File.WriteAllText(controlFilePath, controlFileContent, Encoding.ASCII);

                    var desktopFilePath    = Path.Combine(debUsrAppFolderPath, $"{ExecutableName}.desktop");
                    var desktopFileContent = $"[Desktop Entry]\n" +
                                             $"Type=Application\n" +
                                             $"Name=Wasabi Wallet\n" +
                                             $"GenericName=Bitcoin Wallet\n" +
                                             $"Comment=Privacy focused Bitcoin wallet.\n" +
                                             $"Icon={ExecutableName}\n" +
                                             $"Terminal=false\n" +
                                             $"Exec={ExecutableName}\n" +
                                             $"Categories=Office;Finance;\n" +
                                             $"Keywords=bitcoin;wallet;crypto;blockchain;wasabi;privacy;anon;awesome;qwe;asd;\n";

                    File.WriteAllText(desktopFilePath, desktopFileContent, Encoding.ASCII);

                    var wasabiStarterScriptPath    = Path.Combine(debUsrLocalBinFolderPath, $"{ExecutableName}");
                    var wasabiStarterScriptContent = $"#!/bin/sh\n" +
                                                     $"{ linuxWasabiWalletFolder.TrimEnd('/')}/./{ExecutableName}\n";

                    File.WriteAllText(wasabiStarterScriptPath, wasabiStarterScriptContent, Encoding.ASCII);

                    string debExeLinuxPath              = Tools.LinuxPathCombine(newFolderRelativePath, ExecutableName);
                    string debDestopFileLinuxPath       = Tools.LinuxPathCombine(debUsrAppFolderRelativePath, $"{ExecutableName}.desktop");
                    var    wasabiStarterScriptLinuxPath = Tools.LinuxPathCombine(debUsrLocalBinFolderRelativePath, $"{ExecutableName}");

                    using (var process = Process.Start(new ProcessStartInfo
                    {
                        FileName = "wsl",
                        Arguments = $"cd ~ && sudo umount /mnt/c && sudo mount -t drvfs C: /mnt/c -o metadata && cd /mnt/c/Users/user/Desktop/WalletWasabi/WalletWasabi.Gui/bin/dist && sudo chmod +x {debExeLinuxPath} && sudo chmod +x {wasabiStarterScriptLinuxPath} && sudo chmod -R 0644 {debDestopFileLinuxPath} && sudo chmod -R 0775 {Tools.LinuxPath(debianFolderRelativePath)} && dpkg --build {Tools.LinuxPath(debFolderRelativePath)} $(pwd)",
                        RedirectStandardInput = true,
                        WorkingDirectory = BinDistDirectory
                    }))
                    {
                        process.WaitForExit();
                    }

                    IoHelpers.DeleteRecursivelyWithMagicDustAsync(debFolderPath).GetAwaiter().GetResult();

                    string oldDeb = Path.Combine(BinDistDirectory, $"{ExecutableName}_{VersionPrefix}_amd64.deb");
                    string newDeb = Path.Combine(BinDistDirectory, $"Wasabi-{VersionPrefix}.deb");
                    File.Move(oldDeb, newDeb);

                    IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                    Console.WriteLine($"Deleted {publishedFolder}");
                }
            }
        }
Esempio n. 3
0
        private static void Publish()
        {
            if (Directory.Exists(BinDistDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(BinDistDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {BinDistDirectory}");
            }

            using (var process = Process.Start(new ProcessStartInfo
            {
                FileName = "cmd",
                RedirectStandardInput = true,
                WorkingDirectory = GuiProjectDirectory
            }))
            {
                process.StandardInput.WriteLine("dotnet clean --configuration Release && exit");
                process.WaitForExit();
            }

            var guiBinReleaseDirectory     = Path.GetFullPath(Path.Combine(GuiProjectDirectory, "bin", "Release"));
            var libraryBinReleaseDirectory = Path.GetFullPath(Path.Combine(LibraryProjectDirectory, "bin", "Release"));

            if (Directory.Exists(guiBinReleaseDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(guiBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {guiBinReleaseDirectory}");
            }
            if (Directory.Exists(libraryBinReleaseDirectory))
            {
                IoHelpers.TryDeleteDirectoryAsync(libraryBinReleaseDirectory).GetAwaiter().GetResult();
                Console.WriteLine($"Deleted {libraryBinReleaseDirectory}");
            }

            foreach (string target in Targets)
            {
                string publishedFolder         = Path.Combine(BinDistDirectory, target);
                string currentBinDistDirectory = publishedFolder;

                Console.WriteLine();
                Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

                Console.WriteLine();
                if (!Directory.Exists(currentBinDistDirectory))
                {
                    Directory.CreateDirectory(currentBinDistDirectory);
                    Console.WriteLine($"Created {currentBinDistDirectory}");
                }

                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = $"clean",
                    WorkingDirectory = GuiProjectDirectory
                }))
                {
                    process.WaitForExit();
                }

                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish?tabs=netcore21
                // -c|--configuration {Debug|Release}
                //		Defines the build configuration. The default value is Debug.
                // --force
                //		Forces all dependencies to be resolved even if the last restore was successful. Specifying this flag is the same as deleting the project.assets.json file.
                // -o|--output <OUTPUT_DIRECTORY>
                //		Specifies the path for the output directory.
                //		If not specified, it defaults to ./bin/[configuration]/[framework]/publish/ for a framework-dependent deployment or
                //		./bin/[configuration]/[framework]/[runtime]/publish/ for a self-contained deployment.
                //		If the path is relative, the output directory generated is relative to the project file location, not to the current working directory.
                // --self-contained
                //		Publishes the .NET Core runtime with your application so the runtime does not need to be installed on the target machine.
                //		If a runtime identifier is specified, its default value is true. For more information about the different deployment types, see .NET Core application deployment.
                // -r|--runtime <RUNTIME_IDENTIFIER>
                //		Publishes the application for a given runtime. This is used when creating a self-contained deployment (SCD).
                //		For a list of Runtime Identifiers (RIDs), see the RID catalog. Default is to publish a framework-dependent deployment (FDD).
                // --version-suffix <VERSION_SUFFIX>
                //		Defines the version suffix to replace the asterisk (*) in the version field of the project file.
                // https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-restore?tabs=netcore2x
                // --disable-parallel
                //		Disables restoring multiple projects in parallel.
                // --no-cache
                //		Specifies to not cache packages and HTTP requests.
                // https://github.com/dotnet/docs/issues/7568
                // /p:Version=1.2.3.4
                //		"dotnet publish" supports msbuild command line options like /p:Version=1.2.3.4
                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "dotnet",
                    Arguments = string.Join(" ",
                                            $"publish",
                                            $"--configuration Release",
                                            $"--force",
                                            $"--output \"{currentBinDistDirectory}\"",
                                            $"--self-contained true",
                                            $"--runtime \"{target}\"",
                                            $"--disable-parallel",
                                            $"--no-cache",
                                            $"/p:VersionPrefix={VersionPrefix}",
                                            $"/p:DebugType=none",
                                            $"/p:DebugSymbols=false",
                                            $"/p:ErrorReport=none",
                                            $"/p:DocumentationFile=\"\"",
                                            $"/p:Deterministic=true",
                                            $"/p:RestoreLockedMode=true"),
                    WorkingDirectory = GuiProjectDirectory,
                    RedirectStandardOutput = true
                }))
                {
                    string error = process.StandardOutput.ReadToEnd();
                    process.WaitForExit();
                    if (process.ExitCode != 0)
                    {
                        throw new InvalidOperationException($"dotnet publish returned with error code {process.ExitCode}. Error message was: {error ?? "none"}");
                    }
                }

                Tools.ClearSha512Tags(currentBinDistDirectory);

                // Remove Tor binaries that are not relevant to the platform.
                var torFolder   = new DirectoryInfo(Path.Combine(currentBinDistDirectory, "TorDaemons"));
                var toNotRemove = "";
                if (target.StartsWith("win"))
                {
                    toNotRemove = "win";
                }
                else if (target.StartsWith("linux"))
                {
                    toNotRemove = "lin";
                }
                else if (target.StartsWith("osx"))
                {
                    toNotRemove = "osx";
                }

                foreach (var file in torFolder.EnumerateFiles())
                {
                    if (!file.Name.Contains("data", StringComparison.OrdinalIgnoreCase) && !file.Name.Contains(toNotRemove, StringComparison.OrdinalIgnoreCase))
                    {
                        File.Delete(file.FullName);
                    }
                }

                // Remove binaries that are not relevant to the platform.
                var binaryFolder = new DirectoryInfo(Path.Combine(currentBinDistDirectory, "Microservices", "Binaries"));

                foreach (var dir in binaryFolder.EnumerateDirectories())
                {
                    if (!dir.Name.Contains(toNotRemove, StringComparison.OrdinalIgnoreCase))
                    {
                        IoHelpers.TryDeleteDirectoryAsync(dir.FullName).GetAwaiter().GetResult();
                    }
                }

                // Rename the final exe.
                string oldExecutablePath;
                string newExecutablePath;
                if (target.StartsWith("win"))
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Gui.exe");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, $"{ExecutableName}.exe");
                }
                else                 // Linux & OSX
                {
                    oldExecutablePath = Path.Combine(currentBinDistDirectory, "WalletWasabi.Gui");
                    newExecutablePath = Path.Combine(currentBinDistDirectory, ExecutableName);
                }
                File.Move(oldExecutablePath, newExecutablePath);

                long installedSizeKb = Tools.DirSize(new DirectoryInfo(publishedFolder)) / 1000;

                if (target.StartsWith("win"))
                {
                    var daemonExePath = newExecutablePath[0..^ 4] + "d.exe";