careri
careri

Reputation: 91

MSysGit Pipe Encoding

I'm trying to pipe the output from one git process as input to another git command. But I just can't it to work. git version 1.9.5.msysgit.0

What I want to do with code:

git show e46b22be3031ed53e80472002d332a2588f122c9 | git patch-id

Output:
c2a55fcbc40da401f84ae3b72c250e55f827001a e46b22be3031ed53e80472002d332a2588f122c9

I've piped the output to a file so that I have something to compare with:

git show e46b22be3031ed53e80472002d332a2588f122c9 > git.show.txt

Redirecting the input from the file yields the expected result:

git patch-id < commit.show.txt

Output:
c2a55fcbc40da401f84ae3b72c250e55f827001a e46b22be3031ed53e80472002d332a2588f122c9

To help me solve the problem I've written a proxy application that:

  1. reads piped input from git show
  2. writes the piped input to a file, so that I can compare it with git.show.txt
  3. writes the piped input to the output so that next application can pipe it

So the usage is now:

git show e46b22be3031ed53e80472002d332a2588f122c9 | ConsolePipeConsumer.exe | git patch-id

Incorrect Output:
cf55b48fa7c9ed6f7214641c4d709667abfeb078 e46b22be3031ed53e80472002d332a2588f122c9

The temp file I write is binary equal to git.show.txt, so reading the input works as expected.

I just can't figure out the code page to use for the standard output of my proxy application. I've tried all I can come up with. Or is there something else missing?

Here's the code:

using System;
using System.IO;
using System.Text;
namespace ConsolePipeConsumer
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var encoding = Encoding.Default;                
                Console.SetIn(new StreamReader(Console.OpenStandardInput(8192), encoding));
                Console.Error.WriteLine("StdOut.Encoding={0}", Console.Out.Encoding);
                // What encoding to use for output?
                //Console.SetOut(new StreamWriter(Console.OpenStandardOutput(8192), encoding));
                int c;
                var sb = new StringBuilder();
                while ((c = Console.Read()) >= 0)
                {
                    sb.Append((char)c);
                }
                Console.Write(sb.ToString());
                var tmp = Path.GetTempFileName();
                File.WriteAllText(tmp, sb.ToString(), encoding);
                Console.Error.WriteLine("Piped input written to: " + tmp);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
            }
        }
    }
}

Upvotes: 0

Views: 63

Answers (1)

careri
careri

Reputation: 91

It seemed like the error was me not flushing Console.Out before exiting my proxy application.

I also improved the code by reading/writing bytes as suggested by Edward Thompson.

Here is a working implementation of a proxy application that:

  1. Takes the piped output of e.g. git
  2. Writes debug information about the input
  3. Then pipes the exact same data to the output.

Here's the code:

<!-- language: c# -->    

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
namespace ConsolePipeConsumer
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var pid = Process.GetCurrentProcess().Id;
                var buffer = new byte[1024];
                var tmp = new FileInfo(Path.GetTempFileName());

                using (var reader = new BinaryReader(Console.OpenStandardInput(8192)))
                using (var writer = new BinaryWriter(Console.OpenStandardOutput(8192)))
                using (var tmpWriter = new BinaryWriter(tmp.Create()))
                {
                    int c;
                    int len = 0;
                    while ((c = reader.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        writer.Write(buffer, 0, c);
                        tmpWriter.Write(buffer, 0, c);
                        len += c;
                    }
                    Console.Error.WriteLine("[{0}] Input length: {1}", pid, len);

                    Console.Error.WriteLine("[{0}] Piped input written to: ", pid);
                    Console.Error.WriteLine("[{0}] {1} (File Size={2})", pid, tmp, tmp.Length);
                    writer.Flush();
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
            }
        }
    }
}

Upvotes: 1

Related Questions