From ab14e818be648bf3de05b50d5720559308ffe649 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 28 Jul 2025 14:14:11 +0800 Subject: [PATCH 01/15] refactor: simplify the invocation of external merge/diff tool Signed-off-by: leo --- src/Commands/DiffTool.cs | 25 +++----- src/Commands/MergeTool.cs | 26 +++----- src/Models/ExternalMerger.cs | 100 ++++++++++++++---------------- src/Models/ExternalTool.cs | 10 +-- src/Native/OS.cs | 39 ++++++++++++ src/ViewModels/CommitDetail.cs | 5 +- src/ViewModels/DiffContext.cs | 4 +- src/ViewModels/Preferences.cs | 33 +++++----- src/ViewModels/RevisionCompare.cs | 4 +- src/ViewModels/StashesPage.cs | 4 +- src/ViewModels/WorkingCopy.cs | 10 +-- src/Views/BranchCompare.axaml.cs | 7 +-- src/Views/Preferences.axaml.cs | 2 +- 13 files changed, 133 insertions(+), 136 deletions(-) diff --git a/src/Commands/DiffTool.cs b/src/Commands/DiffTool.cs index b80f55959..6fbb2c24b 100644 --- a/src/Commands/DiffTool.cs +++ b/src/Commands/DiffTool.cs @@ -1,47 +1,36 @@ -using System.IO; - -namespace SourceGit.Commands +namespace SourceGit.Commands { public class DiffTool : Command { - public DiffTool(string repo, int type, string exec, Models.DiffOption option) + public DiffTool(string repo, Models.DiffOption option) { WorkingDirectory = repo; Context = repo; - - _merger = Models.ExternalMerger.Supported.Find(x => x.Type == type); - _exec = exec; _option = option; } public void Open() { - if (_merger == null) + var tool = Native.OS.GetDiffMergeTool(true); + if (tool == null) { App.RaiseException(Context, "Invalid merge tool in preference setting!"); return; } - if (_merger.Type == 0) + if (string.IsNullOrEmpty(tool.Cmd)) { Args = $"difftool -g --no-prompt {_option}"; } - else if (File.Exists(_exec)) - { - var cmd = $"{_exec.Quoted()} {_merger.DiffCmd}"; - Args = $"-c difftool.sourcegit.cmd={cmd.Quoted()} difftool --tool=sourcegit --no-prompt {_option}"; - } else { - App.RaiseException(Context, $"Can NOT find external diff tool in '{_exec}'!"); - return; + var cmd = $"{tool.Exec.Quoted()} {tool.Cmd}"; + Args = $"-c difftool.sourcegit.cmd={cmd.Quoted()} difftool --tool=sourcegit --no-prompt {_option}"; } Exec(); } - private Models.ExternalMerger _merger; - private string _exec; private Models.DiffOption _option; } } diff --git a/src/Commands/MergeTool.cs b/src/Commands/MergeTool.cs index c2262c69f..e3da590d2 100644 --- a/src/Commands/MergeTool.cs +++ b/src/Commands/MergeTool.cs @@ -1,48 +1,38 @@ -using System.IO; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace SourceGit.Commands { public class MergeTool : Command { - public MergeTool(string repo, int type, string exec, string file) + public MergeTool(string repo, string file) { WorkingDirectory = repo; - Context = exec; - - _merger = Models.ExternalMerger.Supported.Find(x => x.Type == type); - _exec = exec; + Context = repo; _file = string.IsNullOrEmpty(file) ? string.Empty : file.Quoted(); } public async Task OpenAsync() { - if (_merger == null) + var tool = Native.OS.GetDiffMergeTool(false); + if (tool == null) { App.RaiseException(Context, "Invalid merge tool in preference setting!"); return false; } - if (_merger.Type == 0) + if (string.IsNullOrEmpty(tool.Cmd)) { Args = $"mergetool {_file}"; } - else if (File.Exists(_exec)) - { - var cmd = $"{_exec.Quoted()} {_merger.Cmd}"; - Args = $"-c mergetool.sourcegit.cmd={cmd.Quoted()} -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {_file}"; - } else { - App.RaiseException(Context, $"Can NOT find external merge tool in '{_exec}'!"); - return false; + var cmd = $"{tool.Exec.Quoted()} {tool.Cmd}"; + Args = $"-c mergetool.sourcegit.cmd={cmd.Quoted()} -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {_file}"; } return await ExecAsync().ConfigureAwait(false); } - private Models.ExternalMerger _merger; - private string _exec; private string _file; } } diff --git a/src/Models/ExternalMerger.cs b/src/Models/ExternalMerger.cs index ed9b9b08a..ce90a7d44 100644 --- a/src/Models/ExternalMerger.cs +++ b/src/Models/ExternalMerger.cs @@ -7,14 +7,13 @@ namespace SourceGit.Models { - public class ExternalMerger + public class ExternalMerger(string icon, string name, string finder, string mergeCmd, string diffCmd) { - public int Type { get; set; } - public string Icon { get; set; } - public string Name { get; set; } - public string Exec { get; set; } - public string Cmd { get; set; } - public string DiffCmd { get; set; } + public string Icon { get; } = icon; + public string Name { get; } = name; + public string Finder { get; } = finder; + public string MergeCmd { get; } = mergeCmd; + public string DiffCmd { get; } = diffCmd; public Bitmap IconImage { @@ -32,74 +31,69 @@ static ExternalMerger() if (OperatingSystem.IsWindows()) { Supported = new List() { - new ExternalMerger(0, "git", "Use Git Settings", "", "", ""), - new ExternalMerger(1, "vscode", "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(3, "vs", "Visual Studio", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(4, "tortoise_merge", "Tortoise Merge", "TortoiseMerge.exe;TortoiseGitMerge.exe", "-base:\"$BASE\" -theirs:\"$REMOTE\" -mine:\"$LOCAL\" -merged:\"$MERGED\"", "-base:\"$LOCAL\" -theirs:\"$REMOTE\""), - new ExternalMerger(5, "kdiff3", "KDiff3", "kdiff3.exe", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(6, "beyond_compare", "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(7, "win_merge", "WinMerge", "WinMergeU.exe", "\"$MERGED\"", "-u -e -sw \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(8, "codium", "VSCodium", "VSCodium.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(9, "p4merge", "P4Merge", "p4merge.exe", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(10, "plastic_merge", "Plastic SCM", "mergetool.exe", "-s=\"$REMOTE\" -b=\"$BASE\" -d=\"$LOCAL\" -r=\"$MERGED\" --automatic", "-s=\"$LOCAL\" -d=\"$REMOTE\""), - new ExternalMerger(11, "meld", "Meld", "Meld.exe", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(12, "cursor", "Cursor", "Cursor.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("git", "Use Git Settings", "", "", ""), + new ExternalMerger("vscode", "Visual Studio Code", "Code.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("vscode_insiders", "Visual Studio Code - Insiders", "Code - Insiders.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("vs", "Visual Studio", "vsDiffMerge.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" /m", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("tortoise_merge", "Tortoise Merge", "TortoiseMerge.exe;TortoiseGitMerge.exe", "-base:\"$BASE\" -theirs:\"$REMOTE\" -mine:\"$LOCAL\" -merged:\"$MERGED\"", "-base:\"$LOCAL\" -theirs:\"$REMOTE\""), + new ExternalMerger("kdiff3", "KDiff3", "kdiff3.exe", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("beyond_compare", "Beyond Compare", "BComp.exe", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("win_merge", "WinMerge", "WinMergeU.exe", "\"$MERGED\"", "-u -e -sw \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("codium", "VSCodium", "VSCodium.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("p4merge", "P4Merge", "p4merge.exe", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("plastic_merge", "Plastic SCM", "mergetool.exe", "-s=\"$REMOTE\" -b=\"$BASE\" -d=\"$LOCAL\" -r=\"$MERGED\" --automatic", "-s=\"$LOCAL\" -d=\"$REMOTE\""), + new ExternalMerger("meld", "Meld", "Meld.exe", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("cursor", "Cursor", "Cursor.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), }; } else if (OperatingSystem.IsMacOS()) { Supported = new List() { - new ExternalMerger(0, "git", "Use Git Settings", "", "", ""), - new ExternalMerger(1, "xcode", "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(2, "vscode", "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(3, "vscode_insiders", "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", "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(5, "beyond_compare", "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(6, "codium", "VSCodium", "/Applications/VSCodium.app/Contents/Resources/app/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(7, "p4merge", "P4Merge", "/Applications/p4merge.app/Contents/Resources/launchp4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(8, "cursor", "Cursor", "/Applications/Cursor.app/Contents/Resources/app/bin/cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("git", "Use Git Settings", "", "", ""), + new ExternalMerger("xcode", "FileMerge", "/usr/bin/opendiff", "\"$BASE\" \"$LOCAL\" \"$REMOTE\" -ancestor \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("vscode", "Visual Studio Code", "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("vscode_insiders", "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("kdiff3", "KDiff3", "/Applications/kdiff3.app/Contents/MacOS/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("beyond_compare", "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("codium", "VSCodium", "/Applications/VSCodium.app/Contents/Resources/app/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("p4merge", "P4Merge", "/Applications/p4merge.app/Contents/Resources/launchp4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("cursor", "Cursor", "/Applications/Cursor.app/Contents/Resources/app/bin/cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), }; } else if (OperatingSystem.IsLinux()) { Supported = new List() { - new ExternalMerger(0, "git", "Use Git Settings", "", "", ""), - new ExternalMerger(1, "vscode", "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(2, "vscode_insiders", "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(3, "kdiff3", "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(4, "beyond_compare", "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(5, "meld", "Meld", "/usr/bin/meld", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(6, "codium", "VSCodium", "/usr/share/codium/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(7, "p4merge", "P4Merge", "/usr/local/bin/p4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), - new ExternalMerger(8, "cursor", "Cursor", "cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("git", "Use Git Settings", "", "", ""), + new ExternalMerger("vscode", "Visual Studio Code", "/usr/share/code/code", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("vscode_insiders", "Visual Studio Code - Insiders", "/usr/share/code-insiders/code-insiders", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("kdiff3", "KDiff3", "/usr/bin/kdiff3", "\"$REMOTE\" -b \"$BASE\" \"$LOCAL\" -o \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("beyond_compare", "Beyond Compare", "/usr/bin/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("meld", "Meld", "/usr/bin/meld", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("codium", "VSCodium", "/usr/share/codium/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("p4merge", "P4Merge", "/usr/local/bin/p4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""), + new ExternalMerger("cursor", "Cursor", "cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""), }; } else { Supported = new List() { - new ExternalMerger(0, "git", "Use Git Settings", "", "", ""), + new ExternalMerger("git", "Use Git Settings", "", "", ""), }; } } - public ExternalMerger(int type, string icon, string name, string exec, string cmd, string diffCmd) - { - Type = type; - Icon = icon; - Name = name; - Exec = exec; - Cmd = cmd; - DiffCmd = diffCmd; - } - - public string[] GetPatterns() + public string[] GetPatternsToFindExecFile() { if (OperatingSystem.IsWindows()) - return Exec.Split(';'); + return Finder.Split(';', StringSplitOptions.RemoveEmptyEntries); - var choices = Exec.Split(';', StringSplitOptions.RemoveEmptyEntries); - return Array.ConvertAll(choices, Path.GetFileName); + return [Path.GetFileName(Finder)]; } } + + public class DiffMergeTool(string exec, string cmd) + { + public string Exec { get; } = exec; + public string Cmd { get; } = cmd; + } } diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs index 377eba2f2..f453c08f6 100644 --- a/src/Models/ExternalTool.cs +++ b/src/Models/ExternalTool.cs @@ -12,13 +12,14 @@ namespace SourceGit.Models { public class ExternalTool { - public string Name { get; private set; } - public Bitmap IconImage { get; private set; } = null; + public string Name { get; } + public string ExecFile { get; } + public Bitmap IconImage { get; } public ExternalTool(string name, string icon, string execFile, Func execArgsGenerator = null) { Name = name; - _execFile = execFile; + ExecFile = execFile; _execArgsGenerator = execArgsGenerator ?? (repo => repo.Quoted()); try @@ -38,13 +39,12 @@ public void Open(string repo) Process.Start(new ProcessStartInfo() { WorkingDirectory = repo, - FileName = _execFile, + FileName = ExecFile, Arguments = _execArgsGenerator.Invoke(repo), UseShellExecute = false, }); } - private string _execFile = string.Empty; private Func _execArgsGenerator = null; } diff --git a/src/Native/OS.cs b/src/Native/OS.cs index df72aff88..f991bca74 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -76,6 +76,18 @@ public static List ExternalTools set; } = []; + public static int ExternalMergerType + { + get; + set; + } = 0; + + public static string ExternalMergerExecFile + { + get; + set; + } = string.Empty; + public static bool UseSystemWindowFrame { get => OperatingSystem.IsLinux() && _enableSystemWindowFrame; @@ -158,6 +170,33 @@ public static void SetShellOrTerminal(Models.ShellOrTerminal shell) ShellOrTerminal = _backend.FindTerminal(shell); } + public static Models.DiffMergeTool GetDiffMergeTool(bool onlyDiff) + { + if (ExternalMergerType < 0 || ExternalMergerType >= Models.ExternalMerger.Supported.Count) + return null; + + if (ExternalMergerType != 0 && (string.IsNullOrEmpty(ExternalMergerExecFile) || !File.Exists(ExternalMergerExecFile))) + return null; + + var tool = Models.ExternalMerger.Supported[ExternalMergerType]; + return new Models.DiffMergeTool(ExternalMergerExecFile, onlyDiff ? tool.DiffCmd : tool.MergeCmd); + } + + public static void AutoSelectExternalMergeToolExecFile() + { + if (ExternalMergerType >= 0 && ExternalMergerType < Models.ExternalMerger.Supported.Count) + { + var merger = Models.ExternalMerger.Supported[ExternalMergerType]; + var externalTool = ExternalTools.Find(x => x.Name.Equals(merger.Name, StringComparison.Ordinal)); + if (externalTool != null) + ExternalMergerExecFile = externalTool.ExecFile; + else if (!OperatingSystem.IsWindows() && File.Exists(merger.Finder)) + ExternalMergerExecFile = merger.Finder; + else + ExternalMergerExecFile = string.Empty; + } + } + public static void OpenInFileManager(string path, bool select = false) { _backend.OpenInFileManager(path, select); diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index fbf0d4aa3..14ccc77ba 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -207,10 +207,7 @@ public string GetAbsPath(string path) public void OpenChangeInMergeTool(Models.Change c) { - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - var opt = new Models.DiffOption(_commit, c); - new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open(); + new Commands.DiffTool(_repo.FullPath, new Models.DiffOption(_commit, c)).Open(); } public async Task SaveChangesAsPatchAsync(List changes, string saveTo) diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 025ceddd4..e5ee18ca3 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -95,9 +95,7 @@ public void DecrUnified() public void OpenExternalMergeTool() { - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - new Commands.DiffTool(_repo, toolType, toolPath, _option).Open(); + new Commands.DiffTool(_repo, _option).Open(); } private void LoadDiffContent() diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index 05be06010..1a8364268 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -356,25 +356,34 @@ public string ShellOrTerminalPath public int ExternalMergeToolType { - get => _externalMergeToolType; + get => Native.OS.ExternalMergerType; set { - var changed = SetProperty(ref _externalMergeToolType, value); - if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMerger.Supported.Count) + if (Native.OS.ExternalMergerType != value) { - var tool = Models.ExternalMerger.Supported[value]; - if (File.Exists(tool.Exec)) - ExternalMergeToolPath = tool.Exec; - else - ExternalMergeToolPath = string.Empty; + Native.OS.ExternalMergerType = value; + OnPropertyChanged(); + + if (!_isLoading) + { + Native.OS.AutoSelectExternalMergeToolExecFile(); + OnPropertyChanged(nameof(ExternalMergeToolPath)); + } } } } public string ExternalMergeToolPath { - get => _externalMergeToolPath; - set => SetProperty(ref _externalMergeToolPath, value); + get => Native.OS.ExternalMergerExecFile; + set + { + if (!Native.OS.ExternalMergerExecFile.Equals(value, StringComparison.Ordinal)) + { + Native.OS.ExternalMergerExecFile = value; + OnPropertyChanged(); + } + } } public uint StatisticsSampleColor @@ -716,11 +725,7 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private Models.ChangeViewMode _stashChangeViewMode = Models.ChangeViewMode.List; private string _gitDefaultCloneDir = string.Empty; - private int _shellOrTerminal = -1; - private int _externalMergeToolType = 0; - private string _externalMergeToolPath = string.Empty; - private uint _statisticsSampleColor = 0xFF00FF00; } } diff --git a/src/ViewModels/RevisionCompare.cs b/src/ViewModels/RevisionCompare.cs index 1d4350a16..1634a454e 100644 --- a/src/ViewModels/RevisionCompare.cs +++ b/src/ViewModels/RevisionCompare.cs @@ -100,9 +100,7 @@ public void Dispose() public void OpenChangeWithExternalDiffTool(Models.Change change) { var opt = new Models.DiffOption(GetSHA(_startPoint), GetSHA(_endPoint), change); - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - new Commands.DiffTool(_repo, toolType, toolPath, opt).Open(); + new Commands.DiffTool(_repo, opt).Open(); } public void NavigateTo(string commitSHA) diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index 53c699e13..6dde16bf3 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -193,9 +193,7 @@ public void OpenChangeWithExternalDiffTool(Models.Change change) else opt = new Models.DiffOption(_selectedStash.Parents[0], _selectedStash.SHA, change); - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open(); + new Commands.DiffTool(_repo.FullPath, opt).Open(); } public async Task CheckoutSingleFileAsync(Models.Change change) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 28a2a78f6..f784c8111 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -531,18 +531,12 @@ public async Task UseMineAsync(List changes) public async Task UseExternalMergeToolAsync(Models.Change change) { - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - var file = change?.Path; - return await new Commands.MergeTool(_repo.FullPath, toolType, toolPath, file).OpenAsync(); + return await new Commands.MergeTool(_repo.FullPath, change?.Path).OpenAsync(); } public void UseExternalDiffTool(Models.Change change, bool isUnstaged) { - var toolType = Preferences.Instance.ExternalMergeToolType; - var toolPath = Preferences.Instance.ExternalMergeToolPath; - var opt = new Models.DiffOption(change, isUnstaged); - new Commands.DiffTool(_repo.FullPath, toolType, toolPath, opt).Open(); + new Commands.DiffTool(_repo.FullPath, new Models.DiffOption(change, isUnstaged)).Open(); } public async Task ContinueMergeAsync() diff --git a/src/Views/BranchCompare.axaml.cs b/src/Views/BranchCompare.axaml.cs index 5a6143114..dbd014c84 100644 --- a/src/Views/BranchCompare.axaml.cs +++ b/src/Views/BranchCompare.axaml.cs @@ -28,12 +28,7 @@ private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e openWithMerger.Tag = OperatingSystem.IsMacOS() ? "⌘+⇧+D" : "Ctrl+Shift+D"; openWithMerger.Click += (_, ev) => { - var pref = ViewModels.Preferences.Instance; - var toolType = pref.ExternalMergeToolType; - var toolPath = pref.ExternalMergeToolPath; - var opt = new Models.DiffOption(vm.Base.Head, vm.To.Head, change); - - new Commands.DiffTool(repo, toolType, toolPath, opt).Open(); + new Commands.DiffTool(repo, new Models.DiffOption(vm.Base.Head, vm.To.Head, change)).Open(); ev.Handled = true; }; menu.Items.Add(openWithMerger); diff --git a/src/Views/Preferences.axaml.cs b/src/Views/Preferences.axaml.cs index a6b4b7221..ca9800725 100644 --- a/src/Views/Preferences.axaml.cs +++ b/src/Views/Preferences.axaml.cs @@ -349,7 +349,7 @@ private async void SelectExternalMergeTool(object _, RoutedEventArgs e) var tool = Models.ExternalMerger.Supported[type]; var options = new FilePickerOpenOptions() { - FileTypeFilter = [new FilePickerFileType(tool.Name) { Patterns = tool.GetPatterns() }], + FileTypeFilter = [new FilePickerFileType(tool.Name) { Patterns = tool.GetPatternsToFindExecFile() }], AllowMultiple = false, }; From 0acff99945d950bcd38c85c7098631b6be21301b Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 28 Jul 2025 17:23:24 +0800 Subject: [PATCH 02/15] refactor: use `^` instead of `` as base revsion when getting changes of commit (#1625) Signed-off-by: leo --- src/ViewModels/CommitDetail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 14ccc77ba..759b2741e 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -354,7 +354,7 @@ private void Refresh() Task.Run(async () => { - var parent = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0]; + var parent = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : $"{_commit.SHA}^"; var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token }; var changes = await cmd.ReadAsync().ConfigureAwait(false); var visible = changes; From 5ce919ab66eaf622ea131da36ed2170c972d8494 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 28 Jul 2025 20:43:39 +0800 Subject: [PATCH 03/15] ci: use `pwsh` to make Windows packages instead of `bash` Signed-off-by: leo --- .github/workflows/package.yml | 4 ++-- build/scripts/package.win.ps1 | 2 ++ build/scripts/package.windows.sh | 16 ---------------- 3 files changed, 4 insertions(+), 18 deletions(-) create mode 100644 build/scripts/package.win.ps1 delete mode 100755 build/scripts/package.windows.sh diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 37d8afbab..d203dd2e2 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -22,11 +22,11 @@ jobs: name: sourcegit.${{ matrix.runtime }} path: build/SourceGit - name: Package - shell: bash + shell: pwsh env: VERSION: ${{ inputs.version }} RUNTIME: ${{ matrix.runtime }} - run: ./build/scripts/package.windows.sh + run: ./build/scripts/package.win.ps1 - name: Upload package artifact uses: actions/upload-artifact@v4 with: diff --git a/build/scripts/package.win.ps1 b/build/scripts/package.win.ps1 new file mode 100644 index 000000000..04cd07134 --- /dev/null +++ b/build/scripts/package.win.ps1 @@ -0,0 +1,2 @@ +Remove-Item -Path build\SourceGit\*.pdb -Force +Compress-Archive -Path build\SourceGit -DestinationPath "build\sourcegit_${env:VERSION}.${env:RUNTIME}.zip" -Force \ No newline at end of file diff --git a/build/scripts/package.windows.sh b/build/scripts/package.windows.sh deleted file mode 100755 index c22a9d354..000000000 --- a/build/scripts/package.windows.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -o -set -u -set pipefail - -cd build - -rm -rf SourceGit/*.pdb - -if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then - powershell -Command "Compress-Archive -Path SourceGit -DestinationPath \"sourcegit_$VERSION.$RUNTIME.zip\" -Force" -else - zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit -fi From a2f478a0d9721acc42787d50880d5d9095adf5d3 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 29 Jul 2025 11:49:35 +0800 Subject: [PATCH 04/15] ux: use bold font for error keywords in command log Signed-off-by: leo --- src/Views/CommandLogContentPresenter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Views/CommandLogContentPresenter.cs b/src/Views/CommandLogContentPresenter.cs index a2499f8d8..7aa66575f 100644 --- a/src/Views/CommandLogContentPresenter.cs +++ b/src/Views/CommandLogContentPresenter.cs @@ -50,7 +50,9 @@ protected override void ColorizeLine(DocumentLine line) { ChangeLinePart(line.Offset + idx, line.Offset + err.Length + 1, v => { + var old = v.TextRunProperties.Typeface; v.TextRunProperties.SetForegroundBrush(Brushes.Red); + v.TextRunProperties.SetTypeface(new Typeface(old.FontFamily, old.Style, FontWeight.Bold)); }); } } From 42afd96da7f0fa88dd39fb4a9e2c59e1caec1fcc Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 30 Jul 2025 10:48:00 +0800 Subject: [PATCH 05/15] ux: update icons Signed-off-by: leo --- src/Resources/Icons.axaml | 5 +++-- src/Views/Histories.axaml.cs | 8 ++++---- src/Views/SubmodulesView.axaml.cs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 0fe311c94..bc2b42968 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -49,7 +49,6 @@ M416 832H128V128h384v192C512 355 541 384 576 384L768 384v32c0 19 13 32 32 32S832 435 832 416v-64c0-6 0-19-6-25l-256-256c-6-6-19-6-25-6H128A64 64 0 0064 128v704C64 867 93 896 129 896h288c19 0 32-13 32-32S435 832 416 832zM576 172 722 320H576V172zM736 512C614 512 512 614 512 736S614 960 736 960s224-102 224-224S858 512 736 512zM576 736C576 646 646 576 736 576c32 0 58 6 83 26l-218 218c-19-26-26-51-26-83zm160 160c-32 0-64-13-96-32l224-224c19 26 32 58 32 96 0 90-70 160-160 160z M896 320c0-19-6-32-19-45l-192-192c-13-13-26-19-45-19H192c-38 0-64 26-64 64v768c0 38 26 64 64 64h640c38 0 64-26 64-64V320zm-256 384H384c-19 0-32-13-32-32s13-32 32-32h256c19 0 32 13 32 32s-13 32-32 32zm166-384H640V128l192 192h-26z M599 425 599 657 425 832 425 425 192 192 832 192Z - M505 74c-145 3-239 68-239 68-12 8-15 25-7 37 9 13 25 15 38 6 0 0 184-136 448 2 12 7 29 3 36-10 8-13 3-29-12-37-71-38-139-56-199-63-23-3-44-3-65-3m17 111c-254-3-376 201-376 201-8 12-5 29 7 37 12 8 29 4 39-10 0 0 103-178 329-175 226 3 325 173 325 173 8 12 24 17 37 9 14-8 17-24 9-37 0 0-117-195-370-199m-31 106c-72 5-140 31-192 74C197 449 132 603 204 811c5 14 20 21 34 17 14-5 21-20 16-34-66-191-7-316 79-388 84-69 233-85 343-17 54 34 96 93 118 151 22 58 20 114 3 141-18 28-54 38-86 30-32-8-58-31-59-80-1-73-58-118-118-125-57-7-123 24-140 92-32 125 49 302 238 361 14 4 29-3 34-17 4-14-3-29-18-34-163-51-225-206-202-297 10-41 46-55 84-52 37 4 69 26 69 73 2 70 48 117 100 131 52 13 112-3 144-52 33-50 28-120 3-188-26-68-73-136-140-178a356 356 0 00-213-52m15 104v0c-76 3-152 42-195 125-56 106-31 215 7 293 38 79 90 131 90 131 10 11 27 11 38 0s11-26 0-38c0 0-46-47-79-116s-54-157-8-244c48-90 133-111 208-90 76 22 140 88 138 186-2 15 9 28 24 29 15 1 27-10 29-27 3-122-79-210-176-239a246 246 0 00-75-9m9 213c-15 0-26 13-26 27 0 0 1 63 36 124 36 61 112 119 244 107 15-1 26-13 25-28-1-15-14-26-30-25-116 11-165-33-193-81-28-47-29-98-29-98a27 27 0 00-27-27z M853 267H514c-4 0-6-2-9-4l-38-66c-13-21-38-36-64-36H171c-41 0-75 34-75 75v555c0 41 34 75 75 75h683c41 0 75-34 75-75V341c0-41-34-75-75-75zm-683-43h233c4 0 6 2 9 4l38 66c13 21 38 36 64 36H853c6 0 11 4 11 11v75h-704V235c0-6 4-11 11-11zm683 576H171c-6 0-11-4-11-11V480h704V789c0 6-4 11-11 11z M1088 227H609L453 78a11 11 0 00-7-3H107a43 43 0 00-43 43v789a43 43 0 0043 43h981a43 43 0 0043-43V270a43 43 0 00-43-43zM757 599c0 5-5 9-10 9h-113v113c0 5-4 9-9 9h-56c-5 0-9-4-9-9V608h-113c-5 0-10-4-10-9V543c0-5 5-9 10-9h113V420c0-5 4-9 9-9h56c5 0 9 4 9 9V533h113c5 0 10 4 10 9v56z M922 450c-6-9-15-13-26-13h-11V341c0-41-34-75-75-75H514c-4 0-6-2-9-4l-38-66c-13-21-38-36-64-36H171c-41 0-75 34-75 75v597c0 6 2 13 6 19 6 9 15 13 26 13h640c13 0 26-9 30-21l128-363c4-11 2-21-4-30zM171 224h233c4 0 6 2 9 4l38 66c13 21 38 36 64 36H811c6 0 11 4 11 11v96H256c-13 0-26 9-30 21l-66 186V235c0-6 4-11 11-11zm574 576H173l105-299h572l-105 299z @@ -60,6 +59,7 @@ M525 0C235 0 0 235 0 525c0 232 150 429 359 498 26 5 36-11 36-25 0-12-1-54-1-97-146 31-176-63-176-63-23-61-58-76-58-76-48-32 3-32 3-32 53 3 81 54 81 54 47 80 123 57 153 43 4-34 18-57 33-70-116-12-239-57-239-259 0-57 21-104 54-141-5-13-23-67 5-139 0 0 44-14 144 54 42-11 87-17 131-17s90 6 131 17C756 203 801 217 801 217c29 72 10 126 5 139 34 37 54 83 54 141 0 202-123 246-240 259 19 17 36 48 36 97 0 70-1 127-1 144 0 14 10 30 36 25 209-70 359-266 359-498C1050 235 814 0 525 0z M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z M30 271l241 0 0-241-241 0 0 241zM392 271l241 0 0-241-241 0 0 241zM753 30l0 241 241 0 0-241-241 0zM30 632l241 0 0-241-241 0 0 241zM392 632l241 0 0-241-241 0 0 241zM753 632l241 0 0-241-241 0 0 241zM30 994l241 0 0-241-241 0 0 241zM392 994l241 0 0-241-241 0 0 241zM753 994l241 0 0-241-241 0 0 241z + M566 585l37-146-145 0-37 146 145 0zM1005 297l-32 128q-4 14-18 14l-187 0-37 146 178 0q9 0 14 7 6 8 3 16l-32 128q-3 14-18 14l-187 0-46 187q-4 14-18 14l-128 0q-9 0-15-7-5-7-3-16l45-178-145 0-46 187q-4 14-18 14l-129 0q-9 0-14-7-5-7-3-16l45-178-178 0q-9 0-14-7-5-7-3-16l32-128q4-14 18-14l187 0 37-146-178 0q-9 0-14-7-6-8-3-16l32-128q3-14 18-14l187 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 145 0 46-187q4-14 18-14l128 0q9 0 14 7 5 7 3 16l-45 178 178 0q9 0 14 7 5 7 3 16z M0 512M1024 512M512 0M512 1024M955 323q0 23-16 39l-414 414-78 78q-16 16-39 16t-39-16l-78-78-207-207q-16-16-16-39t16-39l78-78q16-16 39-16t39 16l168 169 375-375q16-16 39-16t39 16l78 78q16 16 16 39z M416 64H768v64h-64v704h64v64H448v-64h64V512H416a224 224 0 1 1 0-448zM576 832h64V128H576v704zM416 128H512v320H416a160 160 0 0 1 0-320z M24 512A488 488 0 01512 24A488 488 0 011000 512A488 488 0 01512 1000A488 488 0 0124 512zm447-325v327L243 619l51 111 300-138V187H471z @@ -114,6 +114,7 @@ M155 143h715v81H155V143zm358 94 358 369H662l1 278H363V605H155l358-369z M702 677 590 565a148 148 0 10-25 27L676 703zm-346-200a115 115 0 11115 115A115 115 0 01355 478z M928 500a21 21 0 00-19-20L858 472a11 11 0 01-9-9c-1-6-2-13-3-19a11 11 0 015-12l46-25a21 21 0 0010-26l-8-22a21 21 0 00-24-13l-51 10a11 11 0 01-12-6c-3-6-6-11-10-17a11 11 0 011-13l34-39a21 21 0 001-28l-15-18a20 20 0 00-27-4l-45 27a11 11 0 01-13-1c-5-4-10-9-15-12a11 11 0 01-3-12l19-49a21 21 0 00-9-26l-20-12a21 21 0 00-27 6L650 193a9 9 0 01-11 3c-1-1-12-5-20-7a11 11 0 01-7-10l1-52a21 21 0 00-17-22l-23-4a21 21 0 00-24 14L532 164a11 11 0 01-11 7h-20a11 11 0 01-11-7l-17-49a21 21 0 00-24-15l-23 4a21 21 0 00-17 22l1 52a11 11 0 01-8 11c-5 2-15 6-19 7c-4 1-8 0-12-4l-33-40A21 21 0 00313 146l-20 12A21 21 0 00285 184l19 49a11 11 0 01-3 12c-5 4-10 8-15 12a11 11 0 01-13 1L228 231a21 21 0 00-27 4L186 253a21 21 0 001 28L221 320a11 11 0 011 13c-3 5-7 11-10 17a11 11 0 01-12 6l-51-10a21 21 0 00-24 13l-8 22a21 21 0 0010 26l46 25a11 11 0 015 12l0 3c-1 6-2 11-3 16a11 11 0 01-9 9l-51 8A21 21 0 0096 500v23A21 21 0 00114 544l51 8a11 11 0 019 9c1 6 2 13 3 19a11 11 0 01-5 12l-46 25a21 21 0 00-10 26l8 22a21 21 0 0024 13l51-10a11 11 0 0112 6c3 6 6 11 10 17a11 11 0 01-1 13l-34 39a21 21 0 00-1 28l15 18a20 20 0 0027 4l45-27a11 11 0 0113 1c5 4 10 9 15 12a11 11 0 013 12l-19 49a21 21 0 009 26l20 12a21 21 0 0027-6L374 832c3-3 7-5 10-4c7 3 12 5 20 7a11 11 0 018 10l-1 52a21 21 0 0017 22l23 4a21 21 0 0024-14l17-50a11 11 0 0111-7h20a11 11 0 0111 7l17 49a21 21 0 0020 15a19 19 0 004 0l23-4a21 21 0 0017-22l-1-52a11 11 0 018-10c8-3 13-5 18-7l1 0c6-2 9 0 11 3l34 41A21 21 0 00710 878l20-12a21 21 0 009-26l-18-49a11 11 0 013-12c5-4 10-8 15-12a11 11 0 0113-1l45 27a21 21 0 0027-4l15-18a21 21 0 00-1-28l-34-39a11 11 0 01-1-13c3-5 7-11 10-17a11 11 0 0112-6l51 10a21 21 0 0024-13l8-22a21 21 0 00-10-26l-46-25a11 11 0 01-5-12l0-3c1-6 2-11 3-16a11 11 0 019-9l51-8a21 21 0 0018-21v-23zm-565 188a32 32 0 01-51 5a270 270 0 011-363a32 32 0 0151 6l91 161a32 32 0 010 31zM512 782a270 270 0 01-57-6a32 32 0 01-20-47l92-160a32 32 0 0127-16h184a32 32 0 0130 41c-35 109-137 188-257 188zm15-328L436 294a32 32 0 0121-47a268 268 0 0155-6c120 0 222 79 257 188a32 32 0 01-30 41h-184a32 32 0 01-28-16z + M653 435l-26 119H725c9 0 13 4 13 13v47c0 9-4 13-13 13h-107l-21 115c0 9-4 13-13 13h-47c-9 0-13-4-13-13l21-111H427l-21 115c0 9-4 13-13 13H346c-9 0-13-4-13-13l21-107h-85c-4-9-9-21-13-34v-38c0-9 4-13 13-13h98l26-119H294c-9 0-13-4-13-13V375c0-9 4-13 13-13h115l13-81c0-9 4-13 13-13h43c9 0 13 4 13 13L469 363h119l13-81c0-9 4-13 13-13h47c9 0 13 4 13 13l-13 77h85c9 0 13 4 13 13v47c0 9-4 13-13 13h-98v4zM512 0C230 0 0 230 0 512c0 145 60 282 166 375L90 1024H512c282 0 512-230 512-512S794 0 512 0zm-73 559h124l26-119h-128l-21 119z M900 287c40 69 60 144 60 225s-20 156-60 225c-40 69-94 123-163 163-69 40-144 60-225 60s-156-20-225-60c-69-40-123-94-163-163C84 668 64 593 64 512s20-156 60-225 94-123 163-163c69-40 144-60 225-60s156 20 225 60 123 94 163 163zM762 512c0-9-3-16-9-22L578 315l-44-44c-6-6-13-9-22-9s-16 3-22 9l-44 44-176 176c-6 6-9 13-9 22s3 16 9 22l44 44c6 6 13 9 22 9s16-3 22-9l92-92v269c0 9 3 16 9 22 6 6 13 9 22 9h62c8 0 16-3 22-9 6-6 9-13 9-22V486l92 92c6 6 13 9 22 9 8 0 16-3 22-9l44-44c6-6 9-13 9-22z M512 939C465 939 427 900 427 853 427 806 465 768 512 768 559 768 597 806 597 853 597 900 559 939 512 939M555 85 555 555 747 363 807 423 512 719 217 423 277 363 469 555 469 85 555 85Z M961 320 512 577 63 320 512 62l449 258zM512 628 185 442 63 512 512 770 961 512l-123-70L512 628zM512 821 185 634 63 704 512 962l449-258L839 634 512 821z @@ -123,7 +124,7 @@ M558 545 790 403c24-15 31-47 16-71-15-24-46-31-70-17L507 457 277 315c-24-15-56-7-71 17-15 24-7 56 17 71l232 143V819c0 28 23 51 51 51 28 0 51-23 51-51V545h0zM507 0l443 256v512L507 1024 63 768v-512L507 0z M770 320a41 41 0 00-56-14l-252 153L207 306a41 41 0 10-43 70l255 153 2 296a41 41 0 0082 0l-2-295 255-155a41 41 0 0014-56zM481 935a42 42 0 01-42 0L105 741a42 42 0 01-21-36v-386a42 42 0 0121-36L439 89a42 42 0 0142 0l335 193a42 42 0 0121 36v87h84v-87a126 126 0 00-63-109L523 17a126 126 0 00-126 0L63 210a126 126 0 00-63 109v386a126 126 0 0063 109l335 193a126 126 0 00126 0l94-54-42-72zM1029 700h-126v-125a42 42 0 00-84 0v126h-126a42 42 0 000 84h126v126a42 42 0 1084 0v-126h126a42 42 0 000-84z M416 587c21 0 37 17 37 37v299A37 37 0 01416 960h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299zm448 0c21 0 37 17 37 37v299A37 37 0 01864 960h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299zM758 91l183 189a37 37 0 010 52l-182 188a37 37 0 01-53 1l-183-189a37 37 0 010-52l182-188a37 37 0 0153-1zM416 139c21 0 37 17 37 37v299A37 37 0 01416 512h-299a37 37 0 01-37-37v-299c0-21 17-37 37-37h299z - M653 435l-26 119H725c9 0 13 4 13 13v47c0 9-4 13-13 13h-107l-21 115c0 9-4 13-13 13h-47c-9 0-13-4-13-13l21-111H427l-21 115c0 9-4 13-13 13H346c-9 0-13-4-13-13l21-107h-85c-4-9-9-21-13-34v-38c0-9 4-13 13-13h98l26-119H294c-9 0-13-4-13-13V375c0-9 4-13 13-13h115l13-81c0-9 4-13 13-13h43c9 0 13 4 13 13L469 363h119l13-81c0-9 4-13 13-13h47c9 0 13 4 13 13l-13 77h85c9 0 13 4 13 13v47c0 9-4 13-13 13h-98v4zM512 0C230 0 0 230 0 512c0 145 60 282 166 375L90 1024H512c282 0 512-230 512-512S794 0 512 0zm-73 559h124l26-119h-128l-21 119z + M512 0C230 0 0 230 0 512c0 145 60 282 166 375L90 1024H512c282 0 512-230 512-512S794 0 512 0z M875 128h-725A107 107 0 0043 235v555A107 107 0 00149 896h725a107 107 0 00107-107v-555A107 107 0 00875 128zm-115 640h-183v-58l25-3c15 0 19-8 14-24l-22-61H419l-28 82 39 2V768h-166v-58l18-3c18-2 22-11 26-24l125-363-40-4V256h168l160 448 39 3zM506 340l-72 218h145l-71-218h-2z M177 156c-22 5-33 17-36 37c-10 57-33 258-13 278l445 445c23 23 61 23 84 0l246-246c23-23 23-61 0-84l-445-445C437 120 231 145 177 156zM331 344c-26 26-69 26-95 0c-26-26-26-69 0-95s69-26 95 0C357 276 357 318 331 344z M683 537h-144v-142h-142V283H239a44 44 0 00-41 41v171a56 56 0 0014 34l321 321a41 41 0 0058 0l174-174a41 41 0 000-58zm-341-109a41 41 0 110-58a41 41 0 010 58zM649 284V142h-69v142h-142v68h142v142h69v-142h142v-68h-142z diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index e4ec2e238..83ce5ee0c 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -414,7 +414,7 @@ private ContextMenu CreateContextMenuForMultipleCommits(ViewModels.Repository re var copyShas = new MenuItem(); copyShas.Header = App.Text("CommitCM.CopySHA"); - copyShas.Icon = App.CreateMenuIcon("Icons.Fingerprint"); + copyShas.Icon = App.CreateMenuIcon("Icons.Hash"); copyShas.Click += async (_, e) => { var builder = new StringBuilder(); @@ -427,7 +427,7 @@ private ContextMenu CreateContextMenuForMultipleCommits(ViewModels.Repository re var copyInfos = new MenuItem(); copyInfos.Header = App.Text("CommitCM.CopySHA") + " - " + App.Text("CommitCM.CopySubject"); - copyInfos.Icon = App.CreateMenuIcon("Icons.Info"); + copyInfos.Icon = App.CreateMenuIcon("Icons.ShaAndSubject"); copyInfos.Tag = OperatingSystem.IsMacOS() ? "⌘+C" : "Ctrl+C"; copyInfos.Click += async (_, e) => { @@ -826,7 +826,7 @@ private ContextMenu CreateContextMenuForSingleCommit(ViewModels.Repository repo, var copySHA = new MenuItem(); copySHA.Header = App.Text("CommitCM.CopySHA"); - copySHA.Icon = App.CreateMenuIcon("Icons.Fingerprint"); + copySHA.Icon = App.CreateMenuIcon("Icons.Hash"); copySHA.Click += async (_, e) => { await App.CopyTextAsync(commit.SHA); @@ -844,7 +844,7 @@ private ContextMenu CreateContextMenuForSingleCommit(ViewModels.Repository repo, var copyInfo = new MenuItem(); copyInfo.Header = App.Text("CommitCM.CopySHA") + " - " + App.Text("CommitCM.CopySubject"); - copyInfo.Icon = App.CreateMenuIcon("Icons.Info"); + copyInfo.Icon = App.CreateMenuIcon("Icons.ShaAndSubject"); copyInfo.Tag = OperatingSystem.IsMacOS() ? "⌘+C" : "Ctrl+C"; copyInfo.Click += async (_, e) => { diff --git a/src/Views/SubmodulesView.axaml.cs b/src/Views/SubmodulesView.axaml.cs index ed97e70db..c24ac6c01 100644 --- a/src/Views/SubmodulesView.axaml.cs +++ b/src/Views/SubmodulesView.axaml.cs @@ -254,7 +254,7 @@ private void OnItemContextRequested(object sender, ContextRequestedEventArgs e) var copySHA = new MenuItem(); copySHA.Header = App.Text("CommitDetail.Info.SHA"); - copySHA.Icon = App.CreateMenuIcon("Icons.Fingerprint"); + copySHA.Icon = App.CreateMenuIcon("Icons.Hash"); copySHA.Click += async (_, ev) => { await App.CopyTextAsync(submodule.SHA); From 072b7f8af5418eb2abb7772bba3ae061acb2a701 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 30 Jul 2025 10:57:25 +0800 Subject: [PATCH 06/15] ux: use another label `Submodule.CopyBranch` instead of `Submodule.Branch` Signed-off-by: leo --- src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/Views/SubmodulesView.axaml.cs | 18 +++++++++--------- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 655f6e976..7e1ffeabf 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -759,6 +759,7 @@ SUBMODULES Add Submodule BRANCH + Branch Relative Path De-initialize Fetch nested submodules diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 711ab12f3..7403ff787 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -763,6 +763,7 @@ 子模块 添加子模块 跟踪分支 + 跟踪分支 相对路径 取消初始化 拉取子孙模块 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 61956e97f..4ebfc9ad1 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -763,6 +763,7 @@ 子模組 新增子模組 追蹤分支 + 追蹤分支 相對路徑 取消初始化 提取子模組 diff --git a/src/Views/SubmodulesView.axaml.cs b/src/Views/SubmodulesView.axaml.cs index c24ac6c01..fdd88c086 100644 --- a/src/Views/SubmodulesView.axaml.cs +++ b/src/Views/SubmodulesView.axaml.cs @@ -261,6 +261,15 @@ private void OnItemContextRequested(object sender, ContextRequestedEventArgs e) ev.Handled = true; }; + var copyBranch = new MenuItem(); + copyBranch.Header = App.Text("Submodule.CopyBranch"); + copyBranch.Icon = App.CreateMenuIcon("Icons.Branch"); + copyBranch.Click += async (_, ev) => + { + await App.CopyTextAsync(submodule.Branch); + ev.Handled = true; + }; + var copyRelativePath = new MenuItem(); copyRelativePath.Header = App.Text("Submodule.CopyPath"); copyRelativePath.Icon = App.CreateMenuIcon("Icons.Folder"); @@ -279,15 +288,6 @@ private void OnItemContextRequested(object sender, ContextRequestedEventArgs e) ev.Handled = true; }; - var copyBranch = new MenuItem(); - copyBranch.Header = App.Text("Submodule.Branch"); - copyBranch.Icon = App.CreateMenuIcon("Icons.Branch"); - copyBranch.Click += async (_, ev) => - { - await App.CopyTextAsync(submodule.Branch); - ev.Handled = true; - }; - var copy = new MenuItem(); copy.Header = App.Text("Copy"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); From df48678c7c8adf306bbf5ebb691f9ee1614e0e7b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Jul 2025 02:58:12 +0000 Subject: [PATCH 07/15] doc: Update translation status and sort locale files --- TRANSLATION.md | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index 1fbb4824f..1446dadb1 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,18 +6,26 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-%E2%88%9A-brightgreen) +### ![de__DE](https://img.shields.io/badge/de__DE-99.88%25-yellow) -### ![es__ES](https://img.shields.io/badge/es__ES-99.88%25-yellow) +
+Missing keys in de_DE.axaml + +- Text.Submodule.CopyBranch + +
+ +### ![es__ES](https://img.shields.io/badge/es__ES-99.77%25-yellow)
Missing keys in es_ES.axaml - Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit +- Text.Submodule.CopyBranch
-### ![fr__FR](https://img.shields.io/badge/fr__FR-82.04%25-yellow) +### ![fr__FR](https://img.shields.io/badge/fr__FR-81.95%25-yellow)
Missing keys in fr_FR.axaml @@ -147,6 +155,7 @@ This document shows the translation status of each locale file in the repository - Text.Stash.Mode - Text.StashCM.CopyMessage - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move @@ -178,7 +187,7 @@ This document shows the translation status of each locale file in the repository
-### ![it__IT](https://img.shields.io/badge/it__IT-87.32%25-yellow) +### ![it__IT](https://img.shields.io/badge/it__IT-87.22%25-yellow)
Missing keys in it_IT.axaml @@ -280,6 +289,7 @@ This document shows the translation status of each locale file in the repository - Text.Stash.Mode - Text.StashCM.CopyMessage - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move @@ -294,7 +304,7 @@ This document shows the translation status of each locale file in the repository
-### ![ja__JP](https://img.shields.io/badge/ja__JP-82.04%25-yellow) +### ![ja__JP](https://img.shields.io/badge/ja__JP-81.95%25-yellow)
Missing keys in ja_JP.axaml @@ -426,6 +436,7 @@ This document shows the translation status of each locale file in the repository - Text.Stash.Mode - Text.StashCM.CopyMessage - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move @@ -455,7 +466,7 @@ This document shows the translation status of each locale file in the repository
-### ![pt__BR](https://img.shields.io/badge/pt__BR-75.00%25-yellow) +### ![pt__BR](https://img.shields.io/badge/pt__BR-74.91%25-red)
Missing keys in pt_BR.axaml @@ -645,6 +656,7 @@ This document shows the translation status of each locale file in the repository - Text.StashCM.CopyMessage - Text.StashCM.SaveAsPatch - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move @@ -676,9 +688,16 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) +### ![ru__RU](https://img.shields.io/badge/ru__RU-99.88%25-yellow) + +
+Missing keys in ru_RU.axaml + +- Text.Submodule.CopyBranch + +
-### ![ta__IN](https://img.shields.io/badge/ta__IN-82.16%25-yellow) +### ![ta__IN](https://img.shields.io/badge/ta__IN-82.06%25-yellow)
Missing keys in ta_IN.axaml @@ -809,6 +828,7 @@ This document shows the translation status of each locale file in the repository - Text.Stash.Mode - Text.StashCM.CopyMessage - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move @@ -838,7 +858,7 @@ This document shows the translation status of each locale file in the repository
-### ![uk__UA](https://img.shields.io/badge/uk__UA-83.33%25-yellow) +### ![uk__UA](https://img.shields.io/badge/uk__UA-83.24%25-yellow)
Missing keys in uk_UA.axaml @@ -964,6 +984,7 @@ This document shows the translation status of each locale file in the repository - Text.Stash.Mode - Text.StashCM.CopyMessage - Text.Submodule.Branch +- Text.Submodule.CopyBranch - Text.Submodule.Deinit - Text.Submodule.Histories - Text.Submodule.Move From 243747500677f2c924178d076282a5aa94b48232 Mon Sep 17 00:00:00 2001 From: heartacker <1876302+heartacker@users.noreply.github.com> Date: Wed, 30 Jul 2025 11:53:29 +0800 Subject: [PATCH 08/15] feature: self host GitLab URLs in CommitLink (#1635) --- src/Models/CommitLink.cs | 8 ++++++-- src/Models/Remote.cs | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Models/CommitLink.cs b/src/Models/CommitLink.cs index 08caad8d1..a260cb7b7 100644 --- a/src/Models/CommitLink.cs +++ b/src/Models/CommitLink.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using System.Text.RegularExpressions; namespace SourceGit.Models { - public class CommitLink + public partial class CommitLink { public string Name { get; set; } = null; public string URLPrefix { get; set; } = null; @@ -14,6 +15,9 @@ public CommitLink(string name, string prefix) URLPrefix = prefix; } + [GeneratedRegex(@"^(http|https)://[^/]*gitlab[^/]*(:[0-9]+)?.*$")] + private static partial Regex REG_GITLAB(); + public static List Get(List remotes) { var outs = new List(); @@ -28,7 +32,7 @@ public static List Get(List remotes) if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) outs.Add(new($"GitHub ({trimmedUrl[19..]})", $"{url}/commit/")); - else if (url.StartsWith("https://gitlab./", StringComparison.Ordinal)) + else if (REG_GITLAB().IsMatch(url)) outs.Add(new($"GitLab ({trimmedUrl[(trimmedUrl[15..].IndexOf('/') + 16)..]})", $"{url}/-/commit/")); else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) outs.Add(new($"Gitee ({trimmedUrl[18..]})", $"{url}/commit/")); diff --git a/src/Models/Remote.cs b/src/Models/Remote.cs index 6e36cfb9e..a2592215c 100644 --- a/src/Models/Remote.cs +++ b/src/Models/Remote.cs @@ -8,10 +8,13 @@ public partial class Remote { [GeneratedRegex(@"^https?://[^/]+/.+[^/\.]$")] private static partial Regex REG_HTTPS(); + [GeneratedRegex(@"^git://[^/]+/.+[^/\.]$")] private static partial Regex REG_GIT(); + [GeneratedRegex(@"^[\w\-]+@[\w\.\-]+(\:[0-9]+)?:([a-zA-z0-9~%][\w\-\./~%]*)?[a-zA-Z0-9](\.git)?$")] private static partial Regex REG_SSH1(); + [GeneratedRegex(@"^ssh://([\w\-]+@)?[\w\.\-]+(\:[0-9]+)?/([a-zA-z0-9~%][\w\-\./~%]*)?[a-zA-Z0-9](\.git)?$")] private static partial Regex REG_SSH2(); From 3ced2b7fd222f41a4d6cbd1068e4e5e35022bbc9 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 30 Jul 2025 12:05:14 +0800 Subject: [PATCH 09/15] code_review: PR #1635 Signed-off-by: leo --- src/Models/CommitLink.cs | 45 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Models/CommitLink.cs b/src/Models/CommitLink.cs index a260cb7b7..fd3224921 100644 --- a/src/Models/CommitLink.cs +++ b/src/Models/CommitLink.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; namespace SourceGit.Models { - public partial class CommitLink + public class CommitLink { public string Name { get; set; } = null; public string URLPrefix { get; set; } = null; @@ -15,35 +14,35 @@ public CommitLink(string name, string prefix) URLPrefix = prefix; } - [GeneratedRegex(@"^(http|https)://[^/]*gitlab[^/]*(:[0-9]+)?.*$")] - private static partial Regex REG_GITLAB(); - public static List Get(List remotes) { var outs = new List(); foreach (var remote in remotes) { - if (remote.TryGetVisitURL(out var url)) + if (remote.TryGetVisitURL(out var link)) { - var trimmedUrl = url.AsSpan(); - if (url.EndsWith(".git")) - trimmedUrl = url.AsSpan(0, url.Length - 4); + if (link.EndsWith(".git")) + link = link.Substring(0, link.Length - 4); + + var uri = new Uri(link, UriKind.Absolute); + var host = uri.Host; + var route = uri.AbsolutePath.TrimStart('/'); - if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) - outs.Add(new($"GitHub ({trimmedUrl[19..]})", $"{url}/commit/")); - else if (REG_GITLAB().IsMatch(url)) - outs.Add(new($"GitLab ({trimmedUrl[(trimmedUrl[15..].IndexOf('/') + 16)..]})", $"{url}/-/commit/")); - else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) - outs.Add(new($"Gitee ({trimmedUrl[18..]})", $"{url}/commit/")); - else if (url.StartsWith("https://bitbucket.org/", StringComparison.Ordinal)) - outs.Add(new($"BitBucket ({trimmedUrl[22..]})", $"{url}/commits/")); - else if (url.StartsWith("https://codeberg.org/", StringComparison.Ordinal)) - outs.Add(new($"Codeberg ({trimmedUrl[21..]})", $"{url}/commit/")); - else if (url.StartsWith("https://gitea.org/", StringComparison.Ordinal)) - outs.Add(new($"Gitea ({trimmedUrl[18..]})", $"{url}/commit/")); - else if (url.StartsWith("https://git.sr.ht/", StringComparison.Ordinal)) - outs.Add(new($"sourcehut ({trimmedUrl[18..]})", $"{url}/commit/")); + if (host.Equals("github.com", StringComparison.Ordinal)) + outs.Add(new($"GitHub ({route})", $"{link}/commit/")); + else if (host.Contains("gitlab", StringComparison.Ordinal)) + outs.Add(new($"GitLab ({route})", $"{link}/-/commit/")); + else if (host.Equals("gitee.com", StringComparison.Ordinal)) + outs.Add(new($"Gitee ({route})", $"{link}/commit/")); + else if (host.Equals("bitbucket.org", StringComparison.Ordinal)) + outs.Add(new($"BitBucket ({route})", $"{link}/commits/")); + else if (host.Equals("codeberg.org", StringComparison.Ordinal)) + outs.Add(new($"Codeberg ({route})", $"{link}/commit/")); + else if (host.Equals("gitea.org", StringComparison.Ordinal)) + outs.Add(new($"Gitea ({route})", $"{link}/commit/")); + else if (host.Equals("github.com", StringComparison.Ordinal)) + outs.Add(new($"sourcehut ({route})", $"{link}/commit/")); } } From 7d09af1636e7cd8c85f93e549bd468ae1b4b0188 Mon Sep 17 00:00:00 2001 From: leo Date: Wed, 30 Jul 2025 13:28:35 +0800 Subject: [PATCH 10/15] fix: wrong host name for sourcehut Signed-off-by: leo --- src/Models/CommitLink.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/CommitLink.cs b/src/Models/CommitLink.cs index fd3224921..4d8e22a28 100644 --- a/src/Models/CommitLink.cs +++ b/src/Models/CommitLink.cs @@ -41,7 +41,7 @@ public static List Get(List remotes) outs.Add(new($"Codeberg ({route})", $"{link}/commit/")); else if (host.Equals("gitea.org", StringComparison.Ordinal)) outs.Add(new($"Gitea ({route})", $"{link}/commit/")); - else if (host.Equals("github.com", StringComparison.Ordinal)) + else if (host.Equals("git.sr.ht", StringComparison.Ordinal)) outs.Add(new($"sourcehut ({route})", $"{link}/commit/")); } } From a1363c7acfaa86e775644253b18d549aa7953391 Mon Sep 17 00:00:00 2001 From: AquariusStar <48148723+AquariusStar@users.noreply.github.com> Date: Mon, 4 Aug 2025 05:14:41 +0300 Subject: [PATCH 11/15] localization: update russian translate (#1649) --- src/Resources/Locales/ru_RU.axaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index daf839ed6..0331abee2 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -136,8 +136,8 @@ Редактировать... Исправить в родительском... Интерактивное перемещение ${0}$ в ${1}$ - Имзенить комментарий... - Втиуснуть в родительский... + Изменить комментарий... + Втиснуть в родительский... Влить в ${0}$ Влить ... Выложить ${0}$ в ${1}$ @@ -762,7 +762,8 @@ РЕВИЗИИ: ПОДМОДУЛИ Добавить подмодули - Ветка + ВЕТКА + Ветка Каталог Удалить подмодуль Извлечение вложенных подмодулей From a0080c7b040d49636ea8c374c51fc0555b8d0b25 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 4 Aug 2025 02:14:53 +0000 Subject: [PATCH 12/15] doc: Update translation status and sort locale files --- TRANSLATION.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index 1446dadb1..b4e1af7d2 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -688,14 +688,7 @@ This document shows the translation status of each locale file in the repository
-### ![ru__RU](https://img.shields.io/badge/ru__RU-99.88%25-yellow) - -
-Missing keys in ru_RU.axaml - -- Text.Submodule.CopyBranch - -
+### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) ### ![ta__IN](https://img.shields.io/badge/ta__IN-82.06%25-yellow) From a279ec486bb4d768f51484df34186c915a1b346b Mon Sep 17 00:00:00 2001 From: Sina Hinderks Date: Mon, 4 Aug 2025 04:15:01 +0200 Subject: [PATCH 13/15] localization: update German translations (#1656) --- src/Resources/Locales/de_DE.axaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index a304bddba..af00a8cfe 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -763,6 +763,7 @@ SUBMODULE Submodul hinzufügen BRANCH + Branch Relativen Pfad De-initialisiere Submodul Untergeordnete Submodule fetchen From 3744cd341294ac29913991600601470343adfc76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 4 Aug 2025 02:15:13 +0000 Subject: [PATCH 14/15] doc: Update translation status and sort locale files --- TRANSLATION.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index b4e1af7d2..58c8029ea 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,14 +6,7 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-99.88%25-yellow) - -
-Missing keys in de_DE.axaml - -- Text.Submodule.CopyBranch - -
+### ![de__DE](https://img.shields.io/badge/de__DE-%E2%88%9A-brightgreen) ### ![es__ES](https://img.shields.io/badge/es__ES-99.77%25-yellow) From 0834889a116368d6d5efb65c9cf735fd1d053bb4 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 4 Aug 2025 10:17:37 +0800 Subject: [PATCH 15/15] version: Release 20225.29 Signed-off-by: leo --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 99b162bd6..9851c0cad 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.28 \ No newline at end of file +2025.29 \ No newline at end of file