using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
namespace SourceGit.Commands {
///
/// 取消命令执行的对象
///
public class Cancellable {
public bool IsCancelRequested { get; set; } = false;
}
///
/// 命令接口
///
public class Command {
///
/// 读取全部输出时的结果
///
public class ReadToEndResult {
public bool IsSuccess { get; set; }
public string Output { get; set; }
public string Error { get; set; }
}
///
/// 运行路径
///
public string Cwd { get; set; } = "";
///
/// 参数
///
public string Args { get; set; } = "";
///
/// 使用标准错误输出
///
public bool TraitErrorAsOutput { get; set; } = false;
///
/// 用于取消命令指行的Token
///
public Cancellable Token { get; set; } = null;
///
/// 运行
///
public bool Exec() {
var start = new ProcessStartInfo();
start.FileName = Models.Preference.Instance.Git.Path;
start.Arguments = "--no-pager -c core.quotepath=off " + Args;
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.StandardOutputEncoding = Encoding.UTF8;
start.StandardErrorEncoding = Encoding.UTF8;
if (!string.IsNullOrEmpty(Cwd)) start.WorkingDirectory = Cwd;
var progressFilter = new Regex(@"\d+\%");
var errs = new List();
var proc = new Process() { StartInfo = start };
var isCancelled = false;
proc.OutputDataReceived += (o, e) => {
if (Token != null && Token.IsCancelRequested) {
isCancelled = true;
proc.CancelErrorRead();
proc.CancelOutputRead();
#if NET48
proc.Kill();
#else
proc.Kill(true);
#endif
return;
}
if (e.Data == null) return;
OnReadline(e.Data);
};
proc.ErrorDataReceived += (o, e) => {
if (Token != null && Token.IsCancelRequested) {
isCancelled = true;
proc.CancelErrorRead();
proc.CancelOutputRead();
#if NET48
proc.Kill();
#else
proc.Kill(true);
#endif
return;
}
if (e.Data == null) return;
if (TraitErrorAsOutput) OnReadline(e.Data);
if (string.IsNullOrEmpty(e.Data)) return;
if (progressFilter.IsMatch(e.Data)) return;
if (e.Data.StartsWith("remote: Counting objects:", StringComparison.Ordinal)) return;
errs.Add(e.Data);
};
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
int exitCode = proc.ExitCode;
proc.Close();
if (!isCancelled && exitCode != 0 && errs.Count > 0) {
Models.Exception.Raise(string.Join("\n", errs));
return false;
} else {
return true;
}
}
///
/// 直接读取全部标准输出
///
public ReadToEndResult ReadToEnd() {
var start = new ProcessStartInfo();
start.FileName = Models.Preference.Instance.Git.Path;
start.Arguments = "--no-pager -c core.quotepath=off " + Args;
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.StandardOutputEncoding = Encoding.UTF8;
start.StandardErrorEncoding = Encoding.UTF8;
if (!string.IsNullOrEmpty(Cwd)) start.WorkingDirectory = Cwd;
var proc = new Process() { StartInfo = start };
proc.Start();
var rs = new ReadToEndResult();
rs.Output = proc.StandardOutput.ReadToEnd();
rs.Error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
rs.IsSuccess = proc.ExitCode == 0;
proc.Close();
return rs;
}
///
/// 调用Exec时的读取函数
///
///
public virtual void OnReadline(string line) {}
}
}