mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-22 19:04:59 +00:00
feat: add safe command termination
This commit is contained in:
parent
b2ab62825e
commit
34ae392251
5 changed files with 115 additions and 13 deletions
|
@ -37,6 +37,12 @@ namespace SourceGit.Commands
|
||||||
public string Args { get; set; } = string.Empty;
|
public string Args { get; set; } = string.Empty;
|
||||||
public bool RaiseError { get; set; } = true;
|
public bool RaiseError { get; set; } = true;
|
||||||
public bool TraitErrorAsOutput { get; set; } = false;
|
public bool TraitErrorAsOutput { get; set; } = false;
|
||||||
|
public bool Cancelable { get; } = false;
|
||||||
|
|
||||||
|
public Command(bool cancelable = false)
|
||||||
|
{
|
||||||
|
Cancelable = cancelable;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Exec()
|
public bool Exec()
|
||||||
{
|
{
|
||||||
|
@ -109,12 +115,22 @@ namespace SourceGit.Commands
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_proc = proc;
|
||||||
|
|
||||||
|
int exitCode;
|
||||||
|
try
|
||||||
|
{
|
||||||
proc.BeginOutputReadLine();
|
proc.BeginOutputReadLine();
|
||||||
proc.BeginErrorReadLine();
|
proc.BeginErrorReadLine();
|
||||||
proc.WaitForExit();
|
proc.WaitForExit();
|
||||||
|
|
||||||
int exitCode = proc.ExitCode;
|
exitCode = proc.ExitCode;
|
||||||
proc.Close();
|
proc.Close();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_proc = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isCancelled && exitCode != 0)
|
if (!isCancelled && exitCode != 0)
|
||||||
{
|
{
|
||||||
|
@ -150,6 +166,10 @@ namespace SourceGit.Commands
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_proc = proc;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
var rs = new ReadToEndResult()
|
var rs = new ReadToEndResult()
|
||||||
{
|
{
|
||||||
StdOut = proc.StandardOutput.ReadToEnd(),
|
StdOut = proc.StandardOutput.ReadToEnd(),
|
||||||
|
@ -162,6 +182,22 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_proc = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryCancel()
|
||||||
|
{
|
||||||
|
if (!this.Cancelable)
|
||||||
|
throw new Exception("Command is not cancelable!");
|
||||||
|
|
||||||
|
if (_proc is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Native.OS.TerminateSafely(_proc);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void OnReadline(string line)
|
protected virtual void OnReadline(string line)
|
||||||
{
|
{
|
||||||
|
@ -226,5 +262,7 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
[GeneratedRegex(@"\d+%")]
|
[GeneratedRegex(@"\d+%")]
|
||||||
private static partial Regex REG_PROGRESS();
|
private static partial Regex REG_PROGRESS();
|
||||||
|
|
||||||
|
private Process _proc = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
@ -11,6 +12,14 @@ namespace SourceGit.Native
|
||||||
[SupportedOSPlatform("linux")]
|
[SupportedOSPlatform("linux")]
|
||||||
internal class Linux : OS.IBackend
|
internal class Linux : OS.IBackend
|
||||||
{
|
{
|
||||||
|
private enum SIGNAL : int
|
||||||
|
{
|
||||||
|
TERM = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("c")]
|
||||||
|
private static extern int kill(int pid, int sig);
|
||||||
|
|
||||||
public void SetupApp(AppBuilder builder)
|
public void SetupApp(AppBuilder builder)
|
||||||
{
|
{
|
||||||
builder.With(new X11PlatformOptions() { EnableIme = true });
|
builder.With(new X11PlatformOptions() { EnableIme = true });
|
||||||
|
@ -97,6 +106,12 @@ namespace SourceGit.Native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TerminateSafely(Process process)
|
||||||
|
{
|
||||||
|
if (kill(process.Id, (int)SIGNAL.TERM) == 0)
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
private string FindExecutable(string filename)
|
private string FindExecutable(string filename)
|
||||||
{
|
{
|
||||||
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
@ -11,6 +12,14 @@ namespace SourceGit.Native
|
||||||
[SupportedOSPlatform("macOS")]
|
[SupportedOSPlatform("macOS")]
|
||||||
internal class MacOS : OS.IBackend
|
internal class MacOS : OS.IBackend
|
||||||
{
|
{
|
||||||
|
private enum SIGNAL : int
|
||||||
|
{
|
||||||
|
TERM = 15
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("System")]
|
||||||
|
private static extern int kill(int pid, int sig);
|
||||||
|
|
||||||
public void SetupApp(AppBuilder builder)
|
public void SetupApp(AppBuilder builder)
|
||||||
{
|
{
|
||||||
builder.With(new MacOSPlatformOptions()
|
builder.With(new MacOSPlatformOptions()
|
||||||
|
@ -88,5 +97,11 @@ namespace SourceGit.Native
|
||||||
{
|
{
|
||||||
Process.Start("open", $"\"{file}\"");
|
Process.Start("open", $"\"{file}\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TerminateSafely(Process process)
|
||||||
|
{
|
||||||
|
if (kill(process.Id, (int)SIGNAL.TERM) == 0)
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace SourceGit.Native
|
||||||
void OpenInFileManager(string path, bool select);
|
void OpenInFileManager(string path, bool select);
|
||||||
void OpenBrowser(string url);
|
void OpenBrowser(string url);
|
||||||
void OpenWithDefaultEditor(string file);
|
void OpenWithDefaultEditor(string file);
|
||||||
|
|
||||||
|
void TerminateSafely(Process process);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string DataDir
|
public static string DataDir
|
||||||
|
@ -168,6 +170,11 @@ namespace SourceGit.Native
|
||||||
_backend.OpenWithDefaultEditor(file);
|
_backend.OpenWithDefaultEditor(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void TerminateSafely(Process process)
|
||||||
|
{
|
||||||
|
_backend.TerminateSafely(process);
|
||||||
|
}
|
||||||
|
|
||||||
private static void UpdateGitVersion()
|
private static void UpdateGitVersion()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_gitExecutable) || !File.Exists(_gitExecutable))
|
if (string.IsNullOrEmpty(_gitExecutable) || !File.Exists(_gitExecutable))
|
||||||
|
|
|
@ -35,6 +35,11 @@ namespace SourceGit.Native
|
||||||
public int cyBottomHeight;
|
public int cyBottomHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum CTRL_EVENT : int
|
||||||
|
{
|
||||||
|
CTRL_C = 0
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("ntdll.dll")]
|
[DllImport("ntdll.dll")]
|
||||||
private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation);
|
private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation);
|
||||||
|
|
||||||
|
@ -53,6 +58,12 @@ namespace SourceGit.Native
|
||||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
|
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
|
||||||
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags);
|
private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
public static extern bool SetConsoleCtrlHandler(IntPtr handlerRoutine, bool add);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId);
|
||||||
|
|
||||||
public void SetupApp(AppBuilder builder)
|
public void SetupApp(AppBuilder builder)
|
||||||
{
|
{
|
||||||
// Fix drop shadow issue on Windows 10
|
// Fix drop shadow issue on Windows 10
|
||||||
|
@ -212,6 +223,22 @@ namespace SourceGit.Native
|
||||||
Process.Start(start);
|
Process.Start(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TerminateSafely(Process process)
|
||||||
|
{
|
||||||
|
if (SetConsoleCtrlHandler(IntPtr.Zero, true))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (GenerateConsoleCtrlEvent((int)CTRL_EVENT.CTRL_C, process.Id))
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
SetConsoleCtrlHandler(IntPtr.Zero, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void FixWindowFrameOnWin10(Window w)
|
private void FixWindowFrameOnWin10(Window w)
|
||||||
{
|
{
|
||||||
var platformHandle = w.TryGetPlatformHandle();
|
var platformHandle = w.TryGetPlatformHandle();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue