diff --git a/README.md b/README.md index 4ccde98f..e048bf78 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,20 @@ Opensource Git GUI client. > **Linux** only tested on **Ubuntu 22.04** on **X11**. -## How to use +## How to Use **To use this tool, you need to install Git(>=2.23.0) first.** You can download the latest stable from [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) or download workflow artifacts from [Github Actions](https://github.com/sourcegit-scm/sourcegit/actions) to try this app based on latest commits. +This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationData}/SourceGit"`, which is platform-dependent, to store user settings, downloaded avatars and crash logs. + +| OS | PATH | +| --- | --- | +| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` | +| Linux | `/home/USER_NAME/.config/SourceGit` | +| macOS | `/Users/USER_NAME/.config/SourceGit` | + For **Windows** users: * **MSYS Git is NOT supported**. Please use official [Git for Windows](https://git-scm.com/download/win) instead. @@ -64,7 +72,8 @@ This app supports open repository in external tools listed in the table below. | JetBrains Fleet | YES | YES | YES | FLEET_PATH | | Sublime Text | YES | YES | YES | SUBLIME_TEXT_PATH | -You can set the given environment variable for special tool if it can NOT be found by this app automatically. +> * You can set the given environment variable for special tool if it can NOT be found by this app automatically. +> * Installing `JetBrains Toolbox` will help this app to find other JetBrains tools installed on your device. ## Screenshots diff --git a/VERSION b/VERSION index f7b1c8ff..8d04a0f3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.9 \ No newline at end of file +8.10 \ No newline at end of file diff --git a/src/App.JsonCodeGen.cs b/src/App.JsonCodeGen.cs index af73a68e..7269b252 100644 --- a/src/App.JsonCodeGen.cs +++ b/src/App.JsonCodeGen.cs @@ -4,6 +4,7 @@ namespace SourceGit { [JsonSourceGenerationOptions(WriteIndented = true, IgnoreReadOnlyFields = true, IgnoreReadOnlyProperties = true)] [JsonSerializable(typeof(Models.Version))] + [JsonSerializable(typeof(Models.JetBrainsState))] [JsonSerializable(typeof(ViewModels.Preference))] internal partial class JsonCodeGen : JsonSerializerContext { } } diff --git a/src/App.axaml.cs b/src/App.axaml.cs index eeacb56d..eb4655c4 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -164,7 +164,7 @@ namespace SourceGit try { // Fetch lastest release information. - var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(2) }; + var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(5) }; var data = await client.GetStringAsync("https://sourcegit-scm.github.io/data/version.json"); // Parse json into Models.Version. diff --git a/src/Commands/IsConflictResolved.cs b/src/Commands/IsConflictResolved.cs new file mode 100644 index 00000000..49bc56fa --- /dev/null +++ b/src/Commands/IsConflictResolved.cs @@ -0,0 +1,20 @@ +namespace SourceGit.Commands +{ + public class IsConflictResolved : Command + { + public IsConflictResolved(string repo, Models.Change change) + { + var opt = new Models.DiffOption(change, true); + + WorkingDirectory = repo; + Context = repo; + Args = $"diff -a --ignore-cr-at-eol --check {opt}"; + } + + public bool Result() + { + var rs = ReadToEnd(); + return rs.IsSuccess; + } + } +} diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs index 70219dcf..8a72b35d 100644 --- a/src/Models/DiffResult.cs +++ b/src/Models/DiffResult.cs @@ -388,11 +388,11 @@ namespace SourceGit.Models } [GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")] - private static partial Regex indicatorRegex(); + private static partial Regex REG_INDICATOR(); private bool ProcessIndicatorForPatch(StringBuilder builder, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed) { - var match = indicatorRegex().Match(indicator.Content); + var match = REG_INDICATOR().Match(indicator.Content); var oldStart = int.Parse(match.Groups[1].Value); var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; var oldCount = 0; @@ -461,7 +461,7 @@ namespace SourceGit.Models private bool ProcessIndicatorForPatchSingleSide(StringBuilder builder, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool isOldSide, bool tailed) { - var match = indicatorRegex().Match(indicator.Content); + var match = REG_INDICATOR().Match(indicator.Content); var oldStart = int.Parse(match.Groups[1].Value); var newStart = int.Parse(match.Groups[2].Value) + ignoreRemoves - ignoreAdds; var oldCount = 0; diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs index cb50df58..2b49fae0 100644 --- a/src/Models/ExternalTool.cs +++ b/src/Models/ExternalTool.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; using Avalonia.Media.Imaging; using Avalonia.Platform; @@ -19,8 +21,24 @@ namespace SourceGit.Models { get { - var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{Icon}.png", UriKind.RelativeOrAbsolute)); - return new Bitmap(icon); + if (_isFirstTimeGetIcon) + { + _isFirstTimeGetIcon = false; + + if (!string.IsNullOrWhiteSpace(Icon)) + { + try + { + var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{Icon}.png", UriKind.RelativeOrAbsolute)); + _iconImage = new Bitmap(icon); + } + catch + { + } + } + } + + return _iconImage; } } @@ -34,6 +52,41 @@ namespace SourceGit.Models UseShellExecute = false, }); } + + private bool _isFirstTimeGetIcon = true; + private Bitmap _iconImage = null; + } + + public class JetBrainsState + { + [JsonPropertyName("version")] + public int Version { get; set; } = 0; + [JsonPropertyName("appVersion")] + public string AppVersion { get; set; } = string.Empty; + [JsonPropertyName("tools")] + public List Tools { get; set; } = new List(); + } + + public class JetBrainsTool + { + [JsonPropertyName("channelId")] + public string ChannelId { get; set; } + [JsonPropertyName("toolId")] + public string ToolId { get; set; } + [JsonPropertyName("productCode")] + public string ProductCode { get; set; } + [JsonPropertyName("tag")] + public string Tag { get; set; } + [JsonPropertyName("displayName")] + public string DisplayName { get; set; } + [JsonPropertyName("displayVersion")] + public string DisplayVersion { get; set; } + [JsonPropertyName("buildNumber")] + public string BuildNumber { get; set; } + [JsonPropertyName("installLocation")] + public string InstallLocation { get; set; } + [JsonPropertyName("launchCommand")] + public string LaunchCommand { get; set; } } public class ExternalToolsFinder @@ -44,26 +97,6 @@ namespace SourceGit.Models private set; } = new List(); - public void VSCode(Func platform_finder) - { - TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE_PATH", platform_finder); - } - - public void VSCodeInsiders(Func platform_finder) - { - TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS_PATH", platform_finder); - } - - public void Fleet(Func platform_finder) - { - TryAdd("JetBrains Fleet", "fleet", "\"{0}\"", "FLEET_PATH", platform_finder); - } - - public void SublimeText(Func platform_finder) - { - TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT_PATH", platform_finder); - } - public void TryAdd(string name, string icon, string args, string env, Func finder) { var path = Environment.GetEnvironmentVariable(env); @@ -79,8 +112,52 @@ namespace SourceGit.Models Name = name, Icon = icon, OpenCmdArgs = args, - Executable = path, + Executable = path }); } + + public void VSCode(Func platform_finder) + { + TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE_PATH", platform_finder); + } + + public void VSCodeInsiders(Func platform_finder) + { + TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS_PATH", platform_finder); + } + + public void Fleet(Func platform_finder) + { + TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET_PATH", platform_finder); + } + + public void SublimeText(Func platform_finder) + { + TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT_PATH", platform_finder); + } + + public void FindJetBrainsFromToolbox(Func platform_finder) + { + var exclude = new List { "fleet", "dotmemory", "dottrace", "resharper-u", "androidstudio" }; + var supported_icons = new List { "CL", "DB", "DL", "DS", "GO", "IC", "IU", "JB", "PC", "PS", "PY", "QA", "QD", "RD", "RM", "RR", "WRS", "WS" }; + var state = Path.Combine(platform_finder(), "state.json"); + if (File.Exists(state)) + { + var stateData = JsonSerializer.Deserialize(File.ReadAllText(state), JsonCodeGen.Default.JetBrainsState); + foreach (var tool in stateData.Tools) + { + if (exclude.Contains(tool.ToolId.ToLowerInvariant())) + continue; + + Founded.Add(new ExternalTool + { + Name = $"{tool.DisplayName} {tool.DisplayVersion}", + Icon = supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : $"JetBrains/JB", + OpenCmdArgs = "\"{0}\"", + Executable = Path.Combine(tool.InstallLocation, tool.LaunchCommand), + }); + } + } + } } } diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index 176941cc..338f91d4 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -57,7 +57,8 @@ namespace SourceGit.Native var finder = new Models.ExternalToolsFinder(); finder.VSCode(() => FindExecutable("code")); finder.VSCodeInsiders(() => FindExecutable("code-insiders")); - finder.Fleet(FindJetBrainFleet); + finder.Fleet(FindJetBrainsFleet); + finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox"); finder.SublimeText(() => FindExecutable("subl")); return finder.Founded; } @@ -174,7 +175,7 @@ namespace SourceGit.Native return null; } - private string FindJetBrainFleet() + private string FindJetBrainsFleet() { var path = $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox/apps/fleet/bin/Fleet"; return File.Exists(path) ? path : FindExecutable("fleet"); diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index f4ddc2ea..450b87ba 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -33,6 +33,7 @@ namespace SourceGit.Native finder.VSCode(() => "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"); finder.VSCodeInsiders(() => "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/Applications/Fleet.app/Contents/MacOS/Fleet"); + finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/Library/Application Support/JetBrains/Toolbox"); finder.SublimeText(() => "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl"); return finder.Founded; } diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 2d22ac42..8c4ab022 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -111,6 +111,7 @@ namespace SourceGit.Native finder.VSCode(FindVSCode); finder.VSCodeInsiders(FindVSCodeInsiders); finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe"); + finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox"); finder.SublimeText(FindSublimeText); return finder.Founded; } diff --git a/src/Resources/ExternalToolIcons/JetBrains/CL.png b/src/Resources/ExternalToolIcons/JetBrains/CL.png new file mode 100644 index 00000000..834a4120 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/CL.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/DB.png b/src/Resources/ExternalToolIcons/JetBrains/DB.png new file mode 100644 index 00000000..44d4f73d Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/DB.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/DL.png b/src/Resources/ExternalToolIcons/JetBrains/DL.png new file mode 100644 index 00000000..3610740f Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/DL.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/DS.png b/src/Resources/ExternalToolIcons/JetBrains/DS.png new file mode 100644 index 00000000..f969b98b Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/DS.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/GO.png b/src/Resources/ExternalToolIcons/JetBrains/GO.png new file mode 100644 index 00000000..83cc84f7 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/GO.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/IC.png b/src/Resources/ExternalToolIcons/JetBrains/IC.png new file mode 100644 index 00000000..243c4a38 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/IC.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/IU.png b/src/Resources/ExternalToolIcons/JetBrains/IU.png new file mode 100644 index 00000000..243c4a38 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/IU.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/JB.png b/src/Resources/ExternalToolIcons/JetBrains/JB.png new file mode 100644 index 00000000..85ead673 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/JB.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/PC.png b/src/Resources/ExternalToolIcons/JetBrains/PC.png new file mode 100644 index 00000000..1755f7de Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/PC.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/PS.png b/src/Resources/ExternalToolIcons/JetBrains/PS.png new file mode 100644 index 00000000..b988ddde Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/PS.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/PY.png b/src/Resources/ExternalToolIcons/JetBrains/PY.png new file mode 100644 index 00000000..1755f7de Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/PY.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/QA.png b/src/Resources/ExternalToolIcons/JetBrains/QA.png new file mode 100644 index 00000000..9b45d085 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/QA.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/QD.png b/src/Resources/ExternalToolIcons/JetBrains/QD.png new file mode 100644 index 00000000..109ac1ef Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/QD.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/RD.png b/src/Resources/ExternalToolIcons/JetBrains/RD.png new file mode 100644 index 00000000..0732f09e Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/RD.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/RM.png b/src/Resources/ExternalToolIcons/JetBrains/RM.png new file mode 100644 index 00000000..b4815546 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/RM.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/RR.png b/src/Resources/ExternalToolIcons/JetBrains/RR.png new file mode 100644 index 00000000..16c57d15 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/RR.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/WRS.png b/src/Resources/ExternalToolIcons/JetBrains/WRS.png new file mode 100644 index 00000000..09a299f9 Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/WRS.png differ diff --git a/src/Resources/ExternalToolIcons/JetBrains/WS.png b/src/Resources/ExternalToolIcons/JetBrains/WS.png new file mode 100644 index 00000000..80b1a23b Binary files /dev/null and b/src/Resources/ExternalToolIcons/JetBrains/WS.png differ diff --git a/src/Resources/ExternalToolIcons/rider.png b/src/Resources/ExternalToolIcons/rider.png new file mode 100644 index 00000000..6ab3b8cb Binary files /dev/null and b/src/Resources/ExternalToolIcons/rider.png differ diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 55c997c4..fed4f46b 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -211,6 +211,7 @@ Go to next page Create new page REPOSITORY + Force to reload this repository Stage/Unstage selected changes Toggle commit search Switch to 'Changes' @@ -426,11 +427,13 @@ Sort Changes Amend + You can stage this file now. COMMIT COMMIT & PUSH Enter commit message CTRL + Enter CONFLICTS DETECTED + FILE CONFLICTS ARE RESOLVED RECENT INPUT MESSAGES INCLUDE UNTRACKED FILES MESSAGE HISTORIES diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index a6fdb67f..c2500d54 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -211,6 +211,7 @@ 切换到下一个页面 新建页面 仓库页面快捷键 + 重新加载仓库状态 将选中的变更暂存或从暂存列表中移除 打开/关闭历史搜索 显示本地更改 @@ -426,11 +427,13 @@ 排序 本地更改 修补(--amend) + 现在您已可将其加入暂存区中 提交 提交并推送 填写提交信息 CTRL + Enter 检测到冲突 + 文件冲突已解决 最近输入的提交信息 显示未跟踪文件 历史提交信息 diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml index a1549a13..866fc987 100644 --- a/src/Resources/Styles.axaml +++ b/src/Resources/Styles.axaml @@ -88,9 +88,9 @@ + Command="{Binding $parent[SelectableTextBlock].Copy}" + IsEnabled="{Binding $parent[SelectableTextBlock].CanCopy}" + InputGesture="{x:Static TextBox.CopyGesture}"> @@ -254,7 +254,7 @@ + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" + CornerRadius="{TemplateBinding CornerRadius}" + ContentTemplate="{TemplateBinding ContentTemplate}" + Content="{TemplateBinding Content}" + Padding="{TemplateBinding Padding}" + VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" + HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" /> + Width="4" + HorizontalAlignment="Left" VerticalAlignment="Stretch" + IsHitTestVisible="False" + IsVisible="{TemplateBinding IsSelected}"/> @@ -529,16 +529,16 @@ + Margin="8,4" + MaxWidth="{TemplateBinding MaxWidth}" + MinHeight="{TemplateBinding MinHeight}" + HorizontalAlignment="{TemplateBinding HorizontalAlignment}"> + ItemsPanel="{TemplateBinding ItemsPanel}" + Margin="{DynamicResource MenuFlyoutScrollerMargin}" + KeyboardNavigation.TabNavigation="Continue" + Grid.IsSharedSizeScope="True" /> @@ -557,20 +557,20 @@ + Margin="4" + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="0" + Padding="4,2" + CornerRadius="{TemplateBinding CornerRadius}"> + Theme="{StaticResource FluentMenuScrollViewer}" + VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"> + ItemsPanel="{TemplateBinding ItemsPanel}" + Margin="{DynamicResource MenuFlyoutScrollerMargin}" + KeyboardNavigation.TabNavigation="Continue" + Grid.IsSharedSizeScope="True" /> @@ -581,18 +581,18 @@ @@ -906,15 +906,15 @@ + Width="{TemplateBinding Width}" + Height="{TemplateBinding Height}" + HorizontalAlignment="Center" + VerticalAlignment="Center"> + Data="M 4 0 L 8 4 L 4 8 Z" + Fill="{DynamicResource TreeViewItemForeground}" + HorizontalAlignment="Center" + VerticalAlignment="Center"/> @@ -933,11 +933,11 @@ @@ -949,7 +949,7 @@ - + - + @@ -109,11 +78,12 @@ - - - - - + + + + + + + + + + + + +