diff --git a/.editorconfig b/.editorconfig
index 22c741b9..f3c9a7bf 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -71,20 +71,20 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
-dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
-dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# private static fields should have s_ prefix
dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion
-dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
+dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style
-dotnet_naming_symbols.private_static_fields.applicable_kinds = field
+dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
@@ -93,14 +93,14 @@ dotnet_naming_style.private_static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
-dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
-dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
diff --git a/README.md b/README.md
index 8c12c646..f9ba3072 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ You can find the current translation status in [TRANSLATION.md](https://github.c
**To use this tool, you need to install Git(>=2.25.1) 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.
+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.
@@ -93,7 +93,7 @@ For **macOS** users:
brew tap ybeapps/homebrew-sourcegit
brew install --cask --no-quarantine sourcegit
```
-* If you want to install `SourceGit.app` from Github Release manually, you need run following command to make sure it works:
+* If you want to install `SourceGit.app` from GitHub Release manually, you need run following command to make sure it works:
```shell
sudo xattr -cr /Applications/SourceGit.app
```
diff --git a/TRANSLATION.md b/TRANSLATION.md
index 94ff684b..1fa3259d 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -6,49 +6,29 @@ This document shows the translation status of each locale file in the repository
### 
-### 
+### 
+
+### 
-Missing keys in de_DE.axaml
+Missing keys in es_ES.axaml
-- Text.BranchCM.ResetToSelectedCommit
-- Text.CommitDetail.Changes.Count
-- Text.CreateBranch.OverwriteExisting
-- Text.DeinitSubmodule
-- Text.DeinitSubmodule.Force
-- Text.DeinitSubmodule.Path
-- Text.Diff.Submodule.Deleted
-- Text.GitFlow.FinishWithPush
-- Text.GitFlow.FinishWithSquash
-- Text.Hotkeys.Global.SwitchWorkspace
-- Text.Hotkeys.Global.SwitchTab
-- Text.Hotkeys.TextEditor.OpenExternalMergeTool
-- Text.Launcher.Workspaces
-- Text.Launcher.Pages
-- Text.Pull.RecurseSubmodules
-- Text.Repository.ClearStashes
-- Text.Repository.ShowSubmodulesAsTree
-- Text.ResetWithoutCheckout
-- Text.ResetWithoutCheckout.MoveTo
-- Text.ResetWithoutCheckout.Target
-- Text.Submodule.Deinit
-- Text.Submodule.Status
-- Text.Submodule.Status.Modified
-- Text.Submodule.Status.NotInited
-- Text.Submodule.Status.RevisionChanged
-- Text.Submodule.Status.Unmerged
-- Text.Submodule.URL
-- Text.WorkingCopy.ResetAuthor
+- Text.CommitCM.PushRevision
+- Text.Merge.Edit
+- Text.Push.Revision
+- Text.Push.Revision.Title
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
+- Text.WorkingCopy.AddToGitIgnore.InFolder
-### 
-
-### 
+### 
Missing keys in fr_FR.axaml
+- Text.Avatar.Load
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
@@ -58,9 +38,12 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
@@ -80,8 +63,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@@ -93,6 +79,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
@@ -104,6 +92,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
@@ -113,12 +102,16 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in it_IT.axaml
+- Text.Avatar.Load
- Text.BranchCM.ResetToSelectedCommit
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
@@ -129,21 +122,28 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.Global.SwitchTab
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.ClearStashes
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.Submodule.Deinit
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ResetAuthor
-### 
+### 
Missing keys in ja_JP.axaml
+- Text.Avatar.Load
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
@@ -154,9 +154,12 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
@@ -176,8 +179,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@@ -185,12 +191,13 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.FilterCommits
- Text.Repository.Search.ByContent
- Text.Repository.ShowSubmodulesAsTree
-- Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
@@ -202,6 +209,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
@@ -211,7 +219,7 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in pt_BR.axaml
@@ -222,6 +230,7 @@ This document shows the translation status of each locale file in the repository
- Text.ApplyStash.DropAfterApply
- Text.ApplyStash.RestoreIndex
- Text.ApplyStash.Stash
+- Text.Avatar.Load
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
@@ -234,12 +243,15 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.ResetToSelectedCommit
- Text.BranchUpstreamInvalid
- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
- Text.Clone.RecurseSubmodules
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.Merge
- Text.CommitCM.MergeMultiple
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CommitDetail.Files.Search
- Text.CommitDetail.Info.Children
@@ -280,6 +292,7 @@ This document shows the translation status of each locale file in the repository
- Text.InProgress.Revert.Head
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Merge.Source
- Text.MergeMultiple
- Text.MergeMultiple.CommitChanges
@@ -293,6 +306,8 @@ This document shows the translation status of each locale file in the repository
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Preferences.Git.SSLVerify
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@@ -308,8 +323,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.ShowSubmodulesAsTree
- Text.Repository.Skip
- Text.Repository.Tags.OrderByCreatorDate
-- Text.Repository.Tags.OrderByNameAsc
-- Text.Repository.Tags.OrderByNameDes
+- Text.Repository.Tags.OrderByName
- Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs
@@ -322,8 +336,8 @@ This document shows the translation status of each locale file in the repository
- Text.SetUpstream.Unset
- Text.SetUpstream.Upstream
- Text.SHALinkCM.NavigateTo
-- Text.Stash.AutoRestore
-- Text.Stash.AutoRestore.Tip
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.StashCM.SaveAsPatch
- Text.Submodule.Deinit
- Text.Submodule.Status
@@ -336,6 +350,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.CommitToEdit
- Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
@@ -347,22 +362,14 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
-
-Missing keys in ru_RU.axaml
-
-- Text.BranchCM.CompareWithCurrent
-- Text.Repository.ClearStashes
-- Text.WorkingCopy.ResetAuthor
-
-
-
-### 
+### 
Missing keys in ta_IN.axaml
+- Text.Avatar.Load
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
@@ -373,9 +380,12 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.Git.PreferredMergeMode
@@ -395,8 +405,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@@ -408,6 +421,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
@@ -420,6 +435,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
@@ -428,11 +444,12 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in uk_UA.axaml
+- Text.Avatar.Load
- Text.Bisect
- Text.Bisect.Abort
- Text.Bisect.Bad
@@ -442,9 +459,12 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
- Text.Checkout.RecurseSubmodules
+- Text.Checkout.WithFastForward
+- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
+- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.CommitMessageTextBox.SubjectCount
- Text.ConfigureWorkspace.Name
@@ -460,8 +480,11 @@ This document shows the translation status of each locale file in the repository
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
- Text.Launcher.Workspaces
- Text.Launcher.Pages
+- Text.Merge.Edit
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
+- Text.Push.Revision
+- Text.Push.Revision.Title
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
@@ -473,6 +496,8 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.Stash.Mode
+- Text.StashCM.CopyMessage
- Text.Submodule.Deinit
- Text.Submodule.Status
- Text.Submodule.Status.Modified
@@ -484,6 +509,7 @@ This document shows the translation status of each locale file in the repository
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
+- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ResetAuthor
diff --git a/VERSION b/VERSION
index 67a3d7e0..11692c6b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2025.20
\ No newline at end of file
+2025.23
\ No newline at end of file
diff --git a/build/README.md b/build/README.md
index b4358a55..17305edf 100644
--- a/build/README.md
+++ b/build/README.md
@@ -12,4 +12,4 @@
dotnet publish -c Release -r $RUNTIME_IDENTIFIER -o $DESTINATION_FOLDER src/SourceGit.csproj
```
> [!NOTE]
-> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replece the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
+> Please replace the `$RUNTIME_IDENTIFIER` with one of `win-x64`,`win-arm64`,`linux-x64`,`linux-arm64`,`osx-x64`,`osx-arm64`, and replace the `$DESTINATION_FOLDER` with the real path that will store the output executable files.
diff --git a/src/App.axaml.cs b/src/App.axaml.cs
index 411f5cfb..6b42700d 100644
--- a/src/App.axaml.cs
+++ b/src/App.axaml.cs
@@ -301,7 +301,7 @@ namespace SourceGit
return await clipboard.GetTextAsync();
}
}
- return default;
+ return null;
}
public static string Text(string key, params object[] args)
@@ -323,8 +323,7 @@ namespace SourceGit
icon.Height = 12;
icon.Stretch = Stretch.Uniform;
- var geo = Current?.FindResource(key) as StreamGeometry;
- if (geo != null)
+ if (Current?.FindResource(key) is StreamGeometry geo)
icon.Data = geo;
return icon;
@@ -338,7 +337,7 @@ namespace SourceGit
return null;
}
- public static ViewModels.Launcher GetLauncer()
+ public static ViewModels.Launcher GetLauncher()
{
return Current is App app ? app._launcher : null;
}
@@ -522,7 +521,7 @@ namespace SourceGit
private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop)
{
var args = desktop.Args;
- if (args == null || args.Length <= 1 || !args[0].Equals("--core-editor", StringComparison.Ordinal))
+ if (args is not { Length: > 1 } || !args[0].Equals("--core-editor", StringComparison.Ordinal))
return false;
var file = args[1];
@@ -532,8 +531,8 @@ namespace SourceGit
return true;
}
- var editor = new Views.StandaloneCommitMessageEditor();
- editor.SetFile(file);
+ var editor = new Views.CommitMessageEditor();
+ editor.AsStandalone(file);
desktop.MainWindow = editor;
return true;
}
@@ -682,8 +681,7 @@ namespace SourceGit
}
var name = sb.ToString();
- var idx = name.IndexOf('#');
- if (idx >= 0)
+ if (name.Contains('#', StringComparison.Ordinal))
{
if (!name.Equals("fonts:Inter#Inter", StringComparison.Ordinal) &&
!name.Equals("fonts:SourceGit#JetBrains Mono", StringComparison.Ordinal))
diff --git a/src/App.manifest b/src/App.manifest
index b3bc3bdf..11a2ff11 100644
--- a/src/App.manifest
+++ b/src/App.manifest
@@ -1,7 +1,7 @@
diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs
index 0bb45c98..1fc51fa4 100644
--- a/src/Commands/Blame.cs
+++ b/src/Commands/Blame.cs
@@ -51,7 +51,7 @@ namespace SourceGit.Commands
private void ParseLine(string line)
{
- if (line.IndexOf('\0', StringComparison.Ordinal) >= 0)
+ if (line.Contains('\0', StringComparison.Ordinal))
{
_result.IsBinary = true;
_result.LineInfos.Clear();
@@ -89,7 +89,7 @@ namespace SourceGit.Commands
private readonly Models.BlameData _result = new Models.BlameData();
private readonly StringBuilder _content = new StringBuilder();
- private readonly string _dateFormat = Models.DateTimeFormat.Actived.DateOnly;
+ private readonly string _dateFormat = Models.DateTimeFormat.Active.DateOnly;
private string _lastSHA = string.Empty;
private bool _needUnifyCommitSHA = false;
private int _minSHALen = 64;
diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs
index 9bfa1c15..975922fc 100644
--- a/src/Commands/Command.cs
+++ b/src/Commands/Command.cs
@@ -194,7 +194,7 @@ namespace SourceGit.Commands
private void HandleOutput(string line, List errs)
{
- line = line ?? string.Empty;
+ line ??= string.Empty;
Log?.AppendLine(line);
// Lines to hide in error message.
diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs
index 17410bc9..1585e7e3 100644
--- a/src/Commands/Commit.cs
+++ b/src/Commands/Commit.cs
@@ -34,6 +34,6 @@ namespace SourceGit.Commands
return succ;
}
- private string _tmpFile = string.Empty;
+ private readonly string _tmpFile;
}
}
diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs
index 7b4a496d..c88e087a 100644
--- a/src/Commands/CompareRevisions.cs
+++ b/src/Commands/CompareRevisions.cs
@@ -39,7 +39,7 @@ namespace SourceGit.Commands
foreach (var line in lines)
ParseLine(line);
- _changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
+ _changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
return _changes;
}
diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs
index e621ed7d..18d2ba93 100644
--- a/src/Commands/LFS.cs
+++ b/src/Commands/LFS.cs
@@ -10,7 +10,7 @@ namespace SourceGit.Commands
[GeneratedRegex(@"^(.+)\s+([\w.]+)\s+\w+:(\d+)$")]
private static partial Regex REG_LOCK();
- class SubCmd : Command
+ private class SubCmd : Command
{
public SubCmd(string repo, string args, Models.ICommandLog log)
{
diff --git a/src/Commands/Merge.cs b/src/Commands/Merge.cs
index b08377b9..32898593 100644
--- a/src/Commands/Merge.cs
+++ b/src/Commands/Merge.cs
@@ -5,11 +5,20 @@ namespace SourceGit.Commands
{
public class Merge : Command
{
- public Merge(string repo, string source, string mode)
+ public Merge(string repo, string source, string mode, bool edit)
{
WorkingDirectory = repo;
Context = repo;
- Args = $"merge --progress {source} {mode}";
+ Editor = EditorType.CoreEditor;
+
+ var builder = new StringBuilder();
+ builder.Append("merge --progress ");
+ builder.Append(edit ? "--edit " : "--no-edit ");
+ builder.Append(source);
+ builder.Append(' ');
+ builder.Append(mode);
+
+ Args = builder.ToString();
}
public Merge(string repo, List targets, bool autoCommit, string strategy)
diff --git a/src/Commands/MergeTool.cs b/src/Commands/MergeTool.cs
index f67f5e48..fc6d0d75 100644
--- a/src/Commands/MergeTool.cs
+++ b/src/Commands/MergeTool.cs
@@ -24,7 +24,7 @@ namespace SourceGit.Commands
if (!File.Exists(toolPath))
{
- Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT found external merge tool in '{toolPath}'!"));
+ Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!"));
return false;
}
@@ -54,7 +54,7 @@ namespace SourceGit.Commands
if (!File.Exists(toolPath))
{
- Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT found external diff tool in '{toolPath}'!"));
+ Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!"));
return false;
}
diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs
index d0ecd322..f268d709 100644
--- a/src/Commands/QueryBranches.cs
+++ b/src/Commands/QueryBranches.cs
@@ -48,16 +48,12 @@ namespace SourceGit.Commands
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
{
b.IsUpstreamGone = false;
-
- if (b.TrackStatus == null)
- b.TrackStatus = new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
+ b.TrackStatus ??= new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
}
else
{
b.IsUpstreamGone = true;
-
- if (b.TrackStatus == null)
- b.TrackStatus = new Models.BranchTrackStatus();
+ b.TrackStatus ??= new Models.BranchTrackStatus();
}
}
}
diff --git a/src/Commands/QueryCommitsForInteractiveRebase.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs
index 615060a5..9f238319 100644
--- a/src/Commands/QueryCommitsForInteractiveRebase.cs
+++ b/src/Commands/QueryCommitsForInteractiveRebase.cs
@@ -90,6 +90,6 @@ namespace SourceGit.Commands
private List _commits = [];
private Models.InteractiveCommit _current = null;
- private string _boundary = "";
+ private readonly string _boundary;
}
}
diff --git a/src/Commands/QueryFileContent.cs b/src/Commands/QueryFileContent.cs
index f887859c..83d0a575 100644
--- a/src/Commands/QueryFileContent.cs
+++ b/src/Commands/QueryFileContent.cs
@@ -35,5 +35,39 @@ namespace SourceGit.Commands
return stream;
}
+
+ public static Stream FromLFS(string repo, string oid, long size)
+ {
+ var starter = new ProcessStartInfo();
+ starter.WorkingDirectory = repo;
+ starter.FileName = Native.OS.GitExecutable;
+ starter.Arguments = $"lfs smudge";
+ starter.UseShellExecute = false;
+ starter.CreateNoWindow = true;
+ starter.WindowStyle = ProcessWindowStyle.Hidden;
+ starter.RedirectStandardInput = true;
+ starter.RedirectStandardOutput = true;
+
+ var stream = new MemoryStream();
+ try
+ {
+ var proc = new Process() { StartInfo = starter };
+ proc.Start();
+ proc.StandardInput.WriteLine("version https://git-lfs.github.com/spec/v1");
+ proc.StandardInput.WriteLine($"oid sha256:{oid}");
+ proc.StandardInput.WriteLine($"size {size}");
+ proc.StandardOutput.BaseStream.CopyTo(stream);
+ proc.WaitForExit();
+ proc.Close();
+
+ stream.Position = 0;
+ }
+ catch (Exception e)
+ {
+ App.RaiseException(repo, $"Failed to query file content: {e}");
+ }
+
+ return stream;
+ }
}
}
diff --git a/src/Commands/QueryFileSize.cs b/src/Commands/QueryFileSize.cs
index 9016d826..30af7715 100644
--- a/src/Commands/QueryFileSize.cs
+++ b/src/Commands/QueryFileSize.cs
@@ -16,9 +16,6 @@ namespace SourceGit.Commands
public long Result()
{
- if (_result != 0)
- return _result;
-
var rs = ReadToEnd();
if (rs.IsSuccess)
{
@@ -29,7 +26,5 @@ namespace SourceGit.Commands
return 0;
}
-
- private readonly long _result = 0;
}
}
diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs
index b4067aaf..2b8987b6 100644
--- a/src/Commands/QueryStashes.cs
+++ b/src/Commands/QueryStashes.cs
@@ -9,7 +9,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
- Args = "stash list --format=%H%n%P%n%ct%n%gd%n%s";
+ Args = $"stash list -z --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B\"";
}
public List Result()
@@ -19,55 +19,50 @@ namespace SourceGit.Commands
if (!rs.IsSuccess)
return outs;
- var nextPartIdx = 0;
- var start = 0;
- var end = rs.StdOut.IndexOf('\n', start);
- while (end > 0)
+ var items = rs.StdOut.Split('\0', StringSplitOptions.RemoveEmptyEntries);
+ foreach (var item in items)
{
- var line = rs.StdOut.Substring(start, end - start);
+ var current = new Models.Stash();
- switch (nextPartIdx)
+ var nextPartIdx = 0;
+ var start = 0;
+ var end = item.IndexOf('\n', start);
+ while (end > 0 && nextPartIdx < 4)
{
- case 0:
- _current = new Models.Stash() { SHA = line };
- outs.Add(_current);
- break;
- case 1:
- ParseParent(line);
- break;
- case 2:
- _current.Time = ulong.Parse(line);
- break;
- case 3:
- _current.Name = line;
- break;
- case 4:
- _current.Message = line;
+ var line = item.Substring(start, end - start);
+
+ switch (nextPartIdx)
+ {
+ case 0:
+ current.SHA = line;
+ break;
+ case 1:
+ if (line.Length > 6)
+ current.Parents.AddRange(line.Split(' ', StringSplitOptions.RemoveEmptyEntries));
+ break;
+ case 2:
+ current.Time = ulong.Parse(line);
+ break;
+ case 3:
+ current.Name = line;
+ break;
+ }
+
+ nextPartIdx++;
+
+ start = end + 1;
+ if (start >= item.Length - 1)
break;
+
+ end = item.IndexOf('\n', start);
}
- nextPartIdx++;
- if (nextPartIdx > 4)
- nextPartIdx = 0;
+ if (start < item.Length)
+ current.Message = item.Substring(start);
- start = end + 1;
- end = rs.StdOut.IndexOf('\n', start);
+ outs.Add(current);
}
-
- if (start < rs.StdOut.Length)
- _current.Message = rs.StdOut.Substring(start);
-
return outs;
}
-
- private void ParseParent(string data)
- {
- if (data.Length < 8)
- return;
-
- _current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
- }
-
- private Models.Stash _current = null;
}
}
diff --git a/src/Commands/QueryTags.cs b/src/Commands/QueryTags.cs
index 4b706439..896d555e 100644
--- a/src/Commands/QueryTags.cs
+++ b/src/Commands/QueryTags.cs
@@ -24,7 +24,7 @@ namespace SourceGit.Commands
var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries);
foreach (var record in records)
{
- var subs = record.Split('\0', StringSplitOptions.None);
+ var subs = record.Split('\0');
if (subs.Length != 6)
continue;
diff --git a/src/Commands/SaveRevisionFile.cs b/src/Commands/SaveRevisionFile.cs
index 99e89093..64e8f8a5 100644
--- a/src/Commands/SaveRevisionFile.cs
+++ b/src/Commands/SaveRevisionFile.cs
@@ -10,15 +10,15 @@ namespace SourceGit.Commands
{
public static void Run(string repo, string revision, string file, string saveTo)
{
+ var dir = Path.GetDirectoryName(saveTo);
+ if (!Directory.Exists(dir))
+ Directory.CreateDirectory(dir);
+
var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result();
if (isLFSFiltered)
{
- var tmpFile = saveTo + ".tmp";
- if (ExecCmd(repo, $"show {revision}:\"{file}\"", tmpFile))
- {
- ExecCmd(repo, $"lfs smudge", saveTo, tmpFile);
- }
- File.Delete(tmpFile);
+ var pointerStream = QueryFileContent.Run(repo, revision, file);
+ ExecCmd(repo, $"lfs smudge", saveTo, pointerStream);
}
else
{
@@ -26,7 +26,7 @@ namespace SourceGit.Commands
}
}
- private static bool ExecCmd(string repo, string args, string outputFile, string inputFile = null)
+ private static void ExecCmd(string repo, string args, string outputFile, Stream input = null)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -45,27 +45,11 @@ namespace SourceGit.Commands
{
var proc = new Process() { StartInfo = starter };
proc.Start();
-
- if (inputFile != null)
- {
- using (StreamReader sr = new StreamReader(inputFile))
- {
- while (true)
- {
- var line = sr.ReadLine();
- if (line == null)
- break;
- proc.StandardInput.WriteLine(line);
- }
- }
- }
-
+ if (input != null)
+ proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
proc.StandardOutput.BaseStream.CopyTo(sw);
proc.WaitForExit();
- var rs = proc.ExitCode == 0;
proc.Close();
-
- return rs;
}
catch (Exception e)
{
@@ -73,7 +57,6 @@ namespace SourceGit.Commands
{
App.RaiseException(repo, "Save file failed: " + e.Message);
});
- return false;
}
}
}
diff --git a/src/Commands/UnstageChangesForAmend.cs b/src/Commands/UnstageChangesForAmend.cs
index c930f136..19def067 100644
--- a/src/Commands/UnstageChangesForAmend.cs
+++ b/src/Commands/UnstageChangesForAmend.cs
@@ -23,13 +23,11 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t");
_patchBuilder.Append(c.OriginalPath);
- _patchBuilder.Append("\n");
}
else if (c.Index == Models.ChangeState.Added)
{
_patchBuilder.Append("0 0000000000000000000000000000000000000000\t");
_patchBuilder.Append(c.Path);
- _patchBuilder.Append("\n");
}
else if (c.Index == Models.ChangeState.Deleted)
{
@@ -37,7 +35,6 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t");
_patchBuilder.Append(c.Path);
- _patchBuilder.Append("\n");
}
else
{
@@ -46,8 +43,9 @@ namespace SourceGit.Commands
_patchBuilder.Append(c.DataForAmend.ObjectHash);
_patchBuilder.Append("\t");
_patchBuilder.Append(c.Path);
- _patchBuilder.Append("\n");
}
+
+ _patchBuilder.Append("\n");
}
}
diff --git a/src/Converters/ObjectConverters.cs b/src/Converters/ObjectConverters.cs
new file mode 100644
index 00000000..f7c57764
--- /dev/null
+++ b/src/Converters/ObjectConverters.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using Avalonia.Data.Converters;
+
+namespace SourceGit.Converters
+{
+ public static class ObjectConverters
+ {
+ public class IsTypeOfConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value == null || parameter == null)
+ return false;
+
+ return value.GetType().IsAssignableTo((Type)parameter);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return new NotImplementedException();
+ }
+ }
+
+ public static readonly IsTypeOfConverter IsTypeOf = new IsTypeOfConverter();
+ }
+}
diff --git a/src/Models/AvatarManager.cs b/src/Models/AvatarManager.cs
index a9ef3eb4..bc9fbe95 100644
--- a/src/Models/AvatarManager.cs
+++ b/src/Models/AvatarManager.cs
@@ -17,7 +17,7 @@ namespace SourceGit.Models
{
public interface IAvatarHost
{
- void OnAvatarResourceChanged(string email);
+ void OnAvatarResourceChanged(string email, Bitmap image);
}
public partial class AvatarManager
@@ -26,10 +26,7 @@ namespace SourceGit.Models
{
get
{
- if (_instance == null)
- _instance = new AvatarManager();
-
- return _instance;
+ return _instance ??= new AvatarManager();
}
}
@@ -38,7 +35,7 @@ namespace SourceGit.Models
[GeneratedRegex(@"^(?:(\d+)\+)?(.+?)@.+\.github\.com$")]
private static partial Regex REG_GITHUB_USER_EMAIL();
- private object _synclock = new object();
+ private readonly Lock _synclock = new();
private string _storePath;
private List _avatars = new List();
private Dictionary _resources = new Dictionary();
@@ -119,7 +116,7 @@ namespace SourceGit.Models
Dispatcher.UIThread.InvokeAsync(() =>
{
_resources[email] = img;
- NotifyResourceChanged(email);
+ NotifyResourceChanged(email, img);
});
}
@@ -144,14 +141,13 @@ namespace SourceGit.Models
if (_defaultAvatars.Contains(email))
return null;
- if (_resources.ContainsKey(email))
- _resources.Remove(email);
+ _resources.Remove(email);
var localFile = Path.Combine(_storePath, GetEmailHash(email));
if (File.Exists(localFile))
File.Delete(localFile);
- NotifyResourceChanged(email);
+ NotifyResourceChanged(email, null);
}
else
{
@@ -179,13 +175,40 @@ namespace SourceGit.Models
lock (_synclock)
{
- if (!_requesting.Contains(email))
- _requesting.Add(email);
+ _requesting.Add(email);
}
return null;
}
+ public void SetFromLocal(string email, string file)
+ {
+ try
+ {
+ Bitmap image = null;
+
+ using (var stream = File.OpenRead(file))
+ {
+ image = Bitmap.DecodeToWidth(stream, 128);
+ }
+
+ if (image == null)
+ return;
+
+ _resources[email] = image;
+
+ _requesting.Remove(email);
+
+ var store = Path.Combine(_storePath, GetEmailHash(email));
+ File.Copy(file, store, true);
+ NotifyResourceChanged(email, image);
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+
private void LoadDefaultAvatar(string key, string img)
{
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
@@ -203,12 +226,10 @@ namespace SourceGit.Models
return builder.ToString();
}
- private void NotifyResourceChanged(string email)
+ private void NotifyResourceChanged(string email, Bitmap image)
{
foreach (var avatar in _avatars)
- {
- avatar.OnAvatarResourceChanged(email);
- }
+ avatar.OnAvatarResourceChanged(email, image);
}
}
}
diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs
index d8eb8ab6..f0f4b39b 100644
--- a/src/Models/Commit.cs
+++ b/src/Models/Commit.cs
@@ -19,7 +19,7 @@ namespace SourceGit.Models
public class Commit
{
// As retrieved by: git mktree Parents { get; set; } = new List();
- public List Decorators { get; set; } = new List();
+ public List Parents { get; set; } = new();
+ public List Decorators { get; set; } = new();
public bool HasDecorators => Decorators.Count > 0;
- public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
- public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
- public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly);
- public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly);
+ public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
+ public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
+ public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
+ public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
public bool IsMerged { get; set; } = false;
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
@@ -49,7 +49,7 @@ namespace SourceGit.Models
public int Color { get; set; } = 0;
public double Opacity => IsMerged ? 1 : OpacityForNotMerged;
public FontWeight FontWeight => IsCurrentHead ? FontWeight.Bold : FontWeight.Regular;
- public Thickness Margin { get; set; } = new Thickness(0);
+ public Thickness Margin { get; set; } = new(0);
public IBrush Brush => CommitGraph.Pens[Color].Brush;
public void ParseDecorators(string data)
@@ -113,7 +113,7 @@ namespace SourceGit.Models
if (l.Type != r.Type)
return (int)l.Type - (int)r.Type;
else
- return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
+ return NumericSort.Compare(l.Name, r.Name);
});
}
}
@@ -121,6 +121,6 @@ namespace SourceGit.Models
public class CommitFullMessage
{
public string Message { get; set; } = string.Empty;
- public List Inlines { get; set; } = [];
+ public InlineElementCollector Inlines { get; set; } = new();
}
}
diff --git a/src/Models/CommitTemplate.cs b/src/Models/CommitTemplate.cs
index 56e1992c..3f331543 100644
--- a/src/Models/CommitTemplate.cs
+++ b/src/Models/CommitTemplate.cs
@@ -4,7 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
- public partial class CommitTemplate : ObservableObject
+ public class CommitTemplate : ObservableObject
{
public string Name
{
diff --git a/src/Models/DateTimeFormat.cs b/src/Models/DateTimeFormat.cs
index 4e8aa550..16276c40 100644
--- a/src/Models/DateTimeFormat.cs
+++ b/src/Models/DateTimeFormat.cs
@@ -25,7 +25,7 @@ namespace SourceGit.Models
set;
} = 0;
- public static DateTimeFormat Actived
+ public static DateTimeFormat Active
{
get => Supported[ActiveIndex];
}
diff --git a/src/Models/DealWithChangesAfterStashing.cs b/src/Models/DealWithChangesAfterStashing.cs
new file mode 100644
index 00000000..63889c96
--- /dev/null
+++ b/src/Models/DealWithChangesAfterStashing.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace SourceGit.Models
+{
+ public class DealWithChangesAfterStashing
+ {
+ public string Label { get; set; }
+ public string Desc { get; set; }
+
+ public static readonly List Supported = [
+ new ("Discard", "All (or selected) changes will be discarded"),
+ new ("Keep Index", "Staged changes are left intact"),
+ new ("Keep All", "All (or selected) changes are left intact"),
+ ];
+
+ public DealWithChangesAfterStashing(string label, string desc)
+ {
+ Label = label;
+ Desc = desc;
+ }
+ }
+}
diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs
index b2d91310..71ed2d9e 100644
--- a/src/Models/DiffResult.cs
+++ b/src/Models/DiffResult.cs
@@ -16,11 +16,10 @@ namespace SourceGit.Models
Deleted,
}
- public class TextInlineRange
+ public class TextInlineRange(int p, int n)
{
- public int Start { get; set; }
- public int End { get; set; }
- public TextInlineRange(int p, int n) { Start = p; End = p + n - 1; }
+ public int Start { get; set; } = p;
+ public int End { get; set; } = p + n - 1;
}
public class TextDiffLine
@@ -556,7 +555,7 @@ namespace SourceGit.Models
}
else if (test.Type == TextDiffLineType.Added)
{
- if (i < start - 1)
+ if (i < start - 1 || isOldSide)
{
if (revert)
{
@@ -566,18 +565,7 @@ namespace SourceGit.Models
}
else
{
- if (isOldSide)
- {
- if (revert)
- {
- newCount++;
- oldCount++;
- }
- }
- else
- {
- newCount++;
- }
+ newCount++;
}
if (i == end - 1 && tailed)
@@ -655,9 +643,7 @@ namespace SourceGit.Models
public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0";
}
- public class NoOrEOLChange
- {
- }
+ public class NoOrEOLChange;
public class FileModeDiff
{
diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs
index 103e91bc..697c171a 100644
--- a/src/Models/ExternalTool.cs
+++ b/src/Models/ExternalTool.cs
@@ -107,8 +107,7 @@ namespace SourceGit.Models
// Ignore
}
- if (_customPaths == null)
- _customPaths = new ExternalToolPaths();
+ _customPaths ??= new ExternalToolPaths();
}
public void TryAdd(string name, string icon, Func finder, Func execArgsGenerator = null)
diff --git a/src/Models/ImageDecoder.cs b/src/Models/ImageDecoder.cs
new file mode 100644
index 00000000..6fe0f428
--- /dev/null
+++ b/src/Models/ImageDecoder.cs
@@ -0,0 +1,10 @@
+namespace SourceGit.Models
+{
+ public enum ImageDecoder
+ {
+ None = 0,
+ Builtin,
+ Pfim,
+ Tiff,
+ }
+}
diff --git a/src/Models/InlineElement.cs b/src/Models/InlineElement.cs
index 53761403..ea7bcee8 100644
--- a/src/Models/InlineElement.cs
+++ b/src/Models/InlineElement.cs
@@ -2,8 +2,7 @@
{
public enum InlineElementType
{
- None = 0,
- Keyword,
+ Keyword = 0,
Link,
CommitSHA,
Code,
@@ -11,10 +10,10 @@
public class InlineElement
{
- public InlineElementType Type { get; set; } = InlineElementType.None;
- public int Start { get; set; } = 0;
- public int Length { get; set; } = 0;
- public string Link { get; set; } = "";
+ public InlineElementType Type { get; }
+ public int Start { get; }
+ public int Length { get; }
+ public string Link { get; }
public InlineElement(InlineElementType type, int start, int length, string link)
{
@@ -24,7 +23,7 @@
Link = link;
}
- public bool Intersect(int start, int length)
+ public bool IsIntersecting(int start, int length)
{
if (start == Start)
return true;
diff --git a/src/Models/InlineElementCollector.cs b/src/Models/InlineElementCollector.cs
new file mode 100644
index 00000000..d81aaf8d
--- /dev/null
+++ b/src/Models/InlineElementCollector.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace SourceGit.Models
+{
+ public class InlineElementCollector
+ {
+ public int Count => _implementation.Count;
+ public InlineElement this[int index] => _implementation[index];
+
+ public InlineElement Intersect(int start, int length)
+ {
+ foreach (var elem in _implementation)
+ {
+ if (elem.IsIntersecting(start, length))
+ return elem;
+ }
+
+ return null;
+ }
+
+ public void Add(InlineElement element)
+ {
+ _implementation.Add(element);
+ }
+
+ public void Sort()
+ {
+ _implementation.Sort((l, r) => l.Start.CompareTo(r.Start));
+ }
+
+ public void Clear()
+ {
+ _implementation.Clear();
+ }
+
+ private readonly List _implementation = [];
+ }
+}
diff --git a/src/Models/IpcChannel.cs b/src/Models/IpcChannel.cs
index d47a46bd..001c65a6 100644
--- a/src/Models/IpcChannel.cs
+++ b/src/Models/IpcChannel.cs
@@ -8,10 +8,7 @@ namespace SourceGit.Models
{
public class IpcChannel : IDisposable
{
- public bool IsFirstInstance
- {
- get => _isFirstInstance;
- }
+ public bool IsFirstInstance { get; }
public event Action MessageReceived;
@@ -19,8 +16,8 @@ namespace SourceGit.Models
{
try
{
- _singletoneLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
- _isFirstInstance = true;
+ _singletonLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
+ IsFirstInstance = true;
_server = new NamedPipeServerStream(
"SourceGitIPCChannel" + Environment.UserName,
PipeDirection.In,
@@ -32,7 +29,7 @@ namespace SourceGit.Models
}
catch
{
- _isFirstInstance = false;
+ IsFirstInstance = false;
}
}
@@ -67,7 +64,7 @@ namespace SourceGit.Models
public void Dispose()
{
_cancellationTokenSource?.Cancel();
- _singletoneLock?.Dispose();
+ _singletonLock?.Dispose();
}
private async void StartServer()
@@ -96,8 +93,7 @@ namespace SourceGit.Models
}
}
- private FileStream _singletoneLock = null;
- private bool _isFirstInstance = false;
+ private FileStream _singletonLock = null;
private NamedPipeServerStream _server = null;
private CancellationTokenSource _cancellationTokenSource = null;
}
diff --git a/src/Models/IssueTrackerRule.cs b/src/Models/IssueTrackerRule.cs
index fe0fe8e0..40c84b9e 100644
--- a/src/Models/IssueTrackerRule.cs
+++ b/src/Models/IssueTrackerRule.cs
@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
+using System.Text.RegularExpressions;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -46,7 +45,7 @@ namespace SourceGit.Models
set => SetProperty(ref _urlTemplate, value);
}
- public void Matches(List outs, string message)
+ public void Matches(InlineElementCollector outs, string message)
{
if (_regex == null || string.IsNullOrEmpty(_urlTemplate))
return;
@@ -60,17 +59,7 @@ namespace SourceGit.Models
var start = match.Index;
var len = match.Length;
- var intersect = false;
- foreach (var exist in outs)
- {
- if (exist.Intersect(start, len))
- {
- intersect = true;
- break;
- }
- }
-
- if (intersect)
+ if (outs.Intersect(start, len) != null)
continue;
var link = _urlTemplate;
diff --git a/src/Models/LFSObject.cs b/src/Models/LFSObject.cs
index 0f281253..8bc2dda2 100644
--- a/src/Models/LFSObject.cs
+++ b/src/Models/LFSObject.cs
@@ -1,8 +1,22 @@
-namespace SourceGit.Models
+using System.Text.RegularExpressions;
+
+namespace SourceGit.Models
{
- public class LFSObject
+ public partial class LFSObject
{
+ [GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
+ private static partial Regex REG_FORMAT();
+
public string Oid { get; set; } = string.Empty;
public long Size { get; set; } = 0;
+
+ public static LFSObject Parse(string content)
+ {
+ var match = REG_FORMAT().Match(content);
+ if (match.Success)
+ return new() { Oid = match.Groups[1].Value, Size = long.Parse(match.Groups[2].Value) };
+
+ return null;
+ }
}
}
diff --git a/src/Models/Null.cs b/src/Models/Null.cs
index e22ef8b3..1820d4d0 100644
--- a/src/Models/Null.cs
+++ b/src/Models/Null.cs
@@ -1,6 +1,4 @@
namespace SourceGit.Models
{
- public class Null
- {
- }
+ public class Null;
}
diff --git a/src/Models/NumericSort.cs b/src/Models/NumericSort.cs
index ed5002e6..baaf3da4 100644
--- a/src/Models/NumericSort.cs
+++ b/src/Models/NumericSort.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Models
+using System;
+
+namespace SourceGit.Models
{
public static class NumericSort
{
@@ -10,52 +12,35 @@
int marker1 = 0;
int marker2 = 0;
- char[] tmp1 = new char[len1];
- char[] tmp2 = new char[len2];
-
while (marker1 < len1 && marker2 < len2)
{
char c1 = s1[marker1];
char c2 = s2[marker2];
- int loc1 = 0;
- int loc2 = 0;
bool isDigit1 = char.IsDigit(c1);
bool isDigit2 = char.IsDigit(c2);
if (isDigit1 != isDigit2)
return c1.CompareTo(c2);
- do
- {
- tmp1[loc1] = c1;
- loc1++;
- marker1++;
+ int subLen1 = 1;
+ while (marker1 + subLen1 < len1 && char.IsDigit(s1[marker1 + subLen1]) == isDigit1)
+ subLen1++;
- if (marker1 < len1)
- c1 = s1[marker1];
- else
- break;
- } while (char.IsDigit(c1) == isDigit1);
+ int subLen2 = 1;
+ while (marker2 + subLen2 < len2 && char.IsDigit(s2[marker2 + subLen2]) == isDigit2)
+ subLen2++;
- do
- {
- tmp2[loc2] = c2;
- loc2++;
- marker2++;
+ string sub1 = s1.Substring(marker1, subLen1);
+ string sub2 = s2.Substring(marker2, subLen2);
- if (marker2 < len2)
- c2 = s2[marker2];
- else
- break;
- } while (char.IsDigit(c2) == isDigit2);
+ marker1 += subLen1;
+ marker2 += subLen2;
- string sub1 = new string(tmp1, 0, loc1);
- string sub2 = new string(tmp2, 0, loc2);
int result;
if (isDigit1)
- result = loc1 == loc2 ? string.CompareOrdinal(sub1, sub2) : loc1 - loc2;
+ result = (subLen1 == subLen2) ? string.CompareOrdinal(sub1, sub2) : (subLen1 - subLen2);
else
- result = string.CompareOrdinal(sub1, sub2);
+ result = string.Compare(sub1, sub2, StringComparison.OrdinalIgnoreCase);
if (result != 0)
return result;
diff --git a/src/Models/RepositorySettings.cs b/src/Models/RepositorySettings.cs
index 34189073..4e51b368 100644
--- a/src/Models/RepositorySettings.cs
+++ b/src/Models/RepositorySettings.cs
@@ -32,7 +32,7 @@ namespace SourceGit.Models
set;
} = false;
- public bool OnlyHighlighCurrentBranchInHistories
+ public bool OnlyHighlightCurrentBranchInHistories
{
get;
set;
@@ -176,19 +176,13 @@ namespace SourceGit.Models
set;
} = false;
- public bool KeepIndexWhenStash
+ public int ChangesAfterStashing
{
get;
set;
- } = false;
+ } = 0;
- public bool AutoRestoreAfterStash
- {
- get;
- set;
- } = false;
-
- public string PreferedOpenAIService
+ public string PreferredOpenAIService
{
get;
set;
@@ -287,9 +281,8 @@ namespace SourceGit.Models
return false;
}
- for (int i = 0; i < HistoriesFilters.Count; i++)
+ foreach (var filter in HistoriesFilters)
{
- var filter = HistoriesFilters[i];
if (filter.Type != type)
continue;
@@ -453,5 +446,19 @@ namespace SourceGit.Models
if (act != null)
CustomActions.Remove(act);
}
+
+ public void MoveCustomActionUp(CustomAction act)
+ {
+ var idx = CustomActions.IndexOf(act);
+ if (idx > 0)
+ CustomActions.Move(idx - 1, idx);
+ }
+
+ public void MoveCustomActionDown(CustomAction act)
+ {
+ var idx = CustomActions.IndexOf(act);
+ if (idx < CustomActions.Count - 1)
+ CustomActions.Move(idx + 1, idx);
+ }
}
}
diff --git a/src/Models/RevisionFile.cs b/src/Models/RevisionFile.cs
index 8cc1be2a..29a23efa 100644
--- a/src/Models/RevisionFile.cs
+++ b/src/Models/RevisionFile.cs
@@ -1,4 +1,6 @@
-using Avalonia.Media.Imaging;
+using System.Globalization;
+using System.IO;
+using Avalonia.Media.Imaging;
namespace SourceGit.Models
{
@@ -9,10 +11,17 @@ namespace SourceGit.Models
public class RevisionImageFile
{
- public Bitmap Image { get; set; } = null;
- public long FileSize { get; set; } = 0;
- public string ImageType { get; set; } = string.Empty;
+ public Bitmap Image { get; }
+ public long FileSize { get; }
+ public string ImageType { get; }
public string ImageSize => Image != null ? $"{Image.PixelSize.Width} x {Image.PixelSize.Height}" : "0 x 0";
+
+ public RevisionImageFile(string file, Bitmap img, long size)
+ {
+ Image = img;
+ FileSize = size;
+ ImageType = Path.GetExtension(file)!.Substring(1).ToUpper(CultureInfo.CurrentCulture);
+ }
}
public class RevisionTextFile
diff --git a/src/Models/SelfUpdate.cs b/src/Models/SelfUpdate.cs
index e02f80d8..05fa6124 100644
--- a/src/Models/SelfUpdate.cs
+++ b/src/Models/SelfUpdate.cs
@@ -33,9 +33,7 @@ namespace SourceGit.Models
}
}
- public class AlreadyUpToDate
- {
- }
+ public class AlreadyUpToDate;
public class SelfUpdateFailed
{
diff --git a/src/Models/Stash.cs b/src/Models/Stash.cs
index 257b6d33..2b77be50 100644
--- a/src/Models/Stash.cs
+++ b/src/Models/Stash.cs
@@ -11,6 +11,24 @@ namespace SourceGit.Models
public ulong Time { get; set; } = 0;
public string Message { get; set; } = "";
- public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
+ public string Subject
+ {
+ get
+ {
+ var idx = Message.IndexOf('\n', StringComparison.Ordinal);
+ return idx > 0 ? Message.Substring(0, idx).Trim() : Message;
+ }
+ }
+
+ public string TimeStr
+ {
+ get
+ {
+ return DateTime.UnixEpoch
+ .AddSeconds(Time)
+ .ToLocalTime()
+ .ToString(DateTimeFormat.Active.DateTime);
+ }
+ }
}
}
diff --git a/src/Models/Tag.cs b/src/Models/Tag.cs
index 20678530..87944637 100644
--- a/src/Models/Tag.cs
+++ b/src/Models/Tag.cs
@@ -5,8 +5,7 @@ namespace SourceGit.Models
public enum TagSortMode
{
CreatorDate = 0,
- NameInAscending,
- NameInDescending,
+ Name,
}
public class Tag : ObservableObject
diff --git a/src/Models/TemplateEngine.cs b/src/Models/TemplateEngine.cs
index 8472750c..8f60bd74 100644
--- a/src/Models/TemplateEngine.cs
+++ b/src/Models/TemplateEngine.cs
@@ -102,7 +102,7 @@ namespace SourceGit.Models
private int? Integer()
{
var start = _pos;
- while (Peek() is char c && c >= '0' && c <= '9')
+ while (Peek() is >= '0' and <= '9')
{
_pos++;
}
@@ -118,7 +118,7 @@ namespace SourceGit.Models
// text token start
var tok = _pos;
bool esc = false;
- while (Next() is char c)
+ while (Next() is { } c)
{
if (esc)
{
@@ -129,7 +129,7 @@ namespace SourceGit.Models
{
case ESCAPE:
// allow to escape only \ and $
- if (Peek() is char nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR))
+ if (Peek() is { } nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR))
{
esc = true;
FlushText(tok, _pos - 1);
@@ -173,7 +173,7 @@ namespace SourceGit.Models
if (Next() != VARIABLE_START)
return null;
int name_start = _pos;
- while (Next() is char c)
+ while (Next() is { } c)
{
// name character, continue advancing
if (IsNameChar(c))
@@ -228,7 +228,7 @@ namespace SourceGit.Models
var sb = new StringBuilder();
var tok = _pos;
var esc = false;
- while (Next() is char c)
+ while (Next() is { } c)
{
if (esc)
{
@@ -277,7 +277,7 @@ namespace SourceGit.Models
var sb = new StringBuilder();
var tok = _pos;
var esc = false;
- while (Next() is char c)
+ while (Next() is { } c)
{
if (esc)
{
@@ -402,7 +402,7 @@ namespace SourceGit.Models
sb.AppendJoin(", ", paths);
if (max < context.changes.Count)
- sb.AppendFormat(" and {0} other files", context.changes.Count - max);
+ sb.Append($" and {context.changes.Count - max} other files");
return sb.ToString();
}
diff --git a/src/Models/TextInlineChange.cs b/src/Models/TextInlineChange.cs
index c96d839f..afe5bec4 100644
--- a/src/Models/TextInlineChange.cs
+++ b/src/Models/TextInlineChange.cs
@@ -2,30 +2,22 @@
namespace SourceGit.Models
{
- public class TextInlineChange
+ public class TextInlineChange(int dp, int dc, int ap, int ac)
{
- public int DeletedStart { get; set; }
- public int DeletedCount { get; set; }
- public int AddedStart { get; set; }
- public int AddedCount { get; set; }
+ public int DeletedStart { get; set; } = dp;
+ public int DeletedCount { get; set; } = dc;
+ public int AddedStart { get; set; } = ap;
+ public int AddedCount { get; set; } = ac;
- class Chunk
+ private class Chunk(int hash, int start, int size)
{
- public int Hash;
+ public readonly int Hash = hash;
+ public readonly int Start = start;
+ public readonly int Size = size;
public bool Modified;
- public int Start;
- public int Size;
-
- public Chunk(int hash, int start, int size)
- {
- Hash = hash;
- Modified = false;
- Start = start;
- Size = size;
- }
}
- enum Edit
+ private enum Edit
{
None,
DeletedRight,
@@ -34,7 +26,7 @@ namespace SourceGit.Models
AddedLeft,
}
- class EditResult
+ private class EditResult
{
public Edit State;
public int DeleteStart;
@@ -43,14 +35,6 @@ namespace SourceGit.Models
public int AddEnd;
}
- public TextInlineChange(int dp, int dc, int ap, int ac)
- {
- DeletedStart = dp;
- DeletedCount = dc;
- AddedStart = ap;
- AddedCount = ac;
- }
-
public static List Compare(string oldValue, string newValue)
{
var hashes = new Dictionary();
@@ -204,11 +188,10 @@ namespace SourceGit.Models
for (int i = 0; i <= half; i++)
{
-
for (int j = -i; j <= i; j += 2)
{
var idx = j + half;
- int o, n;
+ int o;
if (j == -i || (j != i && forward[idx - 1] < forward[idx + 1]))
{
o = forward[idx + 1];
@@ -220,7 +203,7 @@ namespace SourceGit.Models
rs.State = Edit.DeletedRight;
}
- n = o - j;
+ var n = o - j;
var startX = o;
var startY = n;
@@ -258,7 +241,7 @@ namespace SourceGit.Models
for (int j = -i; j <= i; j += 2)
{
var idx = j + half;
- int o, n;
+ int o;
if (j == -i || (j != i && reverse[idx + 1] <= reverse[idx - 1]))
{
o = reverse[idx + 1] - 1;
@@ -270,7 +253,7 @@ namespace SourceGit.Models
rs.State = Edit.AddedLeft;
}
- n = o - (j + delta);
+ var n = o - (j + delta);
var endX = o;
var endY = n;
@@ -312,8 +295,7 @@ namespace SourceGit.Models
private static void AddChunk(List chunks, Dictionary hashes, string data, int start)
{
- int hash;
- if (hashes.TryGetValue(data, out hash))
+ if (hashes.TryGetValue(data, out var hash))
{
chunks.Add(new Chunk(hash, start, data.Length));
}
diff --git a/src/Models/User.cs b/src/Models/User.cs
index 066ab747..0b4816fe 100644
--- a/src/Models/User.cs
+++ b/src/Models/User.cs
@@ -26,11 +26,7 @@ namespace SourceGit.Models
public override bool Equals(object obj)
{
- if (obj == null || !(obj is User))
- return false;
-
- var other = obj as User;
- return Name == other.Name && Email == other.Email;
+ return obj is User other && Name == other.Name && Email == other.Email;
}
public override int GetHashCode()
diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs
index 928951ca..4d6656e3 100644
--- a/src/Models/Watcher.cs
+++ b/src/Models/Watcher.cs
@@ -12,27 +12,50 @@ namespace SourceGit.Models
{
_repo = repo;
- _wcWatcher = new FileSystemWatcher();
- _wcWatcher.Path = fullpath;
- _wcWatcher.Filter = "*";
- _wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
- _wcWatcher.IncludeSubdirectories = true;
- _wcWatcher.Created += OnWorkingCopyChanged;
- _wcWatcher.Renamed += OnWorkingCopyChanged;
- _wcWatcher.Changed += OnWorkingCopyChanged;
- _wcWatcher.Deleted += OnWorkingCopyChanged;
- _wcWatcher.EnableRaisingEvents = true;
+ var testGitDir = new DirectoryInfo(Path.Combine(fullpath, ".git")).FullName;
+ var desiredDir = new DirectoryInfo(gitDir).FullName;
+ if (testGitDir.Equals(desiredDir, StringComparison.Ordinal))
+ {
+ var combined = new FileSystemWatcher();
+ combined.Path = fullpath;
+ combined.Filter = "*";
+ combined.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
+ combined.IncludeSubdirectories = true;
+ combined.Created += OnRepositoryChanged;
+ combined.Renamed += OnRepositoryChanged;
+ combined.Changed += OnRepositoryChanged;
+ combined.Deleted += OnRepositoryChanged;
+ combined.EnableRaisingEvents = true;
- _repoWatcher = new FileSystemWatcher();
- _repoWatcher.Path = gitDir;
- _repoWatcher.Filter = "*";
- _repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
- _repoWatcher.IncludeSubdirectories = true;
- _repoWatcher.Created += OnRepositoryChanged;
- _repoWatcher.Renamed += OnRepositoryChanged;
- _repoWatcher.Changed += OnRepositoryChanged;
- _repoWatcher.Deleted += OnRepositoryChanged;
- _repoWatcher.EnableRaisingEvents = true;
+ _watchers.Add(combined);
+ }
+ else
+ {
+ var wc = new FileSystemWatcher();
+ wc.Path = fullpath;
+ wc.Filter = "*";
+ wc.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
+ wc.IncludeSubdirectories = true;
+ wc.Created += OnWorkingCopyChanged;
+ wc.Renamed += OnWorkingCopyChanged;
+ wc.Changed += OnWorkingCopyChanged;
+ wc.Deleted += OnWorkingCopyChanged;
+ wc.EnableRaisingEvents = true;
+
+ var git = new FileSystemWatcher();
+ git.Path = gitDir;
+ git.Filter = "*";
+ git.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
+ git.IncludeSubdirectories = true;
+ git.Created += OnGitDirChanged;
+ git.Renamed += OnGitDirChanged;
+ git.Changed += OnGitDirChanged;
+ git.Deleted += OnGitDirChanged;
+ git.EnableRaisingEvents = true;
+
+ _watchers.Add(wc);
+ _watchers.Add(git);
+ }
_timer = new Timer(Tick, null, 100, 100);
}
@@ -77,22 +100,13 @@ namespace SourceGit.Models
public void Dispose()
{
- _repoWatcher.EnableRaisingEvents = false;
- _repoWatcher.Created -= OnRepositoryChanged;
- _repoWatcher.Renamed -= OnRepositoryChanged;
- _repoWatcher.Changed -= OnRepositoryChanged;
- _repoWatcher.Deleted -= OnRepositoryChanged;
- _repoWatcher.Dispose();
- _repoWatcher = null;
-
- _wcWatcher.EnableRaisingEvents = false;
- _wcWatcher.Created -= OnWorkingCopyChanged;
- _wcWatcher.Renamed -= OnWorkingCopyChanged;
- _wcWatcher.Changed -= OnWorkingCopyChanged;
- _wcWatcher.Deleted -= OnWorkingCopyChanged;
- _wcWatcher.Dispose();
- _wcWatcher = null;
+ foreach (var watcher in _watchers)
+ {
+ watcher.EnableRaisingEvents = false;
+ watcher.Dispose();
+ }
+ _watchers.Clear();
_timer.Dispose();
_timer = null;
}
@@ -153,11 +167,45 @@ namespace SourceGit.Models
}
private void OnRepositoryChanged(object o, FileSystemEventArgs e)
+ {
+ if (string.IsNullOrEmpty(e.Name) || e.Name.Equals(".git", StringComparison.Ordinal))
+ return;
+
+ var name = e.Name.Replace('\\', '/').TrimEnd('/');
+ if (name.EndsWith("/.git", StringComparison.Ordinal))
+ return;
+
+ if (name.StartsWith(".git/", StringComparison.Ordinal))
+ HandleGitDirFileChanged(name.Substring(5));
+ else
+ HandleWorkingCopyFileChanged(name);
+ }
+
+ private void OnGitDirChanged(object o, FileSystemEventArgs e)
{
if (string.IsNullOrEmpty(e.Name))
return;
- var name = e.Name.Replace("\\", "/");
+ var name = e.Name.Replace('\\', '/').TrimEnd('/');
+ HandleGitDirFileChanged(name);
+ }
+
+ private void OnWorkingCopyChanged(object o, FileSystemEventArgs e)
+ {
+ if (string.IsNullOrEmpty(e.Name))
+ return;
+
+ var name = e.Name.Replace('\\', '/').TrimEnd('/');
+ if (name.Equals(".git", StringComparison.Ordinal) ||
+ name.StartsWith(".git/", StringComparison.Ordinal) ||
+ name.EndsWith("/.git", StringComparison.Ordinal))
+ return;
+
+ HandleWorkingCopyFileChanged(name);
+ }
+
+ private void HandleGitDirFileChanged(string name)
+ {
if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) ||
name.EndsWith(".lock", StringComparison.Ordinal) ||
name.StartsWith("lfs/", StringComparison.Ordinal))
@@ -200,17 +248,8 @@ namespace SourceGit.Models
}
}
- private void OnWorkingCopyChanged(object o, FileSystemEventArgs e)
+ private void HandleWorkingCopyFileChanged(string name)
{
- if (string.IsNullOrEmpty(e.Name))
- return;
-
- var name = e.Name.Replace("\\", "/");
- if (name.Equals(".git", StringComparison.Ordinal) ||
- name.StartsWith(".git/", StringComparison.Ordinal) ||
- name.EndsWith("/.git", StringComparison.Ordinal))
- return;
-
if (name.StartsWith(".vs/", StringComparison.Ordinal))
return;
@@ -236,8 +275,7 @@ namespace SourceGit.Models
}
private readonly IRepository _repo = null;
- private FileSystemWatcher _repoWatcher = null;
- private FileSystemWatcher _wcWatcher = null;
+ private List _watchers = [];
private Timer _timer = null;
private int _lockCount = 0;
private long _updateWC = 0;
@@ -246,7 +284,7 @@ namespace SourceGit.Models
private long _updateStashes = 0;
private long _updateTags = 0;
- private object _lockSubmodule = new object();
+ private readonly Lock _lockSubmodule = new();
private List _submodules = new List();
}
}
diff --git a/src/Models/Worktree.cs b/src/Models/Worktree.cs
index 3f954650..26f88a8a 100644
--- a/src/Models/Worktree.cs
+++ b/src/Models/Worktree.cs
@@ -23,7 +23,7 @@ namespace SourceGit.Models
get
{
if (IsDetached)
- return $"deteched HEAD at {Head.AsSpan(10)}";
+ return $"detached HEAD at {Head.AsSpan(10)}";
if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal))
return Branch.Substring(11);
diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs
index 2bdcf561..3f6de903 100644
--- a/src/Native/Linux.cs
+++ b/src/Native/Linux.cs
@@ -120,8 +120,8 @@ namespace SourceGit.Native
private string FindExecutable(string filename)
{
var pathVariable = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
- var pathes = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
- foreach (var path in pathes)
+ var paths = pathVariable.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var path in paths)
{
var test = Path.Combine(path, filename);
if (File.Exists(test))
diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs
index 83b11c47..06d80bf0 100644
--- a/src/Native/Windows.cs
+++ b/src/Native/Windows.cs
@@ -54,7 +54,7 @@ namespace SourceGit.Native
public void SetupApp(AppBuilder builder)
{
// Fix drop shadow issue on Windows 10
- if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000, 0))
+ if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000))
{
Window.WindowStateProperty.Changed.AddClassHandler((w, _) => FixWindowFrameOnWin10(w));
Control.LoadedEvent.AddClassHandler((w, _) => FixWindowFrameOnWin10(w));
@@ -80,17 +80,17 @@ namespace SourceGit.Native
var p = IntPtrToPixelPoint(lParam);
GetWindowRect(hWnd, out var rcWindow);
- var borderThinkness = (int)(4 * window.RenderScaling);
+ var borderThickness = (int)(4 * window.RenderScaling);
int y = 1;
int x = 1;
- if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThinkness)
+ if (p.X >= rcWindow.left && p.X < rcWindow.left + borderThickness)
x = 0;
- else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThinkness)
+ else if (p.X < rcWindow.right && p.X >= rcWindow.right - borderThickness)
x = 2;
- if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThinkness)
+ if (p.Y >= rcWindow.top && p.Y < rcWindow.top + borderThickness)
y = 0;
- else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThinkness)
+ else if (p.Y < rcWindow.bottom && p.Y >= rcWindow.bottom - borderThickness)
y = 2;
var zone = y * 3 + x;
@@ -127,23 +127,17 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryHive.LocalMachine,
Microsoft.Win32.RegistryView.Registry64);
- var git = reg.OpenSubKey("SOFTWARE\\GitForWindows");
- if (git != null && git.GetValue("InstallPath") is string installPath)
- {
+ var git = reg.OpenSubKey(@"SOFTWARE\GitForWindows");
+ if (git?.GetValue("InstallPath") is string installPath)
return Path.Combine(installPath, "bin", "git.exe");
- }
var builder = new StringBuilder("git.exe", 259);
if (!PathFindOnPath(builder, null))
- {
return null;
- }
var exePath = builder.ToString();
if (!string.IsNullOrEmpty(exePath))
- {
return exePath;
- }
return null;
}
@@ -181,7 +175,7 @@ namespace SourceGit.Native
break;
case "cmd":
- return "C:\\Windows\\System32\\cmd.exe";
+ return @"C:\Windows\System32\cmd.exe";
case "wt":
var wtFinder = new StringBuilder("wt.exe", 512);
if (PathFindOnPath(wtFinder, null))
@@ -199,8 +193,8 @@ namespace SourceGit.Native
finder.VSCode(FindVSCode);
finder.VSCodeInsiders(FindVSCodeInsiders);
finder.VSCodium(FindVSCodium);
- finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\Programs\\Fleet\\Fleet.exe");
- finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\\JetBrains\\Toolbox");
+ finder.Fleet(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\Programs\Fleet\Fleet.exe");
+ finder.FindJetBrainsFromToolbox(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\JetBrains\Toolbox");
finder.SublimeText(FindSublimeText);
finder.TryAdd("Visual Studio", "vs", FindVisualStudio, GenerateCommandlineArgsForVisualStudio);
return finder.Founded;
@@ -299,9 +293,7 @@ namespace SourceGit.Native
// VSCode (system)
var systemVScode = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{EA457B21-F73E-494C-ACAB-524FDE069978}_is1");
if (systemVScode != null)
- {
return systemVScode.GetValue("DisplayIcon") as string;
- }
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser,
@@ -310,9 +302,7 @@ namespace SourceGit.Native
// VSCode (user)
var vscode = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{771FD6B0-FA20-440A-A002-3B3BAC16DC50}_is1");
if (vscode != null)
- {
return vscode.GetValue("DisplayIcon") as string;
- }
return string.Empty;
}
@@ -326,9 +316,7 @@ namespace SourceGit.Native
// VSCode - Insiders (system)
var systemVScodeInsiders = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1");
if (systemVScodeInsiders != null)
- {
return systemVScodeInsiders.GetValue("DisplayIcon") as string;
- }
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser,
@@ -337,9 +325,7 @@ namespace SourceGit.Native
// VSCode - Insiders (user)
var vscodeInsiders = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{217B4C08-948D-4276-BFBB-BEE930AE5A2C}_is1");
if (vscodeInsiders != null)
- {
return vscodeInsiders.GetValue("DisplayIcon") as string;
- }
return string.Empty;
}
@@ -351,11 +337,9 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryView.Registry64);
// VSCodium (system)
- var systemVScodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1");
- if (systemVScodium != null)
- {
- return systemVScodium.GetValue("DisplayIcon") as string;
- }
+ var systemVSCodium = localMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{88DA3577-054F-4CA1-8122-7D820494CFFB}_is1");
+ if (systemVSCodium != null)
+ return systemVSCodium.GetValue("DisplayIcon") as string;
var currentUser = Microsoft.Win32.RegistryKey.OpenBaseKey(
Microsoft.Win32.RegistryHive.CurrentUser,
@@ -364,9 +348,7 @@ namespace SourceGit.Native
// VSCodium (user)
var vscodium = currentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{2E1F05D1-C245-4562-81EE-28188DB6FD17}_is1");
if (vscodium != null)
- {
return vscodium.GetValue("DisplayIcon") as string;
- }
return string.Empty;
}
@@ -403,15 +385,13 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryView.Registry64);
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
- if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher)
+ if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is { } launcher)
{
// Get actual path to the executable
if (launcher.GetValue(string.Empty) is string CLSID &&
- localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv &&
+ localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is { } devenv &&
devenv.GetValue(string.Empty) is string localServer32)
- {
return localServer32!.Trim('\"');
- }
}
return string.Empty;
diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml
index 9da3a51e..001c7ee7 100644
--- a/src/Resources/Icons.axaml
+++ b/src/Resources/Icons.axaml
@@ -89,7 +89,8 @@
M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z
M64 363l0 204 265 0L329 460c0-11 6-18 14-20C349 437 355 437 362 441c93 60 226 149 226 149 33 22 34 60 0 82 0 0-133 89-226 149-14 9-32-3-32-18l-1-110L64 693l0 117c0 41 34 75 75 75l746 0c41 0 75-34 75-74L960 364c0-0 0-1 0-1L64 363zM64 214l0 75 650 0-33-80c-16-38-62-69-103-69l-440 0C97 139 64 173 64 214z
M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z
- M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z
+ M841 627A43 43 0 00811 555h-299v85h196l-183 183A43 43 0 00555 896h299v-85h-196l183-183zM299 170H213v512H85l171 171 171-171H299zM725 128h-85c-18 0-34 11-40 28l-117 313h91L606 384h154l32 85h91l-117-313A43 43 0 00725 128zm-88 171 32-85h26l32 85h-90z
+ M512 0a512 512 0 01512 512 57 57 0 01-114 0 398 398 0 10-398 398 57 57 0 010 114A512 512 0 01512 0zm367 600 121 120a57 57 0 01-80 81l-40-40V967a57 57 0 01-50 57l-7 0a57 57 0 01-57-57v-205l-40 40a57 57 0 01-75 5l-5-5a57 57 0 01-0-80l120-121a80 80 0 01113-0zM512 272a57 57 0 0157 57V499h114a57 57 0 0156 50L740 556a57 57 0 01-57 57H512a57 57 0 01-57-57v-228a57 57 0 0150-57L512 272z
M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z
M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z
m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z
diff --git a/src/Resources/Images/github.png b/src/Resources/Images/github.png
index 3a7abb16..d3c211da 100644
Binary files a/src/Resources/Images/github.png and b/src/Resources/Images/github.png differ
diff --git a/src/Resources/Images/unreal.png b/src/Resources/Images/unreal.png
index 4faae92b..01ceeb31 100644
Binary files a/src/Resources/Images/unreal.png and b/src/Resources/Images/unreal.png differ
diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml
index 3c900d42..99d9f77c 100644
--- a/src/Resources/Locales/de_DE.axaml
+++ b/src/Resources/Locales/de_DE.axaml
@@ -39,6 +39,8 @@
ALS UNVERÄNDERT ANGENOMMENE DATEIEN
KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN
ENTFERNEN
+ Bild laden...
+ Aktualisieren
BINÄRE DATEI NICHT UNTERSTÜTZT!!!
Bisect
Abbrechen
@@ -66,6 +68,7 @@
Push ${0}$
Rebase ${0}$ auf ${1}$...
Benenne ${0}$ um...
+ Setze ${0}$ zurück auf ${1}$...
Setze verfolgten Branch...
Branch Vergleich
Ungültiger upstream!
@@ -87,6 +90,8 @@
Stashen & wieder anwenden
Alle Submodule updaten
Branch:
+ Auschecken & Fast-Forward
+ Fast-Forward zu:
Cherry Pick
Quelle an Commit-Nachricht anhängen
Commit(s):
@@ -119,6 +124,7 @@
Interactives Rebase von ${0}$ auf diesen Commit
Merge in ${0}$ hinein
Merge ...
+ Push ${0}$ zu ${1}$
Rebase von ${0}$ auf diesen Commit
Reset ${0}$ auf diesen Commit
Commit rückgängig machen
@@ -127,6 +133,7 @@
Squash in den Vorgänger
Squash Nachfolger Commits bis hier
ÄNDERUNGEN
+ geänderte Datei(en)
Änderungen durchsuchen...
DATEIEN
LFS DATEI
@@ -218,6 +225,7 @@
Branch-Namen eingeben.
Leerzeichen werden durch Bindestriche ersetzt.
Lokalen Branch erstellen
+ Überschreibe existierenden Branch
Tag erstellen...
Neuer Tag auf:
Mit GPG signieren
@@ -232,6 +240,9 @@
Ohne Anmerkung
Halte Strg gedrückt, um direkt auszuführen
Ausschneiden
+ De-initialisiere Submodul
+ Erzwinge De-Initialisierung, selbst wenn es lokale Änderungen enthält.
+ Submodul:
Branch löschen
Branch:
Du löscht gerade einen Remote-Branch!!!
@@ -267,6 +278,7 @@
Zeige versteckte Symbole
Nebeneinander
SUBMODUL
+ GELÖSCHT
NEU
Seiten wechseln
Syntax Hervorhebung
@@ -325,6 +337,8 @@
FLOW - Finish Hotfix
FLOW - Finish Release
Ziel:
+ Push zu Remote(s) nach Durchführung des Finish
+ Squash beim Merge
Hotfix:
Hotfix-Prefix:
Git-Flow initialisieren
@@ -386,6 +400,8 @@
Zum vorherigen Tab wechseln
Neuen Tab erstellen
Einstellungen öffnen
+ Aktiven Arbeitsplatz wechseln
+ Aktiven Tab wechseln
REPOSITORY
Gestagte Änderungen committen
Gestagte Änderungen committen und pushen
@@ -406,6 +422,7 @@
Suchpanel schließen
Suche nächste Übereinstimmung
Suche vorherige Übereinstimmung
+ Öffne mit externem Diff/Merge Tool
Öffne Suchpanel
Verwerfen
Stagen
@@ -427,7 +444,10 @@
In Browser öffnen
FEHLER
INFO
+ Arbeitsplätze
+ Tabs
Branch mergen
+ Merge-Nachricht anpassen
Ziel-Branch:
Merge Option:
Quelle:
@@ -460,6 +480,7 @@
Vor {0} Monaten
Vor {0} Jahren
Gestern
+ Verwende 'Shift+Enter' um eine neue Zeile einzufügen. 'Enter' ist das Kürzel für den OK Button
Einstellungen
OPEN AI
Analysierung des Diff Befehl
@@ -529,6 +550,7 @@
Lokale Änderungen:
Verwerfen
Stashen & wieder anwenden
+ Alle Submodule aktualisieren
Remote:
Pull (Fetch & Merge)
Rebase anstatt Merge verwenden
@@ -537,6 +559,8 @@
Erzwinge Push
Lokaler Branch:
Remote:
+ Revision:
+ Push Revision zu Remote-Branch
Push
Remote-Branch:
Remote-Branch verfolgen
@@ -550,7 +574,6 @@
Lokale Änderungen stashen & wieder anwenden
Auf:
Rebase:
- Aktualisieren
Remote hinzufügen
Remote bearbeiten
Name:
@@ -578,6 +601,7 @@
Aufräumen (GC & Prune)
Führt `git gc` auf diesem Repository aus.
Filter aufheben
+ Löschen
Repository Einstellungen
WEITER
Benutzerdefinierte Aktionen
@@ -615,6 +639,7 @@
Commit-Nachricht
SHA
Aktueller Branch
+ Submodule als Baum anzeigen
Zeige Tags als Baum
ÜBERSPRINGEN
Statistiken
@@ -624,8 +649,7 @@
TAGS
NEUER TAG
Nach Erstellungsdatum
- Nach Namen (Aufsteigend)
- Nach Namen (Absteigend)
+ Nach Namen
Sortiere
Öffne im Terminal
Verwende relative Zeitangaben in Verlauf
@@ -639,12 +663,14 @@
Rücksetzmodus:
Verschiebe zu:
Aktueller Branch:
+ Reset Branch (ohne Checkout)
+ Auf:
+ Branch:
Zeige im Datei-Explorer
Commit rückgängig machen
Commit:
Commit Änderungen rückgängig machen
Commit Nachricht umformulieren
- Verwende 'Shift+Enter' um eine neue Zeile einzufügen. 'Enter' ist das Kürzel für den OK Button
Bitte warten...
SPEICHERN
Speichern als...
@@ -670,16 +696,15 @@
Pfad zum privaten SSH Schlüssel
START
Stash
- Automatisch wiederherstellen nach dem Stashen
- Die Arbeitsdateien bleiben unverändert, aber ein Stash wird gespeichert.
Inklusive nicht-verfolgter Dateien
- Behalte gestagte Dateien
Name:
- Optional. Name dieses Stashes
+ Optional. Informationen zu dieses Stashes
+ Modus:
Nur gestagte Änderungen
Gestagte und unstagte Änderungen der ausgewähleten Datei(en) werden gestasht!!!
Lokale Änderungen stashen
Anwenden
+ Kopiere Nachricht
Entfernen
Als Path speichern...
Stash entfernen
@@ -698,11 +723,18 @@
SUBMODULE
Submodul hinzufügen
Relativen Pfad kopieren
+ De-initialisiere Submodul
Untergeordnete Submodule fetchen
Öffne Submodul Repository
Relativer Pfad:
Relativer Ordner um dieses Submodul zu speichern.
Submodul löschen
+ STATUS
+ geändert
+ nicht initialisiert
+ Revision geändert
+ nicht gemerged
+ URL
OK
Tag-Namen kopieren
Tag-Nachricht kopieren
@@ -739,7 +771,7 @@
Git Ignore
Ignoriere alle *{0} Dateien
Ignoriere *{0} Datein im selben Ordner
- Ignoriere Dateien im selben Ordner
+ Ignoriere nicht-verfolgte Dateien in diesem Ordner
Ignoriere nur diese Datei
Amend
Du kannst diese Datei jetzt stagen.
@@ -759,6 +791,7 @@
NICHT-VERFOLGTE DATEIEN INKLUDIEREN
KEINE BISHERIGEN COMMIT-NACHRICHTEN
KEINE COMMIT TEMPLATES
+ Autor zurücksetzen
Rechtsklick auf selektierte Dateien und wähle die Konfliktlösungen aus.
SignOff
GESTAGED
@@ -767,7 +800,7 @@
UNSTAGED
STAGEN
ALLES STAGEN
- ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN
+ ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN
Template: ${0}$
ARBEITSPLATZ:
Arbeitsplätze konfigurieren...
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 4834aef9..d4b4d26f 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -35,6 +35,8 @@
FILES ASSUME UNCHANGED
NO FILES ASSUMED AS UNCHANGED
REMOVE
+ Load Image...
+ Refresh
BINARY FILE NOT SUPPORTED!!!
Bisect
Abort
@@ -84,6 +86,8 @@
Stash & Reapply
Update all submodules
Branch:
+ Checkout & Fast-Forward
+ Fast-Forward to:
Cherry Pick
Append source to commit message
Commit(s):
@@ -116,6 +120,7 @@
Interactively Rebase ${0}$ on Here
Merge to ${0}$
Merge ...
+ Push ${0}$ to ${1}$
Rebase ${0}$ on Here
Reset ${0}$ to Here
Revert Commit
@@ -438,6 +443,7 @@
Workspaces
Pages
Merge Branch
+ Customize merge message
Into:
Merge Option:
Source:
@@ -470,6 +476,7 @@
{0} months ago
{0} years ago
Yesterday
+ Use 'Shift+Enter' to input a new line. 'Enter' is the hotkey of OK button
Preferences
AI
Analyze Diff Prompt
@@ -548,6 +555,8 @@
Force push
Local Branch:
Remote:
+ Revision:
+ Push Revision To Remote
Push Changes To Remote
Remote Branch:
Set as tracking branch
@@ -561,7 +570,6 @@
Stash & reapply local changes
On:
Rebase:
- Refresh
Add Remote
Edit Remote
Name:
@@ -637,8 +645,7 @@
TAGS
New Tag
By Creator Date
- By Name (Ascending)
- By Name (Descending)
+ By Name
Sort
Open in Terminal
Use relative time in histories
@@ -660,7 +667,6 @@
Commit:
Commit revert changes
Reword Commit Message
- Use 'Shift+Enter' to input a new line. 'Enter' is the hotkey of OK button
Running. Please wait...
SAVE
Save As...
@@ -686,16 +692,15 @@
Private SSH key store path
START
Stash
- Auto-restore after stashing
- Your working files remain unchanged, but a stash is saved.
Include untracked files
- Keep staged files
Message:
- Optional. Name of this stash
+ Optional. Message of this stash
+ Mode:
Only staged changes
Both staged and unstaged changes of selected file(s) will be stashed!!!
Stash Local Changes
Apply
+ Copy Message
Drop
Save as Patch...
Drop Stash
@@ -762,7 +767,7 @@
Git Ignore
Ignore all *{0} files
Ignore *{0} files in the same folder
- Ignore files in the same folder
+ Ignore untracked files in this folder
Ignore this file only
Amend
You can stage this file now.
@@ -791,7 +796,7 @@
UNSTAGED
STAGE
STAGE ALL
- VIEW ASSUME UNCHANGED
+ VIEW ASSUME UNCHANGED
Template: ${0}$
WORKSPACE:
Configure Workspaces...
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index 36c60346..d66e515a 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -39,6 +39,8 @@
ARCHIVOS ASUMIDOS COMO SIN CAMBIOS
NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS
REMOVER
+ Cargar Imagen...
+ Refrescar
¡ARCHIVO BINARIO NO SOPORTADO!
Bisect
Abortar
@@ -88,6 +90,8 @@
Stash & Reaplicar
Actualizar todos los submódulos
Rama:
+ Checkout & Fast-Forward
+ Fast-Forward a:
Cherry Pick
Añadir fuente al mensaje de commit
Commit(s):
@@ -474,6 +478,7 @@
Hace {0} meses
Hace {0} años
Ayer
+ Usa 'Shift+Enter' para introducir una nueva línea. 'Enter' es el atajo del botón OK
Preferencias
OPEN AI
Analizar Diff Prompt
@@ -565,7 +570,6 @@
Stash & reaplicar cambios locales
En:
Rebase:
- Refrescar
Añadir Remoto
Editar Remoto
Nombre:
@@ -641,8 +645,7 @@
ETIQUETAS
NUEVA ETIQUETA
Por Fecha de Creación
- Por Nombre (Ascendiente)
- Por Nombre (Descendiente)
+ Por Nombre
Ordenar
Abrir en Terminal
Usar tiempo relativo en las historias
@@ -664,7 +667,6 @@
Commit:
Commit revertir cambios
Reescribir Mensaje de Commit
- Usa 'Shift+Enter' para introducir una nueva línea. 'Enter' es el atajo del botón OK
Ejecutando. Por favor espera...
GUARDAR
Guardar Como...
@@ -690,12 +692,9 @@
Ruta de almacenamiento de la clave privada SSH
INICIAR
Stash
- Restaurar automáticamente después del stashing
- Tus archivos de trabajo permanecen sin cambios, pero se guarda un stash.
Incluir archivos no rastreados
- Mantener archivos staged
Mensaje:
- Opcional. Nombre de este stash
+ Opcional. Información de este stash
Solo cambios staged
¡Tanto los cambios staged como los no staged de los archivos seleccionados serán stashed!
Stash Cambios Locales
@@ -766,7 +765,6 @@
Git Ignore
Ignorar todos los archivos *{0}
Ignorar archivos *{0} en la misma carpeta
- Ignorar archivos en la misma carpeta
Ignorar solo este archivo
Enmendar
Puedes hacer stage a este archivo ahora.
@@ -795,7 +793,7 @@
UNSTAGED
STAGE
STAGE TODO
- VER ASSUME UNCHANGED
+ VER ASSUME UNCHANGED
Plantilla: ${0}$
ESPACIO DE TRABAJO:
Configura Espacios de Trabajo...
diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml
index 25e6ca3e..8e1fd7bd 100644
--- a/src/Resources/Locales/fr_FR.axaml
+++ b/src/Resources/Locales/fr_FR.axaml
@@ -39,6 +39,7 @@
FICHIERS PRÉSUMÉS INCHANGÉS
PAS DE FICHIERS PRÉSUMÉS INCHANGÉS
SUPPRIMER
+ Rafraîchir
FICHIER BINAIRE NON SUPPORTÉ !!!
Blâme
LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!
@@ -443,6 +444,7 @@
il y a {0} mois
il y a {0} ans
Hier
+ Utiliser 'Maj+Entrée' pour insérer une nouvelle ligne. 'Entrée' est la touche pour valider
Préférences
IA
Analyser Diff Prompt
@@ -532,7 +534,6 @@
Stash & réappliquer changements locaux
Sur :
Rebase :
- Rafraîchir
Ajouter dépôt distant
Modifier dépôt distant
Nom :
@@ -602,8 +603,7 @@
TAGS
NOUVEAU TAG
Par date de créateur
- Par nom (Croissant)
- Par nom (Décroissant)
+ Par nom
Trier
Ouvrir dans un terminal
Utiliser le temps relatif dans les historiques
@@ -620,7 +620,6 @@
Commit :
Commit les changements de l'annulation
Reformuler le message de commit
- Utiliser 'Maj+Entrée' pour insérer une nouvelle ligne. 'Entrée' est la touche pour valider
En exécution. Veuillez patienter...
SAUVEGARDER
Sauvegarder en tant que...
@@ -646,12 +645,9 @@
Chemin du magasin de clés privées SSH
START
Stash
- Auto-restauration après le stash
- Vos fichiers de travail restent inchangés, mais une sauvegarde est enregistrée.
Inclure les fichiers non-suivis
- Garder les fichiers indexés
Message :
- Optionnel. Nom de ce stash
+ Optionnel. Information de ce stash
Seulement les changements indexés
Les modifications indexées et non-indexées des fichiers sélectionnés seront stockées!!!
Stash les changements locaux
@@ -711,7 +707,6 @@
Git Ignore
Ignorer tous les *{0} fichiers
Ignorer *{0} fichiers dans le même dossier
- Ignorer les fichiers dans le même dossier
N'ignorer que ce fichier
Amender
Vous pouvez indexer ce fichier.
@@ -734,7 +729,7 @@
NON INDEXÉ
INDEXER
INDEXER TOUT
- VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS
+ VOIR LES FICHIERS PRÉSUMÉS INCHANGÉS
Modèle: ${0}$
ESPACE DE TRAVAIL :
Configurer les espaces de travail...
diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml
index 22c4e8fe..62f15e38 100644
--- a/src/Resources/Locales/it_IT.axaml
+++ b/src/Resources/Locales/it_IT.axaml
@@ -39,6 +39,7 @@
FILE ASSUNTI COME INVARIATI
NESSUN FILE ASSUNTO COME INVARIATO
RIMUOVI
+ Aggiorna
FILE BINARIO NON SUPPORTATO!!!
Biseca
Annulla
@@ -463,6 +464,7 @@
{0} mesi fa
{0} anni fa
Ieri
+ Usa 'Shift+Enter' per inserire una nuova riga. 'Enter' è il tasto rapido per il pulsante OK
Preferenze
AI
Analizza il Prompt Differenza
@@ -553,7 +555,6 @@
Stasha e Riapplica modifiche locali
Su:
Riallinea:
- Aggiorna
Aggiungi Remoto
Modifica Remoto
Nome:
@@ -628,8 +629,7 @@
TAG
NUOVO TAG
Per data di creazione
- Per nome (ascendente)
- Per nome (discendente)
+ Per nome
Ordina
Apri nel Terminale
Usa tempo relativo nello storico
@@ -648,7 +648,6 @@
Commit:
Commit delle modifiche di ripristino
Modifica Messaggio di Commit
- Usa 'Shift+Enter' per inserire una nuova riga. 'Enter' è il tasto rapido per il pulsante OK
In esecuzione. Attendere...
SALVA
Salva come...
@@ -674,12 +673,9 @@
Percorso per la chiave SSH privata
AVVIA
Stasha
- Auto-ripristino dopo lo stash
- I tuoi file di lavoro rimangono inalterati, ma viene salvato uno stash.
Includi file non tracciati
- Mantieni file in stage
Messaggio:
- Opzionale. Nome di questo stash
+ Opzionale. Informazioni di questo stash
Solo modifiche in stage
Sia le modifiche in stage che quelle non in stage dei file selezionati saranno stashate!!!
Stasha Modifiche Locali
@@ -749,7 +745,6 @@
Git Ignore
Ignora tutti i file *{0}
Ignora i file *{0} nella stessa cartella
- Ignora i file nella stessa cartella
Ignora solo questo file
Modifica
Puoi aggiungere in stage questo file ora.
@@ -777,7 +772,7 @@
NON IN STAGE
FAI LO STAGE
FAI LO STAGE DI TUTTO
- VISUALIZZA COME NON MODIFICATO
+ VISUALIZZA COME NON MODIFICATO
Template: ${0}$
WORKSPACE:
Configura Workspaces...
diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml
index 945cf2d9..bf9fe586 100644
--- a/src/Resources/Locales/ja_JP.axaml
+++ b/src/Resources/Locales/ja_JP.axaml
@@ -39,6 +39,7 @@
変更されていないとみなされるファイル
変更されていないとみなされるファイルはありません
削除
+ 更新
バイナリファイルはサポートされていません!!!
Blame
BLAMEではこのファイルはサポートされていません!!!
@@ -442,6 +443,7 @@
{0} ヶ月前
{0} 年前
昨日
+ 改行には'Shift+Enter'キーを使用します。 'Enter"はOKボタンのホットキーとして機能します。
設定
AI
差分分析プロンプト
@@ -531,7 +533,6 @@
ローカルの変更をスタッシュして再適用
On:
リベース:
- 更新
リモートを追加
リモートを編集
名前:
@@ -600,7 +601,7 @@
タグ
新しいタグを作成
作成者日時
- 名前 (昇順)
+ 名前
ソート
ターミナルで開く
履歴に相対時間を使用
@@ -617,7 +618,6 @@
コミット:
コミットの変更を戻す
コミットメッセージを書き直す
- 改行には'Shift+Enter'キーを使用します。 'Enter"はOKボタンのホットキーとして機能します。
実行中です。しばらくお待ちください...
保存
名前を付けて保存...
@@ -643,12 +643,9 @@
プライベートSSHキーストアのパス
スタート
スタッシュ
- スタッシュ後に自動で復元
- 作業ファイルは変更されず、スタッシュが保存されます。
追跡されていないファイルを含める
- ステージされたファイルを保持
メッセージ:
- オプション. このスタッシュの名前を入力
+ オプション. このスタッシュの情報
ステージされた変更のみ
選択したファイルの、ステージされた変更とステージされていない変更の両方がスタッシュされます!!!
ローカルの変更をスタッシュ
@@ -708,7 +705,6 @@
Git Ignore
すべての*{0}ファイルを無視
同じフォルダ内の*{0}ファイルを無視
- 同じフォルダ内のファイルを無視
このファイルのみを無視
Amend
このファイルを今すぐステージできます。
@@ -731,7 +727,7 @@
未ステージのファイル
ステージへ移動
すべてステージへ移動
- 変更されていないとみなしたものを表示
+ 変更されていないとみなしたものを表示
テンプレート: ${0}$
ワークスペース:
ワークスペースを設定...
diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml
index a75d6777..fecd9540 100644
--- a/src/Resources/Locales/pt_BR.axaml
+++ b/src/Resources/Locales/pt_BR.axaml
@@ -33,6 +33,7 @@
ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES
NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES
REMOVER
+ Atualizar
ARQUIVO BINÁRIO NÃO SUPORTADO!!!
Blame
BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!
@@ -405,6 +406,7 @@
{0} meses atrás
{0} anos atrás
Ontem
+ Use 'Shift+Enter' para inserir uma nova linha. 'Enter' é a tecla de atalho do botão OK
Preferências
INTELIGÊNCIA ARTIFICIAL
Prompt para Analisar Diff
@@ -488,7 +490,6 @@
Guardar & reaplicar alterações locais
Em:
Rebase:
- Atualizar
Adicionar Remoto
Editar Remoto
Nome:
@@ -563,7 +564,6 @@
Commit:
Commitar alterações de reversão
Reescrever Mensagem do Commit
- Use 'Shift+Enter' para inserir uma nova linha. 'Enter' é a tecla de atalho do botão OK
Executando. Por favor, aguarde...
SALVAR
Salvar Como...
@@ -585,9 +585,8 @@
INICIAR
Stash
Incluir arquivos não rastreados
- Manter arquivos em stage
Mensagem:
- Opcional. Nome deste stash
+ Opcional. Informações deste stash
Apenas mudanças em stage
Tanto mudanças em stage e fora de stage dos arquivos selecionados serão enviadas para stash!!!
Guardar Alterações Locais
@@ -646,7 +645,6 @@
Git Ignore
Ignorar todos os arquivos *{0}
Ignorar arquivos *{0} na mesma pasta
- Ignorar arquivos na mesma pasta
Ignorar apenas este arquivo
Corrigir
Você pode stagear este arquivo agora.
@@ -667,7 +665,7 @@
UNSTAGED
STAGE
STAGE TODOS
- VER SUPOR NÃO ALTERADO
+ VER SUPOR NÃO ALTERADO
Template: ${0}$
Workspaces:
Configurar workspaces...
diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml
index 0a6ccba4..708ff7cc 100644
--- a/src/Resources/Locales/ru_RU.axaml
+++ b/src/Resources/Locales/ru_RU.axaml
@@ -39,6 +39,8 @@
НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ
СПИСОК ПУСТ
УДАЛИТЬ
+ Загрузить картинку...
+ Обновить
ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!
Раздвоить
О
@@ -50,6 +52,7 @@
Расследование
РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!!
Переключиться на ${0}$...
+ Сравнить с ${0}$
Сравнить с рабочим каталогом
Копировать имя ветки
Изменить действие
@@ -87,6 +90,8 @@
Отложить и примненить повторно
Обновить все подкаталоги
Ветка:
+ Переключиться и перемотать
+ Перемотать к:
Частичный выбор
Добавить источник для ревизии сообщения
Ревизия(и):
@@ -119,6 +124,7 @@
Интерактивное перемещение (rebase -i) ${0}$ сюда
Влить в ${0}$
Влить ...
+ Выложить ${0}$ в ${1}$
Переместить ${0}$ сюда
Сбросить ${0}$ сюда
Отменить ревизию
@@ -441,6 +447,7 @@
Рабочие места
Страницы
Влить ветку
+ Изменить сообщение слияния
В:
Опции слияния:
Источник:
@@ -473,6 +480,7 @@
{0} месяцев назад
{0} лет назад
Вчера
+ Используйте «Shift+Enter» для ввода новой строки. «Enter» - это горячая клавиша кнопки «OK»
Параметры
ОТКРЫТЬ ИИ
Запрос на анализ сравнения
@@ -551,6 +559,8 @@
Принудительно выложить
Локальная ветка:
Внешний репозиторий:
+ Ревизия:
+ Выложить ревизию на удалёную
Выложить изменения на внешний репозиторий
Ветка внешнего репозитория:
Отслеживать ветку
@@ -564,7 +574,6 @@
Отложить и применить повторно локальные изменения
На:
Переместить:
- Обновить
Добавить внешний репозиторий
Редактировать внешний репозиторий
Имя:
@@ -592,6 +601,7 @@
Очистить (Сбор мусора и удаление)
Запустить команду (git gc) для данного репозитория.
Очистить всё
+ Очистить
Настройка репозитория
ПРОДОЛЖИТЬ
Изменить действия
@@ -639,8 +649,7 @@
МЕТКИ
НОВАЯ МЕТКА
По дате создания
- По имени (по возрастанию)
- По имени (по убыванию)
+ По имени
Сортировать
Открыть в терминале
Использовать относительное время в историях
@@ -662,7 +671,6 @@
Ревизия:
Отмена ревизии
Изменить комментарий ревизии
- Используйте «Shift+Enter» для ввода новой строки. «Enter» - это горячая клавиша кнопки «OK»
Запуск. Подождите пожалуйста...
СОХРАНИТЬ
Сохранить как...
@@ -688,16 +696,15 @@
Путь хранения приватного ключа SSH
ЗАПУСК
Отложить
- Автоматически восстанавливать после откладывания
- Ваши рабочие файлы остаются неизменными, но отложенные сохранятся.
Включить неотслеживаемые файлы
- Хранить отложенные файлы
Сообщение:
Имя тайника (необязательно)
+ Режим:
Только сформированные изменения
Сформированные так и несформированные изменения выбранных файлов будут сохранены!!!
Отложить локальные изменения
Принять
+ Копировать сообщение
Отбросить
Сохранить как заплатку...
Отбросить тайник
@@ -764,7 +771,7 @@
Игнорировать Git
Игнорировать все *{0} файлы
Игнорировать *{0} файлы в том же каталоге
- Игнорировать файлы в том же каталоге
+ Игнорировать неотслеживаемые файлы в этом каталоге
Игнорировать только эти файлы
Изменить
Теперь вы можете сформировать этот файл.
@@ -784,6 +791,7 @@
ВКЛЮЧИТЬ НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ
НЕТ ПОСЛЕДНИХ ВХОДНЫХ СООБЩЕНИЙ
НЕТ ШАБЛОНОВ РЕВИЗИИ
+ Сбросить автора
Щёлкните правой кнопкой мыши выбранный файл(ы) и разрешите конфликты.
Завершение работы
СФОРМИРОВАННЫЕ
@@ -792,7 +800,7 @@
НЕСФОРМИРОВАННЫЕ
СФОРМИРОВАТЬ
СФОРМИРОВАТЬ ВСЁ
- ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ
+ ОТКРЫТЬ СПИСОК НЕОТСЛЕЖИВАЕМЫХ ФАЙЛОВ
Шаблон: ${0}$
РАБОЧЕЕ ПРОСТРАНСТВО:
Настройка рабочего пространства...
diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml
index e66af3ff..248d5f42 100644
--- a/src/Resources/Locales/ta_IN.axaml
+++ b/src/Resources/Locales/ta_IN.axaml
@@ -39,6 +39,7 @@
கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது
எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது
நீக்கு
+ புதுப்பி
இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!
குற்றச்சாட்டு
இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!
@@ -442,6 +443,7 @@
{0} திங்களுக்கு முன்பு
{0} ஆண்டுகளுக்கு முன்பு
நேற்று
+ புதிய வரியை உள்ளிட 'உயர்த்து+நுழை' ஐப் பயன்படுத்தவும். 'நுழை' என்பது சரி பொத்தானின் சூடானவிசை ஆகும்
விருப்பத்தேர்வுகள்
செநு
வேறுபாடு உடனடியாக பகுப்பாய்வு செய்
@@ -531,7 +533,6 @@
உள்ளக மாற்றங்களை பதுக்கிவை & மீண்டும் இடு
மேல்:
மறுதளம்:
- புதுப்பி
தொலையைச் சேர்
தொலையைத் திருத்து
பெயர்:
@@ -601,8 +602,7 @@
குறிசொற்கள்
புதிய குறிசொல்
படைப்பாளர் தேதியின்படி
- பெயர் (ஏறுவரிசை) மூலம்
- பெயர் (இறகுவரிசை) மூலம்
+ பெயர் மூலம்
வரிசைப்படுத்து
முனையத்தில் திற
வரலாறுகளில் உறவு நேரத்தைப் பயன்படுத்து
@@ -619,7 +619,6 @@
உறுதிமொழி:
பின்வாங்கு மாற்றங்களை உறுதிமொழி
மாறுசொல் உறுதிமொழி செய்தி
- புதிய வரியை உள்ளிட 'உயர்த்து+நுழை' ஐப் பயன்படுத்தவும். 'நுழை' என்பது சரி பொத்தானின் சூடானவிசை ஆகும்
இயங்குகிறது. காத்திருக்கவும்...
சேமி
எனச் சேமி...
@@ -645,10 +644,7 @@
தனியார் பாஓடு திறவுகோல் கடை பாதை
தொடங்கு
பதுக்கிவை
- பதுக்கிவைத்த பிறகு தானியங்கி மீட்டமை
- உங்கள் செயல்படும் கோப்புகள் மாறாமல் இருக்கும், ஆனால் ஒரு பதுக்கிவைக்கப்படும்.
கண்காணிக்கப்படாத கோப்புகளைச் சேர்
- நிலைப்படுத்தப்பட்ட கோப்புகளை வைத்திரு
செய்தி:
விருப்பத்தேர்வு. இந்த பதுக்கலின் பெயர்
நிலைப்படுத்தப்பட்ட மாற்றங்கள் மட்டும்
@@ -709,7 +705,6 @@
அறிவிலி புறக்கணி
எல்லா *{0} கோப்புகளையும் புறக்கணி
ஒரே கோப்புறையில் *{0} கோப்புகளைப் புறக்கணி
- ஒரே கோப்புறையில் கோப்புகளைப் புறக்கணி
இந்த கோப்பை மட்டும் புறக்கணி
பின்னொட்டு
இந்த கோப்பை இப்போது நீங்கள் நிலைப்படுத்தலாம்.
@@ -733,7 +728,7 @@
நிலைநீக்கு
நிலைபடுத்து
அனைத்தும் நிலைபடுத்து
- மாறாதது எனநினைப்பதை பார்
+ மாறாதது எனநினைப்பதை பார்
வளர்புரு: ${0}$
பணியிடம்:
பணியிடங்களை உள்ளமை...
diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml
index 2e7b399b..5d120117 100644
--- a/src/Resources/Locales/uk_UA.axaml
+++ b/src/Resources/Locales/uk_UA.axaml
@@ -39,6 +39,7 @@
ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
ВИДАЛИТИ
+ Оновити
БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!
Автор рядка
ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!
@@ -447,6 +448,7 @@
{0} місяців тому
{0} років тому
Вчора
+ Використовуйте 'Shift+Enter' для введення нового рядка. 'Enter' - гаряча клавіша кнопки OK
Налаштування
AI
Промпт для аналізу різниці
@@ -536,7 +538,6 @@
Сховати та застосувати локальні зміни
На:
Перебазувати:
- Оновити
Додати віддалене сховище
Редагувати віддалене сховище
Назва:
@@ -606,8 +607,7 @@
ТЕГИ
НОВИЙ ТЕГ
За датою створення
- За назвою (за зростанням)
- За назвою (за спаданням)
+ За назвою
Сортувати
Відкрити в терміналі
Використовувати відносний час в історії
@@ -624,7 +624,6 @@
Коміт:
Закомітити зміни скасування
Змінити повідомлення коміту
- Використовуйте 'Shift+Enter' для введення нового рядка. 'Enter' - гаряча клавіша кнопки OK
Виконується. Будь ласка, зачекайте...
ЗБЕРЕГТИ
Зберегти як...
@@ -650,10 +649,7 @@
Шлях до сховища приватного ключа SSH
ПОЧАТИ
Stash (Сховати)
- Автоматично відновити після схову
- Ваші робочі файли залишаться без змін, але буде збережено схованку.
Включити невідстежувані файли
- Зберегти проіндексовані файли
Повідомлення:
Необов'язково. Назва цієї схованки
Лише проіндексовані зміни
@@ -715,7 +711,6 @@
Git Ignore
Ігнорувати всі файли *{0}
Ігнорувати файли *{0} у цій же теці
- Ігнорувати файли у цій же теці
Ігнорувати лише цей файл
Amend (Доповнити)
Тепер ви можете проіндексувати цей файл.
@@ -743,7 +738,7 @@
НЕПРОІНДЕКСОВАНІ
ІНДЕКСУВАТИ
ІНДЕКСУВАТИ ВСЕ
- ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
+ ПЕРЕГЛЯНУТИ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
Шаблон: ${0}$
РОБОЧИЙ ПРОСТІР:
Налаштувати робочі простори...
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 77a55f75..2a5991fd 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -39,6 +39,8 @@
不跟踪更改的文件
没有不跟踪更改的文件
移除
+ 加载本地图片
+ 重新加载
二进制文件不支持该操作!!!
二分定位(bisect)
终止
@@ -88,6 +90,8 @@
贮藏并自动恢复
同时更新所有子模块
目标分支 :
+ 检出分支并快进
+ 上游分支 :
挑选提交
提交信息中追加来源信息
提交列表 :
@@ -120,6 +124,7 @@
交互式变基(rebase -i) ${0}$ 到此处
合并(merge)此提交至 ${0}$
合并(merge)...
+ 推送(push) ${0}$ 到 ${1}$
变基(rebase) ${0}$ 到此处
重置(reset) ${0}$ 到此处
回滚此提交
@@ -442,6 +447,7 @@
工作区列表
页面列表
合并分支
+ 编辑合并信息
目标分支 :
合并方式 :
合并目标 :
@@ -474,6 +480,7 @@
{0}个月前
{0}年前
昨天
+ 请使用Shift+Enter换行。Enter键已被【确 定】按钮占用。
偏好设置
AI
Analyze Diff Prompt
@@ -552,6 +559,8 @@
启用强制推送
本地分支 :
远程仓库 :
+ 修订 :
+ 推送指定修订到远程仓库
推送到远程仓库
远程分支 :
跟踪远程分支
@@ -565,7 +574,6 @@
自动贮藏并恢复本地变更
目标提交 :
分支 :
- 重新加载
添加远程仓库
编辑远程仓库
远程名 :
@@ -641,8 +649,7 @@
标签列表
新建标签
按创建时间
- 按名称(升序)
- 按名称(降序)
+ 按名称
排序
在终端中打开
在提交列表中使用相对时间
@@ -664,7 +671,6 @@
目标提交 :
回滚后提交更改
编辑提交信息
- 请使用Shift+Enter换行。Enter键已被【确 定】按钮占用。
执行操作中,请耐心等待...
保 存
另存为...
@@ -690,16 +696,15 @@
SSH密钥文件
开 始
贮藏(stash)
- 贮藏后自动恢复工作区
- 工作区文件保持未修改状态,但贮藏内容已保存。
包含未跟踪的文件
- 保留暂存区文件
信息 :
- 选填,用于命名此贮藏
+ 选填,此贮藏的描述信息
+ 模式 :
仅贮藏暂存区的变更
选中文件的所有变更均会被贮藏!
贮藏本地变更
应用(apply)
+ 复制描述信息
删除(drop)
另存为补丁...
丢弃贮藏确认
@@ -766,7 +771,7 @@
添加至 .gitignore 忽略列表
忽略所有 *{0} 文件
忽略同目录下所有 *{0} 文件
- 忽略同目录下所有文件
+ 忽略该目录下的新文件
忽略本文件
修补
现在您已可将其加入暂存区中
@@ -795,7 +800,7 @@
未暂存
暂存选中
暂存所有
- 查看忽略变更文件
+ 查看忽略变更文件
模板:${0}$
工作区:
配置工作区...
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index aef769de..f1736ff8 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -39,6 +39,8 @@
不追蹤變更的檔案
沒有不追蹤變更的檔案
移除
+ 載入本機圖片...
+ 重新載入
二進位檔案不支援該操作!
二分搜尋 (bisect)
中止
@@ -88,6 +90,8 @@
擱置變更並自動復原
同時更新所有子模組
目標分支:
+ 簽出分支並快轉
+ 上游分支 :
揀選提交
提交資訊中追加來源資訊
提交列表:
@@ -120,6 +124,7 @@
互動式重定基底 (rebase -i) ${0}$ 到此處
合併 (merge) 此提交到 ${0}$
合併 (merge)...
+ 推送(push) ${0}$ 至 ${1}$
重定基底 (rebase) ${0}$ 到此處
重設 (reset) ${0}$ 到此處
復原此提交
@@ -442,6 +447,7 @@
工作區列表
頁面列表
合併分支
+ 編輯合併訊息
目標分支:
合併方式:
合併來源:
@@ -474,6 +480,7 @@
{0} 個月前
{0} 年前
昨天
+ 請使用 Shift + Enter 換行。Enter 鍵已被 [確定] 按鈕佔用。
偏好設定
AI
分析變更差異提示詞
@@ -552,6 +559,8 @@
啟用強制推送
本機分支:
遠端存放庫:
+ 修訂:
+ 推送修訂到遠端存放庫
推送到遠端存放庫
遠端分支:
追蹤遠端分支
@@ -565,7 +574,6 @@
自動擱置變更並復原本機變更
目標提交:
分支:
- 重新載入
新增遠端存放庫
編輯遠端存放庫
遠端名稱:
@@ -641,8 +649,7 @@
標籤列表
新增標籤
依建立時間
- 依名稱升序
- 依名稱降序
+ 依名稱
排序
在終端機中開啟
在提交列表中使用相對時間
@@ -664,7 +671,6 @@
目標提交:
復原後提交變更
編輯提交訊息
- 請使用 Shift + Enter 換行。Enter 鍵已被 [確定] 按鈕佔用。
執行操作中,請耐心等待...
儲存
另存新檔...
@@ -690,16 +696,15 @@
SSH 金鑰檔案
開 始
擱置變更 (stash)
- 擱置變更後自動復原工作區
- 工作區檔案保持未修改,但擱置內容已儲存。
包含未追蹤的檔案
- 保留已暫存的變更
擱置變更訊息:
- 選填,用於命名此擱置變更
+ 選填,用於描述此擱置變更
+ 操作模式:
僅擱置已暫存的變更
已選取的檔案中的變更均會被擱置!
擱置本機變更
套用 (apply)
+ 複製描述訊息
刪除 (drop)
另存為修補檔 (patch)...
捨棄擱置變更確認
@@ -766,7 +771,7 @@
加入至 .gitignore 忽略清單
忽略所有 *{0} 檔案
忽略同路徑下所有 *{0} 檔案
- 忽略同路徑下所有檔案
+ 忽略本路徑下的新增檔案
忽略本檔案
修補
現在您已可將其加入暫存區中
@@ -795,7 +800,7 @@
未暫存
暫存選取的檔案
暫存所有檔案
- 檢視不追蹤變更的檔案
+ 檢視不追蹤變更的檔案
範本: ${0}$
工作區:
設定工作區...
diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml
index 923ef22b..f42160a2 100644
--- a/src/Resources/Styles.axaml
+++ b/src/Resources/Styles.axaml
@@ -16,7 +16,7 @@
12
-
+
@@ -38,7 +38,7 @@
-
+
@@ -206,7 +206,7 @@
-
+
-
+
-
+
-
+
-
+
@@ -737,7 +731,7 @@
-
+
@@ -949,6 +947,20 @@
+
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
();
+ if (textDiffView == null)
+ return;
+
+ var presenter = textDiffView.FindDescendantOfType();
+ if (presenter == null)
+ return;
+
+ if (presenter.DataContext is Models.TextDiff combined)
+ combined.ScrollOffset = Vector.Zero;
+ else if (presenter.DataContext is ViewModels.TwoSideTextDiff twoSides)
+ twoSides.File = string.Empty; // Just to reset `SyncScrollOffset` without affect UI refresh.
+
+ (DataContext as ViewModels.DiffContext)?.ToggleFullTextDiff();
+ e.Handled = true;
+ }
}
}
diff --git a/src/Views/DropStash.axaml b/src/Views/DropStash.axaml
index 32685a2c..aa5de85a 100644
--- a/src/Views/DropStash.axaml
+++ b/src/Views/DropStash.axaml
@@ -3,7 +3,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
- xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.DropStash"
x:DataType="vm:DropStash">
@@ -16,14 +15,16 @@
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.StashDropConfirm.Label}"/>
-
-
+
-
-
-
+
+
+
diff --git a/src/Views/FileHistories.axaml b/src/Views/FileHistories.axaml
index e7a5c072..e9c956ec 100644
--- a/src/Views/FileHistories.axaml
+++ b/src/Views/FileHistories.axaml
@@ -13,12 +13,7 @@
Icon="/App.ico"
Title="{DynamicResource Text.FileHistory}"
MinWidth="1280" MinHeight="720">
-
-
-
-
-
-
+
@@ -139,7 +134,7 @@
-
+
+
+
+
+
+
+
+
diff --git a/src/Views/FileHistories.axaml.cs b/src/Views/FileHistories.axaml.cs
index 3631eb71..6a67d120 100644
--- a/src/Views/FileHistories.axaml.cs
+++ b/src/Views/FileHistories.axaml.cs
@@ -25,11 +25,11 @@ namespace SourceGit.Views
e.Handled = true;
}
- private void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
+ private async void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: ViewModels.FileHistoriesSingleRevision single })
{
- single.ResetToSelectedRevision();
+ await single.ResetToSelectedRevision();
NotifyDonePanel.IsVisible = true;
}
@@ -51,7 +51,7 @@ namespace SourceGit.Views
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
- var storageFile = await this.StorageProvider.SaveFilePickerAsync(options);
+ var storageFile = await StorageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
await compare.SaveAsPatch(storageFile.Path.LocalPath);
@@ -76,5 +76,13 @@ namespace SourceGit.Views
ToolTip.SetTip(border, vm.GetCommitFullMessage(commit));
}
}
+
+ private async void OnOpenFileWithDefaultEditor(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is ViewModels.FileHistories { ViewContent: ViewModels.FileHistoriesSingleRevision revision })
+ await revision.OpenWithDefaultEditor();
+
+ e.Handled = true;
+ }
}
}
diff --git a/src/Views/FilterModeInGraph.axaml b/src/Views/FilterModeInGraph.axaml
new file mode 100644
index 00000000..520a3836
--- /dev/null
+++ b/src/Views/FilterModeInGraph.axaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/FilterModeInGraph.axaml.cs b/src/Views/FilterModeInGraph.axaml.cs
new file mode 100644
index 00000000..c3987f91
--- /dev/null
+++ b/src/Views/FilterModeInGraph.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Controls;
+
+namespace SourceGit.Views
+{
+ public partial class FilterModeInGraph : UserControl
+ {
+ public FilterModeInGraph()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/Views/FilterModeSwitchButton.axaml.cs b/src/Views/FilterModeSwitchButton.axaml.cs
index 1d1ae30c..b3b2c3da 100644
--- a/src/Views/FilterModeSwitchButton.axaml.cs
+++ b/src/Views/FilterModeSwitchButton.axaml.cs
@@ -163,5 +163,3 @@ namespace SourceGit.Views
}
}
}
-
-
diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml
index aa9d615b..35951cb1 100644
--- a/src/Views/Histories.axaml
+++ b/src/Views/Histories.axaml
@@ -34,7 +34,7 @@
-
+
@@ -70,7 +70,6 @@
LayoutUpdated="OnCommitListLayoutUpdated"
SelectionChanged="OnCommitListSelectionChanged"
ContextRequested="OnCommitListContextRequested"
- DoubleTapped="OnCommitListDoubleTapped"
KeyDown="OnCommitListKeyDown">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/src/Views/RevisionFileContentViewer.axaml.cs b/src/Views/RevisionFileContentViewer.axaml.cs
index 16f4fc83..cfbb6e3d 100644
--- a/src/Views/RevisionFileContentViewer.axaml.cs
+++ b/src/Views/RevisionFileContentViewer.axaml.cs
@@ -24,6 +24,15 @@ namespace SourceGit.Views
set => SetValue(TabWidthProperty, value);
}
+ public static readonly StyledProperty UseSyntaxHighlightingProperty =
+ AvaloniaProperty.Register(nameof(UseSyntaxHighlighting));
+
+ public bool UseSyntaxHighlighting
+ {
+ get => GetValue(UseSyntaxHighlightingProperty);
+ set => SetValue(UseSyntaxHighlightingProperty, value);
+ }
+
protected override Type StyleKeyOverride => typeof(TextEditor);
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
@@ -72,8 +81,9 @@ namespace SourceGit.Views
if (DataContext is Models.RevisionTextFile source)
{
- UpdateTextMate();
Text = source.Content;
+ Models.TextMateHelper.SetGrammarByFileName(_textMate, source.FileName);
+ ScrollToHome();
}
else
{
@@ -86,9 +96,9 @@ namespace SourceGit.Views
base.OnPropertyChanged(change);
if (change.Property == TabWidthProperty)
- {
Options.IndentationSize = TabWidth;
- }
+ else if (change.Property == UseSyntaxHighlightingProperty)
+ UpdateTextMate();
}
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
@@ -124,11 +134,21 @@ namespace SourceGit.Views
private void UpdateTextMate()
{
- if (_textMate == null)
- _textMate = Models.TextMateHelper.CreateForEditor(this);
+ if (UseSyntaxHighlighting)
+ {
+ _textMate ??= Models.TextMateHelper.CreateForEditor(this);
- if (DataContext is Models.RevisionTextFile file)
- Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName);
+ if (DataContext is Models.RevisionTextFile file)
+ Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName);
+ }
+ else if (_textMate != null)
+ {
+ _textMate.Dispose();
+ _textMate = null;
+ GC.Collect();
+
+ TextArea.TextView.Redraw();
+ }
}
private TextMate.Installation _textMate = null;
@@ -142,4 +162,3 @@ namespace SourceGit.Views
}
}
}
-
diff --git a/src/Views/RevisionFileTreeView.axaml.cs b/src/Views/RevisionFileTreeView.axaml.cs
index b671851c..de396b1a 100644
--- a/src/Views/RevisionFileTreeView.axaml.cs
+++ b/src/Views/RevisionFileTreeView.axaml.cs
@@ -134,10 +134,7 @@ namespace SourceGit.Views
set => SetValue(RevisionProperty, value);
}
- public AvaloniaList Rows
- {
- get => _rows;
- }
+ public AvaloniaList Rows { get; } = [];
public RevisionFileTreeView()
{
@@ -146,7 +143,7 @@ namespace SourceGit.Views
public void SetSearchResult(string file)
{
- _rows.Clear();
+ Rows.Clear();
_searchResult.Clear();
var rows = new List();
@@ -157,14 +154,14 @@ namespace SourceGit.Views
else
{
var vm = DataContext as ViewModels.CommitDetail;
- if (vm == null || vm.Commit == null)
+ if (vm?.Commit == null)
return;
var objects = vm.GetRevisionFilesUnderFolder(file);
- if (objects == null || objects.Count != 1)
+ if (objects is not { Count: 1 })
return;
- var routes = file.Split('/', StringSplitOptions.None);
+ var routes = file.Split('/');
if (routes.Length == 1)
{
_searchResult.Add(new ViewModels.RevisionFileTreeNode
@@ -202,7 +199,7 @@ namespace SourceGit.Views
MakeRows(rows, _searchResult, 0);
}
- _rows.AddRange(rows);
+ Rows.AddRange(rows);
GC.Collect();
}
@@ -212,7 +209,7 @@ namespace SourceGit.Views
node.IsExpanded = !node.IsExpanded;
var depth = node.Depth;
- var idx = _rows.IndexOf(node);
+ var idx = Rows.IndexOf(node);
if (idx == -1)
return;
@@ -223,21 +220,21 @@ namespace SourceGit.Views
{
var subrows = new List();
MakeRows(subrows, subtree, depth + 1);
- _rows.InsertRange(idx + 1, subrows);
+ Rows.InsertRange(idx + 1, subrows);
}
}
else
{
var removeCount = 0;
- for (int i = idx + 1; i < _rows.Count; i++)
+ for (int i = idx + 1; i < Rows.Count; i++)
{
- var row = _rows[i];
+ var row = Rows[i];
if (row.Depth <= depth)
break;
removeCount++;
}
- _rows.RemoveRange(idx + 1, removeCount);
+ Rows.RemoveRange(idx + 1, removeCount);
}
_disableSelectionChangingEvent = false;
@@ -250,11 +247,11 @@ namespace SourceGit.Views
if (change.Property == RevisionProperty)
{
_tree.Clear();
- _rows.Clear();
+ Rows.Clear();
_searchResult.Clear();
var vm = DataContext as ViewModels.CommitDetail;
- if (vm == null || vm.Commit == null)
+ if (vm?.Commit == null)
{
GC.Collect();
return;
@@ -270,16 +267,11 @@ namespace SourceGit.Views
foreach (var obj in objects)
_tree.Add(new ViewModels.RevisionFileTreeNode { Backend = obj });
- _tree.Sort((l, r) =>
- {
- if (l.IsFolder == r.IsFolder)
- return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
- return l.IsFolder ? -1 : 1;
- });
+ SortNodes(_tree);
var topTree = new List();
MakeRows(topTree, _tree, 0);
- _rows.AddRange(topTree);
+ Rows.AddRange(topTree);
GC.Collect();
}
}
@@ -313,16 +305,13 @@ namespace SourceGit.Views
private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _)
{
- if (_disableSelectionChangingEvent)
+ if (_disableSelectionChangingEvent || DataContext is not ViewModels.CommitDetail vm)
return;
- if (sender is ListBox { SelectedItem: ViewModels.RevisionFileTreeNode node } && DataContext is ViewModels.CommitDetail vm)
- {
- if (!node.IsFolder)
- vm.ViewRevisionFile(node.Backend);
- else
- vm.ViewRevisionFile(null);
- }
+ if (sender is ListBox { SelectedItem: ViewModels.RevisionFileTreeNode { IsFolder: false } node })
+ vm.ViewRevisionFile(node.Backend);
+ else
+ vm.ViewRevisionFile(null);
}
private List GetChildrenOfTreeNode(ViewModels.RevisionFileTreeNode node)
@@ -344,13 +333,7 @@ namespace SourceGit.Views
foreach (var obj in objects)
node.Children.Add(new ViewModels.RevisionFileTreeNode() { Backend = obj });
- node.Children.Sort((l, r) =>
- {
- if (l.IsFolder == r.IsFolder)
- return Models.NumericSort.Compare(l.Name, r.Name);
- return l.IsFolder ? -1 : 1;
- });
-
+ SortNodes(node.Children);
return node.Children;
}
@@ -368,8 +351,17 @@ namespace SourceGit.Views
}
}
+ private void SortNodes(List nodes)
+ {
+ nodes.Sort((l, r) =>
+ {
+ if (l.IsFolder == r.IsFolder)
+ return Models.NumericSort.Compare(l.Name, r.Name);
+ return l.IsFolder ? -1 : 1;
+ });
+ }
+
private List _tree = [];
- private AvaloniaList _rows = [];
private bool _disableSelectionChangingEvent = false;
private List _searchResult = [];
}
diff --git a/src/Views/RevisionFiles.axaml b/src/Views/RevisionFiles.axaml
index 6575dc66..961a05b5 100644
--- a/src/Views/RevisionFiles.axaml
+++ b/src/Views/RevisionFiles.axaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
@@ -113,7 +114,49 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/RevisionFiles.axaml.cs b/src/Views/RevisionFiles.axaml.cs
index 3208fbb8..4894d1d4 100644
--- a/src/Views/RevisionFiles.axaml.cs
+++ b/src/Views/RevisionFiles.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Input;
+using Avalonia.Interactivity;
namespace SourceGit.Views
{
@@ -80,5 +81,13 @@ namespace SourceGit.Views
e.Handled = true;
}
+
+ private async void OnOpenFileWithDefaultEditor(object sender, RoutedEventArgs e)
+ {
+ if (DataContext is ViewModels.CommitDetail { CanOpenRevisionFileWithDefaultEditor: true } vm)
+ await vm.OpenRevisionFileWithDefaultEditor(vm.ViewRevisionFilePath);
+
+ e.Handled = true;
+ }
}
}
diff --git a/src/Views/Reword.axaml b/src/Views/Reword.axaml
index 3ea1ad98..3abbd81b 100644
--- a/src/Views/Reword.axaml
+++ b/src/Views/Reword.axaml
@@ -21,7 +21,7 @@
diff --git a/src/Views/SelfUpdate.axaml.cs b/src/Views/SelfUpdate.axaml.cs
index d3776aca..6f4ab94c 100644
--- a/src/Views/SelfUpdate.axaml.cs
+++ b/src/Views/SelfUpdate.axaml.cs
@@ -25,7 +25,6 @@ namespace SourceGit.Views
TextArea.TextView.Margin = new Thickness(4, 0);
TextArea.TextView.Options.EnableHyperlinks = false;
TextArea.TextView.Options.EnableEmailHyperlinks = false;
-
}
protected override void OnLoaded(RoutedEventArgs e)
diff --git a/src/Views/Squash.axaml b/src/Views/Squash.axaml
index 30755bae..30915029 100644
--- a/src/Views/Squash.axaml
+++ b/src/Views/Squash.axaml
@@ -31,7 +31,7 @@
diff --git a/src/Views/StandaloneCommitMessageEditor.axaml.cs b/src/Views/StandaloneCommitMessageEditor.axaml.cs
deleted file mode 100644
index 8a49ee74..00000000
--- a/src/Views/StandaloneCommitMessageEditor.axaml.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.IO;
-
-using Avalonia.Interactivity;
-
-namespace SourceGit.Views
-{
- public partial class StandaloneCommitMessageEditor : ChromelessWindow
- {
- public StandaloneCommitMessageEditor()
- {
- InitializeComponent();
- }
-
- public void SetFile(string file)
- {
- _file = file;
-
- var content = File.ReadAllText(file).ReplaceLineEndings("\n").Trim();
- var firstLineEnd = content.IndexOf('\n');
- if (firstLineEnd == -1)
- {
- Editor.SubjectEditor.Text = content;
- }
- else
- {
- Editor.SubjectEditor.Text = content.Substring(0, firstLineEnd);
- Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1).Trim();
- }
- }
-
- protected override void OnClosed(EventArgs e)
- {
- base.OnClosed(e);
- App.Quit(_exitCode);
- }
-
- private void SaveAndClose(object _1, RoutedEventArgs _2)
- {
- if (!string.IsNullOrEmpty(_file))
- {
- File.WriteAllText(_file, Editor.Text);
- _exitCode = 0;
- }
-
- Close();
- }
-
- private string _file = string.Empty;
- private int _exitCode = -1;
- }
-}
diff --git a/src/Views/StashChanges.axaml b/src/Views/StashChanges.axaml
index 51ed87ac..52af4edd 100644
--- a/src/Views/StashChanges.axaml
+++ b/src/Views/StashChanges.axaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
@@ -11,45 +12,77 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+ Content="{DynamicResource Text.Stash.IncludeUntracked}"
+ IsChecked="{Binding IncludeUntracked, Mode=TwoWay}"
+ ToolTip.Tip="--include-untracked">
+
+
+
+
+
+
+
FontFamilyProperty =
+ AvaloniaProperty.Register(nameof(FontFamily));
+
+ public FontFamily FontFamily
+ {
+ get => GetValue(FontFamilyProperty);
+ set => SetValue(FontFamilyProperty, value);
+ }
+
+ public static readonly StyledProperty FontSizeProperty =
+ AvaloniaProperty.Register(nameof(FontSize), 13);
+
+ public double FontSize
+ {
+ get => GetValue(FontSizeProperty);
+ set => SetValue(FontSizeProperty, value);
+ }
+
+ public static readonly StyledProperty ForegroundProperty =
+ AvaloniaProperty.Register(nameof(Foreground), Brushes.White);
+
+ public IBrush Foreground
+ {
+ get => GetValue(ForegroundProperty);
+ set => SetValue(ForegroundProperty, value);
+ }
+
+ public static readonly StyledProperty PrefixBackgroundProperty =
+ AvaloniaProperty.Register(nameof(PrefixBackground), Brushes.Transparent);
+
+ public IBrush PrefixBackground
+ {
+ get => GetValue(PrefixBackgroundProperty);
+ set => SetValue(PrefixBackgroundProperty, value);
+ }
+
+ public static readonly StyledProperty SubjectProperty =
+ AvaloniaProperty.Register(nameof(Subject));
+
+ public string Subject
+ {
+ get => GetValue(SubjectProperty);
+ set => SetValue(SubjectProperty, value);
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ base.Render(context);
+
+ var subject = Subject;
+ if (string.IsNullOrEmpty(subject))
+ return;
+
+ var typeface = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Normal);
+ var foreground = Foreground;
+ var x = 0.0;
+ var h = Bounds.Height;
+ var prefix = null as FormattedText;
+
+ var match = REG_KEYWORD_ON().Match(subject);
+ if (match.Success)
+ {
+ prefix = new FormattedText(match.Groups[1].Value, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 11, foreground);
+ subject = subject.Substring(match.Length);
+ }
+ else
+ {
+ match = REG_KEYWORD_WIP().Match(subject);
+ if (match.Success)
+ {
+ prefix = new FormattedText($"WIP | {match.Groups[1].Value}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 11, foreground);
+ subject = subject.Substring(match.Length);
+ }
+ }
+
+ if (prefix != null)
+ {
+ var pw = prefix.WidthIncludingTrailingWhitespace;
+ var ph = prefix.Height;
+ var bh = ph + 4;
+ var bw = pw + 12;
+
+ context.DrawRectangle(PrefixBackground, null, new RoundedRect(new Rect(0, (h - bh) * 0.5, bw, bh), new CornerRadius(bh * 0.5)));
+ context.DrawText(prefix, new Point(6, (h - ph) * 0.5));
+ x = bw + 4;
+ }
+
+ var body = new FormattedText(subject, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, FontSize, foreground);
+ context.DrawText(body, new Point(x, (h - body.Height) * 0.5));
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == SubjectProperty ||
+ change.Property == FontFamilyProperty ||
+ change.Property == FontSizeProperty ||
+ change.Property == ForegroundProperty ||
+ change.Property == PrefixBackgroundProperty)
+ {
+ InvalidateVisual();
+ }
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ var typeface = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Normal);
+ var test = new FormattedText("fgl|", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, FontSize, Brushes.White);
+ var h = Math.Max(18, test.Height);
+ return new Size(availableSize.Width, h);
+ }
+
+ [GeneratedRegex(@"^On ([^\s]+)\: ")]
+ private static partial Regex REG_KEYWORD_ON();
+
+ [GeneratedRegex(@"^WIP on ([^\s]+)\: ([a-f0-9]{6,40}) ")]
+ private static partial Regex REG_KEYWORD_WIP();
+ }
+}
diff --git a/src/Views/StashesPage.axaml b/src/Views/StashesPage.axaml
index 15427b93..1c3e2e50 100644
--- a/src/Views/StashesPage.axaml
+++ b/src/Views/StashesPage.axaml
@@ -65,6 +65,7 @@
ItemsSource="{Binding VisibleStashes}"
SelectedItem="{Binding SelectedStash, Mode=TwoWay}"
SelectionMode="Single"
+ KeyDown="OnStashListKeyDown"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
@@ -83,14 +84,23 @@
-
+
-
+
diff --git a/src/Views/StashesPage.axaml.cs b/src/Views/StashesPage.axaml.cs
index 461f9d5d..d152a12f 100644
--- a/src/Views/StashesPage.axaml.cs
+++ b/src/Views/StashesPage.axaml.cs
@@ -1,4 +1,5 @@
using Avalonia.Controls;
+using Avalonia.Input;
namespace SourceGit.Views
{
@@ -23,6 +24,18 @@ namespace SourceGit.Views
layout.StashesLeftWidth = new GridLength(maxLeft, GridUnitType.Pixel);
}
+ private void OnStashListKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key is not (Key.Delete or Key.Back))
+ return;
+
+ if (DataContext is not ViewModels.StashesPage vm)
+ return;
+
+ vm.Drop(vm.SelectedStash);
+ e.Handled = true;
+ }
+
private void OnStashContextRequested(object sender, ContextRequestedEventArgs e)
{
if (DataContext is ViewModels.StashesPage vm && sender is Border border)
diff --git a/src/Views/Statistics.axaml b/src/Views/Statistics.axaml
index a2d18393..163ce031 100644
--- a/src/Views/Statistics.axaml
+++ b/src/Views/Statistics.axaml
@@ -136,7 +136,7 @@
-
+
-
+
diff --git a/src/Views/TagsView.axaml b/src/Views/TagsView.axaml
index 0dbe6dae..655d046a 100644
--- a/src/Views/TagsView.axaml
+++ b/src/Views/TagsView.axaml
@@ -23,6 +23,7 @@
@@ -40,7 +41,7 @@
-
+
+ ToolTip.Placement="Right">
@@ -88,6 +89,7 @@
Margin="8,0,0,0"
ItemsSource="{Binding Tags}"
SelectionMode="Single"
+ KeyDown="OnKeyDown"
SelectionChanged="OnSelectionChanged">
@@ -109,7 +111,7 @@
-
+
-
diff --git a/src/Views/TagsView.axaml.cs b/src/Views/TagsView.axaml.cs
index 6764c7ea..1b384262 100644
--- a/src/Views/TagsView.axaml.cs
+++ b/src/Views/TagsView.axaml.cs
@@ -214,6 +214,19 @@ namespace SourceGit.Views
if (selectedTag != null)
RaiseEvent(new RoutedEventArgs(SelectionChangedEvent));
}
+
+ private void OnKeyDown(object sender, KeyEventArgs e)
+ {
+ if (DataContext is not ViewModels.Repository repo)
+ return;
+
+ var selected = (sender as ListBox)?.SelectedItem;
+ if (selected is ViewModels.TagTreeNode { Tag: { } tagInNode })
+ repo.DeleteTag(tagInNode);
+ else if (selected is Models.Tag tag)
+ repo.DeleteTag(tag);
+
+ e.Handled = true;
+ }
}
}
-
diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs
index 999c3262..e08554e9 100644
--- a/src/Views/TextDiffView.axaml.cs
+++ b/src/Views/TextDiffView.axaml.cs
@@ -348,16 +348,11 @@ namespace SourceGit.Views
private ThemedTextDiffPresenter _presenter = null;
}
- public class LineStyleTransformer : DocumentColorizingTransformer
+ public class LineStyleTransformer(ThemedTextDiffPresenter presenter) : DocumentColorizingTransformer
{
- public LineStyleTransformer(ThemedTextDiffPresenter presenter)
- {
- _presenter = presenter;
- }
-
protected override void ColorizeLine(DocumentLine line)
{
- var lines = _presenter.GetLines();
+ var lines = presenter.GetLines();
var idx = line.LineNumber;
if (idx > lines.Count)
return;
@@ -367,13 +362,11 @@ namespace SourceGit.Views
{
ChangeLinePart(line.Offset, line.EndOffset, v =>
{
- v.TextRunProperties.SetForegroundBrush(_presenter.IndicatorForeground);
- v.TextRunProperties.SetTypeface(new Typeface(_presenter.FontFamily, FontStyle.Italic));
+ v.TextRunProperties.SetForegroundBrush(presenter.IndicatorForeground);
+ v.TextRunProperties.SetTypeface(new Typeface(presenter.FontFamily, FontStyle.Italic));
});
}
}
-
- private readonly ThemedTextDiffPresenter _presenter;
}
public static readonly StyledProperty FileNameProperty =
@@ -765,12 +758,10 @@ namespace SourceGit.Views
}
else if (change.Property == BlockNavigationProperty)
{
- var oldValue = change.OldValue as ViewModels.BlockNavigation;
- if (oldValue != null)
+ if (change.OldValue is ViewModels.BlockNavigation oldValue)
oldValue.PropertyChanged -= OnBlockNavigationPropertyChanged;
- var newValue = change.NewValue as ViewModels.BlockNavigation;
- if (newValue != null)
+ if (change.NewValue is ViewModels.BlockNavigation newValue)
newValue.PropertyChanged += OnBlockNavigationPropertyChanged;
TextArea?.TextView?.Redraw();
@@ -1251,8 +1242,7 @@ namespace SourceGit.Views
{
base.OnDataContextChanged(e);
- var textDiff = DataContext as Models.TextDiff;
- if (textDiff != null)
+ if (DataContext is Models.TextDiff textDiff)
{
var builder = new StringBuilder();
foreach (var line in textDiff.Lines)
@@ -1410,8 +1400,7 @@ namespace SourceGit.Views
return;
}
- var textDiff = this.FindAncestorOfType()?.DataContext as Models.TextDiff;
- if (textDiff != null)
+ if (this.FindAncestorOfType()?.DataContext is Models.TextDiff textDiff)
{
var lineIdx = -1;
foreach (var line in view.VisualLines)
@@ -1537,7 +1526,7 @@ namespace SourceGit.Views
private void DirectSyncScrollOffset()
{
- if (_scrollViewer is { } && DataContext is ViewModels.TwoSideTextDiff diff)
+ if (_scrollViewer is not null && DataContext is ViewModels.TwoSideTextDiff diff)
diff.SyncScrollOffset = _scrollViewer?.Offset ?? Vector.Zero;
}
diff --git a/src/Views/ViewLogs.axaml b/src/Views/ViewLogs.axaml
index 1fb44d66..a3b9e240 100644
--- a/src/Views/ViewLogs.axaml
+++ b/src/Views/ViewLogs.axaml
@@ -44,7 +44,7 @@
-
+
@@ -83,14 +84,14 @@
Width="14" Height="14"
Margin="4,0,4,0"
IsVisible="{Binding !IsComplete}"/>
-
+
-
+
-
+
@@ -61,8 +61,7 @@
ItemsSource="{Binding Rows}"
SelectionMode="Single"
Loaded="SetupTreeViewDragAndDrop"
- LostFocus="OnTreeViewLostFocus"
- KeyDown="OnTreeViewKeyDown">
+ LostFocus="OnTreeViewLostFocus">