From 4882fd9d69ddbd0e53563cc4f22311b3c83516a0 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 9 Apr 2024 10:41:37 +0800 Subject: [PATCH] refactor: external tools and shells * rename Models.ExternalMergeTools to Models.ExternalMerger * supports Git Bash/PowerShell/Command Prompt/Default Shell in Windows Terminal --- src/Models/ExternalMergeTools.cs | 88 -------------------------- src/Models/ExternalMerger.cs | 88 ++++++++++++++++++++++++++ src/Models/Shell.cs | 10 +++ src/Native/OS.cs | 28 +++++++- src/Native/Windows.cs | 53 +++++++++++----- src/Resources/Locales/en_US.axaml | 2 +- src/Resources/Locales/zh_CN.axaml | 2 +- src/Resources/ShellIcons/cmd.png | Bin 0 -> 2263 bytes src/Resources/ShellIcons/git-bash.png | Bin 0 -> 3512 bytes src/Resources/ShellIcons/pwsh.png | Bin 0 -> 9517 bytes src/Resources/ShellIcons/wt.png | Bin 0 -> 2485 bytes src/SourceGit.csproj | 3 +- src/ViewModels/CommitDetail.cs | 2 +- src/ViewModels/DiffContext.cs | 2 +- src/ViewModels/Preference.cs | 29 ++++----- src/ViewModels/RevisionCompare.cs | 2 +- src/ViewModels/WorkingCopy.cs | 2 +- src/Views/Preference.axaml | 80 ++++++++++++++++------- src/Views/Preference.axaml.cs | 4 +- 19 files changed, 243 insertions(+), 152 deletions(-) delete mode 100644 src/Models/ExternalMergeTools.cs create mode 100644 src/Models/ExternalMerger.cs create mode 100644 src/Models/Shell.cs create mode 100644 src/Resources/ShellIcons/cmd.png create mode 100644 src/Resources/ShellIcons/git-bash.png create mode 100644 src/Resources/ShellIcons/pwsh.png create mode 100644 src/Resources/ShellIcons/wt.png diff --git a/src/Models/ExternalMergeTools.cs b/src/Models/ExternalMergeTools.cs deleted file mode 100644 index f07ef088..00000000 --- a/src/Models/ExternalMergeTools.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace SourceGit.Models -{ - public class ExternalMergeTools - { - public int Type { get; set; } - public string Name { get; set; } - public string Exec { get; set; } - public string Cmd { get; set; } - public string DiffCmd { get; set; } - - public static readonly List Supported; - - static ExternalMergeTools() - { - if (OperatingSystem.IsWindows()) - { - Supported = new List() { - new ExternalMergeTools(0, "Custom", "", "", ""), - new ExternalMergeTools(1, "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(2, "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(3, "Visual Studio 2017/2019/2022", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(4, "Tortoise Merge", "TortoiseMerge.exe;TortoiseGitMerge.exe", "-base:\"$BASE\" -theirs:\"$REMOTE\" -mine:\"$LOCAL\" -merged:\"$MERGED\"", "-base:\"$LOCAL\" -theirs:\"$REMOTE\""), - new ExternalMergeTools(5, "KDiff3", "kdiff3.exe", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(6, "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(7, "WinMerge", "WinMergeU.exe", "-u -e \"$REMOTE\" \"$LOCAL\" \"$MERGED\"", "-u -e \"$LOCAL\" \"$REMOTE\""), - }; - } - else if (OperatingSystem.IsMacOS()) - { - Supported = new List() { - new ExternalMergeTools(0, "Custom", "", "", ""), - new ExternalMergeTools(1, "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(2, "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(3, "Visual Studio Code - Insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(4, "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(5, "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - }; - } - else if (OperatingSystem.IsLinux()) - { - Supported = new List() { - new ExternalMergeTools(0, "Custom", "", "", ""), - new ExternalMergeTools(1, "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(2, "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(3, "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMergeTools(4, "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - }; - } - else - { - Supported = new List() { - new ExternalMergeTools(0, "Custom", "", "", ""), - }; - } - } - - public ExternalMergeTools(int type, string name, string exec, string cmd, string diffCmd) - { - Type = type; - Name = name; - Exec = exec; - Cmd = cmd; - DiffCmd = diffCmd; - } - - public string[] GetPatterns() - { - if (OperatingSystem.IsWindows()) - { - return Exec.Split(';'); - } - else - { - var patterns = new List(); - var choices = Exec.Split(';', StringSplitOptions.RemoveEmptyEntries); - foreach (var c in choices) - { - patterns.Add(Path.GetFileName(c)); - } - return patterns.ToArray(); - } - } - } -} diff --git a/src/Models/ExternalMerger.cs b/src/Models/ExternalMerger.cs new file mode 100644 index 00000000..6643bbbb --- /dev/null +++ b/src/Models/ExternalMerger.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace SourceGit.Models +{ + public class ExternalMerger + { + public int Type { get; set; } + public string Name { get; set; } + public string Exec { get; set; } + public string Cmd { get; set; } + public string DiffCmd { get; set; } + + public static readonly List Supported; + + static ExternalMerger() + { + if (OperatingSystem.IsWindows()) + { + Supported = new List() { + new ExternalMerger(0, "Custom", "", "", ""), + new ExternalMerger(1, "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(2, "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(3, "Visual Studio 2017/2019/2022", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(4, "Tortoise Merge", "TortoiseMerge.exe;TortoiseGitMerge.exe", "-base:\"$BASE\" -theirs:\"$REMOTE\" -mine:\"$LOCAL\" -merged:\"$MERGED\"", "-base:\"$LOCAL\" -theirs:\"$REMOTE\""), + new ExternalMerger(5, "KDiff3", "kdiff3.exe", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(6, "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(7, "WinMerge", "WinMergeU.exe", "-u -e \"$REMOTE\" \"$LOCAL\" \"$MERGED\"", "-u -e \"$LOCAL\" \"$REMOTE\""), + }; + } + else if (OperatingSystem.IsMacOS()) + { + Supported = new List() { + new ExternalMerger(0, "Custom", "", "", ""), + new ExternalMerger(1, "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(2, "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(3, "Visual Studio Code - Insiders", "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(4, "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(5, "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + }; + } + else if (OperatingSystem.IsLinux()) + { + Supported = new List() { + new ExternalMerger(0, "Custom", "", "", ""), + new ExternalMerger(1, "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(2, "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(3, "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger(4, "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + }; + } + else + { + Supported = new List() { + new ExternalMerger(0, "Custom", "", "", ""), + }; + } + } + + public ExternalMerger(int type, string name, string exec, string cmd, string diffCmd) + { + Type = type; + Name = name; + Exec = exec; + Cmd = cmd; + DiffCmd = diffCmd; + } + + public string[] GetPatterns() + { + if (OperatingSystem.IsWindows()) + { + return Exec.Split(';'); + } + else + { + var patterns = new List(); + var choices = Exec.Split(';', StringSplitOptions.RemoveEmptyEntries); + foreach (var c in choices) + { + patterns.Add(Path.GetFileName(c)); + } + return patterns.ToArray(); + } + } + } +} diff --git a/src/Models/Shell.cs b/src/Models/Shell.cs new file mode 100644 index 00000000..9960d136 --- /dev/null +++ b/src/Models/Shell.cs @@ -0,0 +1,10 @@ +namespace SourceGit.Models +{ + public enum Shell + { + Default = 0, + PowerShell, + CommandPrompt, + DefaultShellOfWindowsTerminal, + } +} diff --git a/src/Native/OS.cs b/src/Native/OS.cs index 03b98e6d..259b6a22 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -21,7 +21,6 @@ namespace SourceGit.Native } public static string GitExecutable { get; set; } = string.Empty; - public static bool UsePowershellOnWindows { get; set; } = false; public static List ExternalTools { get; set; } = new List(); static OS() @@ -46,6 +45,33 @@ namespace SourceGit.Native ExternalTools = _backend.FindExternalTools(); } + public static Models.Shell GetShell() + { + if (OperatingSystem.IsWindows()) + { + return (_backend as Windows).Shell; + } + else + { + return Models.Shell.Default; + } + } + + public static bool SetShell(Models.Shell shell) + { + if (OperatingSystem.IsWindows()) + { + var windows = (_backend as Windows); + if (windows.Shell != shell) + { + windows.Shell = shell; + return true; + } + } + + return false; + } + public static void SetupApp(AppBuilder builder) { _backend.SetupApp(builder); diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 1b5af417..fbcdb0bf 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -54,6 +54,12 @@ namespace SourceGit.Native [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = false)] private static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, int cild, IntPtr apidl, int dwFlags); + public Models.Shell Shell + { + get; + set; + } = Models.Shell.Default; + public Windows() { var localMachine = Microsoft.Win32.RegistryKey.OpenBaseKey( @@ -143,27 +149,44 @@ namespace SourceGit.Native public void OpenTerminal(string workdir) { - var startInfo = new ProcessStartInfo() { UseShellExecute = true }; - if (!string.IsNullOrEmpty(workdir) && Path.Exists(workdir)) - startInfo.WorkingDirectory = workdir; + var startInfo = new ProcessStartInfo(); - if (OS.UsePowershellOnWindows) + if (!string.IsNullOrEmpty(workdir) && Path.Exists(workdir)) { - startInfo.FileName = _powershellPath; + startInfo.WorkingDirectory = workdir; } else { - var binDir = Path.GetDirectoryName(OS.GitExecutable); - var bash = Path.Combine(binDir, "bash.exe"); - if (!File.Exists(bash)) - { - App.RaiseException(string.IsNullOrEmpty(workdir) ? "" : workdir, $"Can NOT found bash.exe under '{binDir}'"); - return; - } - - startInfo.FileName = bash; + startInfo.WorkingDirectory = "."; } - + + switch (Shell) + { + case Models.Shell.Default: + var binDir = Path.GetDirectoryName(OS.GitExecutable); + var bash = Path.Combine(binDir, "bash.exe"); + if (!File.Exists(bash)) + { + App.RaiseException(string.IsNullOrEmpty(workdir) ? "" : workdir, $"Can NOT found bash.exe under '{binDir}'"); + return; + } + + startInfo.FileName = bash; + break; + case Models.Shell.PowerShell: + startInfo.FileName = _powershellPath; + break; + case Models.Shell.CommandPrompt: + startInfo.FileName = "cmd"; + break; + case Models.Shell.DefaultShellOfWindowsTerminal: + startInfo.FileName = "wt"; + break; + default: + App.RaiseException(string.IsNullOrEmpty(workdir) ? "" : workdir, $"Bad shell configuration!"); + return; + } + Process.Start(startInfo); } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 08b41c0a..8277d3c5 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -266,9 +266,9 @@ User Email Global git user email Install Path + Shell User Name Global git user name - Use Powershell instead of Git bash Git version GPG SIGNING Commit GPG signing diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 8f03755b..fb7fecc3 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -266,9 +266,9 @@ 邮箱 默认GIT用户邮箱 安装路径 + 终端Shell 用户名 默认GIT用户名 - 使用PowerShell替代Git Bash Git 版本 GPG签名 启用提交签名 diff --git a/src/Resources/ShellIcons/cmd.png b/src/Resources/ShellIcons/cmd.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3aa2189625eb96ecc0686893a0791cf1f9cadc GIT binary patch literal 2263 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 literal 0 HcmV?d00001 diff --git a/src/Resources/ShellIcons/wt.png b/src/Resources/ShellIcons/wt.png new file mode 100644 index 0000000000000000000000000000000000000000..3462cc6e3d12ce670fab0f7b127c79665fc91fb6 GIT binary patch literal 2485 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 literal 0 HcmV?d00001 diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 0a3ef8a6..d439eee8 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -22,8 +22,9 @@ - + + diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index fe719517..f290fd4c 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -205,7 +205,7 @@ namespace SourceGit.ViewModels var type = Preference.Instance.ExternalMergeToolType; var exec = Preference.Instance.ExternalMergeToolPath; - var tool = Models.ExternalMergeTools.Supported.Find(x => x.Type == type); + var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); if (tool == null || !File.Exists(exec)) { App.RaiseException(_repo, "Invalid merge tool in preference setting!"); diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 728c4f43..17514656 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -152,7 +152,7 @@ namespace SourceGit.ViewModels var type = Preference.Instance.ExternalMergeToolType; var exec = Preference.Instance.ExternalMergeToolPath; - var tool = Models.ExternalMergeTools.Supported.Find(x => x.Type == type); + var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); if (tool == null || !File.Exists(exec)) { App.RaiseException(_repo, "Invalid merge tool in preference setting!"); diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index 7d97ba4f..8d0520c8 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -200,6 +200,18 @@ namespace SourceGit.ViewModels } } + public Models.Shell GitShell + { + get => Native.OS.GetShell(); + set + { + if (Native.OS.SetShell(value)) + { + OnPropertyChanged(nameof(GitShell)); + } + } + } + public string GitDefaultCloneDir { get => _gitDefaultCloneDir; @@ -219,28 +231,15 @@ namespace SourceGit.ViewModels } } - public bool UsePowershellOnWindows - { - get => Native.OS.UsePowershellOnWindows; - set - { - if (Native.OS.UsePowershellOnWindows != value) - { - Native.OS.UsePowershellOnWindows = value; - OnPropertyChanged(nameof(UsePowershellOnWindows)); - } - } - } - public int ExternalMergeToolType { get => _externalMergeToolType; set { var changed = SetProperty(ref _externalMergeToolType, value); - if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMergeTools.Supported.Count) + if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMerger.Supported.Count) { - var tool = Models.ExternalMergeTools.Supported[value]; + var tool = Models.ExternalMerger.Supported[value]; if (File.Exists(tool.Exec)) ExternalMergeToolPath = tool.Exec; else diff --git a/src/ViewModels/RevisionCompare.cs b/src/ViewModels/RevisionCompare.cs index 167f3a41..1ed85c9e 100644 --- a/src/ViewModels/RevisionCompare.cs +++ b/src/ViewModels/RevisionCompare.cs @@ -166,7 +166,7 @@ namespace SourceGit.ViewModels var type = Preference.Instance.ExternalMergeToolType; var exec = Preference.Instance.ExternalMergeToolPath; - var tool = Models.ExternalMergeTools.Supported.Find(x => x.Type == type); + var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); if (tool == null || !File.Exists(exec)) { App.RaiseException(_repo, "Invalid merge tool in preference setting!"); diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 6aa9d999..a52a31df 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -423,7 +423,7 @@ namespace SourceGit.ViewModels var type = Preference.Instance.ExternalMergeToolType; var exec = Preference.Instance.ExternalMergeToolPath; - var tool = Models.ExternalMergeTools.Supported.Find(x => x.Type == type); + var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type); if (tool == null) { App.RaiseException(_repo.FullPath, "Invalid merge tool in preference setting!"); diff --git a/src/Views/Preference.axaml b/src/Views/Preference.axaml index 49cd30f2..cd2d4ce1 100644 --- a/src/Views/Preference.axaml +++ b/src/Views/Preference.axaml @@ -231,7 +231,7 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -269,31 +307,31 @@ - - - + + + - - - - @@ -376,8 +408,8 @@ MinHeight="28" Padding="8,0" HorizontalAlignment="Stretch" - ItemsSource="{Binding Source={x:Static m:ExternalMergeTools.Supported}}" - DisplayMemberBinding="{Binding Name, x:DataType=m:ExternalMergeTools}" + ItemsSource="{Binding Source={x:Static m:ExternalMerger.Supported}}" + DisplayMemberBinding="{Binding Name, x:DataType=m:ExternalMerger}" SelectedIndex="{Binding ExternalMergeToolType, Mode=TwoWay}"/> = Models.ExternalMergeTools.Supported.Count) + if (type < 0 || type >= Models.ExternalMerger.Supported.Count) { ViewModels.Preference.Instance.ExternalMergeToolType = 0; type = 0; } - var tool = Models.ExternalMergeTools.Supported[type]; + var tool = Models.ExternalMerger.Supported[type]; var options = new FilePickerOpenOptions() { FileTypeFilter = [new FilePickerFileType(tool.Name) { Patterns = tool.GetPatterns() }],