Exemplo n.º 1
0
        public async Task TestCancel()
        {
            const int SecondsToRun = 20;

            using (TestHostContext hc = new TestHostContext(this))
                using (var tokenSource = new CancellationTokenSource())
                {
                    Tracing trace          = hc.GetTrace();
                    var     processInvoker = new ProcessInvoker();
                    processInvoker.Initialize(hc);
                    Stopwatch watch = Stopwatch.StartNew();
#if OS_WINDOWS
                    Task execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
#endif
#if (OS_OSX || OS_LINUX)
                    Task execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token);
#endif
                    tokenSource.Cancel();
                    await Task.WhenAny(new Task[] { execTask });

                    Assert.True(execTask.IsCompleted);
                    Assert.True(!execTask.IsFaulted);
                    Assert.True(execTask.IsCanceled);
                    watch.Stop();
                    var elapsedSeconds = watch.ElapsedMilliseconds / 1000;
                    //if cancellation fails, then execution time is more than 10 seconds
                    Assert.True(elapsedSeconds < SecondsToRun / 2, "cancellation failed, because task took too long to run");
                }
        }
Exemplo n.º 2
0
        public async Task TestCancel()
        {
            const int SecondsToRun = 20;
            using (TestHostContext hc = new TestHostContext(this))
            using (var tokenSource = new CancellationTokenSource())
            {
                Tracing trace = hc.GetTrace();
                var processInvoker = new ProcessInvoker();
                processInvoker.Initialize(hc);
                Stopwatch watch = Stopwatch.StartNew();
#if OS_WINDOWS
                Task execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token);
#endif
#if (OS_OSX || OS_LINUX)
                Task execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token);
#endif
                await Task.Delay(500);
                tokenSource.Cancel();
                await Task.WhenAny(execTask);
                Assert.True(execTask.IsCompleted);
                Assert.True(!execTask.IsFaulted);
                Assert.True(execTask.IsCanceled);
                watch.Stop();
                var elapsedSeconds = watch.ElapsedMilliseconds / 1000;
                //if cancellation fails, then execution time is more than 10 seconds
                Assert.True(elapsedSeconds < SecondsToRun / 2, $"cancellation failed, because task took too long to run. {elapsedSeconds}");
            }
        }
        private async Task RunCommandAsync(params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(_context, nameof(_context));

            // Invoke tf.
            var processInvoker = new ProcessInvoker(_context);
            var outputLock     = new object();

            processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    _context.Output(e.Data);
                }
            };
            processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    _context.Output(e.Data);
                }
            };
            string arguments = FormatArgumentsWithDefaults(args);

            _context.Command($@"{_svn} {arguments}");
            await processInvoker.ExecuteAsync(
                workingDirectory : _context.Variables.GetValueOrDefault("agent.workfolder")?.Value,
                fileName : _svn,
                arguments : arguments,
                environment : null,
                requireExitCodeZero : true,
                cancellationToken : _cancellationToken);
        }
Exemplo n.º 4
0
        private async Task <int> ExecuteGitCommandAsync(AgentTaskPluginExecutionContext context, string repoRoot, string command, string options, IList <string> output)
        {
            string arg = StringUtil.Format($"{command} {options}").Trim();

            context.Command($"git {arg}");

            if (output == null)
            {
                output = new List <string>();
            }

            var processInvoker = new ProcessInvoker(context);

            processInvoker.OutputDataReceived += delegate(object sender, ProcessDataReceivedEventArgs message)
            {
                output.Add(message.Data);
            };

            processInvoker.ErrorDataReceived += delegate(object sender, ProcessDataReceivedEventArgs message)
            {
                context.Output(message.Data);
            };

            return(await processInvoker.ExecuteAsync(
                       workingDirectory : repoRoot,
                       fileName : gitPath,
                       arguments : arg,
                       environment : gitEnv,
                       requireExitCodeZero : false,
                       outputEncoding : s_encoding,
                       cancellationToken : default(CancellationToken)));
        }
 public async Task <int> ExecuteAsync(
     string workingDirectory,
     string fileName,
     string arguments,
     IDictionary <string, string> environment,
     bool requireExitCodeZero,
     Encoding outputEncoding,
     bool killProcessOnCancel,
     Channel <string> redirectStandardIn,
     bool inheritConsoleHandler,
     bool keepStandardInOpen,
     bool highPriorityProcess,
     CancellationToken cancellationToken)
 {
     _invoker.ErrorDataReceived  += this.ErrorDataReceived;
     _invoker.OutputDataReceived += this.OutputDataReceived;
     return(await _invoker.ExecuteAsync(
                workingDirectory,
                fileName,
                arguments,
                environment,
                requireExitCodeZero,
                outputEncoding,
                killProcessOnCancel,
                redirectStandardIn,
                inheritConsoleHandler,
                keepStandardInOpen,
                highPriorityProcess,
                cancellationToken));
 }
Exemplo n.º 6
0
        private async Task <int> ExecuteGitCommandAsync(AgentTaskPluginExecutionContext context, string repoRoot, string command, string options, string additionalCommandLine, CancellationToken cancellationToken)
        {
            string arg = StringUtil.Format($"{additionalCommandLine} {command} {options}").Trim();

            context.Command($"git {arg}");

            var processInvoker = new ProcessInvoker(context);

            processInvoker.OutputDataReceived += delegate(object sender, ProcessDataReceivedEventArgs message)
            {
                context.Output(message.Data);
            };

            processInvoker.ErrorDataReceived += delegate(object sender, ProcessDataReceivedEventArgs message)
            {
                context.Output(message.Data);
            };

            return(await processInvoker.ExecuteAsync(
                       workingDirectory : repoRoot,
                       fileName : gitPath,
                       arguments : arg,
                       environment : GetGitEnvironmentVariables(context),
                       requireExitCodeZero : false,
                       outputEncoding : s_encoding,
                       cancellationToken : cancellationToken));
        }
Exemplo n.º 7
0
        private async Task <FileSharePublishResult> PublishArtifactUsingRobocopyAsync(
            AgentTaskPluginExecutionContext executionContext,
            string dropLocation,
            string downloadFolderPath,
            int parallelCount,
            CancellationToken cancellationToken)
        {
            executionContext.Output(StringUtil.Loc("PublishingArtifactUsingRobocopy"));
            using (var processInvoker = new ProcessInvoker(this.context))
            {
                // Save STDOUT from worker, worker will use STDOUT report unhandle exception.
                processInvoker.OutputDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stdout)
                {
                    if (!string.IsNullOrEmpty(stdout.Data))
                    {
                        executionContext.Output(stdout.Data);
                    }
                };

                // Save STDERR from worker, worker will use STDERR on crash.
                processInvoker.ErrorDataReceived += delegate(object sender, ProcessDataReceivedEventArgs stderr)
                {
                    if (!string.IsNullOrEmpty(stderr.Data))
                    {
                        executionContext.Error(stderr.Data);
                    }
                };

                var trimChars = new[] { '\\', '/' };

                dropLocation       = Path.Combine(dropLocation.TrimEnd(trimChars));
                downloadFolderPath = downloadFolderPath.TrimEnd(trimChars);

                string robocopyArguments = "\"" + dropLocation + "\" \"" + downloadFolderPath + "\" * /E /COPY:DA /NP /R:3";

                robocopyArguments += " /MT:" + parallelCount;

                int exitCode = await processInvoker.ExecuteAsync(
                    workingDirectory : "",
                    fileName : "robocopy",
                    arguments : robocopyArguments,
                    environment : null,
                    requireExitCodeZero : false,
                    outputEncoding : null,
                    killProcessOnCancel : true,
                    cancellationToken : cancellationToken);

                executionContext.Output(StringUtil.Loc("RobocopyBasedPublishArtifactTaskExitCode", exitCode));
                // Exit code returned from robocopy. For more info https://blogs.technet.microsoft.com/deploymentguys/2008/06/16/robocopy-exit-codes/
                if (exitCode >= 8)
                {
                    throw new Exception(StringUtil.Loc("RobocopyBasedPublishArtifactTaskFailed", exitCode));
                }

                return(new FileSharePublishResult(exitCode));
            }
        }
Exemplo n.º 8
0
        public async Task SuccessExitsWithCodeZero()
        {
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace = hc.GetTrace();

                Int32 exitCode       = -1;
                var   processInvoker = new ProcessInvoker();
                processInvoker.Initialize(hc);
#if OS_WINDOWS
                exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"dir >nul\"", null, CancellationToken.None);
#endif
#if (OS_OSX || OS_LINUX)
                exitCode = await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, CancellationToken.None);
#endif

                trace.Info("Exit Code: {0}", exitCode);
                Assert.Equal(0, exitCode);
            }
        }
Exemplo n.º 9
0
        public async Task SuccessExitsWithCodeZero()
        {
            using (TestHostContext hc = new TestHostContext(this))
            using (var tokenSource = new CancellationTokenSource())
            {
                Tracing trace = hc.GetTrace();

                Int32 exitCode = -1;
                var processInvoker = new ProcessInvoker();
                processInvoker.Initialize(hc);
#if OS_WINDOWS
                exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"dir >nul\"", null, tokenSource.Token);
#endif
#if (OS_OSX || OS_LINUX)
                exitCode = await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, tokenSource.Token);
#endif

                trace.Info("Exit Code: {0}", exitCode);
                Assert.Equal(0, exitCode);
            }
        }
        private async Task <string> RunPorcelainCommandAsync(params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(_context, nameof(_context));

            // Invoke tf.
            var processInvoker = new ProcessInvoker(_context);
            var output         = new List <string>();
            var outputLock     = new object();

            processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    _context.Debug(e.Data);
                    output.Add(e.Data);
                }
            };
            processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    _context.Debug(e.Data);
                    output.Add(e.Data);
                }
            };
            string arguments = FormatArgumentsWithDefaults(args);

            _context.Debug($@"{_svn} {arguments}");
            // TODO: Test whether the output encoding needs to be specified on a non-Latin OS.
            try
            {
                await processInvoker.ExecuteAsync(
                    workingDirectory : _context.Variables.GetValueOrDefault("agent.workfolder")?.Value,
                    fileName : _svn,
                    arguments : arguments,
                    environment : null,
                    requireExitCodeZero : true,
                    cancellationToken : _cancellationToken);
            }
            catch (ProcessExitCodeException)
            {
                // The command failed. Dump the output and throw.
                output.ForEach(x => _context.Output(x ?? string.Empty));
                throw;
            }

            // Note, string.join gracefully handles a null element within the IEnumerable<string>.
            return(string.Join(Environment.NewLine, output));
        }
Exemplo n.º 11
0
        protected async Task <TfsVCPorcelainCommandResult> TryRunPorcelainCommandAsync(FormatFlags formatFlags, params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));

            // Invoke tf.
            var processInvoker = new ProcessInvoker(ExecutionContext);
            var result         = new TfsVCPorcelainCommandResult();
            var outputLock     = new object();

            processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    ExecutionContext.Debug(e.Data);
                    result.Output.Add(e.Data);
                }
            };
            processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    ExecutionContext.Debug(e.Data);
                    result.Output.Add(e.Data);
                }
            };
            string arguments = FormatArguments(formatFlags, args);

            ExecutionContext.Debug($@"tf {arguments}");
            // TODO: Test whether the output encoding needs to be specified on a non-Latin OS.
            try
            {
                await processInvoker.ExecuteAsync(
                    workingDirectory : SourcesDirectory,
                    fileName : "tf",
                    arguments : arguments,
                    environment : AdditionalEnvironmentVariables,
                    requireExitCodeZero : true,
                    outputEncoding : OutputEncoding,
                    cancellationToken : CancellationToken);
            }
            catch (ProcessExitCodeException ex)
            {
                result.Exception = ex;
            }

            return(result);
        }
        public void SetupClientCertificate(string clientCert, string clientCertKey, string clientCertArchive, string clientCertPassword)
        {
            ExecutionContext.Debug("Convert client certificate from 'pkcs' format to 'jks' format.");
            string toolPath = WhichUtil.Which("keytool", true, ExecutionContext);
            string jksFile  = Path.Combine(ExecutionContext.Variables.GetValueOrDefault("agent.tempdirectory")?.Value, $"{Guid.NewGuid()}.jks");
            string argLine;

            if (!string.IsNullOrEmpty(clientCertPassword))
            {
                argLine = $"-importkeystore -srckeystore \"{clientCertArchive}\" -srcstoretype pkcs12 -destkeystore \"{jksFile}\" -deststoretype JKS -srcstorepass \"{clientCertPassword}\" -deststorepass \"{clientCertPassword}\"";
            }
            else
            {
                argLine = $"-importkeystore -srckeystore \"{clientCertArchive}\" -srcstoretype pkcs12 -destkeystore \"{jksFile}\" -deststoretype JKS";
            }

            ExecutionContext.Command($"{toolPath} {argLine}");

            using (var processInvoker = new ProcessInvoker(ExecutionContext))
            {
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs args) =>
                {
                    if (!string.IsNullOrEmpty(args.Data))
                    {
                        ExecutionContext.Output(args.Data);
                    }
                };
                processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs args) =>
                {
                    if (!string.IsNullOrEmpty(args.Data))
                    {
                        ExecutionContext.Output(args.Data);
                    }
                };

                processInvoker.ExecuteAsync(ExecutionContext.Variables.GetValueOrDefault("system.defaultworkingdirectory")?.Value, toolPath, argLine, null, true, CancellationToken.None).GetAwaiter().GetResult();

                if (!string.IsNullOrEmpty(clientCertPassword))
                {
                    ExecutionContext.Debug($"Set TF_ADDITIONAL_JAVA_ARGS=-Djavax.net.ssl.keyStore={jksFile} -Djavax.net.ssl.keyStorePassword={clientCertPassword}");
                    AdditionalEnvironmentVariables["TF_ADDITIONAL_JAVA_ARGS"] = $"-Djavax.net.ssl.keyStore={jksFile} -Djavax.net.ssl.keyStorePassword={clientCertPassword}";
                }
                else
                {
                    ExecutionContext.Debug($"Set TF_ADDITIONAL_JAVA_ARGS=-Djavax.net.ssl.keyStore={jksFile}");
                    AdditionalEnvironmentVariables["TF_ADDITIONAL_JAVA_ARGS"] = $"-Djavax.net.ssl.keyStore={jksFile}";
                }
            }
        }
Exemplo n.º 13
0
        private async Task CreateRepository(TestHostContext hostConetxt, string path, string url)
        {
            Directory.CreateDirectory(path);
            var gitPath     = WhichUtil.Which("git", true);
            var environment = new Dictionary <string, string>();

            using (var processInvoker = new ProcessInvoker(hostConetxt.GetTrace()))
            {
                await processInvoker.ExecuteAsync(path, gitPath, "init", environment, CancellationToken.None);
            }

            using (var processInvoker = new ProcessInvoker(hostConetxt.GetTrace()))
            {
                await processInvoker.ExecuteAsync(path, gitPath, $"remote add origin {url}", environment, CancellationToken.None);
            }
        }
Exemplo n.º 14
0
        protected async Task <int> RunCommandAsync(FormatFlags formatFlags, bool quiet, bool failOnNonZeroExitCode, params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));

            // Invoke tf.
            using (var processInvoker = new ProcessInvoker(ExecutionContext))
            {
                var outputLock = new object();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        if (quiet)
                        {
                            ExecutionContext.Debug(e.Data);
                        }
                        else
                        {
                            ExecutionContext.Output(e.Data);
                        }
                    }
                };
                processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        ExecutionContext.Output(e.Data);
                    }
                };
                string arguments = FormatArguments(formatFlags, args);
                ExecutionContext.Command($@"tf {arguments}");

                return(await processInvoker.ExecuteAsync(
                           workingDirectory : SourcesDirectory,
                           fileName : "tf",
                           arguments : arguments,
                           environment : AdditionalEnvironmentVariables,
                           requireExitCodeZero : failOnNonZeroExitCode,
                           outputEncoding : OutputEncoding,
                           cancellationToken : CancellationToken));
            }
        }
Exemplo n.º 15
0
        public async Task DefaultsToCurrentSystemOemEncoding()
        {
            // This test verifies that the additional code pages encoding provider is registered.
            // By default, only Unicode encodings, ASCII, and code page 28591 are supported. An
            // additional provider must be registered to support the full set of encodings that
            // were included in Full .NET prior to 4.6.
            //
            // For example, on an en-US box, this is required for loading the encoding for the
            // default console output code page '437'. Without loading the correct encoding for
            // code page IBM437, some characters cannot be translated correctly, e.g. write 'ç'
            // from powershell.exe.
            using (TestHostContext hc = new TestHostContext(this))
            {
                Tracing trace          = hc.GetTrace();
                var     processInvoker = new ProcessInvoker();
                processInvoker.Initialize(hc);
                var stdout = new List <string>();
                var stderr = new List <string>();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    stdout.Add(e.Data);
                };
                processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    stderr.Add(e.Data);
                };
                await processInvoker.ExecuteAsync(
                    workingDirectory : "",
                    fileName : "powershell.exe",
                    arguments : $@"-NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ""Write-Host 'From STDOUT ''ç''' ; Write-Error 'From STDERR ''ç'''""",
                    environment : null,
                    requireExitCodeZero : false,
                    cancellationToken : CancellationToken.None);

                Assert.Equal(1, stdout.Count);
                Assert.Equal("From STDOUT 'ç'", stdout[0]);
                Assert.True(stderr.Count > 0);
                Assert.True(stderr[0].Contains("From STDERR 'ç'"));
            }
        }
Exemplo n.º 16
0
        private static async Task CreateDirectoryReparsePoint(IHostContext context, string link, string target)
        {
#if OS_WINDOWS
            string fileName  = Environment.GetEnvironmentVariable("ComSpec");
            string arguments = $@"/c ""mklink /J ""{link}"" {target}""""";
#else
            string fileName  = "/bin/ln";
            string arguments = $@"-s ""{target}"" ""{link}""";
#endif
            ArgUtil.File(fileName, nameof(fileName));
            using (var processInvoker = new ProcessInvoker())
            {
                processInvoker.Initialize(context);
                await processInvoker.ExecuteAsync(
                    workingDirectory : context.GetDirectory(WellKnownDirectory.Bin),
                    fileName : fileName,
                    arguments : arguments,
                    environment : null,
                    requireExitCodeZero : true,
                    cancellationToken : CancellationToken.None);
            }
        }
Exemplo n.º 17
0
        protected async Task RunCommandAsync(FormatFlags formatFlags, params string[] args)
        {
            // Validation.
            PluginUtil.NotNull(args, nameof(args));
            PluginUtil.NotNull(ExecutionContext, nameof(ExecutionContext));

            // Invoke tf.
            var processInvoker = new ProcessInvoker(ExecutionContext);
            var outputLock     = new object();

            processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    ExecutionContext.Output(e.Data);
                }
            };
            processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
            {
                lock (outputLock)
                {
                    ExecutionContext.Output(e.Data);
                }
            };
            string arguments = FormatArguments(formatFlags, args);

            ExecutionContext.Command($@"tf {arguments}");
            await processInvoker.ExecuteAsync(
                workingDirectory : SourcesDirectory,
                fileName : "tf",
                arguments : arguments,
                environment : AdditionalEnvironmentVariables,
                requireExitCodeZero : true,
                outputEncoding : OutputEncoding,
                cancellationToken : CancellationToken);
        }
Exemplo n.º 18
0
        protected sealed override Object EvaluateCore(
            EvaluationContext context,
            out ResultMemory resultMemory)
        {
            resultMemory = null;
            var templateContext = context.State as DistributedTask.ObjectTemplating.TemplateContext;

            ArgUtil.NotNull(templateContext, nameof(templateContext));
            templateContext.ExpressionValues.TryGetValue(PipelineTemplateConstants.GitHub, out var githubContextData);
            ArgUtil.NotNull(githubContextData, nameof(githubContextData));
            var githubContext = githubContextData as DictionaryContextData;

            ArgUtil.NotNull(githubContext, nameof(githubContext));
            githubContext.TryGetValue(PipelineTemplateConstants.Workspace, out var workspace);
            var workspaceData = workspace as StringContextData;

            ArgUtil.NotNull(workspaceData, nameof(workspaceData));

            string        githubWorkspace = workspaceData.Value;
            bool          followSymlink   = false;
            List <string> patterns        = new List <string>();
            var           firstParameter  = true;

            foreach (var parameter in Parameters)
            {
                var parameterString = parameter.Evaluate(context).ConvertToString();
                if (firstParameter)
                {
                    firstParameter = false;
                    if (parameterString.StartsWith("--"))
                    {
                        if (string.Equals(parameterString, "--follow-symbolic-links", StringComparison.OrdinalIgnoreCase))
                        {
                            followSymlink = true;
                            continue;
                        }
                        else
                        {
                            throw new ArgumentOutOfRangeException($"Invalid glob option {parameterString}, avaliable option: '--follow-symbolic-links'.");
                        }
                    }
                }

                patterns.Add(parameterString);
            }

            context.Trace.Info($"Search root directory: '{githubWorkspace}'");
            context.Trace.Info($"Search pattern: '{string.Join(", ", patterns)}'");

            string binDir     = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string runnerRoot = new DirectoryInfo(binDir).Parent.FullName;

            string node            = Path.Combine(runnerRoot, "externals", "node12", "bin", $"node{IOUtil.ExeExtension}");
            string hashFilesScript = Path.Combine(binDir, "hashFiles");
            var    hashResult      = string.Empty;
            var    p = new ProcessInvoker(new HashFilesTrace(context.Trace));

            p.ErrorDataReceived += ((_, data) =>
            {
                if (!string.IsNullOrEmpty(data.Data) && data.Data.StartsWith("__OUTPUT__") && data.Data.EndsWith("__OUTPUT__"))
                {
                    hashResult = data.Data.Substring(10, data.Data.Length - 20);
                    context.Trace.Info($"Hash result: '{hashResult}'");
                }
                else
                {
                    context.Trace.Info(data.Data);
                }
            });

            p.OutputDataReceived += ((_, data) =>
            {
                context.Trace.Info(data.Data);
            });

            var env = new Dictionary <string, string>();

            if (followSymlink)
            {
                env["followSymbolicLinks"] = "true";
            }
            env["patterns"] = string.Join(Environment.NewLine, patterns);

            int exitCode = p.ExecuteAsync(workingDirectory: githubWorkspace,
                                          fileName: node,
                                          arguments: $"\"{hashFilesScript.Replace("\"", "\\\"")}\"",
                                          environment: env,
                                          requireExitCodeZero: false,
                                          cancellationToken: new CancellationTokenSource(TimeSpan.FromSeconds(120)).Token).GetAwaiter().GetResult();

            if (exitCode != 0)
            {
                throw new InvalidOperationException($"hashFiles('{ExpressionUtility.StringEscape(string.Join(", ", patterns))}') failed. Fail to hash files under directory '{githubWorkspace}'");
            }

            return(hashResult);
        }
Exemplo n.º 19
0
        protected async Task <TfsVCPorcelainCommandResult> TryRunPorcelainCommandAsync(FormatFlags formatFlags, int retriesOnFailure, params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));

            // Invoke tf.
            using (var processInvoker = new ProcessInvoker(ExecutionContext))
            {
                var result     = new TfsVCPorcelainCommandResult();
                var outputLock = new object();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        ExecutionContext.Debug(e.Data);
                        result.Output.Add(e.Data);
                    }
                };
                processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        ExecutionContext.Debug(e.Data);
                        result.Output.Add(e.Data);
                    }
                };
                string arguments = FormatArguments(formatFlags, args);
                ExecutionContext.Debug($@"tf {arguments}");
                // TODO: Test whether the output encoding needs to be specified on a non-Latin OS.
                try
                {
                    for (int attempt = 0; attempt < retriesOnFailure; attempt++)
                    {
                        int exitCode = await processInvoker.ExecuteAsync(
                            workingDirectory : SourcesDirectory,
                            fileName : "tf",
                            arguments : arguments,
                            environment : AdditionalEnvironmentVariables,
                            requireExitCodeZero : false,
                            outputEncoding : OutputEncoding,
                            cancellationToken : CancellationToken);

                        if (exitCode == 0)
                        {
                            return(result);
                        }

                        int sleep = Math.Min(200 * (int)Math.Pow(5, attempt), 30000);
                        ExecutionContext.Output($"Sleeping for {sleep} ms");
                        Thread.Sleep(sleep);

                        // Use attempt+2 since we're using 0 based indexing and we're displaying this for the next attempt.
                        ExecutionContext.Output($@"Retrying. Attempt ${attempt + 2}/${retriesOnFailure}");
                    }

                    // Perform one last try and fail on non-zero exit code
                    await processInvoker.ExecuteAsync(
                        workingDirectory : SourcesDirectory,
                        fileName : "tf",
                        arguments : arguments,
                        environment : AdditionalEnvironmentVariables,
                        requireExitCodeZero : true,
                        outputEncoding : OutputEncoding,
                        cancellationToken : CancellationToken);
                }
                catch (ProcessExitCodeException ex)
                {
                    result.Exception = ex;
                }

                return(result);
            }
        }
        protected async Task RunCommandAsync(FormatFlags formatFlags, bool quiet, int retriesOnFailure, params string[] args)
        {
            // Validation.
            ArgUtil.NotNull(args, nameof(args));
            ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));

            // Invoke tf.
            using (var processInvoker = new ProcessInvoker(ExecutionContext))
            {
                var outputLock = new object();
                processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        if (quiet)
                        {
                            ExecutionContext.Debug(e.Data);
                        }
                        else
                        {
                            ExecutionContext.Output(e.Data);
                        }
                    }
                };
                processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) =>
                {
                    lock (outputLock)
                    {
                        ExecutionContext.Output(e.Data);
                    }
                };
                string arguments = FormatArguments(formatFlags, args);
                ExecutionContext.Command($@"tf {arguments}");

                for (int attempt = 0; attempt < retriesOnFailure; attempt++)
                {
                    int exitCode = await processInvoker.ExecuteAsync(
                        workingDirectory : SourcesDirectory,
                        fileName : "tf",
                        arguments : arguments,
                        environment : AdditionalEnvironmentVariables,
                        requireExitCodeZero : false,
                        outputEncoding : OutputEncoding,
                        cancellationToken : CancellationToken);

                    if (exitCode == 0)
                    {
                        return;
                    }

                    int sleep = Math.Min(200 * (int)Math.Pow(5, attempt), 30000);
                    ExecutionContext.Output($"Sleeping for {sleep} ms");
                    await Task.Delay(sleep);

                    // Use attempt+2 since we're using 0 based indexing and we're displaying this for the next attempt.
                    ExecutionContext.Output($@"Retrying. Attempt ${attempt+2}/${retriesOnFailure}");
                }

                // Perform one last try and fail on non-zero exit code
                await processInvoker.ExecuteAsync(
                    workingDirectory : SourcesDirectory,
                    fileName : "tf",
                    arguments : arguments,
                    environment : AdditionalEnvironmentVariables,
                    requireExitCodeZero : true,
                    outputEncoding : OutputEncoding,
                    cancellationToken : CancellationToken);
            }
        }
Exemplo n.º 21
0
        private static async Task CreateDirectoryReparsePoint(IHostContext context, string link, string target)
        {
#if OS_WINDOWS
            string fileName = Environment.GetEnvironmentVariable("ComSpec");
            string arguments = $@"/c ""mklink /J ""{link}"" {target}""""";
#else
            string fileName = "/bin/ln";
            string arguments = $@"-s ""{target}"" ""{link}""";
#endif
            ArgUtil.File(fileName, nameof(fileName));
            using (var processInvoker = new ProcessInvoker())
            {
                processInvoker.Initialize(context);
                await processInvoker.ExecuteAsync(
                    workingDirectory: IOUtil.GetBinPath(),
                    fileName: fileName,
                    arguments: arguments,
                    environment: null,
                    requireExitCodeZero: true,
                    cancellationToken: CancellationToken.None);
            }
        }