Пример #1
0
    /// <summary>
    /// Main entry point.
    /// </summary>
    private static async Task Main(string[] args)
    {
        var argsProcessor = new ArgsProcessor(args);

        // For now this is enough. If you run it on macOS you want to sign.
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            MacSignTools.Sign(argsProcessor);
            return;
        }

        // Only binaries mode is for deterministic builds.
        OnlyBinaries = argsProcessor.IsOnlyBinariesMode();

        IsContinuousDelivery = argsProcessor.IsContinuousDeliveryMode();

        ReportStatus();

        if (argsProcessor.IsPublish() || IsContinuousDelivery || OnlyBinaries)
        {
            await PublishAsync().ConfigureAwait(false);

            IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
        }

        if (argsProcessor.IsSign())
        {
            await SignAsync().ConfigureAwait(false);
        }
    }
Пример #2
0
        private static void Main(string[] args)
        {
            // Only binaries mode is for deterministic builds.
            OnlyBinaries = IsOnlyBinariesMode(args);
            ReportStatus();

            if (DoPublish || OnlyBinaries)
            {
                Publish();
                if (OnlyBinaries)
                {
                    IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
                }
            }

            if (DoSign && !OnlyBinaries)
            {
                Sign();
            }

            if (DoRestoreProgramCs && !OnlyBinaries)
            {
                RestoreProgramCs();
            }
        }
Пример #3
0
        private static void Main(string[] args)
        {
            // Start with digest creation and return if only digest creation.
            CreateDigests();

            OnlyCreateDigests = IsOnlyCreateDigestsMode(args);
            if (OnlyCreateDigests)
            {
                return;
            }

            // Only binaries mode is for deterministic builds.
            OnlyBinaries = IsOnlyBinariesMode(args);
            ReportStatus();

            if (DoPublish || OnlyBinaries)
            {
                Publish();
                if (OnlyBinaries)
                {
                    IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
                }
            }

            if (DoSign && !OnlyBinaries)
            {
                Sign();
            }

            if (DoRestoreProgramCs && !OnlyBinaries)
            {
                RestoreProgramCs();
            }
        }
Пример #4
0
        private static async Task Main(string[] args)
        {
            var argsProcessor = new ArgsProcessor(args);

            // For now this is enough. If you run it on macOS you want to sign.
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                MacSignTools.Sign();
                return;
            }

            // If I want a list of up to date onions run it with '--getonions'.
            if (argsProcessor.IsGetOnionsMode())
            {
                var api = new BitnodesApi(Console.Out);
                await api.PrintOnionsAsync();

                return;
            }

            // If I want a list of up to date onions run it with '--reduceonions'.
            if (argsProcessor.IsReduceOnionsMode())
            {
                string onionFilePath = Path.Combine(LibraryProjectDirectory, "Tor", "OnionSeeds", "MainOnionSeeds.txt");
                var    currentOnions = File.ReadAllLines(onionFilePath).ToHashSet();

                var api = new BitnodesApi(Console.Out);
                await api.PrintOnionsAsync(currentOnions);

                return;
            }

            // Only binaries mode is for deterministic builds.
            OnlyBinaries = argsProcessor.IsOnlyBinariesMode();

            IsContinuousDelivery = argsProcessor.IsContinuousDeliveryMode();

            ReportStatus();

            if (DoPublish || OnlyBinaries)
            {
                Publish();

                IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
            }

            if (!OnlyBinaries)
            {
                if (DoSign)
                {
                    Sign();
                }

                if (DoRestoreProgramCs)
                {
                    RestoreProgramCs();
                }
            }
        }
Пример #5
0
        private static void Main(string[] args)
        {
            if (MacSignTools.IsMacSignMode())
            {
                MacSignTools.Sign();
                return;
            }

            // If I want a list of up to date onions run it with '--getonions'.
            if (IsGetOnionsMode(args))
            {
                GetOnions();
                return;
            }

            // If I want a list of up to date onions run it with '--getonions'.
            if (IsReduceOnionsMode(args))
            {
                ReduceOnions();
                return;
            }

            // Start with digest creation and return if only digest creation.
            CreateDigests();

            OnlyCreateDigests = IsOnlyCreateDigestsMode(args);
            if (OnlyCreateDigests)
            {
                return;
            }

            // Only binaries mode is for deterministic builds.
            OnlyBinaries = IsOnlyBinariesMode(args);
            ReportStatus();

            if (DoPublish || OnlyBinaries)
            {
                Publish();

                IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
            }

            if (!OnlyBinaries)
            {
                if (DoSign)
                {
                    Sign();
                }

                if (DoRestoreProgramCs)
                {
                    RestoreProgramCs();
                }
            }
        }
Пример #6
0
    private static async Task SignAsync()
    {
        foreach (string target in Targets)
        {
            if (target.StartsWith("win", StringComparison.OrdinalIgnoreCase))
            {
                string publishedFolder = Path.Combine(BinDistDirectory, target);

                Console.WriteLine("Move created .msi");
                var msiPath = Path.Combine(WixProjectDirectory, "bin", "Release", "Wasabi.msi");
                if (!File.Exists(msiPath))
                {
                    throw new Exception(".msi does not exist. Expected path: Wasabi.msi.");
                }
                var msiFileName = Path.GetFileNameWithoutExtension(msiPath);
                var newMsiPath  = Path.Combine(BinDistDirectory, $"{msiFileName}-{VersionPrefix}.msi");
                File.Copy(msiPath, newMsiPath);

                Console.Write("Enter Code Signing Certificate Password: "******"cmd", BinDistDirectory, $"signtool sign /d \"Wasabi Wallet\" /f \"{PfxPath}\" /p {pfxPassword} /t http://timestamp.digicert.com /a \"{newMsiPath}\" && exit");

                await IoHelpers.TryDeleteDirectoryAsync(publishedFolder).ConfigureAwait(false);

                Console.WriteLine($"Deleted {publishedFolder}");
            }
            else if (target.StartsWith("osx", StringComparison.OrdinalIgnoreCase))
            {
                string dmgFilePath = Path.Combine(BinDistDirectory, $"Wasabi-{VersionPrefix}.dmg");
                if (!File.Exists(dmgFilePath))
                {
                    throw new Exception(".dmg does not exist.");
                }
                string zipFilePath = Path.Combine(BinDistDirectory, $"Wasabi-osx-{VersionPrefix}.zip");
                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }
            }
        }

        Console.WriteLine("Signing final files...");
        var finalFiles = Directory.GetFiles(BinDistDirectory);

        foreach (var finalFile in finalFiles)
        {
            StartProcessAndWaitForExit("cmd", BinDistDirectory, $"gpg --armor --detach-sign {finalFile} && exit");

            StartProcessAndWaitForExit("cmd", WixProjectDirectory, $"git checkout -- ComponentsGenerated.wxs && exit");
        }

        IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
    }
        public HomePageViewModel(IScreen screen, WalletManagerViewModel walletManager, AddWalletPageViewModel addWalletPage) : base(screen)
        {
            Title = "Home";

            var list = new SourceList <NavBarItemViewModel>();

            list.Add(addWalletPage);

            walletManager.Items.ToObservableChangeSet()
            .Cast(x => x as NavBarItemViewModel)
            .Sort(SortExpressionComparer <NavBarItemViewModel> .Ascending(i => i.Title))
            .Merge(list.Connect())
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _items)
            .AsObservableList();

            OpenWalletsFolderCommand = ReactiveCommand.Create(() => IoHelpers.OpenFolderInFileExplorer(walletManager.Model.WalletDirectories.WalletsDir));
        }
Пример #8
0
    /// <summary>
    /// Main entry point.
    /// </summary>
    private static async Task Main(string[] args)
    {
        var argsProcessor = new ArgsProcessor(args);

        // For now this is enough. If you run it on macOS you want to sign.
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            MacSignTools.Sign();
            return;
        }

        // Only binaries mode is for deterministic builds.
        OnlyBinaries = argsProcessor.IsOnlyBinariesMode();

        IsContinuousDelivery = argsProcessor.IsContinuousDeliveryMode();

        ReportStatus();

        if (DoPublish || OnlyBinaries)
        {
            await PublishAsync().ConfigureAwait(false);

            IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
        }

#pragma warning disable CS0162 // Unreachable code detected
        if (!OnlyBinaries)
        {
            if (DoSign)
            {
                await SignAsync().ConfigureAwait(false);
            }

            if (DoRestoreProgramCs)
            {
                RestoreProgramCs();
            }
        }
#pragma warning restore CS0162 // Unreachable code detected
    }
Пример #9
0
        private static async Task Main(string[] args)
        {
            var argsProcessor = new ArgsProcessor(args);

            // For now this is enough. If you run it on macOS you want to sign.
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                MacSignTools.Sign();
                return;
            }

            // Only binaries mode is for deterministic builds.
            OnlyBinaries = argsProcessor.IsOnlyBinariesMode();

            IsContinuousDelivery = argsProcessor.IsContinuousDeliveryMode();

            ReportStatus();

            if (DoPublish || OnlyBinaries)
            {
                Publish();

                IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
            }

            if (!OnlyBinaries)
            {
                if (DoSign)
                {
                    Sign();
                }

                if (DoRestoreProgramCs)
                {
                    RestoreProgramCs();
                }
            }
        }
 public OpenWalletsFolderViewModel(string walletDir)
 {
     TargetCommand = ReactiveCommand.Create(
         () => IoHelpers.OpenFolderInFileExplorer(walletDir));
 }
Пример #11
0
        private static void Main(string[] args)
        {
            // 0. Dump Client version (or else wrong .msi will be created) - Helpers.Constants.ClientVersion
            // 1. Publish with Packager.
            // 2. Build WIX project with Release and x64 configuration.
            // 3. Sign with Packager.
            bool doPublish = true;
            bool doSign    = false;

            string packagerProjectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"));
            string solutionDirectory        = Path.GetFullPath(Path.Combine(packagerProjectDirectory, "..\\"));
            string guiProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.Gui\\"));
            string libraryProjectDirectory  = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi\\"));
            string wixProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.WindowsInstaller\\"));
            string binDistDirectory         = Path.GetFullPath(Path.Combine(guiProjectDirectory, "bin\\dist"));

            Console.WriteLine($"{nameof(solutionDirectory)}:\t\t{solutionDirectory}");
            Console.WriteLine($"{nameof(packagerProjectDirectory)}:\t{packagerProjectDirectory}");
            Console.WriteLine($"{nameof(guiProjectDirectory)}:\t\t{guiProjectDirectory}");
            Console.WriteLine($"{nameof(libraryProjectDirectory)}:\t\t{libraryProjectDirectory}");
            Console.WriteLine($"{nameof(wixProjectDirectory)}:\t\t{wixProjectDirectory}");
            Console.WriteLine($"{nameof(binDistDirectory)}:\t\t{binDistDirectory}");

            string versionPrefix  = Helpers.Constants.ClientVersion.ToString();
            string executableName = "wassabee";

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

            // https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog
            // BOTTLENECKS:
            // Tor - win-32, linux-32, osx-64
            // .NET Core - win-32, linux-64, osx-64
            // Avalonia - win7-32, linux-64, osx-64
            // We'll only support x64, if someone complains, we can come back to it.
            // For 32 bit Windows there needs to be a lot of WIX configuration to be done.
            var targets = new List <string>
            {
                "win7-x64",
                "linux-x64",
                "osx-x64"
            };

            Console.WriteLine();
            Console.Write($"{nameof(targets)}:\t\t\t");
            targets.ForEach(x =>
            {
                if (targets.Last() != x)
                {
                    Console.Write($"{x}, ");
                }
                else
                {
                    Console.Write(x);
                }
            });
            Console.WriteLine();

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

                var psiBuild = new ProcessStartInfo
                {
                    FileName = "cmd",
                    RedirectStandardInput = true,
                    WorkingDirectory      = guiProjectDirectory
                };
                var pBuild = Process.Start(psiBuild);
                pBuild.StandardInput.WriteLine("dotnet clean --configuration Release && exit");
                pBuild.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 currentBinDistDirectory = Path.GetFullPath(Path.Combine(binDistDirectory, target));
                    Console.WriteLine();
                    Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

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

                    // 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
                    var psiPublish = new ProcessStartInfo
                    {
                        FileName         = "dotnet",
                        Arguments        = $"publish --configuration Release --force --output {currentBinDistDirectory} --self-contained true --runtime {target} /p:VersionPrefix={versionPrefix} --disable-parallel --no-cache",
                        WorkingDirectory = guiProjectDirectory
                    };
                    var pPublish = Process.Start(psiPublish);
                    pPublish.WaitForExit();

                    // 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);

                    if (target.StartsWith("win"))
                    {
                        var psiEditbin = new ProcessStartInfo
                        {
                            FileName         = "editbin",
                            Arguments        = $"\"{newExecutablePath}\" /SUBSYSTEM:WINDOWS",
                            WorkingDirectory = currentBinDistDirectory
                        };
                        var pEditbin = Process.Start(psiEditbin);
                        pEditbin.WaitForExit();

                        var icoPath   = Path.Combine(guiProjectDirectory, "Assets", "WasabiLogo.ico");
                        var psiRcedit = new ProcessStartInfo
                        {
                            FileName         = "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
                        };
                        var pRcedit = Process.Start(psiRcedit);
                        pRcedit.WaitForExit();
                    }
                }
            }

            if (doSign is true)
            {
                foreach (string target in targets)
                {
                    var publishedFolder = Path.Combine(binDistDirectory, $"{target}");

                    if (target.StartsWith("win", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("Move created .msi");
                        var msiPath = Path.Combine(wixProjectDirectory, @"bin\Release\WasabiInstaller.msi");
                        if (!File.Exists(msiPath))
                        {
                            throw new Exception(".msi doesn't exist. Expected path: WasabiInstaller.msi.");
                        }
                        var msiFileName = Path.GetFileName(msiPath);
                        var newMsiPath  = Path.Combine(binDistDirectory, msiFileName);
                        File.Move(msiPath, newMsiPath);
                    }
                    else if (target.StartsWith("linux", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("Create Linux .tar.gz");
                        if (!Directory.Exists(publishedFolder))
                        {
                            throw new Exception($"{publishedFolder} doesn't exist.");
                        }
                        var newFolderName = "WasabiLinux";
                        var newFolderPath = Path.Combine(binDistDirectory, newFolderName);
                        Directory.Move(publishedFolder, newFolderPath);
                        publishedFolder = newFolderPath;

                        var psiTar = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        var tarProcess = Process.Start(psiTar);
                        tarProcess.StandardInput.WriteLine($"wsl tar -pczvf {newFolderName}.tar.gz {newFolderName} && exit");
                        tarProcess.WaitForExit();
                    }
                    else                     // if (target.StartsWith("osx", StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine("Create OSX .tar.gz");
                        if (!Directory.Exists(publishedFolder))
                        {
                            throw new Exception($"{publishedFolder} doesn't exist.");
                        }
                        var newFolderName = "WasabiOsx";
                        var newFolderPath = Path.Combine(binDistDirectory, newFolderName);
                        Directory.Move(publishedFolder, newFolderPath);
                        publishedFolder = newFolderPath;

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

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

                Console.WriteLine("Signing final files...");
                var finalFiles = Directory.GetFiles(binDistDirectory);

                foreach (var finalFile in finalFiles)
                {
                    var psiSignProcess = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = binDistDirectory
                    };
                    var signProcess = Process.Start(psiSignProcess);
                    signProcess.StandardInput.WriteLine($"gpg --armor --detach-sign {finalFile} && exit");
                    signProcess.WaitForExit();

                    var psiRestoreHeat = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = wixProjectDirectory
                    };
                    var restoreHeatProcess = Process.Start(psiRestoreHeat);
                    restoreHeatProcess.StandardInput.WriteLine($"git checkout -- ComponentsGenerated.wxs && exit");
                    restoreHeatProcess.WaitForExit();
                }

                IoHelpers.OpenFolderInFileExplorer(binDistDirectory);
            }

            Console.WriteLine();
            Console.WriteLine("FINISHED! Press key to exit...");
            Console.ReadKey();
        }
Пример #12
0
        private static void Main(string[] args)
        {
            // 0. Dump Client version (or else wrong .msi will be created) - Helpers.Constants.ClientVersion
            // 1. Publish with Packager.
            // 2. Build WIX project with Release and x64 configuration.
            // 3. Sign with Packager, set restore true so the password won't be kept.
            var doPublish         = true;
            var doSign            = false;
            var doRestoreThisFile = false;
            var pfxPassword       = "******";

            string pfxPath = "C:\\digicert.pfx";
            string packagerProjectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"));
            string solutionDirectory        = Path.GetFullPath(Path.Combine(packagerProjectDirectory, "..\\"));
            string guiProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.Gui\\"));
            string libraryProjectDirectory  = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi\\"));
            string wixProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.WindowsInstaller\\"));
            string binDistDirectory         = Path.GetFullPath(Path.Combine(guiProjectDirectory, "bin\\dist"));

            Console.WriteLine($"{nameof(solutionDirectory)}:\t\t{solutionDirectory}");
            Console.WriteLine($"{nameof(packagerProjectDirectory)}:\t{packagerProjectDirectory}");
            Console.WriteLine($"{nameof(guiProjectDirectory)}:\t\t{guiProjectDirectory}");
            Console.WriteLine($"{nameof(libraryProjectDirectory)}:\t\t{libraryProjectDirectory}");
            Console.WriteLine($"{nameof(wixProjectDirectory)}:\t\t{wixProjectDirectory}");
            Console.WriteLine($"{nameof(binDistDirectory)}:\t\t{binDistDirectory}");

            string versionPrefix  = Helpers.Constants.ClientVersion.ToString();
            string executableName = "wassabee";

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

            // https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog
            // BOTTLENECKS:
            // Tor - win-32, linux-32, osx-64
            // .NET Core - win-32, linux-64, osx-64
            // Avalonia - win7-32, linux-64, osx-64
            // We'll only support x64, if someone complains, we can come back to it.
            // For 32 bit Windows there needs to be a lot of WIX configuration to be done.
            var targets = new List <string>
            {
                "win7-x64",
                "linux-x64",
                "osx-x64"
            };

            Console.WriteLine();
            Console.Write($"{nameof(targets)}:\t\t\t");
            targets.ForEach(x =>
            {
                if (targets.Last() != x)
                {
                    Console.Write($"{x}, ");
                }
                else
                {
                    Console.Write(x);
                }
            });
            Console.WriteLine();

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

                var psiBuild = new ProcessStartInfo
                {
                    FileName = "cmd",
                    RedirectStandardInput = true,
                    WorkingDirectory      = guiProjectDirectory
                };
                using (var pBuild = Process.Start(psiBuild))
                {
                    pBuild.StandardInput.WriteLine("dotnet clean --configuration Release && exit");
                    pBuild.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 currentBinDistDirectory;
                    string publishedFolder = Path.Combine(binDistDirectory, target);
                    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");
                    if (target.StartsWith("osx"))
                    {
                        currentBinDistDirectory = Path.GetFullPath(Path.Combine(macContentsDir, "MacOS"));
                    }
                    else
                    {
                        currentBinDistDirectory = publishedFolder;
                    }
                    Console.WriteLine();
                    Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

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

                    var psiClean = new ProcessStartInfo
                    {
                        FileName         = "dotnet",
                        Arguments        = $"clean",
                        WorkingDirectory = guiProjectDirectory
                    };
                    using (var pClean = Process.Start(psiClean))
                    {
                        pClean.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
                    var psiPublish = new ProcessStartInfo
                    {
                        FileName         = "dotnet",
                        Arguments        = $"publish --configuration Release --force --output \"{currentBinDistDirectory}\" --self-contained true --runtime \"{target}\" /p:VersionPrefix={versionPrefix} --disable-parallel --no-cache",
                        WorkingDirectory = guiProjectDirectory
                    };
                    using (var pPublish = Process.Start(psiPublish))
                    {
                        pPublish.WaitForExit();
                    }

                    // 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 = DirSize(new DirectoryInfo(publishedFolder)) / 1000;

                    if (target.StartsWith("win"))
                    {
                        var psiEditbin = new ProcessStartInfo
                        {
                            FileName         = "editbin",
                            Arguments        = $"\"{newExecutablePath}\" /SUBSYSTEM:WINDOWS",
                            WorkingDirectory = currentBinDistDirectory
                        };
                        using (var pEditbin = Process.Start(psiEditbin))
                        {
                            pEditbin.WaitForExit();
                        }

                        var icoPath   = Path.Combine(guiProjectDirectory, "Assets", "WasabiLogo.ico");
                        var psiRcedit = new ProcessStartInfo
                        {
                            FileName         = "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
                        };
                        using (var pRcedit = Process.Start(psiRcedit))
                        {
                            pRcedit.WaitForExit();
                        }
                    }
                    else if (target.StartsWith("osx"))
                    {
                        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);

                        var psiCreateSymLink = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = publishedFolder
                        };
                        using (var createSymLinkProcess = Process.Start(psiCreateSymLink))
                        {
                            createSymLinkProcess.StandardInput.WriteLine($"wsl ln -s /Applications && exit");
                            createSymLinkProcess.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));

                        var psiGenIsoImage = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };

                        string uncompressedDmgFileName = $"Wasabi-uncompressed.dmg";
                        string uncompressedDmgFilePath = Path.Combine(binDistDirectory, uncompressedDmgFileName);
                        string dmgFileName             = $"Wasabi-{versionPrefix}.dmg";
                        using (var genIsoImageProcess = Process.Start(psiGenIsoImage))
                        {
                            // 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
                            genIsoImageProcess.StandardInput.WriteLine($"wsl genisoimage -D -V \"Wasabi Wallet\" -no-pad -apple -r -dir-mode 755 -o \"{uncompressedDmgFileName}\" \"{new DirectoryInfo(publishedFolder).Name}\" && exit");
                            genIsoImageProcess.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
                        var psiDmg = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        using (var dmgProcess = Process.Start(psiDmg))
                        {
                            dmgProcess.StandardInput.WriteLine($"wsl ~/libdmg-hfsplus/build/dmg/./dmg dmg \"{uncompressedDmgFileName}\" \"{dmgFileName}\" && exit");
                            dmgProcess.WaitForExit();
                        }
                        // In case compression above doesn't work:
                        //var psiBzip = new ProcessStartInfo
                        //{
                        //	FileName = "cmd",
                        //	RedirectStandardInput = true,
                        //	WorkingDirectory = binDistDirectory
                        //};
                        //var bzipProcess = Process.Start(psiBzip);
                        //bzipProcess.StandardInput.WriteLine($"wsl bzip2 \"{uncompressedDmgFileName}\" && exit");
                        //bzipProcess.WaitForExit();

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

                        IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                        Console.WriteLine($"Deleted {publishedFolder}");
                    }
                    else if (target.StartsWith("linux"))
                    {
                        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;

                        var psiTar = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        using (var tarProcess = Process.Start(psiTar))
                        {
                            tarProcess.StandardInput.WriteLine($"wsl tar -pczvf {newFolderName}.tar.gz {newFolderName} && exit");
                            tarProcess.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 = 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              = LinuxPathCombine(newFolderRelativePath, executableName);
                        string debDestopFileLinuxPath       = LinuxPathCombine(debUsrAppFolderRelativePath, $"{executableName}.desktop");
                        var    wasabiStarterScriptLinuxPath = LinuxPathCombine(debUsrLocalBinFolderRelativePath, $"{executableName}");
                        var    psi = 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 {LinuxPath(debianFolderRelativePath)} && dpkg --build {LinuxPath(debFolderRelativePath)} $(pwd)",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };

                        using (var p = Process.Start(psi))
                        {
                            p.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}");
                    }
                }
            }

            if (doSign is true)
            {
                foreach (string target in targets)
                {
                    if (target.StartsWith("win", StringComparison.OrdinalIgnoreCase))
                    {
                        string publishedFolder = Path.Combine(binDistDirectory, target);

                        Console.WriteLine("Move created .msi");
                        var msiPath = Path.Combine(wixProjectDirectory, @"bin\Release\Wasabi.msi");
                        if (!File.Exists(msiPath))
                        {
                            throw new Exception(".msi doesn't exist. Expected path: Wasabi.msi.");
                        }
                        var msiFileName = Path.GetFileNameWithoutExtension(msiPath);
                        var newMsiPath  = Path.Combine(binDistDirectory, $"{msiFileName}-{versionPrefix}.msi");
                        File.Move(msiPath, newMsiPath);

                        // Sign code with digicert.
                        var psiSigntool = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        using (var signToolProcess = Process.Start(psiSigntool))
                        {
                            signToolProcess.StandardInput.WriteLine($"signtool sign /d \"Wasabi Wallet\" /f \"{pfxPath}\" /p {pfxPassword} /t http://timestamp.digicert.com /a \"{newMsiPath}\" && exit");
                            signToolProcess.WaitForExit();
                        }

                        IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                        Console.WriteLine($"Deleted {publishedFolder}");
                    }
                }

                Console.WriteLine("Signing final files...");
                var finalFiles = Directory.GetFiles(binDistDirectory);

                foreach (var finalFile in finalFiles)
                {
                    var psiSignProcess = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = binDistDirectory
                    };
                    using (var signProcess = Process.Start(psiSignProcess))
                    {
                        signProcess.StandardInput.WriteLine($"gpg --armor --detach-sign {finalFile} && exit");
                        signProcess.WaitForExit();
                    }

                    var psiRestoreHeat = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = wixProjectDirectory
                    };
                    using (var restoreHeatProcess = Process.Start(psiRestoreHeat))
                    {
                        restoreHeatProcess.StandardInput.WriteLine($"git checkout -- ComponentsGenerated.wxs && exit");
                        restoreHeatProcess.WaitForExit();
                    }

                    if (doRestoreThisFile)
                    {
                        var psiRestoreThisFile = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = packagerProjectDirectory
                        };
                        using (var restoreThisFileProcess = Process.Start(psiRestoreThisFile))
                        {
                            restoreThisFileProcess.StandardInput.WriteLine($"git checkout -- Program.cs && exit");
                            restoreThisFileProcess.WaitForExit();
                        }
                    }
                }

                IoHelpers.OpenFolderInFileExplorer(binDistDirectory);
                return;                 // No need for readkey here.
            }
        }
Пример #13
0
        public void OpenWalletsFolder()
        {
            var path = Global.WalletsDir;

            IoHelpers.OpenFolderInFileExplorer(path);
        }
Пример #14
0
        private void OnOpenWalletsFolder()
        {
            var global = Locator.Current.GetService <Global>();

            IoHelpers.OpenFolderInFileExplorer(global.WalletManager.WalletDirectories.WalletsDir);
        }
Пример #15
0
 public OpenDataFolderViewModel(string dataDir)
 {
     TargetCommand = ReactiveCommand.Create(() => IoHelpers.OpenFolderInFileExplorer(dataDir));
 }
Пример #16
0
        private static void Main(string[] args)
        {
            // 0. Dump Client version (or else wrong .msi will be created) - Helpers.Constants.ClientVersion
            // 1. Publish with Packager.
            // 2. Build WIX project with Release and x64 configuration.
            // 3. Sign with Packager, set restore true so the password won't be kept.
            var doPublish         = true;
            var doSign            = false;
            var doRestoreThisFile = false;
            var pfxPassword       = "******";

            string pfxPath = "C:\\digicert.pfx";
            string packagerProjectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\"));
            string solutionDirectory        = Path.GetFullPath(Path.Combine(packagerProjectDirectory, "..\\"));
            string guiProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.Gui\\"));
            string libraryProjectDirectory  = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi\\"));
            string wixProjectDirectory      = Path.GetFullPath(Path.Combine(solutionDirectory, "WalletWasabi.WindowsInstaller\\"));
            string binDistDirectory         = Path.GetFullPath(Path.Combine(guiProjectDirectory, "bin\\dist"));

            Console.WriteLine($"{nameof(solutionDirectory)}:\t\t{solutionDirectory}");
            Console.WriteLine($"{nameof(packagerProjectDirectory)}:\t{packagerProjectDirectory}");
            Console.WriteLine($"{nameof(guiProjectDirectory)}:\t\t{guiProjectDirectory}");
            Console.WriteLine($"{nameof(libraryProjectDirectory)}:\t\t{libraryProjectDirectory}");
            Console.WriteLine($"{nameof(wixProjectDirectory)}:\t\t{wixProjectDirectory}");
            Console.WriteLine($"{nameof(binDistDirectory)}:\t\t{binDistDirectory}");

            string versionPrefix  = Helpers.Constants.ClientVersion.ToString();
            string executableName = "wassabee";

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

            // https://docs.microsoft.com/en-us/dotnet/articles/core/rid-catalog
            // BOTTLENECKS:
            // Tor - win-32, linux-32, osx-64
            // .NET Core - win-32, linux-64, osx-64
            // Avalonia - win7-32, linux-64, osx-64
            // We'll only support x64, if someone complains, we can come back to it.
            // For 32 bit Windows there needs to be a lot of WIX configuration to be done.
            var targets = new List <string>
            {
                "win7-x64",
                "linux-x64",
                "osx-x64"
            };

            Console.WriteLine();
            Console.Write($"{nameof(targets)}:\t\t\t");
            targets.ForEach(x =>
            {
                if (targets.Last() != x)
                {
                    Console.Write($"{x}, ");
                }
                else
                {
                    Console.Write(x);
                }
            });
            Console.WriteLine();

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

                var psiBuild = new ProcessStartInfo
                {
                    FileName = "cmd",
                    RedirectStandardInput = true,
                    WorkingDirectory      = guiProjectDirectory
                };
                using (var pBuild = Process.Start(psiBuild))
                {
                    pBuild.StandardInput.WriteLine("dotnet clean --configuration Release && exit");
                    pBuild.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 currentBinDistDirectory;
                    string publishedFolder = Path.Combine(binDistDirectory, target);
                    string macWasabiAppDir = Path.Combine(publishedFolder, "Wasabi Wallet.App");
                    string macContentsDir  = Path.Combine(macWasabiAppDir, "Contents");
                    if (target.StartsWith("osx"))
                    {
                        currentBinDistDirectory = Path.GetFullPath(Path.Combine(macContentsDir, "MacOS"));
                    }
                    else
                    {
                        currentBinDistDirectory = publishedFolder;
                    }
                    Console.WriteLine();
                    Console.WriteLine($"{nameof(currentBinDistDirectory)}:\t{currentBinDistDirectory}");

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

                    var psiClean = new ProcessStartInfo
                    {
                        FileName         = "dotnet",
                        Arguments        = $"clean",
                        WorkingDirectory = guiProjectDirectory
                    };
                    using (var pClean = Process.Start(psiClean))
                    {
                        pClean.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
                    var psiPublish = new ProcessStartInfo
                    {
                        FileName         = "dotnet",
                        Arguments        = $"publish --configuration Release --force --output \"{currentBinDistDirectory}\" --self-contained true --runtime \"{target}\" /p:VersionPrefix={versionPrefix} --disable-parallel --no-cache",
                        WorkingDirectory = guiProjectDirectory
                    };
                    using (var pPublish = Process.Start(psiPublish))
                    {
                        pPublish.WaitForExit();
                    }

                    // 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);

                    if (target.StartsWith("win"))
                    {
                        var psiEditbin = new ProcessStartInfo
                        {
                            FileName         = "editbin",
                            Arguments        = $"\"{newExecutablePath}\" /SUBSYSTEM:WINDOWS",
                            WorkingDirectory = currentBinDistDirectory
                        };
                        using (var pEditbin = Process.Start(psiEditbin))
                        {
                            pEditbin.WaitForExit();
                        }

                        var icoPath   = Path.Combine(guiProjectDirectory, "Assets", "WasabiLogo.ico");
                        var psiRcedit = new ProcessStartInfo
                        {
                            FileName         = "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
                        };
                        using (var pRcedit = Process.Start(psiRcedit))
                        {
                            pRcedit.WaitForExit();
                        }
                    }
                    else if (target.StartsWith("osx"))
                    {
                        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>wassabee</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);

                        var psiCreateSymLink = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = publishedFolder
                        };
                        using (var createSymLinkProcess = Process.Start(psiCreateSymLink))
                        {
                            createSymLinkProcess.StandardInput.WriteLine($"wsl ln -s /Applications && exit");
                            createSymLinkProcess.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));

                        var psiGenIsoImage = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };

                        string uncompressedDmgFileName = $"Wasabi-uncompressed.dmg";
                        string uncompressedDmgFilePath = Path.Combine(binDistDirectory, uncompressedDmgFileName);
                        string dmgFileName             = $"Wasabi-{versionPrefix}.dmg";
                        using (var genIsoImageProcess = Process.Start(psiGenIsoImage))
                        {
                            // 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
                            genIsoImageProcess.StandardInput.WriteLine($"wsl genisoimage -D -V \"Wasabi Wallet\" -no-pad -apple -r -o \"{uncompressedDmgFileName}\" \"{new DirectoryInfo(publishedFolder).Name}\" && exit");
                            genIsoImageProcess.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
                        var psiDmg = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        using (var dmgProcess = Process.Start(psiDmg))
                        {
                            dmgProcess.StandardInput.WriteLine($"wsl ~/libdmg-hfsplus/build/dmg/./dmg dmg \"{uncompressedDmgFileName}\" \"{dmgFileName}\" && exit");
                            dmgProcess.WaitForExit();
                        }
                        // In case compression above doesn't work:
                        //var psiBzip = new ProcessStartInfo
                        //{
                        //	FileName = "cmd",
                        //	RedirectStandardInput = true,
                        //	WorkingDirectory = binDistDirectory
                        //};
                        //var bzipProcess = Process.Start(psiBzip);
                        //bzipProcess.StandardInput.WriteLine($"wsl bzip2 \"{uncompressedDmgFileName}\" && exit");
                        //bzipProcess.WaitForExit();

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

                        IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                        Console.WriteLine($"Deleted {publishedFolder}");
                    }
                    else if (target.StartsWith("linux"))
                    {
                        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;

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

                        IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                        Console.WriteLine($"Deleted {publishedFolder}");
                    }
                }
            }

            if (doSign is true)
            {
                foreach (string target in targets)
                {
                    if (target.StartsWith("win", StringComparison.OrdinalIgnoreCase))
                    {
                        string publishedFolder = Path.Combine(binDistDirectory, target);

                        Console.WriteLine("Move created .msi");
                        var msiPath = Path.Combine(wixProjectDirectory, @"bin\Release\Wasabi.msi");
                        if (!File.Exists(msiPath))
                        {
                            throw new Exception(".msi doesn't exist. Expected path: Wasabi.msi.");
                        }
                        var msiFileName = Path.GetFileNameWithoutExtension(msiPath);
                        var newMsiPath  = Path.Combine(binDistDirectory, $"{msiFileName}-{versionPrefix}.msi");
                        File.Move(msiPath, newMsiPath);

                        // Sign code with digicert.
                        var psiSigntool = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = binDistDirectory
                        };
                        using (var signToolProcess = Process.Start(psiSigntool))
                        {
                            signToolProcess.StandardInput.WriteLine($"signtool sign /d \"Wasabi Wallet\" /f \"{pfxPath}\" /p {pfxPassword} /t http://timestamp.digicert.com /a \"{newMsiPath}\" && exit");
                            signToolProcess.WaitForExit();
                        }

                        IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                        Console.WriteLine($"Deleted {publishedFolder}");
                    }
                }

                Console.WriteLine("Signing final files...");
                var finalFiles = Directory.GetFiles(binDistDirectory);

                foreach (var finalFile in finalFiles)
                {
                    var psiSignProcess = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = binDistDirectory
                    };
                    using (var signProcess = Process.Start(psiSignProcess))
                    {
                        signProcess.StandardInput.WriteLine($"gpg --armor --detach-sign {finalFile} && exit");
                        signProcess.WaitForExit();
                    }

                    var psiRestoreHeat = new ProcessStartInfo
                    {
                        FileName = "cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory      = wixProjectDirectory
                    };
                    using (var restoreHeatProcess = Process.Start(psiRestoreHeat))
                    {
                        restoreHeatProcess.StandardInput.WriteLine($"git checkout -- ComponentsGenerated.wxs && exit");
                        restoreHeatProcess.WaitForExit();
                    }

                    if (doRestoreThisFile)
                    {
                        var psiRestoreThisFile = new ProcessStartInfo
                        {
                            FileName = "cmd",
                            RedirectStandardInput = true,
                            WorkingDirectory      = packagerProjectDirectory
                        };
                        using (var restoreThisFileProcess = Process.Start(psiRestoreThisFile))
                        {
                            restoreThisFileProcess.StandardInput.WriteLine($"git checkout -- Program.cs && exit");
                            restoreThisFileProcess.WaitForExit();
                        }
                    }
                }

                IoHelpers.OpenFolderInFileExplorer(binDistDirectory);
                return;                 // No need for readkey here.
            }
        }
Пример #17
0
        public HelpCommands(CommandIconService commandIconService)
        {
            AboutCommand = new CommandDefinition(
                "About",
                commandIconService.GetCompletionKindImage("About"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel());
            }));

            DataFolderCommand = new CommandDefinition(
                "Data Folder",
                commandIconService.GetCompletionKindImage("DataFolder"),
                ReactiveCommand.Create(() =>
            {
                IoHelpers.OpenFolderInFileExplorer(Global.DataDir);
            }));

            CustomerSupportCommand = new CommandDefinition(
                "Customer Support",
                commandIconService.GetCompletionKindImage("CustomerSupport"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new CustomerSupportViewModel());
            }));

            ReportBugCommand = new CommandDefinition(
                "Report Bug",
                commandIconService.GetCompletionKindImage("ReportBug"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new ReportBugViewModel());
            }));

            PrivacyPolicyCommand = new CommandDefinition(
                "Privacy Policy",
                commandIconService.GetCompletionKindImage("PrivacyPolicy"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new PrivacyPolicyViewModel());
            }));

            TermsAndConditionsCommand = new CommandDefinition(
                "Terms and Conditions",
                commandIconService.GetCompletionKindImage("TermsAndConditions"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new TermsAndConditionsViewModel());
            }));

            LegalIssuesCommand = new CommandDefinition(
                "Legal Issues",
                commandIconService.GetCompletionKindImage("LegalIssues"),
                ReactiveCommand.Create(() =>
            {
                IoC.Get <IShell>().AddOrSelectDocument(() => new LegalIssuesViewModel());
            }));

#if DEBUG
            DevToolsCommand = new CommandDefinition(
                "Dev Tools",
                commandIconService.GetCompletionKindImage("DevTools"),
                ReactiveCommand.Create(() =>
            {
                var devTools = new DevTools(Application.Current.Windows.FirstOrDefault());

                var devToolsWindow = new Window
                {
                    Width         = 1024,
                    Height        = 512,
                    Content       = devTools,
                    DataTemplates =
                    {
                        new ViewLocator <Avalonia.Diagnostics.ViewModels.ViewModelBase>(),
                    }
                };

                devToolsWindow.Show();
            }));
#endif
        }
Пример #18
0
 private void OnOpenDataFolder()
 {
     IoHelpers.OpenFolderInFileExplorer(Global.DataDir);
 }
Пример #19
0
        private void OnOpenDataFolder()
        {
            var global = Locator.Current.GetService <Global>();

            IoHelpers.OpenFolderInFileExplorer(global.DataDir);
        }
Пример #20
0
 private void OnOpenWalletsFolder()
 {
     IoHelpers.OpenFolderInFileExplorer(Global.WalletsDir);
 }
Пример #21
0
        private static void Sign()
        {
            foreach (string target in Targets)
            {
                if (target.StartsWith("win", StringComparison.OrdinalIgnoreCase))
                {
                    string publishedFolder = Path.Combine(BinDistDirectory, target);

                    Console.WriteLine("Move created .msi");
                    var msiPath = Path.Combine(WixProjectDirectory, @"bin\Release\Wasabi.msi");
                    if (!File.Exists(msiPath))
                    {
                        throw new Exception(".msi does not exist. Expected path: Wasabi.msi.");
                    }
                    var msiFileName = Path.GetFileNameWithoutExtension(msiPath);
                    var newMsiPath  = Path.Combine(BinDistDirectory, $"{msiFileName}-{VersionPrefix}.msi");
                    File.Move(msiPath, newMsiPath);

                    Console.Write("Enter Code Signing Certificate Password: "******"cmd",
                        RedirectStandardInput = true,
                        WorkingDirectory = BinDistDirectory
                    }))
                    {
                        process.StandardInput.WriteLine($"signtool sign /d \"Wasabi Wallet\" /f \"{PfxPath}\" /p {pfxPassword} /t http://timestamp.digicert.com /a \"{newMsiPath}\" && exit");
                        process.WaitForExit();
                    }

                    IoHelpers.DeleteRecursivelyWithMagicDustAsync(publishedFolder).GetAwaiter().GetResult();
                    Console.WriteLine($"Deleted {publishedFolder}");
                }
            }

            Console.WriteLine("Signing final files...");
            var finalFiles = Directory.GetFiles(BinDistDirectory);

            foreach (var finalFile in finalFiles)
            {
                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "cmd",
                    RedirectStandardInput = true,
                    WorkingDirectory = BinDistDirectory
                }))
                {
                    process.StandardInput.WriteLine($"gpg --armor --detach-sign {finalFile} && exit");
                    process.WaitForExit();
                }

                using (var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "cmd",
                    RedirectStandardInput = true,
                    WorkingDirectory = WixProjectDirectory
                }))
                {
                    process.StandardInput.WriteLine($"git checkout -- ComponentsGenerated.wxs && exit");
                    process.WaitForExit();
                }
            }

            IoHelpers.OpenFolderInFileExplorer(BinDistDirectory);
        }
 public OpenWalletsFolderViewModel()
 {
     TargetCommand = ReactiveCommand.Create(
         () => IoHelpers.OpenFolderInFileExplorer(Services.WalletManager.WalletDirectories.WalletsDir));
 }