This class is responsible for decoding the output from the Mercurial instance running in Command Server mode.
Ejemplo n.º 1
0
        /// <summary>
        /// Decodes the initial block that Mercurial outputs when it is spun up.
        /// </summary>
        private void DecodeInitialBlock()
        {
            char   type;
            string content;
            int    exitCode;

            CommandServerOutputDecoder.DecodeOneBlock(_Process.StandardOutput, out type, out content, out exitCode);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Executes the given <see cref="IMercurialCommand"/> command against
        /// the Mercurial repository.
        /// </summary>
        /// <param name="command">
        /// The <see cref="IMercurialCommand"/> command to execute.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <para><paramref name="command"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="MercurialException">
        /// HG did not complete within the allotted time.
        /// </exception>
        public void Execute(IMercurialCommand command)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }

            if (_Process == null)
            {
                StartPersistentMercurialClient();
            }

            command.Validate();
            command.Before();

            IEnumerable <string> arguments = new[]
            {
                command.Command,
                "--noninteractive",
                "--encoding",
                ClientExecutable.TextEncodingName,
            };

            arguments = arguments.Concat(command.Arguments.Where(a => !StringEx.IsNullOrWhiteSpace(a)));
            arguments = arguments.Concat(command.AdditionalArguments.Where(a => !StringEx.IsNullOrWhiteSpace(a)));

            var commandParts = arguments.ToArray();

            string commandEncoded = string.Join("\0", commandParts.Select(p => p.Trim('"')).ToArray());
            int    length         = commandEncoded.Length;
            var    commandBuffer  = new StringBuilder();

            commandBuffer.Append("runcommand\n");
            commandBuffer.Append((char)((length >> 24) & 0xff));
            commandBuffer.Append((char)((length >> 16) & 0xff));
            commandBuffer.Append((char)((length >> 8) & 0xff));
            commandBuffer.Append((char)(length & 0xff));
            commandBuffer.Append(commandEncoded);

            string commandArguments = null;

            if (command.Observer != null)
            {
                commandArguments = string.Join(" ", commandParts.Skip(1).ToArray());
                command.Observer.Executing(command.Command, commandArguments);
            }

            byte[] buffer = ClientExecutable.TextEncoding.GetBytes(commandBuffer.ToString());
            foreach (byte b in buffer)
            {
                _Process.StandardInput.BaseStream.WriteByte(b);
                _Process.StandardInput.BaseStream.Flush();
            }

            string standardOutput;
            string standardError;
            int    exitCode;

            if (CommandServerOutputDecoder.GetOutput(_Process.StandardOutput, out standardOutput, out standardError, out exitCode))
            {
                if (command.Observer != null)
                {
                    using (var lineReader = new StringReader(standardOutput))
                    {
                        string line;
                        while ((line = lineReader.ReadLine()) != null)
                        {
                            command.Observer.Output(line);
                        }
                    }
                    using (var lineReader = new StringReader(standardError))
                    {
                        string line;
                        while ((line = lineReader.ReadLine()) != null)
                        {
                            command.Observer.ErrorOutput(line);
                        }
                    }
                    command.Observer.Executed(command.Command, commandArguments, exitCode, standardOutput, standardError);
                }
                command.After(exitCode, standardOutput, standardError);
                return;
            }

            StopPersistentMercurialClient();
            throw new MercurialExecutionException("Unable to decode output from executing command, spinning down persistent client");
        }