Skip to content

Instantly share code, notes, and snippets.

@codewings
Last active September 9, 2019 02:09
Show Gist options
  • Save codewings/4c2097c6555cbb26691a6877efa19f12 to your computer and use it in GitHub Desktop.
Save codewings/4c2097c6555cbb26691a6877efa19f12 to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace P4
{
class P4OutputStream : IDisposable
{
public StreamReader Reader { get; set; }
public StreamWriter Writer { get; set; }
public bool Empty
{
get { Writer.Flush(); return Stream.Length == 0; }
}
public P4OutputStream()
{
Stream = new MemoryStream();
Reader = new StreamReader(Stream);
Writer = new StreamWriter(Stream);
}
public void ReceiveOutput(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
Writer.WriteLine(e.Data);
}
}
public StreamReader BeginRead()
{
Writer.Flush();
Stream.Position = 0;
return Reader;
}
public void Dispose()
{
Writer.Close();
Reader.Close();
Stream.Dispose();
Writer.Dispose();
Reader.Dispose();
}
MemoryStream Stream;
}
class P4Command
{
public delegate T CommandAction<T>(StreamReader stream);
public delegate void LogAction(string log);
public static string P4PORT = string.Empty;
public static string P4USER = string.Empty;
public static string P4CLIENT = string.Empty;
public static LogAction P4LOG = line => Console.WriteLine(line);
public static bool LogP4CMD = false;
public static bool Configured
{
get
{
return string.IsNullOrEmpty(P4PORT) == false && string.IsNullOrEmpty(P4USER) == false && string.IsNullOrEmpty(P4CLIENT) == false;
}
}
static void RunProcess(string args, P4OutputStream stdout, string[] stdin = null)
{
var stderr = new P4OutputStream();
{
var pi = new ProcessStartInfo();
pi.FileName = "p4.exe";
pi.Arguments = string.Format("-p {0} -u {1} -c {2} {3}", P4PORT, P4USER, P4CLIENT, args);
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
pi.RedirectStandardError = true;
pi.RedirectStandardInput = stdin != null;
if (LogP4CMD)
{
P4LOG("p4 " + pi.Arguments);
}
var p = new Process();
p.StartInfo = pi;
p.OutputDataReceived += stdout.ReceiveOutput;
p.ErrorDataReceived += stderr.ReceiveOutput;
p.Start();
if (stdin != null)
{
foreach (var str in stdin)
{
p.StandardInput.WriteLine(str);
}
p.StandardInput.WriteLine("\u001A");
}
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
p.Dispose();
if (stderr.Empty == false)
{
P4LOG(stderr.BeginRead().ReadToEnd());
}
}
stderr.Dispose();
}
static int NullOutput(StreamReader stream)
{
stream.ReadToEnd();
return 0;
}
public static int GenericOutput(StreamReader stream)
{
P4LOG(stream.ReadToEnd());
return 0;
}
public static T Run<T>(string args, CommandAction<T> action, string[] inputs, LogAction log)
{
Debug.Assert(Configured == true);
var old = P4LOG;
T result = default(T);
if (log != null) P4LOG = log;
{
try
{
var stdout = new P4OutputStream();
{
RunProcess(args, stdout, inputs);
}
result = action.Invoke(stdout.BeginRead());
stdout.Dispose();
}
catch (Exception ex)
{
P4LOG(ex.Message);
}
}
if (log != null) P4LOG = old;
return result;
}
public static void Run(string args, string[] inputs, LogAction log = null)
{
Run(args, NullOutput, inputs, log);
}
public static void Run(string args, LogAction log = null)
{
Run(args, NullOutput, null, log);
}
public static T Run<T>(string args, CommandAction<T> action, LogAction log = null)
{
return Run(args, action, null, log);
}
#region Shortcuts for common p4 command
public static string NewCL(string desc, LogAction log = null)
{
string[] str = new string[]
{
"Description:\n\t" + desc,
"Change: new"
};
return Run("change -i", stream =>
{
var line = stream.ReadToEnd();
var m = Regex.Match(line, @"\d+");
return m.Success ? m.Value : string.Empty;
}
, str, log);
}
public static void SafeResolveCL(string changlist, LogAction log = null)
{
Run(string.Format("resolve -as -c {0}", changlist), stream =>
{
while (stream.EndOfStream == false)
{
P4LOG(stream.ReadLine());
}
return 0;
}, log);
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment