Merge branch 'release/v2025.29'

This commit is contained in:
leo
2025-08-04 10:17:47 +08:00
29 changed files with 204 additions and 200 deletions

View File

@@ -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:

View File

@@ -8,16 +8,17 @@ This document shows the translation status of each locale file in the repository
### ![de__DE](https://img.shields.io/badge/de__DE-%E2%88%9A-brightgreen)
### ![es__ES](https://img.shields.io/badge/es__ES-99.88%25-yellow)
### ![es__ES](https://img.shields.io/badge/es__ES-99.77%25-yellow)
<details>
<summary>Missing keys in es_ES.axaml</summary>
- Text.Configure.IssueTracker.AddSampleGerritChangeIdCommit
- Text.Submodule.CopyBranch
</details>
### ![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)
<details>
<summary>Missing keys in fr_FR.axaml</summary>
@@ -147,6 +148,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 +180,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![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)
<details>
<summary>Missing keys in it_IT.axaml</summary>
@@ -280,6 +282,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 +297,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![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)
<details>
<summary>Missing keys in ja_JP.axaml</summary>
@@ -426,6 +429,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 +459,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![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)
<details>
<summary>Missing keys in pt_BR.axaml</summary>
@@ -645,6 +649,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
@@ -678,7 +683,7 @@ 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)
### ![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)
<details>
<summary>Missing keys in ta_IN.axaml</summary>
@@ -809,6 +814,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 +844,7 @@ This document shows the translation status of each locale file in the repository
</details>
### ![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)
<details>
<summary>Missing keys in uk_UA.axaml</summary>
@@ -964,6 +970,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

View File

@@ -1 +1 @@
2025.28
2025.29

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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<bool> 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;
}
}

View File

@@ -20,26 +20,29 @@ namespace SourceGit.Models
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);
if (url.StartsWith("https://github.com/", StringComparison.Ordinal))
outs.Add(new($"GitHub ({trimmedUrl[19..]})", $"{url}/commit/"));
else if (url.StartsWith("https://gitlab.", StringComparison.Ordinal))
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/"));
var uri = new Uri(link, UriKind.Absolute);
var host = uri.Host;
var route = uri.AbsolutePath.TrimStart('/');
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("git.sr.ht", StringComparison.Ordinal))
outs.Add(new($"sourcehut ({route})", $"{link}/commit/"));
}
}

View File

@@ -7,14 +7,13 @@ using Avalonia.Platform;
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 @@ namespace SourceGit.Models
if (OperatingSystem.IsWindows())
{
Supported = new List<ExternalMerger>() {
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<ExternalMerger>() {
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<ExternalMerger>() {
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<ExternalMerger>() {
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;
}
}

View File

@@ -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<string, string> execArgsGenerator = null)
{
Name = name;
_execFile = execFile;
ExecFile = execFile;
_execArgsGenerator = execArgsGenerator ?? (repo => repo.Quoted());
try
@@ -38,13 +39,12 @@ namespace SourceGit.Models
Process.Start(new ProcessStartInfo()
{
WorkingDirectory = repo,
FileName = _execFile,
FileName = ExecFile,
Arguments = _execArgsGenerator.Invoke(repo),
UseShellExecute = false,
});
}
private string _execFile = string.Empty;
private Func<string, string> _execArgsGenerator = null;
}

View File

@@ -8,10 +8,13 @@ namespace SourceGit.Models
{
[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();

View File

@@ -76,6 +76,18 @@ namespace SourceGit.Native
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 @@ namespace SourceGit.Native
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);

View File

@@ -49,7 +49,6 @@
<StreamGeometry x:Key="Icons.File.Ignore">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</StreamGeometry>
<StreamGeometry x:Key="Icons.File.Remove">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Filter">M599 425 599 657 425 832 425 425 192 192 832 192Z</StreamGeometry>
<StreamGeometry x:Key="Icons.Fingerprint">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder.Add">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder.Open">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</StreamGeometry>
@@ -60,6 +59,7 @@
<StreamGeometry x:Key="Icons.GitHub">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</StreamGeometry>
<StreamGeometry x:Key="Icons.GitIgnore">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Grid">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Hash">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Head">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</StreamGeometry>
<StreamGeometry x:Key="Icons.HiddenSymbol">M416 64H768v64h-64v704h64v64H448v-64h64V512H416a224 224 0 1 1 0-448zM576 832h64V128H576v704zM416 128H512v320H416a160 160 0 0 1 0-320z</StreamGeometry>
<StreamGeometry x:Key="Icons.Histories">M24 512A488 488 0 01512 24A488 488 0 011000 512A488 488 0 01512 1000A488 488 0 0124 512zm447-325v327L243 619l51 111 300-138V187H471z</StreamGeometry>
@@ -114,6 +114,7 @@
<StreamGeometry x:Key="Icons.ScrollToTop">M155 143h715v81H155V143zm358 94 358 369H662l1 278H363V605H155l358-369z</StreamGeometry>
<StreamGeometry x:Key="Icons.Search">M702 677 590 565a148 148 0 10-25 27L676 703zm-346-200a115 115 0 11115 115A115 115 0 01355 478z</StreamGeometry>
<StreamGeometry x:Key="Icons.Settings">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</StreamGeometry>
<StreamGeometry x:Key="Icons.ShaAndSubject">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</StreamGeometry>
<StreamGeometry x:Key="Icons.SoftwareUpdate">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</StreamGeometry>
<StreamGeometry x:Key="Icons.SquashIntoParent">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Stashes">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</StreamGeometry>
@@ -123,7 +124,7 @@
<StreamGeometry x:Key="Icons.Submodule">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Submodule.Add">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Submodules">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Subject">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Subject">M512 0C230 0 0 230 0 512c0 145 60 282 166 375L90 1024H512c282 0 512-230 512-512S794 0 512 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.SyntaxHighlight">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Tag">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</StreamGeometry>
<StreamGeometry x:Key="Icons.Tag.Add">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</StreamGeometry>

View File

@@ -763,6 +763,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULE</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Submodul hinzufügen</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">BRANCH</x:String>
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">Branch</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Relativen Pfad</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">De-initialisiere Submodul</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Untergeordnete Submodule fetchen</x:String>

View File

@@ -759,6 +759,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Add Submodule</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">BRANCH</x:String>
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">Branch</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Relative Path</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">De-initialize</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch nested submodules</x:String>

View File

@@ -136,8 +136,8 @@
<x:String x:Key="Text.CommitCM.InteractiveRebase.Edit" xml:space="preserve">Редактировать...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Fixup" xml:space="preserve">Исправить в родительском...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Manually" xml:space="preserve">Интерактивное перемещение ${0}$ в ${1}$</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Reword" xml:space="preserve">Имзенить комментарий...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Squash" xml:space="preserve">Втиуснуть в родительский...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Reword" xml:space="preserve">Изменить комментарий...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Squash" xml:space="preserve">Втиснуть в родительский...</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Влить в ${0}$</x:String>
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Влить ...</x:String>
<x:String x:Key="Text.CommitCM.PushRevision" xml:space="preserve">Выложить ${0}$ в ${1}$</x:String>
@@ -762,7 +762,8 @@
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">РЕВИЗИИ: </x:String>
<x:String x:Key="Text.Submodule" xml:space="preserve">ПОДМОДУЛИ</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Добавить подмодули</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">Ветка</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">ВЕТКА</x:String>
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">Ветка</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Каталог</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">Удалить подмодуль</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Извлечение вложенных подмодулей</x:String>

View File

@@ -763,6 +763,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">子模块</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">添加子模块</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">跟踪分支</x:String>
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">跟踪分支</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">相对路径</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">取消初始化</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">拉取子孙模块</x:String>

View File

@@ -763,6 +763,7 @@
<x:String x:Key="Text.Submodule" xml:space="preserve">子模組</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">新增子模組</x:String>
<x:String x:Key="Text.Submodule.Branch" xml:space="preserve">追蹤分支</x:String>
<x:String x:Key="Text.Submodule.CopyBranch" xml:space="preserve">追蹤分支</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">相對路徑</x:String>
<x:String x:Key="Text.Submodule.Deinit" xml:space="preserve">取消初始化</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">提取子模組</x:String>

View File

@@ -207,10 +207,7 @@ namespace SourceGit.ViewModels
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<Models.Change> changes, string saveTo)
@@ -357,7 +354,7 @@ namespace SourceGit.ViewModels
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;

View File

@@ -95,9 +95,7 @@ namespace SourceGit.ViewModels
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()

View File

@@ -356,25 +356,34 @@ namespace SourceGit.ViewModels
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 @@ namespace SourceGit.ViewModels
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;
}
}

View File

@@ -100,9 +100,7 @@ namespace SourceGit.ViewModels
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)

View File

@@ -193,9 +193,7 @@ namespace SourceGit.ViewModels
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)

View File

@@ -531,18 +531,12 @@ namespace SourceGit.ViewModels
public async Task<bool> 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()

View File

@@ -28,12 +28,7 @@ namespace SourceGit.Views
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);

View File

@@ -50,7 +50,9 @@ namespace SourceGit.Views
{
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));
});
}
}

View File

@@ -414,7 +414,7 @@ namespace SourceGit.Views
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 @@ namespace SourceGit.Views
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 @@ namespace SourceGit.Views
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 @@ namespace SourceGit.Views
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) =>
{

View File

@@ -349,7 +349,7 @@ namespace SourceGit.Views
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,
};

View File

@@ -254,13 +254,22 @@ namespace SourceGit.Views
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);
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 @@ namespace SourceGit.Views
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");