Ejemplo n.º 1
0
        ProcessStartData CreateTailLogsProcessStartData(SshTarget target, uint remotePid)
        {
            // If the game process exits, give the tail process a chance to shut down gracefully.
            ProcessManager.ProcessStopHandler stopHandler = (process, reason) =>
            {
                // Did the game process, i.e. the process with pid |remotePid|, exit?
                if (reason != ExitReason.ProcessExited &&
                    reason != ExitReason.DebuggerTerminated)
                {
                    Trace.WriteLine("Game process did not exit, won't wait for tail process exit");
                    return;
                }

                // Give it a second to finish.
                bool exited = process.WaitForExit(TimeSpan.FromSeconds(1));

                // Emit a log message to help tracking down issues, just in case.
                Trace.WriteLine($"Tail process {(exited ? "exited" : "did not exit")} gracefully");
            };

            var startInfo = ProcessStartInfoBuilder.BuildForSsh(
                $"tail --pid={remotePid} -n +0 -F -q /var/game/stdout /var/game/stderr",
                new List <string>(), target);

            return(new ProcessStartData("output tail", startInfo, monitorExit: false,
                                        outputToConsole: true, stopHandler: stopHandler));
        }
Ejemplo n.º 2
0
        ProcessStartData CreateLldbServerProcessStartData(SshTarget target)
        {
            string lldbServerCommand = string.Format(
                "{0} platform --listen 127.0.0.1:{1} --min-gdbserver-port={2} " +
                "--max-gdbserver-port={3}",
                Path.Combine(YetiConstants.LldbServerLinuxPath,
                             YetiConstants.LldbServerLinuxExecutable),
                transportSession.GetRemoteDebuggerPort(),
                transportSession.GetReservedLocalAndRemotePort(),
                transportSession.GetReservedLocalAndRemotePort() + 1);
            List <string> lldbServerEnvironment = new List <string>();

            if (yetiVSIService.DebuggerOptions[DebuggerOption.SERVER_LOGGING] ==
                DebuggerOptionState.ENABLED)
            {
                string channels = "lldb default:posix default:gdb-remote default";
                // gdb-server.log
                lldbServerEnvironment.Add(
                    "LLDB_DEBUGSERVER_LOG_FILE=/usr/local/cloudcast/log/gdb-server.log");
                lldbServerEnvironment.Add("LLDB_SERVER_LOG_CHANNELS=\\\"" + channels + "\\\"");
                // lldb-server.log
                lldbServerCommand += " --log-file=/usr/local/cloudcast/log/lldb-server.log " +
                                     "--log-channels=\\\"" + channels + "\\\"";
            }

            var startInfo = ProcessStartInfoBuilder.BuildForSsh(
                lldbServerCommand, lldbServerEnvironment, target);

            return(new ProcessStartData("lldb server", startInfo));
        }
Ejemplo n.º 3
0
        public void CreateKey(IAbsoluteFilePath outFile, bool overwrite = false)
        {
            if (outFile == null)
            {
                throw new ArgumentNullException(nameof(outFile));
            }

            var privateFile = outFile + ".biprivatekey";
            var publicFile  = outFile + ".bikey";

            if (!overwrite)
            {
                if (File.Exists(privateFile))
                {
                    throw new IOException("File exists: " + privateFile);
                }
                if (File.Exists(publicFile))
                {
                    throw new IOException("File exists: " + publicFile);
                }
            }
            var parentPath = outFile.ParentDirectoryPath;

            if (!parentPath.Exists)
            {
                throw new InvalidOperationException("Does not exist: " + parentPath + " of: " + outFile);
            }
            var startInfo = new ProcessStartInfoBuilder(_dsCreateKeyBin, BuildPathParameters(outFile.FileName))
            {
                WorkingDirectory = parentPath
            }.Build();

            ProcessExitResult(_processManager.LaunchAndGrabTool(startInfo));
        }
Ejemplo n.º 4
0
        // Queries the provided port (gamelet) for a list of running cores.  On an error, a
        // TransportException will be thrown with the error code.
        public async Task <List <CoreListEntry> > GetCoreListAsync(SshTarget sshTarget)
        {
            // TODO: Find a more robust method of listing files on the gamelet.
            ProcessStartInfo processStartInfo = ProcessStartInfoBuilder.BuildForSsh(
                COMMAND, new List <string>(), sshTarget);

            return(await GetCoreListFromProcessStartInfoAsync(processStartInfo));
        }
Ejemplo n.º 5
0
 public async Task <List <ProcessListEntry> > GetBySshAsync(SshTarget target)
 {
     using (var process = remoteProcessFactory.Create(
                ProcessStartInfoBuilder.BuildForSsh(COMMAND, new List <string>(), target)))
     {
         return(await GetByProcessAsync(process));
     }
 }
Ejemplo n.º 6
0
        public async Task GetAsync(SshTarget target, string file, string destination,
                                   ICancelable task)
        {
            await ScpAsync(ProcessStartInfoBuilder.BuildForScpGet(file, target, destination),
                           ProcessManager.CreateForCancelableTask(task));

            // Notify client if operation was cancelled.
            task.ThrowIfCancellationRequested();
        }
Ejemplo n.º 7
0
        public async Task RunWithSuccessAsync(SshTarget target, string command)
        {
            var startInfo =
                ProcessStartInfoBuilder.BuildForSsh(command, new List <string>(), target);

            using (var process = remoteProcessFactory.Create(startInfo))
            {
                await process.RunToExitWithSuccessAsync();
            }
        }
        public void BuildForSsh()
        {
            var startInfo = ProcessStartInfoBuilder.BuildForSsh(
                "test_command arg1 arg2", new List <string>(), new SshTarget("1.2.3.4:56"));

            Assert.AreEqual(GetSshPath(), startInfo.FileName);
            Assert.True(startInfo.Arguments.Contains(
                            "[email protected] -p 56 -- \"test_command arg1 arg2\""));
            Assert.True(startInfo.Arguments.Contains(
                            $"-oUserKnownHostsFile=\"\"\"{GetKnownHostsPath()}\"\"\""));
        }
Ejemplo n.º 9
0
        void CreateFiles(string outFile, bool overwrite = false, int bits = SshKeyPair.DefaultBits,
                         string type = SshKeyPair.DefaultType)
        {
            if (!overwrite && File.Exists(outFile))
            {
                throw new IOException("File exists " + outFile);
            }
            var startInfo = new ProcessStartInfoBuilder(sshKeyGenBin,
                                                        GetParameters(outFile, bits, type)).Build();

            _processManager.LaunchAndGrabTool(startInfo);
        }
Ejemplo n.º 10
0
        public virtual ProcessExitResultWithOutput LaunchAndGrabToolCmd(ProcessStartInfo info,
                                                                        string tool)
        {
            var startInfo =
                new ProcessStartInfoBuilder(Common.Paths.CmdExe,
                                            $"/C \"\"{info.FileName}\" {info.Arguments}\"")
            {
                WorkingDirectory = info.WorkingDirectory.ToAbsoluteDirectoryPathNullSafe()
            }.Build();

            return(LaunchAndGrabTool(startInfo, tool));
        }
        public void BuildForScpGet_PathEndsInBackslash()
        {
            var startInfo = ProcessStartInfoBuilder.BuildForScpGet(
                "path/to/file", new SshTarget("1.2.3.4:56"), "path\\to\\outDir\\");

            Assert.AreEqual(GetScpPath(), startInfo.FileName);
            Assert.True(startInfo.Arguments.Contains("-T"));
            Assert.True(startInfo.Arguments.Contains("-P 56"));
            StringAssert.Contains("[email protected]:\"'path/to/file'\" \"path\\to\\outDir\\\\\"",
                                  startInfo.Arguments);
            Assert.True(startInfo.Arguments.Contains(
                            $"-oUserKnownHostsFile=\"\"\"{GetKnownHostsPath()}\"\"\""));
        }
Ejemplo n.º 12
0
        public void RunExtractPboWithParameters(IAbsoluteFilePath input, IAbsoluteDirectoryPath output,
                                                params string[] parameters)
        {
            if (!input.Exists)
            {
                throw new IOException("File doesn't exist: " + input);
            }
            var startInfo =
                new ProcessStartInfoBuilder(_extractPboBin,
                                            BuildParameters(input.ToString(), output.ToString(), parameters)).Build();

            ProcessExitResult(_processManager.LaunchAndGrabTool(startInfo));
        }
        public void BuildForSshEnv()
        {
            var startInfo = ProcessStartInfoBuilder.BuildForSsh(
                "test_command arg1 arg2", new List <string>()
            {
                "VAR1=X", "VAR2=Y"
            },
                new SshTarget("1.2.3.4:56"));

            Assert.AreEqual(GetSshPath(), startInfo.FileName);
            Assert.True(startInfo.Arguments.Contains(
                            "[email protected] -p 56 -- \"VAR1=X VAR2=Y test_command arg1 arg2\""));
        }
Ejemplo n.º 14
0
        ProcessStartData CreateRgpPortForwardingProcessStartData(SshTarget target)
        {
            var ports = new List <ProcessStartInfoBuilder.PortForwardEntry>()
            {
                new ProcessStartInfoBuilder.PortForwardEntry
                {
                    LocalPort  = WorkstationPorts.RGP_LOCAL,
                    RemotePort = WorkstationPorts.RGP_REMOTE,
                }
            };
            var startInfo = ProcessStartInfoBuilder.BuildForSshPortForward(ports, target);

            return(new ProcessStartData("rgp port forwarding", startInfo));
        }
Ejemplo n.º 15
0
        protected static async Task BuildAndRunBatFile(IProcessManager pm, IAbsoluteDirectoryPath tmpFolder,
                                                       IEnumerable <string> commands, bool asAdministrator = false, bool noisy = false)
        {
            var batFile        = tmpFolder.GetChildFileWithName("install.bat");
            var actualCommands =
                new[] { "chcp 65001" }.Concat(commands)
            .Concat(new[] { "echo finished" })
            .Select(x => x == "" ? x : x + " >> install.log");
            var commandBat = string.Join("\r\n",
                                         new[] { "", "echo starting > install.log" }.Concat(actualCommands)
                                         .Concat(new[] { "" }));
            var encoding = Encoding.UTF8;

            File.WriteAllText(batFile.ToString(), commandBat, encoding);
            if (Common.Flags.Verbose || noisy)
            {
                MainLog.Logger.Info("install.bat content:\n" + commandBat);
            }

            try {
                var pInfo = new ProcessStartInfoBuilder(batFile)
                {
                    WorkingDirectory = tmpFolder
                                       //WindowStyle = ProcessWindowStyle.Minimized
                }.Build();
                pInfo.CreateNoWindow = true;
                var basicLaunchInfo = new BasicLaunchInfo(pInfo)
                {
                    StartMinimized = true
                };
                var r =
                    await(asAdministrator ? pm.LaunchElevatedAsync(basicLaunchInfo) : pm.LaunchAsync(basicLaunchInfo));
                r.ConfirmSuccess();
            } catch (Win32Exception ex) {
                if (ex.IsElevationCancelled())
                {
                    throw ex.HandleUserCancelled();
                }
                throw;
            }
            var logFile = tmpFolder.GetChildFileWithName("install.log");
            var output  = File.ReadAllText(logFile.ToString(), encoding);

            if (Common.Flags.Verbose || noisy)
            {
                MainLog.Logger.Info("install.bat output:\n" + output);
            }
        }
Ejemplo n.º 16
0
            public virtual string Gzip(IAbsoluteFilePath file, IAbsoluteFilePath dest = null,
                                       bool preserveFileNameAndModificationTime       = true, ITProgress status = null)
            {
                if (file == null)
                {
                    throw new ArgumentNullException(nameof(file));
                }
                if (!(file.Exists))
                {
                    throw new ArgumentException("file.Exists");
                }

                var defDest = (file + ".gz").ToAbsoluteFilePath();

                if (dest == null)
                {
                    dest = defDest;
                }

                var cmd = $"-f --best --rsyncable --keep \"{file}\"";

                if (!preserveFileNameAndModificationTime)
                {
                    cmd = "-n " + cmd;
                }

                dest.RemoveReadonlyWhenExists();

                var startInfo =
                    new ProcessStartInfoBuilder(Common.Paths.ToolPath.GetChildFileWithName("gzip.exe"), cmd)
                {
                    WorkingDirectory = file.ParentDirectoryPath
                }.Build();

                var srcSize = file.FileInfo.Length;
                ProcessExitResultWithOutput ret;
                var predictedSize = srcSize * DefaultPredictedCompressionRatio;

                using (StatusProcessor.Conditional(defDest, status, (long)predictedSize))
                    ret = ProcessManager.LaunchAndGrabTool(startInfo, "Gzip pack");
                if (Path.GetFullPath(dest.ToString()) != Path.GetFullPath(defDest.ToString()))
                {
                    FileUtil.Ops.MoveWithRetry(defDest, dest);
                }

                return(ret.StandardOutput + ret.StandardError);
            }
Ejemplo n.º 17
0
        ProcessStartData CreatePortForwardingProcessStartData(SshTarget target)
        {
            var ports = new List <ProcessStartInfoBuilder.PortForwardEntry>()
            {
                new ProcessStartInfoBuilder.PortForwardEntry
                {
                    LocalPort  = transportSession.GetLocalDebuggerPort(),
                    RemotePort = transportSession.GetRemoteDebuggerPort(),
                },
                new ProcessStartInfoBuilder.PortForwardEntry
                {
                    // LLDB returns the GDB server port to the LLDB client, so the local
                    // and remote port must match.
                    LocalPort  = transportSession.GetReservedLocalAndRemotePort(),
                    RemotePort = transportSession.GetReservedLocalAndRemotePort(),
                }
            };
            var startInfo = ProcessStartInfoBuilder.BuildForSshPortForward(ports, target);

            return(new ProcessStartData("lldb port forwarding", startInfo));
        }
Ejemplo n.º 18
0
            public virtual string GzipStdOut(IAbsoluteFilePath inputFile, IAbsoluteFilePath outputFile = null,
                                             bool preserveFileNameAndModificationTime = true, ITProgress status = null)
            {
                if (!(inputFile != null))
                {
                    throw new ArgumentException("inputFile != null");
                }
                if (!(inputFile.Exists))
                {
                    throw new ArgumentException("inputFile.Exists");
                }

                if (outputFile == null)
                {
                    outputFile = (inputFile + ".gz").ToAbsoluteFilePath();
                }

                var cmd = $"-f --best --rsyncable --keep --stdout \"{inputFile}\" > \"{outputFile}\"";

                if (!preserveFileNameAndModificationTime)
                {
                    cmd = "-n " + cmd;
                }

                outputFile.RemoveReadonlyWhenExists();
                var startInfo =
                    new ProcessStartInfoBuilder(Common.Paths.ToolPath.GetChildFileWithName("gzip.exe"), cmd)
                {
                    WorkingDirectory = Common.Paths.LocalDataPath
                }.Build();
                var srcSize = inputFile.FileInfo.Length;
                ProcessExitResultWithOutput ret;
                var predictedSize = srcSize * DefaultPredictedCompressionRatio;

                using (StatusProcessor.Conditional(outputFile, status, (long)predictedSize))
                    ret = ProcessManager.LaunchAndGrabToolCmd(startInfo, "Gzip pack");
                return(ret.StandardOutput + ret.StandardError);
            }
Ejemplo n.º 19
0
        public void Launch(IProcessManager processManager)
        {
            if (Path == null)
            {
                throw new ArgumentNullException(nameof(Path));
            }
            if (!(!String.IsNullOrWhiteSpace(Path)))
            {
                throw new ArgumentException("!String.IsNullOrWhiteSpace(Path)");
            }
            //if (!UserSettings.Current.AppOptions.UseElevatedService) {
            var startInfo = new ProcessStartInfoBuilder(Path, Parameters)
            {
                WorkingDirectory = Path.ToAbsoluteFilePath().ParentDirectoryPath,
                //AsAdministrator = RunAsAdmin
            }.Build();

            MainLog.Logger.Info("Launching external app: " + startInfo.Format());
            processManager.StartAndForget(startInfo);
            //} else {
            //    _wcfClient.Value.Updater_StartAndForget(Path, Parameters, System.IO.Path.GetDirectoryName(Path), RunAsAdmin);
            //}
        }
        public void BuildForSshPortForward()
        {
            var ports = new List <ProcessStartInfoBuilder.PortForwardEntry>()
            {
                new ProcessStartInfoBuilder.PortForwardEntry()
                {
                    LocalPort  = 123,
                    RemotePort = 234,
                },
                new ProcessStartInfoBuilder.PortForwardEntry()
                {
                    LocalPort  = 567,
                    RemotePort = 678,
                },
            };
            var startInfo =
                ProcessStartInfoBuilder.BuildForSshPortForward(ports, new SshTarget("1.2.3.4:56"));

            Assert.AreEqual(GetSshPath(), startInfo.FileName);
            Assert.True(startInfo.Arguments.Contains("-L123:localhost:234 -L567:localhost:678"));
            Assert.True(startInfo.Arguments.Contains("[email protected] -p 56"));
            Assert.True(startInfo.Arguments.Contains(
                            $"-oUserKnownHostsFile=\"\"\"{GetKnownHostsPath()}\"\"\""));
        }
Ejemplo n.º 21
0
        public void SignFile(IAbsoluteFilePath file, IAbsoluteFilePath privateFile)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }

            if (!file.Exists)
            {
                throw new IOException("File doesn't exist: " + file);
            }
            if (!privateFile.Exists)
            {
                throw new IOException("File doesn't exist: " + privateFile);
            }

            var startInfo =
                new ProcessStartInfoBuilder(_dsSignFileBin, BuildPathParameters(privateFile.ToString(), file.ToString()))
            {
                WorkingDirectory = Common.Paths.StartPath
            }.Build();

            ProcessExitResult(_processManager.LaunchAndGrabTool(startInfo));
        }
Ejemplo n.º 22
0
        async Task InvokeSnapApps([NotNull] List <ProcessStartInfoBuilder> allSnapAwareApps,
                                  TimeSpan cancelInvokeProcessesAfterTs, bool isInitialInstall, [NotNull] SemanticVersion semanticVersion,
                                  ILog logger = null, CancellationToken cancellationToken = default)
        {
            if (allSnapAwareApps == null)
            {
                throw new ArgumentNullException(nameof(allSnapAwareApps));
            }
            if (semanticVersion == null)
            {
                throw new ArgumentNullException(nameof(semanticVersion));
            }

            logger?.Info(
                $"Invoking {allSnapAwareApps.Count} processes. " +
                $"Timeout in {cancelInvokeProcessesAfterTs.TotalSeconds:F0} seconds.");

            var firstRunApplicationFilenames = new List <string>();

            var invocationTasks = allSnapAwareApps.ForEachAsync(async x =>
            {
                using var cts = new CancellationTokenSource();
                cts.CancelAfter(cancelInvokeProcessesAfterTs);

                try
                {
                    logger?.Debug(x.ToString());

                    var(exitCode, stdout) = await _snapOs.ProcessManager
                                            .RunAsync(x, cancellationToken) // Two cancellation tokens is intentional because of unit tests mocks.
                                            .WithCancellation(cts.Token);   // Two cancellation tokens is intentional because of unit tests mocks.

                    logger?.Debug($"Processed exited: {exitCode}. Exe: {x.Filename}. Stdout: {stdout}.");
                }
                catch (Exception ex)
                {
                    logger?.ErrorException($"Exception thrown while running application: {x.Filename}. Arguments: {x.Arguments}", ex);
                }

                if (!isInitialInstall)
                {
                    return;
                }

                firstRunApplicationFilenames.Add(x.Filename);
            }, 1 /* at a time */);

            await Task.WhenAll(invocationTasks);

            if (!isInitialInstall)
            {
                return;
            }

            firstRunApplicationFilenames.ForEach(filename =>
            {
                var builder = new ProcessStartInfoBuilder(filename)
                              .Add($"--snapx-first-run {semanticVersion.ToNormalizedString()}");
                try
                {
                    _snapOs.ProcessManager
                    .StartNonBlocking(builder);
                }
                catch (Exception ex)
                {
                    logger?.ErrorException($"Exception thrown while running 'first-run' application: {builder.Filename}. Arguments: {builder.Arguments}", ex);
                }
            });
        }
Ejemplo n.º 23
0
        static async Task <(bool success, bool canContinueIfError, string installerExeAbsolutePath)> BuildInstallerAsync([NotNull] ILog logger, [NotNull] ISnapOs snapOs,
                                                                                                                         [NotNull] ISnapxEmbeddedResources snapxEmbeddedResources, [NotNull] ISnapPack snapPack, [NotNull] ISnapAppReader snapAppReader,
                                                                                                                         [NotNull] ISnapAppWriter snapAppWriter, [NotNull] SnapApp snapApp, ICoreRunLib coreRunLib,
                                                                                                                         [NotNull] string installersWorkingDirectory, string fullNupkgAbsolutePath, [NotNull] string releasesNupkgAbsolutePath, bool offline,
                                                                                                                         CancellationToken cancellationToken)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (snapOs == null)
            {
                throw new ArgumentNullException(nameof(snapOs));
            }
            if (snapxEmbeddedResources == null)
            {
                throw new ArgumentNullException(nameof(snapxEmbeddedResources));
            }
            if (snapPack == null)
            {
                throw new ArgumentNullException(nameof(snapPack));
            }
            if (snapAppReader == null)
            {
                throw new ArgumentNullException(nameof(snapAppReader));
            }
            if (snapAppWriter == null)
            {
                throw new ArgumentNullException(nameof(snapAppWriter));
            }
            if (snapApp == null)
            {
                throw new ArgumentNullException(nameof(snapApp));
            }
            if (installersWorkingDirectory == null)
            {
                throw new ArgumentNullException(nameof(installersWorkingDirectory));
            }
            if (releasesNupkgAbsolutePath == null)
            {
                throw new ArgumentNullException(nameof(releasesNupkgAbsolutePath));
            }

            var installerPrefix = offline ? "offline" : "web";
            var snapChannel     = snapApp.GetCurrentChannelOrThrow();

            logger.Info($"Preparing to build {installerPrefix} installer for channel: {snapChannel.Name}. Version: {snapApp.Version}.");

            var progressSource = new SnapProgressSource {
                Progress = percentage => { logger.Info($"Progress: {percentage}%."); }
            };

            using var rootTempDir = snapOs.Filesystem.WithDisposableTempDirectory(installersWorkingDirectory);
            MemoryStream installerZipMemoryStream;
            MemoryStream warpPackerMemoryStream;

            string snapAppTargetRid;
            string warpPackerRid;
            string warpPackerArch;
            string installerFilename;
            string setupExtension;
            string setupIcon = null;
            var    chmod     = false;
            var    changeSubSystemToWindowsGui = false;
            var    installerIconSupported      = false;

            if (snapOs.OsPlatform == OSPlatform.Windows)
            {
                warpPackerMemoryStream = snapxEmbeddedResources.WarpPackerWindows;
                warpPackerRid          = "win-x64";
                installerIconSupported = true;
            }
            else if (snapOs.OsPlatform == OSPlatform.Linux)
            {
                warpPackerMemoryStream = snapxEmbeddedResources.WarpPackerLinux;
                warpPackerRid          = "linux-x64";
                chmod = true;
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            switch (snapApp.Target.Rid)
            {
            case "win-x64":
                installerZipMemoryStream    = snapxEmbeddedResources.SetupWindows;
                warpPackerArch              = "windows-x64";
                snapAppTargetRid            = "win-x64";
                installerFilename           = "Snap.Installer.exe";
                changeSubSystemToWindowsGui = true;
                setupExtension              = ".exe";
                if (installerIconSupported && snapApp.Target.Icon != null)
                {
                    setupIcon = snapApp.Target.Icon;
                }
                break;

            case "linux-x64":
                installerZipMemoryStream = snapxEmbeddedResources.SetupLinux;
                warpPackerArch           = "linux-x64";
                snapAppTargetRid         = "linux-x64";
                installerFilename        = "Snap.Installer";
                setupExtension           = ".bin";
                break;

            default:
                throw new PlatformNotSupportedException($"Unsupported rid: {snapApp.Target.Rid}");
            }

            var repackageTempDir = snapOs.Filesystem.PathCombine(rootTempDir.WorkingDirectory, "repackage");

            snapOs.Filesystem.DirectoryCreateIfNotExists(repackageTempDir);

            var rootTempDirWarpPackerAbsolutePath = snapOs.Filesystem.PathCombine(rootTempDir.WorkingDirectory, $"warp-packer-{warpPackerRid}.exe");
            var installerRepackageAbsolutePath    = snapOs.Filesystem.PathCombine(repackageTempDir, installerFilename);

            async Task BuildOfflineInstallerAsync()
            {
                if (fullNupkgAbsolutePath == null)
                {
                    throw new ArgumentNullException(nameof(fullNupkgAbsolutePath));
                }

                var repackageDirSnapAppDllAbsolutePath    = snapOs.Filesystem.PathCombine(repackageTempDir, SnapConstants.SnapAppDllFilename);
                var repackageDirFullNupkgAbsolutePath     = snapOs.Filesystem.PathCombine(repackageTempDir, "Setup.nupkg");
                var repackageDirReleasesNupkgAbsolutePath = snapOs.Filesystem.PathCombine(repackageTempDir,
                                                                                          snapOs.Filesystem.PathGetFileName(releasesNupkgAbsolutePath));

                await using (installerZipMemoryStream)
                    await using (warpPackerMemoryStream)
                    {
                        using var snapAppAssemblyDefinition       = snapAppWriter.BuildSnapAppAssembly(snapApp);
                        await using var snapAppDllDstMemoryStream = snapOs.Filesystem.FileWrite(repackageDirSnapAppDllAbsolutePath);
                        await using var warpPackerDstStream       = snapOs.Filesystem.FileWrite(rootTempDirWarpPackerAbsolutePath);
                        using var zipArchive = new ZipArchive(installerZipMemoryStream, ZipArchiveMode.Read);
                        snapAppAssemblyDefinition.Write(snapAppDllDstMemoryStream);

                        progressSource.Raise(10);

                        logger.Info("Extracting installer to temp directory.");
                        zipArchive.ExtractToDirectory(repackageTempDir);

                        progressSource.Raise(20);

                        logger.Info("Copying assets to temp directory.");

                        await Task.WhenAll(
                            warpPackerMemoryStream.CopyToAsync(warpPackerDstStream, cancellationToken),
                            snapOs.Filesystem.FileCopyAsync(fullNupkgAbsolutePath, repackageDirFullNupkgAbsolutePath, cancellationToken),
                            snapOs.Filesystem.FileCopyAsync(releasesNupkgAbsolutePath, repackageDirReleasesNupkgAbsolutePath, cancellationToken));

                        if (installerIconSupported && setupIcon != null)
                        {
                            logger.Debug($"Writing installer icon: {setupIcon}.");

                            var zipArchiveInstallerFilename = snapOs.Filesystem.PathCombine(repackageTempDir, installerFilename);

                            var rcEditOptions = new RcEditOptions
                            {
                                Filename     = zipArchiveInstallerFilename,
                                IconFilename = setupIcon
                            };

                            CommandRcEdit(rcEditOptions, coreRunLib, snapOs.Filesystem, logger);
                        }
                    }
            }

            async Task BuildWebInstallerAsync()
            {
                var repackageDirSnapAppDllAbsolutePath = snapOs.Filesystem.PathCombine(repackageTempDir, SnapConstants.SnapAppDllFilename);

                await using (installerZipMemoryStream)
                    await using (warpPackerMemoryStream)
                    {
                        await using var warpPackerDstStream = snapOs.Filesystem.FileWrite(rootTempDirWarpPackerAbsolutePath);
                        using var zipArchive = new ZipArchive(installerZipMemoryStream, ZipArchiveMode.Read);
                        using var snapAppAssemblyDefinition       = snapAppWriter.BuildSnapAppAssembly(snapApp);
                        await using var snapAppDllDstMemoryStream = snapOs.Filesystem.FileWrite(repackageDirSnapAppDllAbsolutePath);
                        snapAppAssemblyDefinition.Write(snapAppDllDstMemoryStream);

                        progressSource.Raise(10);

                        logger.Info("Extracting installer to temp directory.");
                        zipArchive.ExtractToDirectory(repackageTempDir);

                        progressSource.Raise(20);

                        logger.Info("Copying assets to temp directory.");

                        await Task.WhenAll(
                            warpPackerMemoryStream.CopyToAsync(warpPackerDstStream, cancellationToken));

                        if (installerIconSupported && setupIcon != null)
                        {
                            logger.Debug($"Writing installer icon: {setupIcon}.");

                            var zipArchiveInstallerFilename = snapOs.Filesystem.PathCombine(repackageTempDir, installerFilename);

                            var rcEditOptions = new RcEditOptions
                            {
                                Filename     = zipArchiveInstallerFilename,
                                IconFilename = setupIcon
                            };

                            CommandRcEdit(rcEditOptions, coreRunLib, snapOs.Filesystem, logger);
                        }
                    }
            }

            var installerFinalAbsolutePath = snapOs.Filesystem.PathCombine(installersWorkingDirectory,
                                                                           $"Setup-{snapAppTargetRid}-{snapApp.Id}-{snapChannel.Name}-{installerPrefix}{setupExtension}");

            if (offline)
            {
                await BuildOfflineInstallerAsync();
            }
            else
            {
                await BuildWebInstallerAsync();
            }

            progressSource.Raise(50);

            var processStartInfoBuilder = new ProcessStartInfoBuilder(rootTempDirWarpPackerAbsolutePath)
                                          .Add($"--arch {warpPackerArch}")
                                          .Add($"--exec {installerFilename}")
                                          .Add($"--output {installerFinalAbsolutePath.ForwardSlashesSafe()}")
                                          .Add($"--input_dir {repackageTempDir.ForwardSlashesSafe()}");

            if (chmod)
            {
                await snapOs.ProcessManager.ChmodExecuteAsync(rootTempDirWarpPackerAbsolutePath, cancellationToken);

                await snapOs.ProcessManager.ChmodExecuteAsync(installerRepackageAbsolutePath, cancellationToken);
            }

            logger.Info("Packaging installer.");

            var(exitCode, stdout) = await snapOs.ProcessManager.RunAsync(processStartInfoBuilder, cancellationToken);

            if (exitCode != 0)
            {
                logger.Error(
                    $"Warp packer exited with error code: {exitCode}. Warp packer executable path: {rootTempDirWarpPackerAbsolutePath}. Stdout: {stdout}.");
                return(false, false, null);
            }

            progressSource.Raise(80);

            if (changeSubSystemToWindowsGui)
            {
                // NB! Unable to set icon on warped executable. Please refer to the following issue:
                // https://github.com/electron/rcedit/issues/70

                var rcEditOptions = new RcEditOptions
                {
                    ConvertSubSystemToWindowsGui = true,
                    Filename = installerFinalAbsolutePath,
                    //IconFilename = setupIcon
                };

                CommandRcEdit(rcEditOptions, coreRunLib, snapOs.Filesystem, logger);
            }

            if (chmod)
            {
                await snapOs.ProcessManager.ChmodExecuteAsync(installerFinalAbsolutePath, cancellationToken);
            }

            progressSource.Raise(100);

            return(true, false, installerFinalAbsolutePath);
        }
Ejemplo n.º 24
0
        void RunMakePbo(string parameters)
        {
            var startInfo = new ProcessStartInfoBuilder(_makePboBin, parameters).Build();

            ProcessExitResult(_processManager.LaunchAndGrabTool(startInfo));
        }