diff --git a/.editorconfig b/.editorconfig
index f3c9a7bf..720f49b7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -12,7 +12,6 @@ indent_style = space
indent_size = 4
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
-end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 12792cf6..2e265201 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,10 +7,10 @@ jobs:
matrix:
include:
- name : Windows x64
- os: windows-2019
+ os: windows-2022
runtime: win-x64
- name : Windows ARM64
- os: windows-2019
+ os: windows-2022
runtime: win-arm64
- name : macOS (Intel)
os: macos-13
@@ -31,7 +31,7 @@ jobs:
container: ${{ matrix.container || '' }}
steps:
- name: Install common CLI tools
- if: ${{ startsWith(matrix.runtime, 'linux-') }}
+ if: startsWith(matrix.runtime, 'linux-')
run: |
export DEBIAN_FRONTEND=noninteractive
ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
@@ -45,7 +45,7 @@ jobs:
with:
dotnet-version: 9.0.x
- name: Configure arm64 packages
- if: ${{ matrix.runtime == 'linux-arm64' }}
+ if: matrix.runtime == 'linux-arm64'
run: |
sudo dpkg --add-architecture arm64
echo 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main restricted
@@ -55,7 +55,7 @@ jobs:
sudo sed -i -e 's/^deb http/deb [arch=amd64] http/g' /etc/apt/sources.list
sudo sed -i -e 's/^deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list
- name: Install cross-compiling dependencies
- if: ${{ matrix.runtime == 'linux-arm64' }}
+ if: matrix.runtime == 'linux-arm64'
run: |
sudo apt-get update
sudo apt-get install -y llvm gcc-aarch64-linux-gnu
@@ -64,10 +64,10 @@ jobs:
- name: Publish
run: dotnet publish src/SourceGit.csproj -c Release -o publish -r ${{ matrix.runtime }}
- name: Rename executable file
- if: ${{ startsWith(matrix.runtime, 'linux-') }}
+ if: startsWith(matrix.runtime, 'linux-')
run: mv publish/SourceGit publish/sourcegit
- name: Tar artifact
- if: ${{ startsWith(matrix.runtime, 'linux-') || startsWith(matrix.runtime, 'osx-') }}
+ if: startsWith(matrix.runtime, 'linux-') || startsWith(matrix.runtime, 'osx-')
run: |
tar -cvf "sourcegit.${{ matrix.runtime }}.tar" -C publish .
rm -r publish/*
diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml
new file mode 100644
index 00000000..4d20b20e
--- /dev/null
+++ b/.github/workflows/format-check.yml
@@ -0,0 +1,22 @@
+name: Format Check
+on:
+ push:
+ branches: [ develop ]
+ workflow_dispatch:
+ workflow_call:
+
+jobs:
+ format-check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 9.0.x
+
+ - name: Run formatting check
+ run: dotnet format --verify-no-changes
diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 2dfc97fd..4fb5dca3 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -9,7 +9,7 @@ on:
jobs:
windows:
name: Package Windows
- runs-on: windows-2019
+ runs-on: windows-2022
strategy:
matrix:
runtime: [ win-x64, win-arm64 ]
diff --git a/README.md b/README.md
index f9ba3072..ac3104a1 100644
--- a/README.md
+++ b/README.md
@@ -152,6 +152,7 @@ This app supports open repository in external tools listed in the table below.
| Visual Studio Code | YES | YES | YES |
| Visual Studio Code - Insiders | YES | YES | YES |
| VSCodium | YES | YES | YES |
+| Cursor | YES | YES | YES |
| Fleet | YES | YES | YES |
| Sublime Text | YES | YES | YES |
| Zed | NO | YES | YES |
diff --git a/SourceGit.sln b/SourceGit.sln
index 624322f8..dad5a475 100644
--- a/SourceGit.sln
+++ b/SourceGit.sln
@@ -18,6 +18,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\package.yml = .github\workflows\package.yml
.github\workflows\release.yml = .github\workflows\release.yml
.github\workflows\localization-check.yml = .github\workflows\localization-check.yml
+ .github\workflows\format-check.yml = .github\workflows\format-check.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{49A7C2D6-558C-4FAA-8F5D-EEE81497AED7}"
diff --git a/TRANSLATION.md b/TRANSLATION.md
index 97a4258c..a7cdbc1e 100644
--- a/TRANSLATION.md
+++ b/TRANSLATION.md
@@ -6,11 +6,62 @@ This document shows the translation status of each locale file in the repository
### 
-### 
+### 
-### 
+
+Missing keys in de_DE.axaml
-### 
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
+- Text.CommitCM.CopyCommitMessage
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
+- Text.Submodule.Branch
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
+- Text.Submodule.Update
+
+
+
+### 
+
+
+Missing keys in es_ES.axaml
+
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
+- Text.CommitCM.CopyCommitMessage
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
+- Text.DirHistories
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
+- Text.Submodule.Branch
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
+- Text.Submodule.Update
+
+
+
+### 
Missing keys in fr_FR.axaml
@@ -27,11 +78,15 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.RecurseSubmodules
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
@@ -47,10 +102,11 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
@@ -61,6 +117,7 @@ This document shows the translation status of each locale file in the repository
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.GitFlow.FinishWithPush
@@ -71,6 +128,9 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Merge.Edit
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Push.Revision
@@ -87,14 +147,27 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.Stash.Mode
- Text.StashCM.CopyMessage
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.RelativePath
+- Text.Submodule.RelativePath.Placeholder
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
+- Text.Submodule.Update
- Text.Submodule.URL
- Text.TagCM.CustomAction
- Text.ViewLogs
@@ -112,7 +185,7 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in it_IT.axaml
@@ -122,9 +195,13 @@ This document shows the translation status of each locale file in the repository
- Text.AddToIgnore.Storage
- Text.Avatar.Load
- Text.BranchCM.ResetToSelectedCommit
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.PushRevision
- Text.CommitDetail.Changes.Count
- Text.Configure.CustomAction.Arguments.Tip
@@ -136,16 +213,18 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.CreateBranch.OverwriteExisting
- Text.DeinitSubmodule
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.Hotkeys.Global.SwitchWorkspace
@@ -153,6 +232,9 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Merge.Edit
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Pull.RecurseSubmodules
- Text.Push.Revision
- Text.Push.Revision.Title
@@ -161,9 +243,20 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.Stash.Mode
- Text.StashCM.CopyMessage
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
+- Text.Submodule.Update
- Text.TagCM.CustomAction
- Text.WorkingCopy.AddToGitIgnore.InFolder
- Text.WorkingCopy.ConfirmCommitWithDetachedHead
@@ -171,7 +264,7 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in ja_JP.axaml
@@ -189,11 +282,15 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange
- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.RecurseSubmodules
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
@@ -209,10 +306,11 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
@@ -223,6 +321,7 @@ This document shows the translation status of each locale file in the repository
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.GitFlow.FinishWithPush
@@ -233,6 +332,9 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Merge.Edit
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Push.Revision
@@ -250,14 +352,25 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.Stash.Mode
- Text.StashCM.CopyMessage
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
+- Text.Submodule.Update
- Text.Submodule.URL
- Text.TagCM.CustomAction
- Text.ViewLogs
@@ -275,7 +388,7 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in pt_BR.axaml
@@ -301,12 +414,16 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.MergeMultiBranches
- Text.BranchCM.ResetToSelectedCommit
- Text.BranchUpstreamInvalid
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.RecurseSubmodules
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.Clone.RecurseSubmodules
- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.Merge
@@ -330,10 +447,11 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
@@ -352,6 +470,7 @@ This document shows the translation status of each locale file in the repository
- Text.Diff.Last
- Text.Diff.Submodule.Deleted
- Text.Diff.UseBlockNavigation
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.Fetch.Force
@@ -374,6 +493,9 @@ This document shows the translation status of each locale file in the repository
- Text.MergeMultiple.CommitChanges
- Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Preferences.AI.Streaming
- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.DateFormat
@@ -408,6 +530,11 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.SetUpstream
- Text.SetUpstream.Local
- Text.SetUpstream.Unset
@@ -416,12 +543,18 @@ This document shows the translation status of each locale file in the repository
- Text.Stash.Mode
- Text.StashCM.CopyMessage
- Text.StashCM.SaveAsPatch
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
+- Text.Submodule.Update
- Text.Submodule.URL
- Text.TagCM.CustomAction
- Text.ViewLogs
@@ -443,7 +576,7 @@ This document shows the translation status of each locale file in the repository
### 
-### 
+### 
Missing keys in ta_IN.axaml
@@ -461,11 +594,15 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.WaitingForRange
- Text.BranchCM.CompareWithCurrent
- Text.BranchCM.ResetToSelectedCommit
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.RecurseSubmodules
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
@@ -481,10 +618,11 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
@@ -495,6 +633,7 @@ This document shows the translation status of each locale file in the repository
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.GitFlow.FinishWithPush
@@ -505,6 +644,9 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Merge.Edit
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Push.Revision
@@ -521,14 +663,25 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.Stash.Mode
- Text.StashCM.CopyMessage
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
+- Text.Submodule.Update
- Text.Submodule.URL
- Text.TagCM.CustomAction
- Text.UpdateSubmodules.Target
@@ -546,7 +699,7 @@ This document shows the translation status of each locale file in the repository
-### 
+### 
Missing keys in uk_UA.axaml
@@ -563,11 +716,15 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchCM.ResetToSelectedCommit
+- Text.ChangeSubmoduleUrl
+- Text.ChangeSubmoduleUrl.Submodule
+- Text.ChangeSubmoduleUrl.URL
- Text.Checkout.RecurseSubmodules
- Text.Checkout.WarnLostCommits
- Text.Checkout.WithFastForward
- Text.Checkout.WithFastForward.Upstream
- Text.CommitCM.CopyAuthor
+- Text.CommitCM.CopyCommitMessage
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitCM.PushRevision
@@ -582,10 +739,11 @@ This document shows the translation status of each locale file in the repository
- Text.ConfigureCustomActionControls.CheckedValue
- Text.ConfigureCustomActionControls.CheckedValue.Tip
- Text.ConfigureCustomActionControls.Description
-- Text.ConfigureCustomActionControls.Description.Tip
- Text.ConfigureCustomActionControls.DefaultValue
- Text.ConfigureCustomActionControls.IsFolder
- Text.ConfigureCustomActionControls.Label
+- Text.ConfigureCustomActionControls.Options
+- Text.ConfigureCustomActionControls.Options.Tip
- Text.ConfigureCustomActionControls.Type
- Text.ConfigureWorkspace.Name
- Text.CreateBranch.OverwriteExisting
@@ -593,6 +751,7 @@ This document shows the translation status of each locale file in the repository
- Text.DeinitSubmodule.Force
- Text.DeinitSubmodule.Path
- Text.Diff.Submodule.Deleted
+- Text.DirHistories
- Text.ExecuteCustomAction.Target
- Text.ExecuteCustomAction.Repository
- Text.GitFlow.FinishWithPush
@@ -603,6 +762,9 @@ This document shows the translation status of each locale file in the repository
- Text.Launcher.Workspaces
- Text.Launcher.Pages
- Text.Merge.Edit
+- Text.MoveSubmodule
+- Text.MoveSubmodule.MoveTo
+- Text.MoveSubmodule.Submodule
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Pull.RecurseSubmodules
- Text.Push.Revision
@@ -619,14 +781,25 @@ This document shows the translation status of each locale file in the repository
- Text.ResetWithoutCheckout
- Text.ResetWithoutCheckout.MoveTo
- Text.ResetWithoutCheckout.Target
+- Text.SetSubmoduleBranch
+- Text.SetSubmoduleBranch.Submodule
+- Text.SetSubmoduleBranch.Current
+- Text.SetSubmoduleBranch.New
+- Text.SetSubmoduleBranch.New.Tip
- Text.Stash.Mode
- Text.StashCM.CopyMessage
+- Text.Submodule.Branch
- Text.Submodule.Deinit
+- Text.Submodule.Histories
+- Text.Submodule.Move
+- Text.Submodule.SetBranch
+- Text.Submodule.SetURL
- Text.Submodule.Status
- Text.Submodule.Status.Modified
- Text.Submodule.Status.NotInited
- Text.Submodule.Status.RevisionChanged
- Text.Submodule.Status.Unmerged
+- Text.Submodule.Update
- Text.Submodule.URL
- Text.TagCM.CustomAction
- Text.ViewLogs
diff --git a/VERSION b/VERSION
index 56ea42f8..3918dc69 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2025.24
\ No newline at end of file
+2025.25
\ No newline at end of file
diff --git a/screenshots/theme_dark.png b/screenshots/theme_dark.png
index 85e18481..6e8af07b 100644
Binary files a/screenshots/theme_dark.png and b/screenshots/theme_dark.png differ
diff --git a/screenshots/theme_light.png b/screenshots/theme_light.png
index 2e8cf6fc..10988efd 100644
Binary files a/screenshots/theme_light.png and b/screenshots/theme_light.png differ
diff --git a/src/App.Commands.cs b/src/App.Commands.cs
index 22e9fb51..f26919c7 100644
--- a/src/App.Commands.cs
+++ b/src/App.Commands.cs
@@ -37,22 +37,21 @@ namespace SourceGit
}
}
- public static readonly Command OpenPreferencesCommand = new Command(_ => ShowWindow(new Views.Preferences(), false));
- public static readonly Command OpenHotkeysCommand = new Command(_ => ShowWindow(new Views.Hotkeys(), false));
+ public static readonly Command OpenPreferencesCommand = new Command(async _ => await ShowDialog(new Views.Preferences()));
+ public static readonly Command OpenHotkeysCommand = new Command(async _ => await ShowDialog(new Views.Hotkeys()));
public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir));
- public static readonly Command OpenAboutCommand = new Command(_ => ShowWindow(new Views.About(), false));
+ public static readonly Command OpenAboutCommand = new Command(async _ => await ShowDialog(new Views.About()));
public static readonly Command CheckForUpdateCommand = new Command(_ => (Current as App)?.Check4Update(true));
public static readonly Command QuitCommand = new Command(_ => Quit(0));
- public static readonly Command CopyTextBlockCommand = new Command(p =>
+ public static readonly Command CopyTextBlockCommand = new Command(async p =>
{
- var textBlock = p as TextBlock;
- if (textBlock == null)
+ if (p is not TextBlock textBlock)
return;
if (textBlock.Inlines is { Count: > 0 } inlines)
- CopyText(inlines.Text);
+ await CopyTextAsync(inlines.Text);
else if (!string.IsNullOrEmpty(textBlock.Text))
- CopyText(textBlock.Text);
+ await CopyTextAsync(textBlock.Text);
});
}
}
diff --git a/src/App.JsonCodeGen.cs b/src/App.JsonCodeGen.cs
index 9cad0792..a2e40200 100644
--- a/src/App.JsonCodeGen.cs
+++ b/src/App.JsonCodeGen.cs
@@ -34,6 +34,20 @@ namespace SourceGit
}
}
+ public class DataGridLengthConverter : JsonConverter
+ {
+ public override DataGridLength Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ var size = reader.GetDouble();
+ return new DataGridLength(size, DataGridLengthUnitType.Pixel, 0, size);
+ }
+
+ public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSerializerOptions options)
+ {
+ writer.WriteNumberValue(value.DisplayValue);
+ }
+ }
+
[JsonSourceGenerationOptions(
WriteIndented = true,
IgnoreReadOnlyFields = true,
@@ -41,6 +55,7 @@ namespace SourceGit
Converters = [
typeof(ColorConverter),
typeof(GridLengthConverter),
+ typeof(DataGridLengthConverter),
]
)]
[JsonSerializable(typeof(Models.ExternalToolPaths))]
diff --git a/src/App.axaml b/src/App.axaml
index 186022d5..f4dc3d89 100644
--- a/src/App.axaml
+++ b/src/App.axaml
@@ -28,6 +28,7 @@
+
diff --git a/src/App.axaml.cs b/src/App.axaml.cs
index 935e2e19..53c25325 100644
--- a/src/App.axaml.cs
+++ b/src/App.axaml.cs
@@ -83,88 +83,112 @@ namespace SourceGit
if (ex == null)
return;
- var builder = new StringBuilder();
- builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n");
- builder.Append("----------------------------\n");
- builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n");
- builder.Append($"OS: {Environment.OSVersion}\n");
- builder.Append($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}\n");
- builder.Append($"Source: {ex.Source}\n");
- builder.Append($"Thread Name: {Thread.CurrentThread.Name ?? "Unnamed"}\n");
- builder.Append($"User: {Environment.UserName}\n");
- builder.Append($"App Start Time: {Process.GetCurrentProcess().StartTime}\n");
- builder.Append($"Exception Time: {DateTime.Now}\n");
- builder.Append($"Memory Usage: {Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024} MB\n");
- builder.Append("---------------------------\n\n");
- builder.Append(ex);
-
var time = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
var file = Path.Combine(Native.OS.DataDir, $"crash_{time}.log");
- File.WriteAllText(file, builder.ToString());
+ using var writer = new StreamWriter(file);
+ writer.WriteLine($"Crash::: {ex.GetType().FullName}: {ex.Message}");
+ writer.WriteLine();
+ writer.WriteLine("----------------------------");
+ writer.WriteLine($"Version: {Assembly.GetExecutingAssembly().GetName().Version}");
+ writer.WriteLine($"OS: {Environment.OSVersion}");
+ writer.WriteLine($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}");
+ writer.WriteLine($"Source: {ex.Source}");
+ writer.WriteLine($"Thread Name: {Thread.CurrentThread.Name ?? "Unnamed"}");
+ writer.WriteLine($"User: {Environment.UserName}");
+ writer.WriteLine($"App Start Time: {Process.GetCurrentProcess().StartTime}");
+ writer.WriteLine($"Exception Time: {DateTime.Now}");
+ writer.WriteLine($"Memory Usage: {Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024} MB");
+ writer.WriteLine("----------------------------");
+ writer.WriteLine();
+ writer.WriteLine(ex);
+ writer.Flush();
}
#endregion
#region Utility Functions
- public static void ShowWindow(object data, bool showAsDialog)
+ public static object CreateViewForViewModel(object data)
{
- var impl = (Views.ChromelessWindow target, bool isDialog) =>
- {
- if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
- {
- if (isDialog)
- target.ShowDialog(owner);
- else
- target.Show(owner);
- }
- else
- {
- target.Show();
- }
- };
-
- if (data is Views.ChromelessWindow window)
- {
- impl(window, showAsDialog);
- return;
- }
-
var dataTypeName = data.GetType().FullName;
if (string.IsNullOrEmpty(dataTypeName) || !dataTypeName.Contains(".ViewModels.", StringComparison.Ordinal))
- return;
+ return null;
var viewTypeName = dataTypeName.Replace(".ViewModels.", ".Views.");
var viewType = Type.GetType(viewTypeName);
- if (viewType == null || !viewType.IsSubclassOf(typeof(Views.ChromelessWindow)))
- return;
+ if (viewType != null)
+ return Activator.CreateInstance(viewType);
- window = Activator.CreateInstance(viewType) as Views.ChromelessWindow;
+ return null;
+ }
+
+ public static Task ShowDialog(object data, Window owner = null)
+ {
+ if (owner == null)
+ {
+ if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } mainWindow })
+ owner = mainWindow;
+ else
+ return null;
+ }
+
+ if (data is Views.ChromelessWindow window)
+ return window.ShowDialog(owner);
+
+ window = CreateViewForViewModel(data) as Views.ChromelessWindow;
if (window != null)
{
window.DataContext = data;
- impl(window, showAsDialog);
+ return window.ShowDialog(owner);
}
+
+ return null;
+ }
+
+ public static void ShowWindow(object data)
+ {
+ if (data is Views.ChromelessWindow window)
+ {
+ window.Show();
+ return;
+ }
+
+ window = CreateViewForViewModel(data) as Views.ChromelessWindow;
+ if (window != null)
+ {
+ window.DataContext = data;
+ window.Show();
+ }
+ }
+
+ public static async Task AskConfirmAsync(string message, Action onSure)
+ {
+ if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
+ {
+ var confirm = new Views.Confirm();
+ confirm.Message.Text = message;
+ confirm.OnSure = onSure;
+ return await confirm.ShowDialog(owner);
+ }
+
+ return false;
}
public static void RaiseException(string context, string message)
{
- if (Current is App app && app._launcher != null)
+ if (Current is App { _launcher: not null } app)
app._launcher.DispatchNotification(context, message, true);
}
public static void SendNotification(string context, string message)
{
- if (Current is App app && app._launcher != null)
+ if (Current is App { _launcher: not null } app)
app._launcher.DispatchNotification(context, message, false);
}
public static void SetLocale(string localeKey)
{
- var app = Current as App;
- if (app == null)
- return;
-
- var targetLocale = app.Resources[localeKey] as ResourceDictionary;
- if (targetLocale == null || targetLocale == app._activeLocale)
+ if (Current is not App app ||
+ app.Resources[localeKey] is not ResourceDictionary targetLocale ||
+ targetLocale == app._activeLocale)
return;
if (app._activeLocale != null)
@@ -176,8 +200,7 @@ namespace SourceGit
public static void SetTheme(string theme, string themeOverridesFile)
{
- var app = Current as App;
- if (app == null)
+ if (Current is not App app)
return;
if (theme.Equals("Light", StringComparison.OrdinalIgnoreCase))
@@ -230,8 +253,7 @@ namespace SourceGit
public static void SetFonts(string defaultFont, string monospaceFont, bool onlyUseMonospaceFontInEditor)
{
- var app = Current as App;
- if (app == null)
+ if (Current is not App app)
return;
if (app._fontsOverrides != null)
@@ -283,24 +305,16 @@ namespace SourceGit
}
}
- public static async void CopyText(string data)
+ public static async Task CopyTextAsync(string data)
{
- if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
- {
- if (desktop.MainWindow?.Clipboard is { } clipboard)
- await clipboard.SetTextAsync(data ?? "");
- }
+ if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow.Clipboard: { } clipboard })
+ await clipboard.SetTextAsync(data ?? "");
}
public static async Task GetClipboardTextAsync()
{
- if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
- {
- if (desktop.MainWindow?.Clipboard is { } clipboard)
- {
- return await clipboard.GetTextAsync();
- }
- }
+ if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow.Clipboard: { } clipboard })
+ return await clipboard.GetTextAsync();
return null;
}
@@ -436,33 +450,33 @@ namespace SourceGit
return true;
var collection = JsonSerializer.Deserialize(File.ReadAllText(jobsFile), JsonCodeGen.Default.InteractiveRebaseJobCollection);
- var lines = new List();
+ using var writer = new StreamWriter(file);
foreach (var job in collection.Jobs)
{
switch (job.Action)
{
case Models.InteractiveRebaseAction.Pick:
- lines.Add($"p {job.SHA}");
+ writer.WriteLine($"p {job.SHA}");
break;
case Models.InteractiveRebaseAction.Edit:
- lines.Add($"e {job.SHA}");
+ writer.WriteLine($"e {job.SHA}");
break;
case Models.InteractiveRebaseAction.Reword:
- lines.Add($"r {job.SHA}");
+ writer.WriteLine($"r {job.SHA}");
break;
case Models.InteractiveRebaseAction.Squash:
- lines.Add($"s {job.SHA}");
+ writer.WriteLine($"s {job.SHA}");
break;
case Models.InteractiveRebaseAction.Fixup:
- lines.Add($"f {job.SHA}");
+ writer.WriteLine($"f {job.SHA}");
break;
default:
- lines.Add($"d {job.SHA}");
+ writer.WriteLine($"d {job.SHA}");
break;
}
}
- File.WriteAllLines(file, lines);
+ writer.Flush();
exitCode = 0;
return true;
@@ -561,7 +575,7 @@ namespace SourceGit
Models.AvatarManager.Instance.Start();
string startupRepo = null;
- if (desktop.Args != null && desktop.Args.Length == 1 && Directory.Exists(desktop.Args[0]))
+ if (desktop.Args is { Length: 1 } && Directory.Exists(desktop.Args[0]))
startupRepo = desktop.Args[0];
var pref = ViewModels.Preferences.Instance;
@@ -581,7 +595,7 @@ namespace SourceGit
{
if (!string.IsNullOrEmpty(repo) && Directory.Exists(repo))
{
- var test = new Commands.QueryRepositoryRootPath(repo).ReadToEnd();
+ var test = new Commands.QueryRepositoryRootPath(repo).GetResultAsync().Result;
if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut))
{
Dispatcher.UIThread.Invoke(() =>
@@ -648,9 +662,9 @@ namespace SourceGit
private void ShowSelfUpdateResult(object data)
{
- Dispatcher.UIThread.Post(() =>
+ Dispatcher.UIThread.Post(async () =>
{
- ShowWindow(new ViewModels.SelfUpdate() { Data = data }, true);
+ await ShowDialog(new ViewModels.SelfUpdate { Data = data });
});
}
diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs
index 1fc51fa4..0d55a051 100644
--- a/src/Commands/Blame.cs
+++ b/src/Commands/Blame.cs
@@ -1,6 +1,7 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -19,9 +20,9 @@ namespace SourceGit.Commands
_result.File = file;
}
- public Models.BlameData Result()
+ public async Task ReadAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return _result;
@@ -39,9 +40,7 @@ namespace SourceGit.Commands
foreach (var line in _result.LineInfos)
{
if (line.CommitSHA.Length > _minSHALen)
- {
line.CommitSHA = line.CommitSHA.Substring(0, _minSHALen);
- }
}
}
diff --git a/src/Commands/Branch.cs b/src/Commands/Branch.cs
index f207e976..a5e3208e 100644
--- a/src/Commands/Branch.cs
+++ b/src/Commands/Branch.cs
@@ -1,19 +1,11 @@
using System.Text;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class Branch
{
- public static string ShowCurrent(string repo)
- {
- var cmd = new Command();
- cmd.WorkingDirectory = repo;
- cmd.Context = repo;
- cmd.Args = "branch --show-current";
- return cmd.ReadToEnd().StdOut.Trim();
- }
-
- public static bool Create(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
+ public static async Task CreateAsync(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("branch ");
@@ -28,20 +20,20 @@ namespace SourceGit.Commands
cmd.Context = repo;
cmd.Args = builder.ToString();
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool Rename(string repo, string name, string to, Models.ICommandLog log)
+ public static async Task RenameAsync(string repo, string name, string to, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -M {name} {to}";
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool SetUpstream(string repo, string name, string upstream, Models.ICommandLog log)
+ public static async Task SetUpstreamAsync(string repo, string name, string upstream, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -53,31 +45,31 @@ namespace SourceGit.Commands
else
cmd.Args = $"branch {name} -u {upstream}";
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool DeleteLocal(string repo, string name, Models.ICommandLog log)
+ public static async Task DeleteLocalAsync(string repo, string name, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D {name}";
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool DeleteRemote(string repo, string remote, string name, Models.ICommandLog log)
+ public static async Task DeleteRemoteAsync(string repo, string remote, string name, Models.ICommandLog log)
{
- bool exists = new Remote(repo).HasBranch(remote, name);
+ bool exists = await new Remote(repo).HasBranchAsync(remote, name).ConfigureAwait(false);
if (exists)
- return new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.Exec();
+ return await new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.RunAsync().ConfigureAwait(false);
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D -r {remote}/{name}";
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/Checkout.cs b/src/Commands/Checkout.cs
index d2876740..1aeff870 100644
--- a/src/Commands/Checkout.cs
+++ b/src/Commands/Checkout.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,7 +12,7 @@ namespace SourceGit.Commands
Context = repo;
}
- public bool Branch(string branch, bool force)
+ public async Task BranchAsync(string branch, bool force)
{
var builder = new StringBuilder();
builder.Append("checkout --progress ");
@@ -20,10 +21,10 @@ namespace SourceGit.Commands
builder.Append(branch);
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Branch(string branch, string basedOn, bool force, bool allowOverwrite)
+ public async Task BranchAsync(string branch, string basedOn, bool force, bool allowOverwrite)
{
var builder = new StringBuilder();
builder.Append("checkout --progress ");
@@ -35,17 +36,17 @@ namespace SourceGit.Commands
builder.Append(basedOn);
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Commit(string commitId, bool force)
+ public async Task CommitAsync(string commitId, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --detach --progress {commitId}";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool UseTheirs(List files)
+ public async Task UseTheirsAsync(List files)
{
var builder = new StringBuilder();
builder.Append("checkout --theirs --");
@@ -56,10 +57,10 @@ namespace SourceGit.Commands
builder.Append("\"");
}
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool UseMine(List files)
+ public async Task UseMineAsync(List files)
{
var builder = new StringBuilder();
builder.Append("checkout --ours --");
@@ -69,14 +70,15 @@ namespace SourceGit.Commands
builder.Append(f);
builder.Append("\"");
}
+
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool FileWithRevision(string file, string revision)
+ public async Task FileWithRevisionAsync(string file, string revision)
{
Args = $"checkout --no-overlay {revision} -- \"{file}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs
index a5ec0b56..12fcb72f 100644
--- a/src/Commands/Command.cs
+++ b/src/Commands/Command.cs
@@ -4,18 +4,19 @@ using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public partial class Command
{
- public class ReadToEndResult
+ public class Result
{
public bool IsSuccess { get; set; } = false;
- public string StdOut { get; set; } = "";
- public string StdErr { get; set; } = "";
+ public string StdOut { get; set; } = string.Empty;
+ public string StdErr { get; set; } = string.Empty;
+
+ public static Result Failed(string reason) => new Result() { StdErr = reason };
}
public enum EditorType
@@ -26,15 +27,17 @@ namespace SourceGit.Commands
}
public string Context { get; set; } = string.Empty;
- public CancellationToken CancellationToken { get; set; } = CancellationToken.None;
public string WorkingDirectory { get; set; } = null;
- public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode
+ public EditorType Editor { get; set; } = EditorType.CoreEditor;
public string SSHKey { get; set; } = string.Empty;
public string Args { get; set; } = string.Empty;
+
+ // Only used in `ExecAsync` mode.
+ public CancellationToken CancellationToken { get; set; } = CancellationToken.None;
public bool RaiseError { get; set; } = true;
public Models.ICommandLog Log { get; set; } = null;
- public bool Exec()
+ public async Task ExecAsync()
{
Log?.AppendLine($"$ git {Args}\n");
@@ -45,7 +48,7 @@ namespace SourceGit.Commands
proc.OutputDataReceived += (_, e) => HandleOutput(e.Data, errs);
proc.ErrorDataReceived += (_, e) => HandleOutput(e.Data, errs);
- var dummy = null as Process;
+ Process dummy = null;
var dummyProcLock = new object();
try
{
@@ -68,7 +71,7 @@ namespace SourceGit.Commands
catch (Exception e)
{
if (RaiseError)
- Dispatcher.UIThread.Post(() => App.RaiseException(Context, e.Message));
+ App.RaiseException(Context, e.Message);
Log?.AppendLine(string.Empty);
return false;
@@ -76,7 +79,15 @@ namespace SourceGit.Commands
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
- proc.WaitForExit();
+
+ try
+ {
+ await proc.WaitForExitAsync(CancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception e)
+ {
+ HandleOutput(e.Message, errs);
+ }
if (dummy != null)
{
@@ -96,7 +107,7 @@ namespace SourceGit.Commands
{
var errMsg = string.Join("\n", errs).Trim();
if (!string.IsNullOrEmpty(errMsg))
- Dispatcher.UIThread.Post(() => App.RaiseException(Context, errMsg));
+ App.RaiseException(Context, errMsg);
}
return false;
@@ -105,7 +116,7 @@ namespace SourceGit.Commands
return true;
}
- public ReadToEndResult ReadToEnd()
+ protected async Task ReadToEndAsync()
{
var start = CreateGitStartInfo();
var proc = new Process() { StartInfo = start };
@@ -116,24 +127,16 @@ namespace SourceGit.Commands
}
catch (Exception e)
{
- return new ReadToEndResult()
- {
- IsSuccess = false,
- StdOut = string.Empty,
- StdErr = e.Message,
- };
+ return Result.Failed(e.Message);
}
- var rs = new ReadToEndResult()
- {
- StdOut = proc.StandardOutput.ReadToEnd(),
- StdErr = proc.StandardError.ReadToEnd(),
- };
+ var rs = new Result() { IsSuccess = true };
+ rs.StdOut = await proc.StandardOutput.ReadToEndAsync(CancellationToken).ConfigureAwait(false);
+ rs.StdErr = await proc.StandardError.ReadToEndAsync(CancellationToken).ConfigureAwait(false);
+ await proc.WaitForExitAsync(CancellationToken).ConfigureAwait(false);
- proc.WaitForExit();
rs.IsSuccess = proc.ExitCode == 0;
proc.Close();
-
return rs;
}
diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs
index 1585e7e3..02c4ba89 100644
--- a/src/Commands/Commit.cs
+++ b/src/Commands/Commit.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -7,7 +8,7 @@ namespace SourceGit.Commands
public Commit(string repo, string message, bool signOff, bool amend, bool resetAuthor)
{
_tmpFile = Path.GetTempFileName();
- File.WriteAllText(_tmpFile, message);
+ _message = message;
WorkingDirectory = repo;
Context = repo;
@@ -18,22 +19,22 @@ namespace SourceGit.Commands
Args += resetAuthor ? " --amend --reset-author --no-edit" : " --amend --no-edit";
}
- public bool Run()
+ public async Task RunAsync()
{
- var succ = Exec();
-
try
{
+ await File.WriteAllTextAsync(_tmpFile, _message).ConfigureAwait(false);
+ var succ = await ExecAsync().ConfigureAwait(false);
File.Delete(_tmpFile);
+ return succ;
}
catch
{
- // Ignore
+ return false;
}
-
- return succ;
}
- private readonly string _tmpFile;
+ private readonly string _tmpFile = string.Empty;
+ private readonly string _message = string.Empty;
}
}
diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs
index c88e087a..634d98c9 100644
--- a/src/Commands/CompareRevisions.cs
+++ b/src/Commands/CompareRevisions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -29,21 +30,22 @@ namespace SourceGit.Commands
Args = $"diff --name-status {based} {end} -- \"{path}\"";
}
- public List Result()
+ public async Task> ReadAsync()
{
- var rs = ReadToEnd();
+ var changes = new List();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
- return _changes;
+ return changes;
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
- ParseLine(line);
+ ParseLine(changes, line);
- _changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
- return _changes;
+ changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path));
+ return changes;
}
- private void ParseLine(string line)
+ private void ParseLine(List outs, string line)
{
var match = REG_FORMAT().Match(line);
if (!match.Success)
@@ -53,7 +55,7 @@ namespace SourceGit.Commands
{
var renamed = new Models.Change() { Path = match.Groups[1].Value };
renamed.Set(Models.ChangeState.Renamed);
- _changes.Add(renamed);
+ outs.Add(renamed);
}
return;
@@ -66,23 +68,21 @@ namespace SourceGit.Commands
{
case 'M':
change.Set(Models.ChangeState.Modified);
- _changes.Add(change);
+ outs.Add(change);
break;
case 'A':
change.Set(Models.ChangeState.Added);
- _changes.Add(change);
+ outs.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
- _changes.Add(change);
+ outs.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
- _changes.Add(change);
+ outs.Add(change);
break;
}
}
-
- private readonly List _changes = new List();
}
}
diff --git a/src/Commands/Config.cs b/src/Commands/Config.cs
index 49e8fcb7..78057b22 100644
--- a/src/Commands/Config.cs
+++ b/src/Commands/Config.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -17,15 +18,13 @@ namespace SourceGit.Commands
Context = repository;
_isLocal = true;
}
-
- RaiseError = false;
}
- public Dictionary ListAll()
+ public async Task> ReadAllAsync()
{
Args = "config -l";
- var output = ReadToEnd();
+ var output = await ReadToEndAsync().ConfigureAwait(false);
var rs = new Dictionary();
if (output.IsSuccess)
{
@@ -45,13 +44,15 @@ namespace SourceGit.Commands
return rs;
}
- public string Get(string key)
+ public async Task GetAsync(string key)
{
Args = $"config {key}";
- return ReadToEnd().StdOut.Trim();
+
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ return rs.StdOut.Trim();
}
- public bool Set(string key, string value, bool allowEmpty = false)
+ public async Task SetAsync(string key, string value, bool allowEmpty = false)
{
var scope = _isLocal ? "--local" : "--global";
@@ -60,7 +61,7 @@ namespace SourceGit.Commands
else
Args = $"config {scope} {key} \"{value}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
private bool _isLocal = false;
diff --git a/src/Commands/CountLocalChangesWithoutUntracked.cs b/src/Commands/CountLocalChangesWithoutUntracked.cs
index a704f313..769d732e 100644
--- a/src/Commands/CountLocalChangesWithoutUntracked.cs
+++ b/src/Commands/CountLocalChangesWithoutUntracked.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,9 +12,9 @@ namespace SourceGit.Commands
Args = "--no-optional-locks status -uno --ignore-submodules=all --porcelain";
}
- public int Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs
index 6af0a3cc..c4785e18 100644
--- a/src/Commands/Diff.cs
+++ b/src/Commands/Diff.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -35,9 +36,9 @@ namespace SourceGit.Commands
Args = $"diff --no-ext-diff --patch --unified={unified} {opt}";
}
- public Models.DiffResult Result()
+ public async Task ReadAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var start = 0;
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)
@@ -248,14 +249,10 @@ namespace SourceGit.Commands
foreach (var chunk in chunks)
{
if (chunk.DeletedCount > 0)
- {
left.Highlights.Add(new Models.TextInlineRange(chunk.DeletedStart, chunk.DeletedCount));
- }
if (chunk.AddedCount > 0)
- {
right.Highlights.Add(new Models.TextInlineRange(chunk.AddedStart, chunk.AddedCount));
- }
}
}
}
diff --git a/src/Commands/Discard.cs b/src/Commands/Discard.cs
index f36ca6c9..73899d52 100644
--- a/src/Commands/Discard.cs
+++ b/src/Commands/Discard.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,9 +13,9 @@ namespace SourceGit.Commands
///
///
///
- public static void All(string repo, bool includeIgnored, Models.ICommandLog log)
+ public static async Task AllAsync(string repo, bool includeIgnored, Models.ICommandLog log)
{
- var changes = new QueryLocalChanges(repo).Result();
+ var changes = await new QueryLocalChanges(repo).GetResultAsync().ConfigureAwait(false);
try
{
foreach (var c in changes)
@@ -36,16 +35,13 @@ namespace SourceGit.Commands
}
catch (Exception e)
{
- Dispatcher.UIThread.Invoke(() =>
- {
- App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
- });
+ App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
}
- new Reset(repo, "HEAD", "--hard") { Log = log }.Exec();
+ await new Reset(repo, "HEAD", "--hard") { Log = log }.ExecAsync().ConfigureAwait(false);
if (includeIgnored)
- new Clean(repo) { Log = log }.Exec();
+ await new Clean(repo) { Log = log }.ExecAsync().ConfigureAwait(false);
}
///
@@ -54,7 +50,7 @@ namespace SourceGit.Commands
///
///
///
- public static void Changes(string repo, List changes, Models.ICommandLog log)
+ public static async Task ChangesAsync(string repo, List changes, Models.ICommandLog log)
{
var restores = new List();
@@ -78,17 +74,14 @@ namespace SourceGit.Commands
}
catch (Exception e)
{
- Dispatcher.UIThread.Invoke(() =>
- {
- App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
- });
+ App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
}
if (restores.Count > 0)
{
var pathSpecFile = Path.GetTempFileName();
- File.WriteAllLines(pathSpecFile, restores);
- new Restore(repo, pathSpecFile, false) { Log = log }.Exec();
+ await File.WriteAllLinesAsync(pathSpecFile, restores).ConfigureAwait(false);
+ await new Restore(repo, pathSpecFile, false) { Log = log }.ExecAsync().ConfigureAwait(false);
File.Delete(pathSpecFile);
}
}
diff --git a/src/Commands/Fetch.cs b/src/Commands/Fetch.cs
index edf2a6dd..d25cc80c 100644
--- a/src/Commands/Fetch.cs
+++ b/src/Commands/Fetch.cs
@@ -1,12 +1,15 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class Fetch : Command
{
public Fetch(string repo, string remote, bool noTags, bool force)
{
+ _remoteKey = $"remote.{remote}.sshkey";
+
WorkingDirectory = repo;
Context = repo;
- SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "fetch --progress --verbose ";
if (noTags)
@@ -18,14 +21,24 @@
Args += "--force ";
Args += remote;
+
}
public Fetch(string repo, Models.Branch local, Models.Branch remote)
{
+ _remoteKey = $"remote.{remote.Remote}.sshkey";
+
WorkingDirectory = repo;
Context = repo;
- SSHKey = new Config(repo).Get($"remote.{remote.Remote}.sshkey");
Args = $"fetch --progress --verbose {remote.Remote} {remote.Name}:{local.Name}";
}
+
+ public async Task RunAsync()
+ {
+ SSHKey = await new Config(WorkingDirectory).GetAsync(_remoteKey).ConfigureAwait(false);
+ return await ExecAsync().ConfigureAwait(false);
+ }
+
+ private readonly string _remoteKey;
}
}
diff --git a/src/Commands/GenerateCommitMessage.cs b/src/Commands/GenerateCommitMessage.cs
index df61fdd2..9b6fc4ff 100644
--- a/src/Commands/GenerateCommitMessage.cs
+++ b/src/Commands/GenerateCommitMessage.cs
@@ -2,8 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Threading;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -20,6 +19,11 @@ namespace SourceGit.Commands
Context = repo;
Args = $"diff --diff-algorithm=minimal {opt}";
}
+
+ public async Task ReadAsync()
+ {
+ return await ReadToEndAsync().ConfigureAwait(false);
+ }
}
public GenerateCommitMessage(Models.OpenAIService service, string repo, List changes, CancellationToken cancelToken, Action onResponse)
@@ -31,7 +35,7 @@ namespace SourceGit.Commands
_onResponse = onResponse;
}
- public void Exec()
+ public async Task ExecAsync()
{
try
{
@@ -47,10 +51,10 @@ namespace SourceGit.Commands
responseBuilder.Append("- ");
summaryBuilder.Append("- ");
- var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
+ var rs = await new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadAsync();
if (rs.IsSuccess)
{
- _service.Chat(
+ await _service.ChatAsync(
_service.AnalyzeDiffPrompt,
$"Here is the `git diff` output: {rs.StdOut}",
_cancelToken,
@@ -74,7 +78,7 @@ namespace SourceGit.Commands
var responseBody = responseBuilder.ToString();
var subjectBuilder = new StringBuilder();
- _service.Chat(
+ await _service.ChatAsync(
_service.GenerateSubjectPrompt,
$"Here are the summaries changes:\n{summaryBuilder}",
_cancelToken,
@@ -86,7 +90,7 @@ namespace SourceGit.Commands
}
catch (Exception e)
{
- Dispatcher.UIThread.Post(() => App.RaiseException(_repo, $"Failed to generate commit message: {e}"));
+ App.RaiseException(_repo, $"Failed to generate commit message: {e}");
}
}
diff --git a/src/Commands/GitFlow.cs b/src/Commands/GitFlow.cs
index 1d33fa3a..1f492b89 100644
--- a/src/Commands/GitFlow.cs
+++ b/src/Commands/GitFlow.cs
@@ -1,31 +1,31 @@
using System.Text;
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class GitFlow
{
- public static bool Init(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
+ public static async Task InitAsync(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
{
var config = new Config(repo);
- config.Set("gitflow.branch.master", master);
- config.Set("gitflow.branch.develop", develop);
- config.Set("gitflow.prefix.feature", feature);
- config.Set("gitflow.prefix.bugfix", "bugfix/");
- config.Set("gitflow.prefix.release", release);
- config.Set("gitflow.prefix.hotfix", hotfix);
- config.Set("gitflow.prefix.support", "support/");
- config.Set("gitflow.prefix.versiontag", version, true);
+ await config.SetAsync("gitflow.branch.master", master).ConfigureAwait(false);
+ await config.SetAsync("gitflow.branch.develop", develop).ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.feature", feature).ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.bugfix", "bugfix/").ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.release", release).ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.hotfix", hotfix).ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.support", "support/").ConfigureAwait(false);
+ await config.SetAsync("gitflow.prefix.versiontag", version, true).ConfigureAwait(false);
var init = new Command();
init.WorkingDirectory = repo;
init.Context = repo;
init.Args = "flow init -d";
init.Log = log;
- return init.Exec();
+ return await init.ExecAsync().ConfigureAwait(false);
}
- public static bool Start(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log)
+ public static async Task StartAsync(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log)
{
var start = new Command();
start.WorkingDirectory = repo;
@@ -43,15 +43,15 @@ namespace SourceGit.Commands
start.Args = $"flow hotfix start {name}";
break;
default:
- Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, "Bad git-flow branch type!!!"));
+ App.RaiseException(repo, "Bad git-flow branch type!!!");
return false;
}
start.Log = log;
- return start.Exec();
+ return await start.ExecAsync().ConfigureAwait(false);
}
- public static bool Finish(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
+ public static async Task FinishAsync(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("flow ");
@@ -68,7 +68,7 @@ namespace SourceGit.Commands
builder.Append("hotfix");
break;
default:
- Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, "Bad git-flow branch type!!!"));
+ App.RaiseException(repo, "Bad git-flow branch type!!!");
return false;
}
@@ -86,7 +86,7 @@ namespace SourceGit.Commands
finish.Context = repo;
finish.Args = builder.ToString();
finish.Log = log;
- return finish.Exec();
+ return await finish.ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/IsBareRepository.cs b/src/Commands/IsBareRepository.cs
index f92d0888..98b127ce 100644
--- a/src/Commands/IsBareRepository.cs
+++ b/src/Commands/IsBareRepository.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -10,14 +11,14 @@ namespace SourceGit.Commands
Args = "rev-parse --is-bare-repository";
}
- public bool Result()
+ public async Task GetResultAsync()
{
if (!Directory.Exists(Path.Combine(WorkingDirectory, "refs")) ||
!Directory.Exists(Path.Combine(WorkingDirectory, "objects")) ||
!File.Exists(Path.Combine(WorkingDirectory, "HEAD")))
return false;
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
return rs.IsSuccess && rs.StdOut.Trim() == "true";
}
}
diff --git a/src/Commands/IsBinary.cs b/src/Commands/IsBinary.cs
index af8f54bb..5c3e5673 100644
--- a/src/Commands/IsBinary.cs
+++ b/src/Commands/IsBinary.cs
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -15,9 +16,10 @@ namespace SourceGit.Commands
RaiseError = false;
}
- public bool Result()
+ public async Task GetResultAsync()
{
- return REG_TEST().IsMatch(ReadToEnd().StdOut);
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ return REG_TEST().IsMatch(rs.StdOut.Trim());
}
}
}
diff --git a/src/Commands/IsCommitSHA.cs b/src/Commands/IsCommitSHA.cs
index 1b0c50e3..dcf9b1a9 100644
--- a/src/Commands/IsCommitSHA.cs
+++ b/src/Commands/IsCommitSHA.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class IsCommitSHA : Command
{
@@ -8,9 +10,9 @@
Args = $"cat-file -t {hash}";
}
- public bool Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
return rs.IsSuccess && rs.StdOut.Trim().Equals("commit");
}
}
diff --git a/src/Commands/IsConflictResolved.cs b/src/Commands/IsConflictResolved.cs
index 9b243451..2d53766a 100644
--- a/src/Commands/IsConflictResolved.cs
+++ b/src/Commands/IsConflictResolved.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class IsConflictResolved : Command
{
@@ -11,9 +13,10 @@
Args = $"diff -a --ignore-cr-at-eol --check {opt}";
}
- public bool Result()
+ public async Task GetResultAsync()
{
- return ReadToEnd().IsSuccess;
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ return rs.IsSuccess;
}
}
}
diff --git a/src/Commands/IsLFSFiltered.cs b/src/Commands/IsLFSFiltered.cs
index 2a7234bb..ee716761 100644
--- a/src/Commands/IsLFSFiltered.cs
+++ b/src/Commands/IsLFSFiltered.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class IsLFSFiltered : Command
{
@@ -18,9 +20,9 @@
RaiseError = false;
}
- public bool Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
return rs.IsSuccess && rs.StdOut.Contains("filter\0lfs");
}
}
diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs
index 18d2ba93..30f06e5f 100644
--- a/src/Commands/LFS.cs
+++ b/src/Commands/LFS.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -19,6 +20,11 @@ namespace SourceGit.Commands
Args = args;
Log = log;
}
+
+ public async Task ReadAsync()
+ {
+ return await ReadToEndAsync().ConfigureAwait(false);
+ }
}
public LFS(string repo)
@@ -36,42 +42,42 @@ namespace SourceGit.Commands
return content.Contains("git lfs pre-push");
}
- public bool Install(Models.ICommandLog log)
+ public async Task InstallAsync(Models.ICommandLog log)
{
- return new SubCmd(_repo, "lfs install --local", log).Exec();
+ return await new SubCmd(_repo, "lfs install --local", log).ExecAsync().ConfigureAwait(false);
}
- public bool Track(string pattern, bool isFilenameMode, Models.ICommandLog log)
+ public async Task TrackAsync(string pattern, bool isFilenameMode, Models.ICommandLog log)
{
var opt = isFilenameMode ? "--filename" : "";
- return new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).Exec();
+ return await new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).ExecAsync().ConfigureAwait(false);
}
- public void Fetch(string remote, Models.ICommandLog log)
+ public async Task FetchAsync(string remote, Models.ICommandLog log)
{
- new SubCmd(_repo, $"lfs fetch {remote}", log).Exec();
+ await new SubCmd(_repo, $"lfs fetch {remote}", log).ExecAsync().ConfigureAwait(false);
}
- public void Pull(string remote, Models.ICommandLog log)
+ public async Task PullAsync(string remote, Models.ICommandLog log)
{
- new SubCmd(_repo, $"lfs pull {remote}", log).Exec();
+ await new SubCmd(_repo, $"lfs pull {remote}", log).ExecAsync().ConfigureAwait(false);
}
- public void Push(string remote, Models.ICommandLog log)
+ public async Task PushAsync(string remote, Models.ICommandLog log)
{
- new SubCmd(_repo, $"lfs push {remote}", log).Exec();
+ await new SubCmd(_repo, $"lfs push {remote}", log).ExecAsync().ConfigureAwait(false);
}
- public void Prune(Models.ICommandLog log)
+ public async Task PruneAsync(Models.ICommandLog log)
{
- new SubCmd(_repo, "lfs prune", log).Exec();
+ await new SubCmd(_repo, "lfs prune", log).ExecAsync().ConfigureAwait(false);
}
- public List Locks(string remote)
+ public async Task> GetLocksAsync(string remote)
{
var locks = new List();
var cmd = new SubCmd(_repo, $"lfs locks --remote={remote}", null);
- var rs = cmd.ReadToEnd();
+ var rs = await cmd.ReadAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
@@ -93,21 +99,21 @@ namespace SourceGit.Commands
return locks;
}
- public bool Lock(string remote, string file, Models.ICommandLog log)
+ public async Task LockAsync(string remote, string file, Models.ICommandLog log)
{
- return new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).Exec();
+ return await new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).ExecAsync().ConfigureAwait(false);
}
- public bool Unlock(string remote, string file, bool force, Models.ICommandLog log)
+ public async Task UnlockAsync(string remote, string file, bool force, Models.ICommandLog log)
{
var opt = force ? "-f" : "";
- return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).Exec();
+ return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).ExecAsync().ConfigureAwait(false);
}
- public bool Unlock(string remote, long id, bool force, Models.ICommandLog log)
+ public async Task UnlockAsync(string remote, long id, bool force, Models.ICommandLog log)
{
var opt = force ? "-f" : "";
- return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).Exec();
+ return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).ExecAsync().ConfigureAwait(false);
}
private readonly string _repo;
diff --git a/src/Commands/MergeTool.cs b/src/Commands/MergeTool.cs
index fc6d0d75..7cf0a22c 100644
--- a/src/Commands/MergeTool.cs
+++ b/src/Commands/MergeTool.cs
@@ -1,12 +1,11 @@
using System.IO;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class MergeTool
{
- public static bool OpenForMerge(string repo, int toolType, string toolPath, string file)
+ public static async Task OpenForMergeAsync(string repo, int toolType, string toolPath, string file)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -19,27 +18,27 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"mergetool {fileArg}";
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
if (!File.Exists(toolPath))
{
- Dispatcher.UIThread.Post(() => App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!"));
+ App.RaiseException(repo, $"Can NOT find external merge tool in '{toolPath}'!");
return false;
}
var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
if (supported == null)
{
- Dispatcher.UIThread.Post(() => App.RaiseException(repo, "Invalid merge tool in preference setting!"));
+ App.RaiseException(repo, "Invalid merge tool in preference setting!");
return false;
}
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {fileArg}";
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool OpenForDiff(string repo, int toolType, string toolPath, Models.DiffOption option)
+ public static async Task OpenForDiffAsync(string repo, int toolType, string toolPath, Models.DiffOption option)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -49,24 +48,24 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"difftool -g --no-prompt {option}";
- return cmd.Exec();
+ return await cmd.ExecAsync();
}
if (!File.Exists(toolPath))
{
- Dispatcher.UIThread.Invoke(() => App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!"));
+ App.RaiseException(repo, $"Can NOT find external diff tool in '{toolPath}'!");
return false;
}
var supported = Models.ExternalMerger.Supported.Find(x => x.Type == toolType);
if (supported == null)
{
- Dispatcher.UIThread.Post(() => App.RaiseException(repo, "Invalid merge tool in preference setting!"));
+ App.RaiseException(repo, "Invalid merge tool in preference setting!");
return false;
}
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}";
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/Move.cs b/src/Commands/Move.cs
new file mode 100644
index 00000000..ca719cd7
--- /dev/null
+++ b/src/Commands/Move.cs
@@ -0,0 +1,25 @@
+using System.Text;
+
+namespace SourceGit.Commands
+{
+ public class Move : Command
+ {
+ public Move(string repo, string oldPath, string newPath, bool force)
+ {
+ WorkingDirectory = repo;
+ Context = repo;
+
+ var builder = new StringBuilder();
+ builder.Append("mv -v ");
+ if (force)
+ builder.Append("-f ");
+ builder.Append('"');
+ builder.Append(oldPath);
+ builder.Append("\" \"");
+ builder.Append(newPath);
+ builder.Append('"');
+
+ Args = builder.ToString();
+ }
+ }
+}
diff --git a/src/Commands/Pull.cs b/src/Commands/Pull.cs
index 698fbfce..93896c75 100644
--- a/src/Commands/Pull.cs
+++ b/src/Commands/Pull.cs
@@ -1,12 +1,15 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class Pull : Command
{
public Pull(string repo, string remote, string branch, bool useRebase)
{
+ _remote = remote;
+
WorkingDirectory = repo;
Context = repo;
- SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "pull --verbose --progress ";
if (useRebase)
@@ -14,5 +17,13 @@
Args += $"{remote} {branch}";
}
+
+ public async Task RunAsync()
+ {
+ SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{_remote}.sshkey").ConfigureAwait(false);
+ return await ExecAsync().ConfigureAwait(false);
+ }
+
+ private readonly string _remote;
}
}
diff --git a/src/Commands/Push.cs b/src/Commands/Push.cs
index 8a5fe33c..b822af46 100644
--- a/src/Commands/Push.cs
+++ b/src/Commands/Push.cs
@@ -1,12 +1,15 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class Push : Command
{
public Push(string repo, string local, string remote, string remoteBranch, bool withTags, bool checkSubmodules, bool track, bool force)
{
+ _remote = remote;
+
WorkingDirectory = repo;
Context = repo;
- SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "push --progress --verbose ";
if (withTags)
@@ -23,9 +26,10 @@
public Push(string repo, string remote, string refname, bool isDelete)
{
+ _remote = remote;
+
WorkingDirectory = repo;
Context = repo;
- SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "push ";
if (isDelete)
@@ -33,5 +37,13 @@
Args += $"{remote} {refname}";
}
+
+ public async Task RunAsync()
+ {
+ SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{_remote}.sshkey").ConfigureAwait(false);
+ return await ExecAsync().ConfigureAwait(false);
+ }
+
+ private readonly string _remote;
}
}
diff --git a/src/Commands/QueryAssumeUnchangedFiles.cs b/src/Commands/QueryAssumeUnchangedFiles.cs
index b5c23b0b..0fa0f8d0 100644
--- a/src/Commands/QueryAssumeUnchangedFiles.cs
+++ b/src/Commands/QueryAssumeUnchangedFiles.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -16,10 +17,10 @@ namespace SourceGit.Commands
RaiseError = false;
}
- public List Result()
+ public async Task> GetResultAsync()
{
var outs = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs
index f268d709..e8a8372b 100644
--- a/src/Commands/QueryBranches.cs
+++ b/src/Commands/QueryBranches.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -17,12 +18,10 @@ namespace SourceGit.Commands
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
}
- public List Result(out int localBranchesCount)
+ public async Task> GetResultAsync()
{
- localBranchesCount = 0;
-
var branches = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return branches;
@@ -36,8 +35,6 @@ namespace SourceGit.Commands
branches.Add(b);
if (!b.IsLocal)
remoteHeads.Add(b.FullName, b.Head);
- else
- localBranchesCount++;
}
}
@@ -48,7 +45,7 @@ namespace SourceGit.Commands
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
{
b.IsUpstreamGone = false;
- b.TrackStatus ??= new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
+ b.TrackStatus ??= await new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).GetResultAsync().ConfigureAwait(false);
}
else
{
diff --git a/src/Commands/QueryCommitChildren.cs b/src/Commands/QueryCommitChildren.cs
index 4e99ce7a..6af0abb7 100644
--- a/src/Commands/QueryCommitChildren.cs
+++ b/src/Commands/QueryCommitChildren.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -13,9 +14,9 @@ namespace SourceGit.Commands
Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path ^{commit}";
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var outs = new List();
if (rs.IsSuccess)
{
diff --git a/src/Commands/QueryCommitFullMessage.cs b/src/Commands/QueryCommitFullMessage.cs
index 36b6d1c7..07b77f2e 100644
--- a/src/Commands/QueryCommitFullMessage.cs
+++ b/src/Commands/QueryCommitFullMessage.cs
@@ -1,3 +1,5 @@
+using System.Threading.Tasks;
+
namespace SourceGit.Commands
{
public class QueryCommitFullMessage : Command
@@ -9,12 +11,10 @@ namespace SourceGit.Commands
Args = $"show --no-show-signature --format=%B -s {sha}";
}
- public string Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
- if (rs.IsSuccess)
- return rs.StdOut.TrimEnd();
- return string.Empty;
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ return rs.IsSuccess ? rs.StdOut.TrimEnd() : string.Empty;
}
}
}
diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs
index 133949af..179e4cdd 100644
--- a/src/Commands/QueryCommitSignInfo.cs
+++ b/src/Commands/QueryCommitSignInfo.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class QueryCommitSignInfo : Command
{
@@ -12,9 +14,9 @@
Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}";
}
- public Models.CommitSignInfo Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return null;
diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs
index 8ac9cbc5..6391ff15 100644
--- a/src/Commands/QueryCommits.cs
+++ b/src/Commands/QueryCommits.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -56,9 +57,9 @@ namespace SourceGit.Commands
_findFirstMerged = false;
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return _commits;
@@ -110,7 +111,7 @@ namespace SourceGit.Commands
_current.Subject = rs.StdOut.Substring(start);
if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0)
- MarkFirstMerged();
+ await MarkFirstMergedAsync().ConfigureAwait(false);
return _commits;
}
@@ -120,21 +121,19 @@ namespace SourceGit.Commands
if (data.Length < 8)
return;
- _current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
+ _current.Parents.AddRange(data.Split(' ', StringSplitOptions.RemoveEmptyEntries));
}
- private void MarkFirstMerged()
+ private async Task MarkFirstMergedAsync()
{
Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\"";
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
if (shas.Length == 0)
return;
- var set = new HashSet();
- foreach (var sha in shas)
- set.Add(sha);
+ var set = new HashSet(shas);
foreach (var c in _commits)
{
diff --git a/src/Commands/QueryCommitsForInteractiveRebase.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs
index 9f238319..81e28d4f 100644
--- a/src/Commands/QueryCommitsForInteractiveRebase.cs
+++ b/src/Commands/QueryCommitsForInteractiveRebase.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,9 +15,9 @@ namespace SourceGit.Commands
Args = $"log --date-order --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return _commits;
@@ -85,7 +86,7 @@ namespace SourceGit.Commands
if (data.Length < 8)
return;
- _current.Commit.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
+ _current.Commit.Parents.AddRange(data.Split(' ', StringSplitOptions.RemoveEmptyEntries));
}
private List _commits = [];
diff --git a/src/Commands/QueryCurrentBranch.cs b/src/Commands/QueryCurrentBranch.cs
new file mode 100644
index 00000000..c721d13b
--- /dev/null
+++ b/src/Commands/QueryCurrentBranch.cs
@@ -0,0 +1,20 @@
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
+{
+ public class QueryCurrentBranch : Command
+ {
+ public QueryCurrentBranch(string repo)
+ {
+ WorkingDirectory = repo;
+ Context = repo;
+ Args = "branch --show-current";
+ }
+
+ public async Task GetResultAsync()
+ {
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ return rs.StdOut.Trim();
+ }
+ }
+}
diff --git a/src/Commands/QueryFileContent.cs b/src/Commands/QueryFileContent.cs
index 648b9058..38ee6e4a 100644
--- a/src/Commands/QueryFileContent.cs
+++ b/src/Commands/QueryFileContent.cs
@@ -1,12 +1,13 @@
using System;
using System.Diagnostics;
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class QueryFileContent
{
- public static Stream Run(string repo, string revision, string file)
+ public static async Task RunAsync(string repo, string revision, string file)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -22,8 +23,8 @@ namespace SourceGit.Commands
{
var proc = new Process() { StartInfo = starter };
proc.Start();
- proc.StandardOutput.BaseStream.CopyTo(stream);
- proc.WaitForExit();
+ await proc.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false);
+ await proc.WaitForExitAsync().ConfigureAwait(false);
proc.Close();
stream.Position = 0;
@@ -36,7 +37,7 @@ namespace SourceGit.Commands
return stream;
}
- public static Stream FromLFS(string repo, string oid, long size)
+ public static async Task FromLFSAsync(string repo, string oid, long size)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -53,11 +54,11 @@ namespace SourceGit.Commands
{
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();
+ await proc.StandardInput.WriteLineAsync("version https://git-lfs.github.com/spec/v1").ConfigureAwait(false);
+ await proc.StandardInput.WriteLineAsync($"oid sha256:{oid}").ConfigureAwait(false);
+ await proc.StandardInput.WriteLineAsync($"size {size}").ConfigureAwait(false);
+ await proc.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false);
+ await proc.WaitForExitAsync().ConfigureAwait(false);
proc.Close();
stream.Position = 0;
diff --git a/src/Commands/QueryFileSize.cs b/src/Commands/QueryFileSize.cs
index 30af7715..1371df8b 100644
--- a/src/Commands/QueryFileSize.cs
+++ b/src/Commands/QueryFileSize.cs
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,9 +15,9 @@ namespace SourceGit.Commands
Args = $"ls-tree {revision} -l -- \"{file}\"";
}
- public long Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var match = REG_FORMAT().Match(rs.StdOut);
diff --git a/src/Commands/QueryGitCommonDir.cs b/src/Commands/QueryGitCommonDir.cs
index 1076243e..c5b9339d 100644
--- a/src/Commands/QueryGitCommonDir.cs
+++ b/src/Commands/QueryGitCommonDir.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -8,19 +9,19 @@ namespace SourceGit.Commands
{
WorkingDirectory = workDir;
Args = "rev-parse --git-common-dir";
- RaiseError = false;
}
- public string Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd().StdOut;
- if (string.IsNullOrEmpty(rs))
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ if (!rs.IsSuccess)
return null;
- rs = rs.Trim();
- if (Path.IsPathRooted(rs))
- return rs;
- return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
+ var stdout = rs.StdOut.Trim();
+ if (string.IsNullOrEmpty(stdout))
+ return null;
+
+ return Path.IsPathRooted(stdout) ? stdout : Path.GetFullPath(Path.Combine(WorkingDirectory, stdout));
}
}
}
diff --git a/src/Commands/QueryGitDir.cs b/src/Commands/QueryGitDir.cs
index e3a94baf..ce8bfee6 100644
--- a/src/Commands/QueryGitDir.cs
+++ b/src/Commands/QueryGitDir.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -8,19 +9,19 @@ namespace SourceGit.Commands
{
WorkingDirectory = workDir;
Args = "rev-parse --git-dir";
- RaiseError = false;
}
- public string Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd().StdOut;
- if (string.IsNullOrEmpty(rs))
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ if (!rs.IsSuccess)
return null;
- rs = rs.Trim();
- if (Path.IsPathRooted(rs))
- return rs;
- return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
+ var stdout = rs.StdOut.Trim();
+ if (string.IsNullOrEmpty(stdout))
+ return null;
+
+ return Path.IsPathRooted(stdout) ? stdout : Path.GetFullPath(Path.Combine(WorkingDirectory, stdout));
}
}
}
diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs
index 788ed617..9605014d 100644
--- a/src/Commands/QueryLocalChanges.cs
+++ b/src/Commands/QueryLocalChanges.cs
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -19,13 +18,13 @@ namespace SourceGit.Commands
Args = $"--no-optional-locks status -u{UNTRACKED[includeUntracked ? 1 : 0]} --ignore-submodules=dirty --porcelain";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var outs = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
{
- Dispatcher.UIThread.Post(() => App.RaiseException(Context, rs.StdErr));
+ App.RaiseException(Context, rs.StdErr);
return outs;
}
diff --git a/src/Commands/QueryRefsContainsCommit.cs b/src/Commands/QueryRefsContainsCommit.cs
index cabe1b50..186b6a80 100644
--- a/src/Commands/QueryRefsContainsCommit.cs
+++ b/src/Commands/QueryRefsContainsCommit.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -12,29 +13,28 @@ namespace SourceGit.Commands
Args = $"for-each-ref --format=\"%(refname)\" --contains {commit}";
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = new List();
+ var outs = new List();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
+ if (!rs.IsSuccess)
+ return outs;
- var output = ReadToEnd();
- if (!output.IsSuccess)
- return rs;
-
- var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
+ var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
if (line.EndsWith("/HEAD", StringComparison.Ordinal))
continue;
if (line.StartsWith("refs/heads/", StringComparison.Ordinal))
- rs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead });
+ outs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead });
else if (line.StartsWith("refs/remotes/", StringComparison.Ordinal))
- rs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead });
+ outs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead });
else if (line.StartsWith("refs/tags/", StringComparison.Ordinal))
- rs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag });
+ outs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag });
}
- return rs;
+ return outs;
}
}
}
diff --git a/src/Commands/QueryRemotes.cs b/src/Commands/QueryRemotes.cs
index 7afec74d..bd42aabf 100644
--- a/src/Commands/QueryRemotes.cs
+++ b/src/Commands/QueryRemotes.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -16,10 +17,10 @@ namespace SourceGit.Commands
Args = "remote -v";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var outs = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return outs;
diff --git a/src/Commands/QueryRepositoryRootPath.cs b/src/Commands/QueryRepositoryRootPath.cs
index 016621c8..f7e1eb63 100644
--- a/src/Commands/QueryRepositoryRootPath.cs
+++ b/src/Commands/QueryRepositoryRootPath.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class QueryRepositoryRootPath : Command
{
@@ -7,5 +9,10 @@
WorkingDirectory = path;
Args = "rev-parse --show-toplevel";
}
+
+ public async Task GetResultAsync()
+ {
+ return await ReadToEndAsync().ConfigureAwait(false);
+ }
}
}
diff --git a/src/Commands/QueryRevisionByRefName.cs b/src/Commands/QueryRevisionByRefName.cs
index 7fb4ecfa..64a03e9d 100644
--- a/src/Commands/QueryRevisionByRefName.cs
+++ b/src/Commands/QueryRevisionByRefName.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class QueryRevisionByRefName : Command
{
@@ -9,9 +11,9 @@
Args = $"rev-parse {refname}";
}
- public string Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut))
return rs.StdOut.Trim();
diff --git a/src/Commands/QueryRevisionFileNames.cs b/src/Commands/QueryRevisionFileNames.cs
index c6fd7373..74753412 100644
--- a/src/Commands/QueryRevisionFileNames.cs
+++ b/src/Commands/QueryRevisionFileNames.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,17 +12,14 @@ namespace SourceGit.Commands
Args = $"ls-tree -r -z --name-only {revision}";
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return [];
var lines = rs.StdOut.Split('\0', System.StringSplitOptions.RemoveEmptyEntries);
- var outs = new List();
- foreach (var line in lines)
- outs.Add(line);
- return outs;
+ return [.. lines];
}
}
}
diff --git a/src/Commands/QueryRevisionObjects.cs b/src/Commands/QueryRevisionObjects.cs
index 5c582dcc..e991cd0c 100644
--- a/src/Commands/QueryRevisionObjects.cs
+++ b/src/Commands/QueryRevisionObjects.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -18,9 +19,10 @@ namespace SourceGit.Commands
Args += $" -- \"{parentFolder}\"";
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var outs = new List();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var start = 0;
@@ -28,19 +30,19 @@ namespace SourceGit.Commands
while (end > 0)
{
var line = rs.StdOut.Substring(start, end - start);
- Parse(line);
+ Parse(outs, line);
start = end + 1;
end = rs.StdOut.IndexOf('\0', start);
}
if (start < rs.StdOut.Length)
- Parse(rs.StdOut.Substring(start));
+ Parse(outs, rs.StdOut.Substring(start));
}
- return _objects;
+ return outs;
}
- private void Parse(string line)
+ private void Parse(List outs, string line)
{
var match = REG_FORMAT().Match(line);
if (!match.Success)
@@ -60,9 +62,7 @@ namespace SourceGit.Commands
_ => obj.Type,
};
- _objects.Add(obj);
+ outs.Add(obj);
}
-
- private List _objects = new List();
}
}
diff --git a/src/Commands/QuerySingleCommit.cs b/src/Commands/QuerySingleCommit.cs
index 35289ec5..897459f0 100644
--- a/src/Commands/QuerySingleCommit.cs
+++ b/src/Commands/QuerySingleCommit.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,9 +12,9 @@ namespace SourceGit.Commands
Args = $"show --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}";
}
- public Models.Commit Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut))
{
var commit = new Models.Commit();
diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs
index 78980401..bec033ff 100644
--- a/src/Commands/QueryStagedChangesWithAmend.cs
+++ b/src/Commands/QueryStagedChangesWithAmend.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -19,9 +20,9 @@ namespace SourceGit.Commands
_parent = parent;
}
- public List Result()
+ public async Task> GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return [];
diff --git a/src/Commands/QueryStagedFileBlobGuid.cs b/src/Commands/QueryStagedFileBlobGuid.cs
index 3f52a5f2..b6910034 100644
--- a/src/Commands/QueryStagedFileBlobGuid.cs
+++ b/src/Commands/QueryStagedFileBlobGuid.cs
@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,16 +15,11 @@ namespace SourceGit.Commands
Args = $"ls-files -s -- \"{file}\"";
}
- public string Result()
+ public async Task GetResultAsync()
{
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var match = REG_FORMAT().Match(rs.StdOut.Trim());
- if (match.Success)
- {
- return match.Groups[1].Value;
- }
-
- return string.Empty;
+ return match.Success ? match.Groups[1].Value : string.Empty;
}
}
}
diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs
index 2a84b34a..2b292f71 100644
--- a/src/Commands/QueryStashes.cs
+++ b/src/Commands/QueryStashes.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -12,10 +13,10 @@ namespace SourceGit.Commands
Args = "stash list -z --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B\"";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var outs = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return outs;
diff --git a/src/Commands/QuerySubmodules.cs b/src/Commands/QuerySubmodules.cs
index 663c0ea0..c6dac1f5 100644
--- a/src/Commands/QuerySubmodules.cs
+++ b/src/Commands/QuerySubmodules.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -21,10 +22,10 @@ namespace SourceGit.Commands
Args = "submodule status";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var submodules = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var map = new Dictionary();
@@ -64,11 +65,12 @@ namespace SourceGit.Commands
if (submodules.Count > 0)
{
Args = "config --file .gitmodules --list";
- rs = ReadToEnd();
+ rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var modules = new Dictionary();
lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
+
foreach (var line in lines)
{
var match = REG_FORMAT_MODULE_INFO().Match(line);
@@ -80,21 +82,39 @@ namespace SourceGit.Commands
if (!modules.TryGetValue(name, out var m))
{
- m = new ModuleInfo();
- modules.Add(name, m);
+ // Find name alias.
+ foreach (var kv in modules)
+ {
+ if (kv.Value.Path.Equals(name, StringComparison.Ordinal))
+ {
+ m = kv.Value;
+ break;
+ }
+ }
+
+ if (m == null)
+ {
+ m = new ModuleInfo();
+ modules.Add(name, m);
+ }
}
if (key.Equals("path", StringComparison.Ordinal))
m.Path = val;
else if (key.Equals("url", StringComparison.Ordinal))
m.URL = val;
+ else if (key.Equals("branch", StringComparison.Ordinal))
+ m.Branch = val;
}
}
foreach (var kv in modules)
{
if (map.TryGetValue(kv.Value.Path, out var m))
+ {
m.URL = kv.Value.URL;
+ m.Branch = kv.Value.Branch;
+ }
}
}
}
@@ -113,7 +133,7 @@ namespace SourceGit.Commands
}
Args = $"--no-optional-locks status --porcelain -- {builder}";
- rs = ReadToEnd();
+ rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return submodules;
@@ -137,6 +157,7 @@ namespace SourceGit.Commands
{
public string Path { get; set; } = string.Empty;
public string URL { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
}
}
}
diff --git a/src/Commands/QueryTags.cs b/src/Commands/QueryTags.cs
index 896d555e..ba83cb18 100644
--- a/src/Commands/QueryTags.cs
+++ b/src/Commands/QueryTags.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,10 +15,10 @@ namespace SourceGit.Commands
Args = $"tag -l --format=\"{_boundary}%(refname)%00%(objecttype)%00%(objectname)%00%(*objectname)%00%(creatordate:unix)%00%(contents:subject)%0a%0a%(contents:body)\"";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var tags = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return tags;
diff --git a/src/Commands/QueryTrackStatus.cs b/src/Commands/QueryTrackStatus.cs
index e7e1f1c9..d687d274 100644
--- a/src/Commands/QueryTrackStatus.cs
+++ b/src/Commands/QueryTrackStatus.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,11 +12,11 @@ namespace SourceGit.Commands
Args = $"rev-list --left-right {local}...{upstream}";
}
- public Models.BranchTrackStatus Result()
+ public async Task GetResultAsync()
{
var status = new Models.BranchTrackStatus();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return status;
diff --git a/src/Commands/QueryUpdatableSubmodules.cs b/src/Commands/QueryUpdatableSubmodules.cs
index 03f4a24d..05fcc053 100644
--- a/src/Commands/QueryUpdatableSubmodules.cs
+++ b/src/Commands/QueryUpdatableSubmodules.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -16,10 +17,10 @@ namespace SourceGit.Commands
Args = "submodule status";
}
- public List Result()
+ public async Task> GetResultAsync()
{
var submodules = new List();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
diff --git a/src/Commands/Remote.cs b/src/Commands/Remote.cs
index beaf412b..6a150377 100644
--- a/src/Commands/Remote.cs
+++ b/src/Commands/Remote.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Commands
+using System.Threading.Tasks;
+
+namespace SourceGit.Commands
{
public class Remote : Command
{
@@ -8,50 +10,50 @@
Context = repo;
}
- public bool Add(string name, string url)
+ public async Task AddAsync(string name, string url)
{
Args = $"remote add {name} {url}";
- return Exec();
+ return await ExecAsync();
}
- public bool Delete(string name)
+ public async Task DeleteAsync(string name)
{
Args = $"remote remove {name}";
- return Exec();
+ return await ExecAsync();
}
- public bool Rename(string name, string to)
+ public async Task RenameAsync(string name, string to)
{
Args = $"remote rename {name} {to}";
- return Exec();
+ return await ExecAsync();
}
- public bool Prune(string name)
+ public async Task PruneAsync(string name)
{
Args = $"remote prune {name}";
- return Exec();
+ return await ExecAsync();
}
- public string GetURL(string name, bool isPush)
+ public async Task GetURLAsync(string name, bool isPush)
{
Args = "remote get-url" + (isPush ? " --push " : " ") + name;
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync();
return rs.IsSuccess ? rs.StdOut.Trim() : string.Empty;
}
- public bool SetURL(string name, string url, bool isPush)
+ public async Task SetURLAsync(string name, string url, bool isPush)
{
Args = "remote set-url" + (isPush ? " --push " : " ") + $"{name} {url}";
- return Exec();
+ return await ExecAsync();
}
- public bool HasBranch(string remote, string branch)
+ public async Task HasBranchAsync(string remote, string branch)
{
- SSHKey = new Config(WorkingDirectory).Get($"remote.{remote}.sshkey");
+ SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{remote}.sshkey");
Args = $"ls-remote {remote} {branch}";
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync();
return rs.IsSuccess && rs.StdOut.Trim().Length > 0;
}
}
diff --git a/src/Commands/SaveChangesAsPatch.cs b/src/Commands/SaveChangesAsPatch.cs
index b10037a1..659d5329 100644
--- a/src/Commands/SaveChangesAsPatch.cs
+++ b/src/Commands/SaveChangesAsPatch.cs
@@ -2,20 +2,19 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class SaveChangesAsPatch
{
- public static bool ProcessLocalChanges(string repo, List changes, bool isUnstaged, string saveTo)
+ public static async Task ProcessLocalChangesAsync(string repo, List changes, bool isUnstaged, string saveTo)
{
- using (var sw = File.Create(saveTo))
+ await using (var sw = File.Create(saveTo))
{
foreach (var change in changes)
{
- if (!ProcessSingleChange(repo, new Models.DiffOption(change, isUnstaged), sw))
+ if (!await ProcessSingleChangeAsync(repo, new Models.DiffOption(change, isUnstaged), sw))
return false;
}
}
@@ -23,13 +22,13 @@ namespace SourceGit.Commands
return true;
}
- public static bool ProcessRevisionCompareChanges(string repo, List changes, string baseRevision, string targetRevision, string saveTo)
+ public static async Task ProcessRevisionCompareChangesAsync(string repo, List changes, string baseRevision, string targetRevision, string saveTo)
{
- using (var sw = File.Create(saveTo))
+ await using (var sw = File.Create(saveTo))
{
foreach (var change in changes)
{
- if (!ProcessSingleChange(repo, new Models.DiffOption(baseRevision, targetRevision, change), sw))
+ if (!await ProcessSingleChangeAsync(repo, new Models.DiffOption(baseRevision, targetRevision, change), sw))
return false;
}
}
@@ -37,20 +36,20 @@ namespace SourceGit.Commands
return true;
}
- public static bool ProcessStashChanges(string repo, List opts, string saveTo)
+ public static async Task ProcessStashChangesAsync(string repo, List opts, string saveTo)
{
- using (var sw = File.Create(saveTo))
+ await using (var sw = File.Create(saveTo))
{
foreach (var opt in opts)
{
- if (!ProcessSingleChange(repo, opt, sw))
+ if (!await ProcessSingleChangeAsync(repo, opt, sw))
return false;
}
}
return true;
}
- private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer)
+ private static async Task ProcessSingleChangeAsync(string repo, Models.DiffOption opt, FileStream writer)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -65,8 +64,8 @@ namespace SourceGit.Commands
{
var proc = new Process() { StartInfo = starter };
proc.Start();
- proc.StandardOutput.BaseStream.CopyTo(writer);
- proc.WaitForExit();
+ await proc.StandardOutput.BaseStream.CopyToAsync(writer).ConfigureAwait(false);
+ await proc.WaitForExitAsync().ConfigureAwait(false);
var rs = proc.ExitCode == 0;
proc.Close();
@@ -74,10 +73,7 @@ namespace SourceGit.Commands
}
catch (Exception e)
{
- Dispatcher.UIThread.Invoke(() =>
- {
- App.RaiseException(repo, "Save change to patch failed: " + e.Message);
- });
+ App.RaiseException(repo, "Save change to patch failed: " + e.Message);
return false;
}
}
diff --git a/src/Commands/SaveRevisionFile.cs b/src/Commands/SaveRevisionFile.cs
index b6127ea6..24d803df 100644
--- a/src/Commands/SaveRevisionFile.cs
+++ b/src/Commands/SaveRevisionFile.cs
@@ -1,32 +1,31 @@
using System;
using System.Diagnostics;
using System.IO;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class SaveRevisionFile
{
- public static void Run(string repo, string revision, string file, string saveTo)
+ public static async Task RunAsync(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();
+ var isLFSFiltered = await new IsLFSFiltered(repo, revision, file).GetResultAsync().ConfigureAwait(false);
if (isLFSFiltered)
{
- var pointerStream = QueryFileContent.Run(repo, revision, file);
- ExecCmd(repo, "lfs smudge", saveTo, pointerStream);
+ var pointerStream = await QueryFileContent.RunAsync(repo, revision, file).ConfigureAwait(false);
+ await ExecCmdAsync(repo, "lfs smudge", saveTo, pointerStream).ConfigureAwait(false);
}
else
{
- ExecCmd(repo, $"show {revision}:\"{file}\"", saveTo);
+ await ExecCmdAsync(repo, $"show {revision}:\"{file}\"", saveTo).ConfigureAwait(false);
}
}
- private static void ExecCmd(string repo, string args, string outputFile, Stream input = null)
+ private static async Task ExecCmdAsync(string repo, string args, string outputFile, Stream input = null)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -39,24 +38,21 @@ namespace SourceGit.Commands
starter.RedirectStandardOutput = true;
starter.RedirectStandardError = true;
- using (var sw = File.OpenWrite(outputFile))
+ await using (var sw = File.OpenWrite(outputFile))
{
try
{
var proc = new Process() { StartInfo = starter };
proc.Start();
if (input != null)
- proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
- proc.StandardOutput.BaseStream.CopyTo(sw);
- proc.WaitForExit();
+ await proc.StandardInput.WriteAsync(await new StreamReader(input).ReadToEndAsync());
+ await proc.StandardOutput.BaseStream.CopyToAsync(sw);
+ await proc.WaitForExitAsync();
proc.Close();
}
catch (Exception e)
{
- Dispatcher.UIThread.Invoke(() =>
- {
- App.RaiseException(repo, "Save file failed: " + e.Message);
- });
+ App.RaiseException(repo, "Save file failed: " + e.Message);
}
}
}
diff --git a/src/Commands/Stash.cs b/src/Commands/Stash.cs
index 7d1a269b..9774ed56 100644
--- a/src/Commands/Stash.cs
+++ b/src/Commands/Stash.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,7 +12,7 @@ namespace SourceGit.Commands
Context = repo;
}
- public bool Push(string message, bool includeUntracked = true, bool keepIndex = false)
+ public async Task PushAsync(string message, bool includeUntracked = true, bool keepIndex = false)
{
var builder = new StringBuilder();
builder.Append("stash push ");
@@ -24,10 +25,10 @@ namespace SourceGit.Commands
builder.Append("\"");
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Push(string message, List changes, bool keepIndex)
+ public async Task PushAsync(string message, List changes, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --include-untracked ");
@@ -41,10 +42,10 @@ namespace SourceGit.Commands
builder.Append($"\"{c.Path}\" ");
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Push(string message, string pathspecFromFile, bool keepIndex)
+ public async Task PushAsync(string message, string pathspecFromFile, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --include-untracked --pathspec-from-file=\"");
@@ -57,10 +58,10 @@ namespace SourceGit.Commands
builder.Append("\"");
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool PushOnlyStaged(string message, bool keepIndex)
+ public async Task PushOnlyStagedAsync(string message, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --staged ");
@@ -70,32 +71,32 @@ namespace SourceGit.Commands
builder.Append(message);
builder.Append("\"");
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Apply(string name, bool restoreIndex)
+ public async Task ApplyAsync(string name, bool restoreIndex)
{
var opts = restoreIndex ? "--index" : string.Empty;
Args = $"stash apply -q {opts} \"{name}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Pop(string name)
+ public async Task PopAsync(string name)
{
Args = $"stash pop -q --index \"{name}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Drop(string name)
+ public async Task DropAsync(string name)
{
Args = $"stash drop -q \"{name}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Clear()
+ public async Task ClearAsync()
{
Args = "stash clear";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/Statistics.cs b/src/Commands/Statistics.cs
index e11c1740..513b9640 100644
--- a/src/Commands/Statistics.cs
+++ b/src/Commands/Statistics.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,10 +12,10 @@ namespace SourceGit.Commands
Args = $"log --date-order --branches --remotes -{max} --format=%ct$%aN±%aE";
}
- public Models.Statistics Result()
+ public async Task ReadAsync()
{
var statistics = new Models.Statistics();
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
if (!rs.IsSuccess)
return statistics;
diff --git a/src/Commands/Submodule.cs b/src/Commands/Submodule.cs
index 025d035a..ce93e017 100644
--- a/src/Commands/Submodule.cs
+++ b/src/Commands/Submodule.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,25 +12,38 @@ namespace SourceGit.Commands
Context = repo;
}
- public bool Add(string url, string relativePath, bool recursive)
+ public async Task AddAsync(string url, string relativePath, bool recursive)
{
Args = $"-c protocol.file.allow=always submodule add \"{url}\" \"{relativePath}\"";
- if (!Exec())
+
+ var succ = await ExecAsync().ConfigureAwait(false);
+ if (!succ)
return false;
if (recursive)
- {
Args = $"submodule update --init --recursive -- \"{relativePath}\"";
- return Exec();
- }
else
- {
Args = $"submodule update --init -- \"{relativePath}\"";
- return true;
- }
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Update(List modules, bool init, bool recursive, bool useRemote = false)
+ public async Task SetURLAsync(string path, string url)
+ {
+ Args = $"submodule set-url -- \"{path}\" \"{url}\"";
+ return await ExecAsync().ConfigureAwait(false);
+ }
+
+ public async Task SetBranchAsync(string path, string branch)
+ {
+ if (string.IsNullOrEmpty(branch))
+ Args = $"submodule set-branch -d -- \"{path}\"";
+ else
+ Args = $"submodule set-branch -b \"{branch}\" -- \"{path}\"";
+
+ return await ExecAsync().ConfigureAwait(false);
+ }
+
+ public async Task UpdateAsync(List modules, bool init, bool recursive, bool useRemote = false)
{
var builder = new StringBuilder();
builder.Append("submodule update");
@@ -48,19 +62,19 @@ namespace SourceGit.Commands
}
Args = builder.ToString();
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Deinit(string module, bool force)
+ public async Task DeinitAsync(string module, bool force)
{
Args = force ? $"submodule deinit -f -- \"{module}\"" : $"submodule deinit -- \"{module}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Delete(string module)
+ public async Task DeleteAsync(string module)
{
Args = $"rm -rf \"{module}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/Tag.cs b/src/Commands/Tag.cs
index 017afea0..d372573a 100644
--- a/src/Commands/Tag.cs
+++ b/src/Commands/Tag.cs
@@ -1,20 +1,21 @@
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class Tag
{
- public static bool Add(string repo, string name, string basedOn, Models.ICommandLog log)
+ public static async Task AddAsync(string repo, string name, string basedOn, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag --no-sign {name} {basedOn}";
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool Add(string repo, string name, string basedOn, string message, bool sign, Models.ICommandLog log)
+ public static async Task AddAsync(string repo, string name, string basedOn, string message, bool sign, Models.ICommandLog log)
{
var param = sign ? "--sign -a" : "--no-sign -a";
var cmd = new Command();
@@ -26,26 +27,26 @@ namespace SourceGit.Commands
if (!string.IsNullOrEmpty(message))
{
string tmp = Path.GetTempFileName();
- File.WriteAllText(tmp, message);
+ await File.WriteAllTextAsync(tmp, message);
cmd.Args += $"-F \"{tmp}\"";
- var succ = cmd.Exec();
+ var succ = await cmd.ExecAsync().ConfigureAwait(false);
File.Delete(tmp);
return succ;
}
cmd.Args += $"-m {name}";
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
- public static bool Delete(string repo, string name, Models.ICommandLog log)
+ public static async Task DeleteAsync(string repo, string name, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag --delete {name}";
cmd.Log = log;
- return cmd.Exec();
+ return await cmd.ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Commands/UnstageChangesForAmend.cs b/src/Commands/UnstageChangesForAmend.cs
index 19def067..049811e5 100644
--- a/src/Commands/UnstageChangesForAmend.cs
+++ b/src/Commands/UnstageChangesForAmend.cs
@@ -2,8 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
-
-using Avalonia.Threading;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -49,7 +48,7 @@ namespace SourceGit.Commands
}
}
- public bool Exec()
+ public async Task ExecAsync()
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = _repo;
@@ -66,25 +65,22 @@ namespace SourceGit.Commands
{
var proc = new Process() { StartInfo = starter };
proc.Start();
- proc.StandardInput.Write(_patchBuilder.ToString());
+ await proc.StandardInput.WriteAsync(_patchBuilder.ToString());
proc.StandardInput.Close();
- var err = proc.StandardError.ReadToEnd();
- proc.WaitForExit();
+ var err = await proc.StandardError.ReadToEndAsync().ConfigureAwait(false);
+ await proc.WaitForExitAsync().ConfigureAwait(false);
var rs = proc.ExitCode == 0;
proc.Close();
if (!rs)
- Dispatcher.UIThread.Invoke(() => App.RaiseException(_repo, err));
+ App.RaiseException(_repo, err);
return rs;
}
catch (Exception e)
{
- Dispatcher.UIThread.Invoke(() =>
- {
- App.RaiseException(_repo, "Failed to unstage changes: " + e.Message);
- });
+ App.RaiseException(_repo, "Failed to unstage changes: " + e.Message);
return false;
}
}
diff --git a/src/Commands/Worktree.cs b/src/Commands/Worktree.cs
index 1198a443..4e6bc4e4 100644
--- a/src/Commands/Worktree.cs
+++ b/src/Commands/Worktree.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -12,13 +13,13 @@ namespace SourceGit.Commands
Context = repo;
}
- public List List()
+ public async Task> ReadAllAsync()
{
Args = "worktree list --porcelain";
- var rs = ReadToEnd();
+ var rs = await ReadToEndAsync().ConfigureAwait(false);
var worktrees = new List();
- var last = null as Models.Worktree;
+ Models.Worktree last = null;
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
@@ -56,7 +57,7 @@ namespace SourceGit.Commands
return worktrees;
}
- public bool Add(string fullpath, string name, bool createNew, string tracking)
+ public async Task AddAsync(string fullpath, string name, bool createNew, string tracking)
{
Args = "worktree add ";
@@ -78,35 +79,35 @@ namespace SourceGit.Commands
else if (!string.IsNullOrEmpty(name) && !createNew)
Args += name;
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Prune()
+ public async Task PruneAsync()
{
Args = "worktree prune -v";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Lock(string fullpath)
+ public async Task LockAsync(string fullpath)
{
Args = $"worktree lock \"{fullpath}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Unlock(string fullpath)
+ public async Task UnlockAsync(string fullpath)
{
Args = $"worktree unlock \"{fullpath}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
- public bool Remove(string fullpath, bool force)
+ public async Task RemoveAsync(string fullpath, bool force)
{
if (force)
Args = $"worktree remove -f \"{fullpath}\"";
else
Args = $"worktree remove \"{fullpath}\"";
- return Exec();
+ return await ExecAsync().ConfigureAwait(false);
}
}
}
diff --git a/src/Models/ApplyWhiteSpaceMode.cs b/src/Models/ApplyWhiteSpaceMode.cs
index aad45f57..9bcd04b3 100644
--- a/src/Models/ApplyWhiteSpaceMode.cs
+++ b/src/Models/ApplyWhiteSpaceMode.cs
@@ -1,6 +1,6 @@
namespace SourceGit.Models
{
- public class ApplyWhiteSpaceMode
+ public class ApplyWhiteSpaceMode(string n, string d, string a)
{
public static readonly ApplyWhiteSpaceMode[] Supported =
[
@@ -10,15 +10,8 @@
new ApplyWhiteSpaceMode("Error All", "Similar to 'error', but shows more", "error-all"),
];
- public string Name { get; set; }
- public string Desc { get; set; }
- public string Arg { get; set; }
-
- public ApplyWhiteSpaceMode(string n, string d, string a)
- {
- Name = n;
- Desc = d;
- Arg = a;
- }
+ public string Name { get; set; } = n;
+ public string Desc { get; set; } = d;
+ public string Arg { get; set; } = a;
}
}
diff --git a/src/Models/AvatarManager.cs b/src/Models/AvatarManager.cs
index f0006652..06c205e4 100644
--- a/src/Models/AvatarManager.cs
+++ b/src/Models/AvatarManager.cs
@@ -55,7 +55,7 @@ namespace SourceGit.Models
{
while (true)
{
- var email = null as string;
+ string email = null;
lock (_synclock)
{
@@ -79,7 +79,7 @@ namespace SourceGit.Models
$"https://www.gravatar.com/avatar/{md5}?d=404";
var localFile = Path.Combine(_storePath, md5);
- var img = null as Bitmap;
+ Bitmap img = null;
try
{
var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(2) };
@@ -113,7 +113,7 @@ namespace SourceGit.Models
_requesting.Remove(email);
}
- Dispatcher.UIThread.InvokeAsync(() =>
+ Dispatcher.UIThread.Post(() =>
{
_resources[email] = img;
NotifyResourceChanged(email, img);
@@ -197,7 +197,10 @@ namespace SourceGit.Models
_resources[email] = image;
- _requesting.Remove(email);
+ lock (_synclock)
+ {
+ _requesting.Remove(email);
+ }
var store = Path.Combine(_storePath, GetEmailHash(email));
File.Copy(file, store, true);
diff --git a/src/Models/Branch.cs b/src/Models/Branch.cs
index 7146da3f..350bc5b5 100644
--- a/src/Models/Branch.cs
+++ b/src/Models/Branch.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Text.RegularExpressions;
namespace SourceGit.Models
{
@@ -29,7 +30,7 @@ namespace SourceGit.Models
CommitterDate,
}
- public class Branch
+ public partial class Branch
{
public string Name { get; set; }
public string FullName { get; set; }
@@ -44,5 +45,13 @@ namespace SourceGit.Models
public bool IsUpstreamGone { get; set; }
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
+
+ [GeneratedRegex(@"\s+")]
+ private static partial Regex REG_FIX_NAME();
+
+ public static string FixName(string name)
+ {
+ return REG_FIX_NAME().Replace(name, "-");
+ }
}
}
diff --git a/src/Models/CRLFMode.cs b/src/Models/CRLFMode.cs
index 3f510f00..46f5442f 100644
--- a/src/Models/CRLFMode.cs
+++ b/src/Models/CRLFMode.cs
@@ -2,23 +2,16 @@
namespace SourceGit.Models
{
- public class CRLFMode
+ public class CRLFMode(string name, string value, string desc)
{
- public string Name { get; set; }
- public string Value { get; set; }
- public string Desc { get; set; }
+ public string Name { get; set; } = name;
+ public string Value { get; set; } = value;
+ public string Desc { get; set; } = desc;
public static readonly List Supported = new List() {
new CRLFMode("TRUE", "true", "Commit as LF, checkout as CRLF"),
new CRLFMode("INPUT", "input", "Only convert for commit"),
new CRLFMode("FALSE", "false", "Do NOT convert"),
};
-
- public CRLFMode(string name, string value, string desc)
- {
- Name = name;
- Value = value;
- Desc = desc;
- }
}
}
diff --git a/src/Models/CommitGraph.cs b/src/Models/CommitGraph.cs
index 01488656..cb569610 100644
--- a/src/Models/CommitGraph.cs
+++ b/src/Models/CommitGraph.cs
@@ -6,6 +6,13 @@ using Avalonia.Media;
namespace SourceGit.Models
{
+ public record CommitGraphLayout(double startY, double clipWidth, double rowHeight)
+ {
+ public double StartY { get; set; } = startY;
+ public double ClipWidth { get; set; } = clipWidth;
+ public double RowHeight { get; set; } = rowHeight;
+ }
+
public class CommitGraph
{
public static List Pens { get; } = [];
@@ -75,7 +82,7 @@ namespace SourceGit.Models
foreach (var commit in commits)
{
- var major = null as PathHelper;
+ PathHelper major = null;
var isMerged = commit.IsMerged;
// Update current y offset
diff --git a/src/Models/CommitLink.cs b/src/Models/CommitLink.cs
index 2891e5d6..02308975 100644
--- a/src/Models/CommitLink.cs
+++ b/src/Models/CommitLink.cs
@@ -27,19 +27,19 @@ namespace SourceGit.Models
trimmedUrl = url.AsSpan(0, url.Length - 4);
if (url.StartsWith("https://github.com/", StringComparison.Ordinal))
- outs.Add(new($"Github ({trimmedUrl.Slice(19)})", $"{url}/commit/"));
+ outs.Add(new($"Github ({trimmedUrl[19..]})", $"{url}/commit/"));
else if (url.StartsWith("https://gitlab.", StringComparison.Ordinal))
- outs.Add(new($"GitLab ({trimmedUrl.Slice(trimmedUrl.Slice(15).IndexOf('/') + 16)})", $"{url}/-/commit/"));
+ outs.Add(new($"GitLab ({trimmedUrl[(trimmedUrl[15..].IndexOf('/') + 16)..]})", $"{url}/-/commit/"));
else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal))
- outs.Add(new($"Gitee ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
+ outs.Add(new($"Gitee ({trimmedUrl[18..]})", $"{url}/commit/"));
else if (url.StartsWith("https://bitbucket.org/", StringComparison.Ordinal))
- outs.Add(new($"BitBucket ({trimmedUrl.Slice(22)})", $"{url}/commits/"));
+ outs.Add(new($"BitBucket ({trimmedUrl[22..]})", $"{url}/commits/"));
else if (url.StartsWith("https://codeberg.org/", StringComparison.Ordinal))
- outs.Add(new($"Codeberg ({trimmedUrl.Slice(21)})", $"{url}/commit/"));
+ outs.Add(new($"Codeberg ({trimmedUrl[21..]})", $"{url}/commit/"));
else if (url.StartsWith("https://gitea.org/", StringComparison.Ordinal))
- outs.Add(new($"Gitea ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
+ outs.Add(new($"Gitea ({trimmedUrl[18..]})", $"{url}/commit/"));
else if (url.StartsWith("https://git.sr.ht/", StringComparison.Ordinal))
- outs.Add(new($"sourcehut ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
+ outs.Add(new($"sourcehut ({trimmedUrl[18..]})", $"{url}/commit/"));
}
}
diff --git a/src/Models/CustomAction.cs b/src/Models/CustomAction.cs
index c6130fe0..1ed65b8b 100644
--- a/src/Models/CustomAction.cs
+++ b/src/Models/CustomAction.cs
@@ -16,6 +16,7 @@ namespace SourceGit.Models
TextBox = 0,
PathSelector,
CheckBox,
+ ComboBox,
}
public class CustomActionControl : ObservableObject
diff --git a/src/Models/DealWithChangesAfterStashing.cs b/src/Models/DealWithChangesAfterStashing.cs
index 63889c96..9393ce74 100644
--- a/src/Models/DealWithChangesAfterStashing.cs
+++ b/src/Models/DealWithChangesAfterStashing.cs
@@ -2,21 +2,15 @@
namespace SourceGit.Models
{
- public class DealWithChangesAfterStashing
+ public class DealWithChangesAfterStashing(string label, string desc)
{
- public string Label { get; set; }
- public string Desc { get; set; }
+ public string Label { get; set; } = label;
+ public string Desc { get; set; } = desc;
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/DiffOption.cs b/src/Models/DiffOption.cs
index 69f93980..fe32528c 100644
--- a/src/Models/DiffOption.cs
+++ b/src/Models/DiffOption.cs
@@ -29,6 +29,8 @@ namespace SourceGit.Models
{
_workingCopyChange = change;
_isUnstaged = isUnstaged;
+ _path = change.Path;
+ _orgPath = change.OriginalPath;
if (isUnstaged)
{
@@ -37,13 +39,8 @@ namespace SourceGit.Models
case ChangeState.Added:
case ChangeState.Untracked:
_extra = "--no-index";
- _path = change.Path;
_orgPath = "/dev/null";
break;
- default:
- _path = change.Path;
- _orgPath = change.OriginalPath;
- break;
}
}
else
@@ -52,9 +49,6 @@ namespace SourceGit.Models
_extra = $"--cached {change.DataForAmend.ParentSHA}";
else
_extra = "--cached";
-
- _path = change.Path;
- _orgPath = change.OriginalPath;
}
}
diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs
index 2f06c0cf..95ffa99f 100644
--- a/src/Models/DiffResult.cs
+++ b/src/Models/DiffResult.cs
@@ -1,5 +1,5 @@
using System.Collections.Generic;
-using System.Text;
+using System.IO;
using System.Text.RegularExpressions;
using Avalonia;
@@ -148,13 +148,13 @@ namespace SourceGit.Models
var isTracked = !string.IsNullOrEmpty(fileBlobGuid);
var fileGuid = isTracked ? fileBlobGuid : "00000000";
- var builder = new StringBuilder();
- builder.Append("diff --git a/").Append(change.Path).Append(" b/").Append(change.Path).Append('\n');
+ using var writer = new StreamWriter(output);
+ writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
if (!revert && !isTracked)
- builder.Append("new file mode 100644\n");
- builder.Append("index 00000000...").Append(fileGuid).Append('\n');
- builder.Append("--- ").Append((revert || isTracked) ? $"a/{change.Path}\n" : "/dev/null\n");
- builder.Append("+++ b/").Append(change.Path).Append('\n');
+ writer.WriteLine("new file mode 100644");
+ writer.WriteLine($"index 00000000...{fileGuid}");
+ writer.WriteLine($"--- {(revert || isTracked ? $"a/{change.Path}" : "/dev/null")}");
+ writer.WriteLine($"+++ b/{change.Path}");
var additions = selection.EndLine - selection.StartLine;
if (selection.StartLine != 1)
@@ -163,43 +163,43 @@ namespace SourceGit.Models
if (revert)
{
var totalLines = Lines.Count - 1;
- builder.Append("@@ -0,").Append(totalLines - additions).Append(" +0,").Append(totalLines).Append(" @@");
+ writer.WriteLine($"@@ -0,{totalLines - additions} +0,{totalLines} @@");
for (int i = 1; i <= totalLines; i++)
{
var line = Lines[i];
if (line.Type != TextDiffLineType.Added)
continue;
- builder.Append(selection.IsInRange(i) ? "\n+" : "\n ").Append(line.Content);
+ writer.WriteLine($"{(selection.IsInRange(i) ? "+" : " ")}{line.Content}");
}
}
else
{
- builder.Append("@@ -0,0 +0,").Append(additions).Append(" @@");
+ writer.WriteLine($"@@ -0,0 +0,{additions} @@");
for (int i = selection.StartLine - 1; i < selection.EndLine; i++)
{
var line = Lines[i];
if (line.Type != TextDiffLineType.Added)
continue;
- builder.Append("\n+").Append(line.Content);
+ writer.WriteLine($"+{line.Content}");
}
}
- builder.Append("\n\\ No newline at end of file\n");
- System.IO.File.WriteAllText(output, builder.ToString());
+ writer.WriteLine("\\ No newline at end of file");
+ writer.Flush();
}
public void GeneratePatchFromSelection(Change change, string fileTreeGuid, TextDiffSelection selection, bool revert, string output)
{
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
- var builder = new StringBuilder();
- builder.Append("diff --git a/").Append(change.Path).Append(" b/").Append(change.Path).Append('\n');
- builder.Append("index 00000000...").Append(fileTreeGuid).Append(" 100644\n");
- builder.Append("--- a/").Append(orgFile).Append('\n');
- builder.Append("+++ b/").Append(change.Path);
+ using var writer = new StreamWriter(output);
+ writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
+ writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
+ writer.WriteLine($"--- a/{orgFile}");
+ writer.WriteLine($"+++ b/{change.Path}");
// If last line of selection is a change. Find one more line.
- var tail = null as string;
+ string tail = null;
if (selection.EndLine < Lines.Count)
{
var lastLine = Lines[selection.EndLine - 1];
@@ -210,21 +210,12 @@ namespace SourceGit.Models
var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator)
break;
- if (revert)
+ if (line.Type == TextDiffLineType.Normal ||
+ (revert && line.Type == TextDiffLineType.Added) ||
+ (!revert && line.Type == TextDiffLineType.Deleted))
{
- if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added)
- {
- tail = line.Content;
- break;
- }
- }
- else
- {
- if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Deleted)
- {
- tail = line.Content;
- break;
- }
+ tail = line.Content;
+ break;
}
}
}
@@ -264,21 +255,21 @@ namespace SourceGit.Models
var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator)
{
- ProcessIndicatorForPatch(builder, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, tail != null);
+ ProcessIndicatorForPatch(writer, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, tail != null);
}
else if (line.Type == TextDiffLineType.Added)
{
if (revert)
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Deleted)
{
if (!revert)
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Normal)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
}
}
@@ -289,42 +280,39 @@ namespace SourceGit.Models
var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator)
{
- if (!ProcessIndicatorForPatch(builder, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, tail != null))
- {
+ if (!ProcessIndicatorForPatch(writer, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, tail != null))
break;
- }
}
else if (line.Type == TextDiffLineType.Normal)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Added)
{
- builder.Append("\n+").Append(line.Content);
+ writer.WriteLine($"+{line.Content}");
}
else if (line.Type == TextDiffLineType.Deleted)
{
- builder.Append("\n-").Append(line.Content);
+ writer.WriteLine($"-{line.Content}");
}
}
- builder.Append("\n ").Append(tail);
- builder.Append("\n");
- System.IO.File.WriteAllText(output, builder.ToString());
+ writer.WriteLine($" {tail}");
+ writer.Flush();
}
public void GeneratePatchFromSelectionSingleSide(Change change, string fileTreeGuid, TextDiffSelection selection, bool revert, bool isOldSide, string output)
{
var orgFile = !string.IsNullOrEmpty(change.OriginalPath) ? change.OriginalPath : change.Path;
- var builder = new StringBuilder();
- builder.Append("diff --git a/").Append(change.Path).Append(" b/").Append(change.Path).Append('\n');
- builder.Append("index 00000000...").Append(fileTreeGuid).Append(" 100644\n");
- builder.Append("--- a/").Append(orgFile).Append('\n');
- builder.Append("+++ b/").Append(change.Path);
+ using var writer = new StreamWriter(output);
+ writer.WriteLine($"diff --git a/{change.Path} b/{change.Path}");
+ writer.WriteLine($"index 00000000...{fileTreeGuid} 100644");
+ writer.WriteLine($"--- a/{orgFile}");
+ writer.WriteLine($"+++ b/{change.Path}");
// If last line of selection is a change. Find one more line.
- var tail = null as string;
+ string tail = null;
if (selection.EndLine < Lines.Count)
{
var lastLine = Lines[selection.EndLine - 1];
@@ -389,21 +377,21 @@ namespace SourceGit.Models
var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator)
{
- ProcessIndicatorForPatchSingleSide(builder, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, isOldSide, tail != null);
+ ProcessIndicatorForPatchSingleSide(writer, line, i, selection.StartLine, selection.EndLine, ignoreRemoves, ignoreAdds, revert, isOldSide, tail != null);
}
else if (line.Type == TextDiffLineType.Added)
{
if (revert)
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Deleted)
{
if (!revert)
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Normal)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
}
}
@@ -414,14 +402,12 @@ namespace SourceGit.Models
var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator)
{
- if (!ProcessIndicatorForPatchSingleSide(builder, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, isOldSide, tail != null))
- {
+ if (!ProcessIndicatorForPatchSingleSide(writer, line, i, selection.StartLine, selection.EndLine, selection.IgnoredDeletes, selection.IgnoredAdds, revert, isOldSide, tail != null))
break;
- }
}
else if (line.Type == TextDiffLineType.Normal)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else if (line.Type == TextDiffLineType.Added)
{
@@ -429,7 +415,7 @@ namespace SourceGit.Models
{
if (revert)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else
{
@@ -438,20 +424,20 @@ namespace SourceGit.Models
}
else
{
- builder.Append("\n+").Append(line.Content);
+ writer.WriteLine($"+{line.Content}");
}
}
else if (line.Type == TextDiffLineType.Deleted)
{
if (isOldSide)
{
- builder.Append("\n-").Append(line.Content);
+ writer.WriteLine($"-{line.Content}");
}
else
{
if (!revert)
{
- builder.Append("\n ").Append(line.Content);
+ writer.WriteLine($" {line.Content}");
}
else
{
@@ -461,12 +447,11 @@ namespace SourceGit.Models
}
}
- builder.Append("\n ").Append(tail);
- builder.Append("\n");
- System.IO.File.WriteAllText(output, builder.ToString());
+ writer.WriteLine($" {tail}");
+ writer.Flush();
}
- private bool ProcessIndicatorForPatch(StringBuilder builder, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed)
+ private bool ProcessIndicatorForPatch(StreamWriter writer, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool tailed)
{
var match = REG_INDICATOR().Match(indicator.Content);
var oldStart = int.Parse(match.Groups[1].Value);
@@ -531,11 +516,11 @@ namespace SourceGit.Models
if (oldCount == 0 && newCount == 0)
return false;
- builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
+ writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
return true;
}
- private bool ProcessIndicatorForPatchSingleSide(StringBuilder builder, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool isOldSide, bool tailed)
+ private bool ProcessIndicatorForPatchSingleSide(StreamWriter writer, TextDiffLine indicator, int idx, int start, int end, int ignoreRemoves, int ignoreAdds, bool revert, bool isOldSide, bool tailed)
{
var match = REG_INDICATOR().Match(indicator.Content);
var oldStart = int.Parse(match.Groups[1].Value);
@@ -611,7 +596,7 @@ namespace SourceGit.Models
if (oldCount == 0 && newCount == 0)
return false;
- builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
+ writer.WriteLine($"@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
return true;
}
diff --git a/src/Models/ExternalMerger.cs b/src/Models/ExternalMerger.cs
index fe67ad6a..ed9b9b08 100644
--- a/src/Models/ExternalMerger.cs
+++ b/src/Models/ExternalMerger.cs
@@ -44,6 +44,7 @@ namespace SourceGit.Models
new ExternalMerger(9, "p4merge", "P4Merge", "p4merge.exe", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(10, "plastic_merge", "Plastic SCM", "mergetool.exe", "-s=\"$REMOTE\" -b=\"$BASE\" -d=\"$LOCAL\" -r=\"$MERGED\" --automatic", "-s=\"$LOCAL\" -d=\"$REMOTE\""),
new ExternalMerger(11, "meld", "Meld", "Meld.exe", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
+ new ExternalMerger(12, "cursor", "Cursor", "Cursor.exe", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
};
}
else if (OperatingSystem.IsMacOS())
@@ -57,6 +58,7 @@ namespace SourceGit.Models
new ExternalMerger(5, "beyond_compare", "Beyond Compare", "/Applications/Beyond Compare.app/Contents/MacOS/bcomp", "\"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(6, "codium", "VSCodium", "/Applications/VSCodium.app/Contents/Resources/app/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(7, "p4merge", "P4Merge", "/Applications/p4merge.app/Contents/Resources/launchp4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
+ new ExternalMerger(8, "cursor", "Cursor", "/Applications/Cursor.app/Contents/Resources/app/bin/cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
};
}
else if (OperatingSystem.IsLinux())
@@ -70,6 +72,7 @@ namespace SourceGit.Models
new ExternalMerger(5, "meld", "Meld", "/usr/bin/meld", "\"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"", "\"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(6, "codium", "VSCodium", "/usr/share/codium/bin/codium", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
new ExternalMerger(7, "p4merge", "P4Merge", "/usr/local/bin/p4merge", "-tw 4 \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"", "-tw 4 \"$LOCAL\" \"$REMOTE\""),
+ new ExternalMerger(8, "cursor", "Cursor", "cursor", "-n --wait \"$MERGED\"", "-n --wait --diff \"$LOCAL\" \"$REMOTE\""),
};
}
else
@@ -93,19 +96,10 @@ namespace SourceGit.Models
public string[] GetPatterns()
{
if (OperatingSystem.IsWindows())
- {
return Exec.Split(';');
- }
- else
- {
- var patterns = new List();
- var choices = Exec.Split(';', StringSplitOptions.RemoveEmptyEntries);
- foreach (var c in choices)
- {
- patterns.Add(Path.GetFileName(c));
- }
- return patterns.ToArray();
- }
+
+ var choices = Exec.Split(';', StringSplitOptions.RemoveEmptyEntries);
+ return Array.ConvertAll(choices, Path.GetFileName);
}
}
}
diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs
index 697c171a..f884fb4a 100644
--- a/src/Models/ExternalTool.cs
+++ b/src/Models/ExternalTool.cs
@@ -154,6 +154,11 @@ namespace SourceGit.Models
TryAdd("Zed", "zed", platformFinder);
}
+ public void Cursor(Func platformFinder)
+ {
+ TryAdd("Cursor", "cursor", platformFinder);
+ }
+
public void FindJetBrainsFromToolbox(Func platformFinder)
{
var exclude = new List { "fleet", "dotmemory", "dottrace", "resharper-u", "androidstudio" };
diff --git a/src/Models/MergeMode.cs b/src/Models/MergeMode.cs
index 5dc70030..a217514e 100644
--- a/src/Models/MergeMode.cs
+++ b/src/Models/MergeMode.cs
@@ -1,25 +1,33 @@
namespace SourceGit.Models
{
- public class MergeMode
+ public class MergeMode(string n, string d, string a)
{
+ public static readonly MergeMode Default =
+ new MergeMode("Default", "Fast-forward if possible", "");
+
+ public static readonly MergeMode FastForward =
+ new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only");
+
+ public static readonly MergeMode NoFastForward =
+ new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff");
+
+ public static readonly MergeMode Squash =
+ new MergeMode("Squash", "Squash merge", "--squash");
+
+ public static readonly MergeMode DontCommit
+ = new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit");
+
public static readonly MergeMode[] Supported =
[
- new MergeMode("Default", "Fast-forward if possible", ""),
- new MergeMode("Fast-forward", "Refuse to merge when fast-forward is not possible", "--ff-only"),
- new MergeMode("No Fast-forward", "Always create a merge commit", "--no-ff"),
- new MergeMode("Squash", "Squash merge", "--squash"),
- new MergeMode("Don't commit", "Merge without commit", "--no-ff --no-commit"),
+ Default,
+ FastForward,
+ NoFastForward,
+ Squash,
+ DontCommit,
];
- public string Name { get; set; }
- public string Desc { get; set; }
- public string Arg { get; set; }
-
- public MergeMode(string n, string d, string a)
- {
- Name = n;
- Desc = d;
- Arg = a;
- }
+ public string Name { get; set; } = n;
+ public string Desc { get; set; } = d;
+ public string Arg { get; set; } = a;
}
}
diff --git a/src/Models/OpenAI.cs b/src/Models/OpenAI.cs
index ab2a92b3..9ca3506e 100644
--- a/src/Models/OpenAI.cs
+++ b/src/Models/OpenAI.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
+using System.Threading.Tasks;
using Azure.AI.OpenAI;
using CommunityToolkit.Mvvm.ComponentModel;
using OpenAI;
@@ -173,7 +174,7 @@ namespace SourceGit.Models
""";
}
- public void Chat(string prompt, string question, CancellationToken cancellation, Action onUpdate)
+ public async Task ChatAsync(string prompt, string question, CancellationToken cancellation, Action onUpdate)
{
var server = new Uri(_server);
var key = new ApiKeyCredential(_apiKey);
@@ -191,9 +192,9 @@ namespace SourceGit.Models
if (_streaming)
{
- var updates = client.CompleteChatStreaming(messages, null, cancellation);
+ var updates = client.CompleteChatStreamingAsync(messages, null, cancellation);
- foreach (var update in updates)
+ await foreach (var update in updates)
{
if (update.ContentUpdate.Count > 0)
rsp.Append(update.ContentUpdate[0].Text);
@@ -201,7 +202,7 @@ namespace SourceGit.Models
}
else
{
- var completion = client.CompleteChat(messages, null, cancellation);
+ var completion = await client.CompleteChatAsync(messages, null, cancellation);
if (completion.Value.Content.Count > 0)
rsp.Append(completion.Value.Content[0].Text);
diff --git a/src/Models/ResetMode.cs b/src/Models/ResetMode.cs
index 827ccaa9..1c84dc8e 100644
--- a/src/Models/ResetMode.cs
+++ b/src/Models/ResetMode.cs
@@ -2,7 +2,7 @@
namespace SourceGit.Models
{
- public class ResetMode
+ public class ResetMode(string n, string d, string a, string k, IBrush b)
{
public static readonly ResetMode[] Supported =
[
@@ -13,19 +13,10 @@ namespace SourceGit.Models
new ResetMode("Hard", "Discard all changes", "--hard", "H", Brushes.Red),
];
- public string Name { get; set; }
- public string Desc { get; set; }
- public string Arg { get; set; }
- public string Key { get; set; }
- public IBrush Color { get; set; }
-
- public ResetMode(string n, string d, string a, string k, IBrush b)
- {
- Name = n;
- Desc = d;
- Arg = a;
- Key = k;
- Color = b;
- }
+ public string Name { get; set; } = n;
+ public string Desc { get; set; } = d;
+ public string Arg { get; set; } = a;
+ public string Key { get; set; } = k;
+ public IBrush Color { get; set; } = b;
}
}
diff --git a/src/Models/Submodule.cs b/src/Models/Submodule.cs
index ca73a8de..17080713 100644
--- a/src/Models/Submodule.cs
+++ b/src/Models/Submodule.cs
@@ -14,6 +14,7 @@
public string Path { get; set; } = string.Empty;
public string SHA { get; set; } = string.Empty;
public string URL { get; set; } = string.Empty;
+ public string Branch { get; set; } = string.Empty;
public SubmoduleStatus Status { get; set; } = SubmoduleStatus.Normal;
public bool IsDirty => Status > SubmoduleStatus.NotInited;
}
diff --git a/src/Models/TemplateEngine.cs b/src/Models/TemplateEngine.cs
index 8f60bd74..c2ce28b2 100644
--- a/src/Models/TemplateEngine.cs
+++ b/src/Models/TemplateEngine.cs
@@ -88,9 +88,7 @@ namespace SourceGit.Models
{
var c = Peek();
if (c is not null)
- {
_pos++;
- }
return c;
}
@@ -129,7 +127,7 @@ namespace SourceGit.Models
{
case ESCAPE:
// allow to escape only \ and $
- if (Peek() is { } nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR))
+ if (Peek() is ESCAPE or VARIABLE_ANCHOR)
{
esc = true;
FlushText(tok, _pos - 1);
@@ -320,9 +318,7 @@ namespace SourceGit.Models
private static string EvalVariable(Context context, string name)
{
if (!s_variables.TryGetValue(name, out var getter))
- {
return string.Empty;
- }
return getter(context);
}
@@ -334,9 +330,7 @@ namespace SourceGit.Models
private static string EvalVariable(Context context, SlicedVariable variable)
{
if (!s_slicedVariables.TryGetValue(variable.name, out var getter))
- {
return string.Empty;
- }
return getter(context, variable.count);
}
diff --git a/src/Models/TextInlineChange.cs b/src/Models/TextInlineChange.cs
index afe5bec4..bc1873e2 100644
--- a/src/Models/TextInlineChange.cs
+++ b/src/Models/TextInlineChange.cs
@@ -50,7 +50,7 @@ namespace SourceGit.Models
var ret = new List();
var posOld = 0;
var posNew = 0;
- var last = null as TextInlineChange;
+ TextInlineChange last = null;
do
{
while (posOld < sizeOld && posNew < sizeNew && !chunksOld[posOld].Modified && !chunksNew[posNew].Modified)
@@ -295,16 +295,12 @@ namespace SourceGit.Models
private static void AddChunk(List chunks, Dictionary hashes, string data, int start)
{
- if (hashes.TryGetValue(data, out var hash))
- {
- chunks.Add(new Chunk(hash, start, data.Length));
- }
- else
+ if (!hashes.TryGetValue(data, out var hash))
{
hash = hashes.Count;
hashes.Add(data, hash);
- chunks.Add(new Chunk(hash, start, data.Length));
}
+ chunks.Add(new Chunk(hash, start, data.Length));
}
}
}
diff --git a/src/Models/TextMateHelper.cs b/src/Models/TextMateHelper.cs
index b7efae72..e9903890 100644
--- a/src/Models/TextMateHelper.cs
+++ b/src/Models/TextMateHelper.cs
@@ -33,7 +33,7 @@ namespace SourceGit.Models
var extension = Path.GetExtension(file);
if (extension == ".h")
extension = ".cpp";
- else if (extension == ".resx" || extension == ".plist" || extension == ".manifest")
+ else if (extension is ".resx" or ".plist" or ".manifest")
extension = ".xml";
else if (extension == ".command")
extension = ".sh";
diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs
index 4d6656e3..9ba7ee9c 100644
--- a/src/Models/Watcher.cs
+++ b/src/Models/Watcher.cs
@@ -256,6 +256,7 @@ namespace SourceGit.Models
if (name.Equals(".gitmodules", StringComparison.Ordinal))
{
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
+ _updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
return;
}
diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs
index 3f6de903..03608649 100644
--- a/src/Native/Linux.cs
+++ b/src/Native/Linux.cs
@@ -52,6 +52,7 @@ namespace SourceGit.Native
finder.VSCode(() => FindExecutable("code"));
finder.VSCodeInsiders(() => FindExecutable("code-insiders"));
finder.VSCodium(() => FindExecutable("codium"));
+ finder.Cursor(() => FindExecutable("cursor"));
finder.Fleet(FindJetBrainsFleet);
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}/JetBrains/Toolbox");
finder.SublimeText(() => FindExecutable("subl"));
diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs
index 8ee84cb5..1e7ac59e 100644
--- a/src/Native/MacOS.cs
+++ b/src/Native/MacOS.cs
@@ -74,6 +74,7 @@ namespace SourceGit.Native
finder.VSCode(() => "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code");
finder.VSCodeInsiders(() => "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code");
finder.VSCodium(() => "/Applications/VSCodium.app/Contents/Resources/app/bin/codium");
+ finder.Cursor(() => "/Applications/Cursor.app/Contents/Resources/app/bin/cursor");
finder.Fleet(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/Applications/Fleet.app/Contents/MacOS/Fleet");
finder.FindJetBrainsFromToolbox(() => $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/Library/Application Support/JetBrains/Toolbox");
finder.SublimeText(() => "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl");
diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs
index 02d8142b..e71bf782 100644
--- a/src/Native/Windows.cs
+++ b/src/Native/Windows.cs
@@ -67,7 +67,7 @@ namespace SourceGit.Native
window.ExtendClientAreaToDecorationsHint = true;
window.Classes.Add("fix_maximized_padding");
- Win32Properties.AddWndProcHookCallback(window, (IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
+ Win32Properties.AddWndProcHookCallback(window, (IntPtr hWnd, uint msg, IntPtr _, IntPtr lParam, ref bool handled) =>
{
// Custom WM_NCHITTEST
if (msg == 0x0084)
@@ -184,6 +184,7 @@ namespace SourceGit.Native
finder.VSCode(FindVSCode);
finder.VSCodeInsiders(FindVSCodeInsiders);
finder.VSCodium(FindVSCodium);
+ finder.Cursor(FindCursor);
finder.Fleet(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\Programs\Fleet\Fleet.exe");
finder.FindJetBrainsFromToolbox(() => $@"{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}\JetBrains\Toolbox");
finder.SublimeText(FindSublimeText);
@@ -257,7 +258,7 @@ namespace SourceGit.Native
{
// Schedule the DWM frame extension to run in the next render frame
// to ensure proper timing with the window initialization sequence
- Dispatcher.UIThread.InvokeAsync(() =>
+ Dispatcher.UIThread.Post(() =>
{
var platformHandle = w.TryGetPlatformHandle();
if (platformHandle == null)
@@ -387,6 +388,20 @@ namespace SourceGit.Native
return string.Empty;
}
+
+ private string FindCursor()
+ {
+ var cursorPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ "Programs",
+ "Cursor",
+ "Cursor.exe");
+
+ if (File.Exists(cursorPath))
+ return cursorPath;
+
+ return string.Empty;
+ }
#endregion
private void OpenFolderAndSelectFile(string folderPath)
diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml
index b1528c5a..6289ad18 100644
--- a/src/Resources/Icons.axaml
+++ b/src/Resources/Icons.axaml
@@ -89,7 +89,7 @@
M896 64H128C96 64 64 96 64 128v768c0 32 32 64 64 64h768c32 0 64-32 64-64V128c0-32-32-64-64-64z m-64 736c0 16-17 32-32 32H224c-18 0-32-12-32-32V224c0-16 16-32 32-32h576c15 0 32 16 32 32v576zM512 384c-71 0-128 57-128 128s57 128 128 128 128-57 128-128-57-128-128-128z
M0 512M1024 512M512 0M512 1024M813 448c-46 0-83 37-83 83 0 46 37 83 83 83 46 0 83-37 83-83 0-46-37-83-83-83zM211 448C165 448 128 485 128 531c0 46 37 83 83 83 46 0 83-37 83-83 0-46-37-83-83-83zM512 448c-46 0-83 37-83 83 0 46 37 83 83 83 46 0 83-37 83-83C595 485 558 448 512 448z
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
+ 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
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
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/CL.png b/src/Resources/Images/ExternalToolIcons/JetBrains/CL.png
index 9d9cf6bd..01902a92 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/CL.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/CL.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/DB.png b/src/Resources/Images/ExternalToolIcons/JetBrains/DB.png
index c7326287..694713cd 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/DB.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/DB.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/DL.png b/src/Resources/Images/ExternalToolIcons/JetBrains/DL.png
index 2715c1dd..fc76eb93 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/DL.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/DL.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/DS.png b/src/Resources/Images/ExternalToolIcons/JetBrains/DS.png
index 417f8337..f456aab9 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/DS.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/DS.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/GO.png b/src/Resources/Images/ExternalToolIcons/JetBrains/GO.png
index 744938fc..72cea44c 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/GO.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/GO.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/JB.png b/src/Resources/Images/ExternalToolIcons/JetBrains/JB.png
index e9a3d1c0..73a7b8a9 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/JB.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/JB.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/PC.png b/src/Resources/Images/ExternalToolIcons/JetBrains/PC.png
index 38ae8274..f3e15a63 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/PC.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/PC.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/PS.png b/src/Resources/Images/ExternalToolIcons/JetBrains/PS.png
index e5e2ceaf..e06fe661 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/PS.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/PS.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/PY.png b/src/Resources/Images/ExternalToolIcons/JetBrains/PY.png
index 38ae8274..f3e15a63 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/PY.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/PY.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/QA.png b/src/Resources/Images/ExternalToolIcons/JetBrains/QA.png
index 499b2eff..a962becf 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/QA.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/QA.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/QD.png b/src/Resources/Images/ExternalToolIcons/JetBrains/QD.png
index 225f3652..d2b7c420 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/QD.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/QD.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/RD.png b/src/Resources/Images/ExternalToolIcons/JetBrains/RD.png
index a2fa3d33..871988c3 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/RD.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/RD.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/RM.png b/src/Resources/Images/ExternalToolIcons/JetBrains/RM.png
index 1adfa654..5fe13b62 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/RM.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/RM.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/RR.png b/src/Resources/Images/ExternalToolIcons/JetBrains/RR.png
index ee27634a..5f72b09b 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/RR.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/RR.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/WRS.png b/src/Resources/Images/ExternalToolIcons/JetBrains/WRS.png
index 2d8f9c36..5ea6cd56 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/WRS.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/WRS.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/WS.png b/src/Resources/Images/ExternalToolIcons/JetBrains/WS.png
index 09dda1fc..6b5cb0f2 100644
Binary files a/src/Resources/Images/ExternalToolIcons/JetBrains/WS.png and b/src/Resources/Images/ExternalToolIcons/JetBrains/WS.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/beyond_compare.png b/src/Resources/Images/ExternalToolIcons/beyond_compare.png
index c7aaf18b..dc05f32c 100644
Binary files a/src/Resources/Images/ExternalToolIcons/beyond_compare.png and b/src/Resources/Images/ExternalToolIcons/beyond_compare.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/codium.png b/src/Resources/Images/ExternalToolIcons/codium.png
index 10abb719..58c49bcc 100644
Binary files a/src/Resources/Images/ExternalToolIcons/codium.png and b/src/Resources/Images/ExternalToolIcons/codium.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/cursor.png b/src/Resources/Images/ExternalToolIcons/cursor.png
new file mode 100644
index 00000000..1e0092bb
Binary files /dev/null and b/src/Resources/Images/ExternalToolIcons/cursor.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/fleet.png b/src/Resources/Images/ExternalToolIcons/fleet.png
index 5e9d84f6..55232784 100644
Binary files a/src/Resources/Images/ExternalToolIcons/fleet.png and b/src/Resources/Images/ExternalToolIcons/fleet.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/git.png b/src/Resources/Images/ExternalToolIcons/git.png
index a05a1322..034f3b9c 100644
Binary files a/src/Resources/Images/ExternalToolIcons/git.png and b/src/Resources/Images/ExternalToolIcons/git.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/kdiff3.png b/src/Resources/Images/ExternalToolIcons/kdiff3.png
index 1e2a0bbb..640aacbe 100644
Binary files a/src/Resources/Images/ExternalToolIcons/kdiff3.png and b/src/Resources/Images/ExternalToolIcons/kdiff3.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/meld.png b/src/Resources/Images/ExternalToolIcons/meld.png
index b9885f15..59cdc7c5 100644
Binary files a/src/Resources/Images/ExternalToolIcons/meld.png and b/src/Resources/Images/ExternalToolIcons/meld.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/p4merge.png b/src/Resources/Images/ExternalToolIcons/p4merge.png
index 010d8f6f..352fc21d 100644
Binary files a/src/Resources/Images/ExternalToolIcons/p4merge.png and b/src/Resources/Images/ExternalToolIcons/p4merge.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/plastic_merge.png b/src/Resources/Images/ExternalToolIcons/plastic_merge.png
index 0d82fc86..53d2e336 100644
Binary files a/src/Resources/Images/ExternalToolIcons/plastic_merge.png and b/src/Resources/Images/ExternalToolIcons/plastic_merge.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/rider.png b/src/Resources/Images/ExternalToolIcons/rider.png
index 6ab3b8cb..411d7732 100644
Binary files a/src/Resources/Images/ExternalToolIcons/rider.png and b/src/Resources/Images/ExternalToolIcons/rider.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/sublime_text.png b/src/Resources/Images/ExternalToolIcons/sublime_text.png
index 89e4a286..ca0cdebf 100644
Binary files a/src/Resources/Images/ExternalToolIcons/sublime_text.png and b/src/Resources/Images/ExternalToolIcons/sublime_text.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/tortoise_merge.png b/src/Resources/Images/ExternalToolIcons/tortoise_merge.png
index eb5b1a8a..10ffe0ef 100644
Binary files a/src/Resources/Images/ExternalToolIcons/tortoise_merge.png and b/src/Resources/Images/ExternalToolIcons/tortoise_merge.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/vs.png b/src/Resources/Images/ExternalToolIcons/vs.png
index d79fbcfd..072ee5cb 100644
Binary files a/src/Resources/Images/ExternalToolIcons/vs.png and b/src/Resources/Images/ExternalToolIcons/vs.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/vscode.png b/src/Resources/Images/ExternalToolIcons/vscode.png
index 23b6af54..9c15c8d7 100644
Binary files a/src/Resources/Images/ExternalToolIcons/vscode.png and b/src/Resources/Images/ExternalToolIcons/vscode.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/vscode_insiders.png b/src/Resources/Images/ExternalToolIcons/vscode_insiders.png
index 38fe8a1e..b48ed667 100644
Binary files a/src/Resources/Images/ExternalToolIcons/vscode_insiders.png and b/src/Resources/Images/ExternalToolIcons/vscode_insiders.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/win_merge.png b/src/Resources/Images/ExternalToolIcons/win_merge.png
index 8f9f53d4..41077691 100644
Binary files a/src/Resources/Images/ExternalToolIcons/win_merge.png and b/src/Resources/Images/ExternalToolIcons/win_merge.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/xcode.png b/src/Resources/Images/ExternalToolIcons/xcode.png
index faccf441..6c7d7202 100644
Binary files a/src/Resources/Images/ExternalToolIcons/xcode.png and b/src/Resources/Images/ExternalToolIcons/xcode.png differ
diff --git a/src/Resources/Images/ExternalToolIcons/zed.png b/src/Resources/Images/ExternalToolIcons/zed.png
index 07c4c50f..f2b5cead 100644
Binary files a/src/Resources/Images/ExternalToolIcons/zed.png and b/src/Resources/Images/ExternalToolIcons/zed.png differ
diff --git a/src/Resources/Images/ShellIcons/cmd.png b/src/Resources/Images/ShellIcons/cmd.png
index efa27dd4..aa118434 100644
Binary files a/src/Resources/Images/ShellIcons/cmd.png and b/src/Resources/Images/ShellIcons/cmd.png differ
diff --git a/src/Resources/Images/ShellIcons/custom.png b/src/Resources/Images/ShellIcons/custom.png
index 0175688f..6b11e3d3 100644
Binary files a/src/Resources/Images/ShellIcons/custom.png and b/src/Resources/Images/ShellIcons/custom.png differ
diff --git a/src/Resources/Images/ShellIcons/deepin-terminal.png b/src/Resources/Images/ShellIcons/deepin-terminal.png
index 78eef1b4..3bc708cd 100644
Binary files a/src/Resources/Images/ShellIcons/deepin-terminal.png and b/src/Resources/Images/ShellIcons/deepin-terminal.png differ
diff --git a/src/Resources/Images/ShellIcons/foot.png b/src/Resources/Images/ShellIcons/foot.png
index c5dbd0a5..a5ce6fdf 100644
Binary files a/src/Resources/Images/ShellIcons/foot.png and b/src/Resources/Images/ShellIcons/foot.png differ
diff --git a/src/Resources/Images/ShellIcons/git-bash.png b/src/Resources/Images/ShellIcons/git-bash.png
index 767e0a4e..e48485cb 100644
Binary files a/src/Resources/Images/ShellIcons/git-bash.png and b/src/Resources/Images/ShellIcons/git-bash.png differ
diff --git a/src/Resources/Images/ShellIcons/gnome-terminal.png b/src/Resources/Images/ShellIcons/gnome-terminal.png
index f9edd2e3..3fa56a81 100644
Binary files a/src/Resources/Images/ShellIcons/gnome-terminal.png and b/src/Resources/Images/ShellIcons/gnome-terminal.png differ
diff --git a/src/Resources/Images/ShellIcons/iterm2.png b/src/Resources/Images/ShellIcons/iterm2.png
index 16fbd3bd..c9410f56 100644
Binary files a/src/Resources/Images/ShellIcons/iterm2.png and b/src/Resources/Images/ShellIcons/iterm2.png differ
diff --git a/src/Resources/Images/ShellIcons/kitty.png b/src/Resources/Images/ShellIcons/kitty.png
index 465c2863..6ed70319 100644
Binary files a/src/Resources/Images/ShellIcons/kitty.png and b/src/Resources/Images/ShellIcons/kitty.png differ
diff --git a/src/Resources/Images/ShellIcons/konsole.png b/src/Resources/Images/ShellIcons/konsole.png
index e1dbcd49..f9fe06ea 100644
Binary files a/src/Resources/Images/ShellIcons/konsole.png and b/src/Resources/Images/ShellIcons/konsole.png differ
diff --git a/src/Resources/Images/ShellIcons/lxterminal.png b/src/Resources/Images/ShellIcons/lxterminal.png
index 99f62683..19f29475 100644
Binary files a/src/Resources/Images/ShellIcons/lxterminal.png and b/src/Resources/Images/ShellIcons/lxterminal.png differ
diff --git a/src/Resources/Images/ShellIcons/mac-terminal.png b/src/Resources/Images/ShellIcons/mac-terminal.png
index 569af756..62099f3f 100644
Binary files a/src/Resources/Images/ShellIcons/mac-terminal.png and b/src/Resources/Images/ShellIcons/mac-terminal.png differ
diff --git a/src/Resources/Images/ShellIcons/mate-terminal.png b/src/Resources/Images/ShellIcons/mate-terminal.png
index d48cedfa..7dc2945a 100644
Binary files a/src/Resources/Images/ShellIcons/mate-terminal.png and b/src/Resources/Images/ShellIcons/mate-terminal.png differ
diff --git a/src/Resources/Images/ShellIcons/ptyxis.png b/src/Resources/Images/ShellIcons/ptyxis.png
index 9202f6e1..71d62d5a 100644
Binary files a/src/Resources/Images/ShellIcons/ptyxis.png and b/src/Resources/Images/ShellIcons/ptyxis.png differ
diff --git a/src/Resources/Images/ShellIcons/pwsh.png b/src/Resources/Images/ShellIcons/pwsh.png
index 12edf757..ebb9e0da 100644
Binary files a/src/Resources/Images/ShellIcons/pwsh.png and b/src/Resources/Images/ShellIcons/pwsh.png differ
diff --git a/src/Resources/Images/ShellIcons/warp.png b/src/Resources/Images/ShellIcons/warp.png
index 7d604d8e..e053468d 100644
Binary files a/src/Resources/Images/ShellIcons/warp.png and b/src/Resources/Images/ShellIcons/warp.png differ
diff --git a/src/Resources/Images/ShellIcons/wezterm.png b/src/Resources/Images/ShellIcons/wezterm.png
index ed7a659f..9a80820b 100644
Binary files a/src/Resources/Images/ShellIcons/wezterm.png and b/src/Resources/Images/ShellIcons/wezterm.png differ
diff --git a/src/Resources/Images/ShellIcons/wt.png b/src/Resources/Images/ShellIcons/wt.png
index f2a874f4..01e48f0b 100644
Binary files a/src/Resources/Images/ShellIcons/wt.png and b/src/Resources/Images/ShellIcons/wt.png differ
diff --git a/src/Resources/Images/ShellIcons/xfce4-terminal.png b/src/Resources/Images/ShellIcons/xfce4-terminal.png
index 9eda3d00..eed9223e 100644
Binary files a/src/Resources/Images/ShellIcons/xfce4-terminal.png and b/src/Resources/Images/ShellIcons/xfce4-terminal.png differ
diff --git a/src/Resources/Images/github.png b/src/Resources/Images/github.png
index d3c211da..54658efa 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 01ceeb31..85d19999 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 741ddcb6..99e5f12d 100644
--- a/src/Resources/Locales/de_DE.axaml
+++ b/src/Resources/Locales/de_DE.axaml
@@ -44,11 +44,11 @@
ENTFERNEN
Bild laden...
Aktualisieren
- BINÄRE DATEI NICHT UNTERSTÜTZT!!!
+ BINÄRE DATEI WIRD NICHT UNTERSTÜTZT!!!
Bisect
Abbrechen
Schlecht
- Bisecting. Ist der aktuelle HEAD gut oder fehlerhaft?
+ Bisecting. Ist der aktuelle HEAD gut oder schlecht?
Gut
Überspringen
Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken.
@@ -74,7 +74,7 @@
Setze ${0}$ zurück auf ${1}$...
Setze verfolgten Branch...
Branch Vergleich
- Ungültiger upstream!
+ Ungültiger Upstream!
Bytes
ABBRECHEN
Auf Vorgänger-Revision zurücksetzen
@@ -121,7 +121,6 @@
Mit Worktree vergleichen
Author
Committer
- Information
SHA
Betreff
Benutzerdefinierte Aktion
@@ -185,12 +184,12 @@
Standard Remote
Bevorzugter Merge Modus
TICKETSYSTEM
- Beispiel Azure DevOps Rule hinzufügen
- Beispiel für Gitee Issue Regel einfügen
- Beispiel für Gitee Pull Request Regel einfügen
- Beispiel für Github-Regel hinzufügen
- Beispiel für Gitlab Issue Regel einfügen
- Beispiel für Gitlab Merge Request einfügen
+ Beispiel für Azure DevOps Regel hinzufügen
+ Beispiel für Gitee Issue Regel hinzufügen
+ Beispiel für Gitee Pull Request Regel hinzufügen
+ Beispiel für Github Regel hinzufügen
+ Beispiel für Gitlab Issue Regel hinzufügen
+ Beispiel für Gitlab Merge Request Regel hinzufügen
Beispiel für Jira-Regel hinzufügen
Neue Regel
Ticketnummer Regex-Ausdruck:
@@ -208,10 +207,11 @@
Wert bei Markierung:
Wenn markiert, wird dieser Wert in Kommandozeilen-Argumenten benutzt
Beschreibung:
- Dient als Platzhalter in TextBox/Path Selector (Pfadeingabe) oder als Tooltip in CheckBox (Kontrollkästchen)
Standardwert:
- Ordner?
+ Auf Ordner einschränken
Bezeichnung:
+ Einträge:
+ Nutze '|', um Einträge zu trennen
Typ:
Arbeitsplätze
Farbe
@@ -229,7 +229,7 @@
Kurzbeschreibung:
Typ der Änderung:
Kopieren
- Kopiere gesamten Text
+ Gesamten Text kopieren
Ganzen Pfad kopieren
Pfad kopieren
Branch erstellen...
@@ -239,7 +239,7 @@
Verwerfen
Stashen & wieder anwenden
Neuer Branch-Name:
- Branch-Namen eingeben.
+ Branch-Name
Leerzeichen werden durch Bindestriche ersetzt.
Lokalen Branch erstellen
Überschreibe existierenden Branch
@@ -307,6 +307,7 @@
Mehr Zeilen anzeigen
WÄHLE EINE DATEI AUS UM ÄNDERUNGEN ANZUZEIGEN
Öffne in Merge Tool
+ Verzeichnisverlauf
Änderungen verwerfen
Alle Änderungen in der Arbeitskopie.
Änderungen:
@@ -326,7 +327,7 @@
Ohne Tags fetchen
Remote:
Remote-Änderungen fetchen
- Als unverändert annehmen
+ Als unverändert betrachten
Verwerfen...
Verwerfe {0} Dateien...
Verwerfe Änderungen in ausgewählten Zeilen
@@ -350,11 +351,11 @@
Development-Branch:
Feature:
Feature-Prefix:
- FLOW - Finish Feature
- FLOW - Finish Hotfix
- FLOW - Finish Release
+ FLOW - Feature abschließen
+ FLOW - Hotfix abschließen
+ FLOW - Release abschließen
Ziel:
- Push zu Remote(s) nach Durchführung des Finish
+ Push zu Remote(s) nach Abschluss
Squash beim Merge
Hotfix:
Hotfix-Prefix:
@@ -388,7 +389,7 @@
Entsperren
Erzwinge entsperren
Prune
- Führt `git lfs prune` aus um alte LFS Dateien von lokalem Speicher zu löschen
+ Führt `git lfs prune` aus um alte LFS Dateien vom lokalen Speicher zu löschen
Pull
Führt `git lfs pull` aus um alle Git LFS Dasteien für aktuellen Ref & Checkout herunterzuladen
LFS Objekte pullen
@@ -401,7 +402,7 @@
Verlauf
AUTOR
AUTOR ZEITPUNKT
- GRAPH & COMMIT-NACHRICHT
+ VERLAUF & COMMIT-NACHRICHT
SHA
COMMIT ZEITPUNKT
{0} COMMITS AUSGEWÄHLT
@@ -447,13 +448,13 @@
Initialisiere Repository
Pfad:
Cherry-Pick wird durchgeführt.
- Verarbeite commit
- Merge request wird durchgeführt.
+ Verarbeite Commit
+ Merge Request wird durchgeführt.
Verarbeite
Rebase wird durchgeführt.
Angehalten bei
Revert wird durchgeführt.
- Reverte commit
+ Reverte Commit
Interaktiver Rebase
Auf:
Ziel Branch:
@@ -472,7 +473,7 @@
Alle Änderungen committen
Strategie:
Ziele:
- Bewege Repository Knoten
+ Verschiebe Repository Knoten
Wähle Vorgänger-Knoten für:
Name:
Git wurde NICHT konfiguriert. Gehe bitte zuerst in die [Einstellungen] und konfiguriere Git.
@@ -500,9 +501,9 @@
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
+ System-Prompt für Diff Analyse
API Schlüssel
- Generiere Nachricht Befehl
+ System-Prompt für Erstellung von Commit-Nachricht
Modell
Name
Server
@@ -521,7 +522,7 @@
Verwende nativen Fensterrahmen
DIFF/MERGE TOOL
Installationspfad
- Installationspfad zum Diff/Merge Tool
+ Pfad zum Diff/Merge Tool
Tool
ALLGEMEIN
Beim Starten nach Updates suchen
@@ -530,15 +531,15 @@
Commit-Historie
Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt
Zeige Nachfolger in den Commit Details
- Zeige Tags im Commit Graph
+ Zeige Tags im Commit Verlauf
Längenvorgabe für Commit-Nachrichten
GIT
Aktiviere Auto-CRLF
- Klon Standardordner
+ Standard Klon-Ordner
Benutzer Email
Globale Git Benutzer Email
Aktiviere --prune beim Fetchen
- Aktiviere --ignore-cr-at-eol beim Unterschied
+ Aktiviere --ignore-cr-at-eol beim Diff
Diese App setzt Git (>= 2.25.1) voraus
Installationspfad
Aktiviere HTTP SSL Verifizierung
@@ -549,11 +550,11 @@
Commit-Signierung
GPG Format
GPG Installationspfad
- Installationspfad zum GPG Programm
+ Pfad zum GPG Programm
Tag-Signierung
Benutzer Signierungsschlüssel
GPG Benutzer Signierungsschlüssel
- EINBINDUNGEN
+ INTEGRATIONEN
SHELL/TERMINAL
Pfad
Shell/Terminal
@@ -577,7 +578,7 @@
Lokaler Branch:
Remote:
Revision:
- Push Revision zu Remote-Branch
+ Revision zu Remote-Branch pushen
Push
Remote-Branch:
Remote-Branch verfolgen
@@ -603,7 +604,7 @@
Fetch
Im Browser öffnen
Prune
- Bestätige das entfernen des Worktrees
+ Bestätige das Entfernen des Worktrees
Aktiviere `--force` Option
Ziel:
Branch umbenennen
@@ -613,7 +614,7 @@
ABBRECHEN
Änderungen automatisch von Remote fetchen...
Sortieren
- Nach Commit Datum
+ Nach Commit-Datum
Nach Name
Aufräumen (GC & Prune)
Führt `git gc` auf diesem Repository aus.
@@ -627,10 +628,10 @@
Aktiviere '--reflog' Option
Öffne im Datei-Browser
Suche Branches/Tags/Submodule
- Sichtbarkeit im Graphen
+ Sichtbarkeit im Verlauf
Aufheben
- Im Graph ausblenden
- Im Graph filtern
+ Im Verlauf ausblenden
+ Im Verlauf filtern
Aktiviere '--first-parent' Option
LAYOUT
Horizontal
@@ -642,10 +643,10 @@
Zum HEAD wechseln
Erstelle Branch
BENACHRICHTIGUNGEN LÖSCHEN
- Nur aktuellen Branch im Graphen hervorheben
+ Nur aktuellen Branch im Verlauf hervorheben
Öffne in {0}
Öffne in externen Tools
- Aktualisiern
+ Aktualisieren
REMOTES
REMOTE HINZUFÜGEN
Commit suchen
@@ -665,7 +666,7 @@
SUBMODUL AKTUALISIEREN
TAGS
NEUER TAG
- Nach Erstellungsdatum
+ Nach Erstelldatum
Nach Namen
Sortiere
Öffne im Terminal
@@ -687,7 +688,7 @@
Commit rückgängig machen
Commit:
Commit Änderungen rückgängig machen
- Commit Nachricht umformulieren
+ Commit-Nachricht umformulieren
Bitte warten...
SPEICHERN
Speichern als...
@@ -700,7 +701,7 @@
Download
Diese Version überspringen
Software Update
- Es sind momentan kein Updates verfügbar.
+ Es sind momentan keine Updates verfügbar.
Setze verfolgten Branch
Branch:
Upstream Verfolgung aufheben
@@ -715,7 +716,7 @@
Stash
Inklusive nicht-verfolgter Dateien
Name:
- Optional. Informationen zu dieses Stashes
+ Optional. Informationen zu diesem Stash
Modus:
Nur gestagte Änderungen
Gestagte und unstagte Änderungen der ausgewähleten Datei(en) werden gestasht!!!
@@ -723,7 +724,7 @@
Anwenden
Kopiere Nachricht
Entfernen
- Als Path speichern...
+ Als Patch speichern...
Stash entfernen
Entfernen:
Stashes
@@ -739,12 +740,12 @@
COMMITS:
SUBMODULE
Submodul hinzufügen
- Relativen Pfad kopieren
+ Relativen Pfad
De-initialisiere Submodul
Untergeordnete Submodule fetchen
Öffne Submodul Repository
Relativer Pfad:
- Relativer Ordner um dieses Submodul zu speichern.
+ Relativer Pfad um dieses Submodul zu speichern.
Submodul löschen
STATUS
geändert
@@ -778,11 +779,11 @@
Lösche
DRAG & DROP VON ORDNER UNTERSTÜTZT. BENUTZERDEFINIERTE GRUPPIERUNG UNTERSTÜTZT.
Bearbeiten
- Bewege in eine andere Gruppe
+ Verschiebe in eine andere Gruppe
Öffne alle Repositories
Öffne Repository
Öffne Terminal
- Klon Standardordner erneut nach Repositories durchsuchen
+ Standard Klon-Ordner erneut nach Repositories durchsuchen
Suche Repositories...
Sortieren
Änderungen
@@ -806,7 +807,7 @@
ALLE KONFLIKTE IN EXTERNEM MERGE-TOOL ÖFFNEN
DATEI KONFLIKTE GELÖST
MEINE VERSION VERWENDEN
- DEREN VERSION VERWENDEN
+ IHRE VERSION VERWENDEN
NICHT-VERFOLGTE DATEIEN INKLUDIEREN
KEINE BISHERIGEN COMMIT-NACHRICHTEN
KEINE COMMIT TEMPLATES
@@ -819,7 +820,7 @@
UNSTAGED
STAGEN
ALLES STAGEN
- ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN
+ ALS UNVERÄNDERT BETRACHTETE ANZEIGEN
Template: ${0}$
ARBEITSPLATZ:
Arbeitsplätze konfigurieren...
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 2ce384c0..99c422f4 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -80,6 +80,9 @@
Show as File and Dir List
Show as Path List
Show as Filesystem Tree
+ Change Submodule's URL
+ Submodule:
+ URL:
Checkout Branch
Checkout Commit
Commit:
@@ -116,8 +119,8 @@
Compare with HEAD
Compare with Worktree
Author
+ Message
Committer
- Information
SHA
Subject
Custom Action
@@ -204,10 +207,11 @@
Checked Value:
When checked, this value will be used in command-line arguments
Description:
- Used as placeholder in TextBox/PathSelector or tooltip in CheckBox
Default:
Is Folder:
Label:
+ Options:
+ Use '|' as delimitter for options
Type:
Workspaces
Color
@@ -303,6 +307,7 @@
Increase Number of Visible Lines
SELECT FILE TO VIEW CHANGES
Open in Merge Tool
+ Dir Histories
Discard Changes
All local changes in working copy.
Changes:
@@ -468,6 +473,9 @@
Commit all changes
Strategy:
Targets:
+ Move Submodule
+ Move To:
+ Submodule:
Move Repository Node
Select parent node for:
Name:
@@ -697,6 +705,11 @@
Skip This Version
Software Update
There are currently no updates available.
+ Set Submodule's Branch
+ Submodule:
+ Current:
+ Change To:
+ Optional. Set to default when it is empty.
Set Tracking Branch
Branch:
Unset upstream
@@ -735,18 +748,24 @@
COMMITS:
SUBMODULES
Add Submodule
- Copy Relative Path
- De-initialize Submodule
+ Branch
+ Relative Path
+ De-initialize
Fetch nested submodules
- Open Submodule Repository
+ Histories
+ Move To
+ Open Repository
Relative Path:
Relative folder to store this module.
- Delete Submodule
+ Delete
+ Set Branch
+ Change URL
STATUS
modified
not initialized
revision changed
unmerged
+ Update
URL
OK
Copy Tag Name
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index 5d45798a..8654e5ed 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -121,7 +121,6 @@
Comparar con Worktree
Autor
Committer
- Información
SHA
Asunto
Acción personalizada
@@ -208,7 +207,6 @@
Valor Comprobado:
Cuando sea comprobado, este valor será usado en argumentos de la línea de comandos
Descripción:
- Utilizado como marcador de posición en CajaDeTexto/SelectorDeRuta ó tooltip en CheckBox
Por defecto:
Es Carpeta:
Etiqueta:
@@ -739,7 +737,7 @@
COMMITS:
SUBMÓDULOS
Añadir Submódulo
- Copiar Ruta Relativa
+ Ruta Relativa
Desinicializar Submódulo
Fetch submódulos anidados
Abrir Repositorio del Submódulo
diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml
index 10e9bc14..55de07a2 100644
--- a/src/Resources/Locales/fr_FR.axaml
+++ b/src/Resources/Locales/fr_FR.axaml
@@ -103,7 +103,6 @@
Cherry-Pick ...
Comparer avec HEAD
Comparer avec le worktree
- Informations
SHA
Action personnalisée
Rebase interactif de ${0}$ ici
@@ -665,11 +664,9 @@
COMMITS:
SOUS-MODULES
Ajouter un sous-module
- Copier le chemin relatif
+ Chemin relatif
Fetch les sous-modules imbriqués
Ouvrir le dépôt de sous-module
- Relative Path:
- Relative folder to store this module.
Supprimer le sous-module
OK
Copier le nom du Tag
diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml
index 57075725..9b2102b6 100644
--- a/src/Resources/Locales/it_IT.axaml
+++ b/src/Resources/Locales/it_IT.axaml
@@ -113,7 +113,6 @@
Confronta con Worktree
Autore
Committer
- Informazioni
SHA
Oggetto
Azione Personalizzata
@@ -693,7 +692,7 @@
COMMIT:
SOTTOMODULI
Aggiungi Sottomodulo
- Copia Percorso Relativo
+ Percorso Relativo
Recupera sottomoduli annidati
Apri Repository del Sottomodulo
Percorso Relativo:
diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml
index 166264c9..3780ffdc 100644
--- a/src/Resources/Locales/ja_JP.axaml
+++ b/src/Resources/Locales/ja_JP.axaml
@@ -102,7 +102,6 @@
チェリーピック...
HEADと比較
ワークツリーと比較
- 情報
SHA
カスタムアクション
${0}$ ブランチをここにインタラクティブリベース
@@ -663,7 +662,7 @@
コミット:
サブモジュール
サブモジュールを追加
- 相対パスをコピー
+ 相対パス
ネストされたサブモジュールを取得する
サブモジュールのリポジトリを開く
相対パス:
diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml
index 7036ee6a..75da3552 100644
--- a/src/Resources/Locales/pt_BR.axaml
+++ b/src/Resources/Locales/pt_BR.axaml
@@ -93,7 +93,6 @@
Cherry-Pick ...
Comparar com HEAD
Comparar com Worktree
- Informações
SHA
Ação customizada
Rebase Interativo ${0}$ até Aqui
@@ -603,7 +602,7 @@
COMMITS:
SUBMÓDULOS
Adicionar Submódulo
- Copiar Caminho Relativo
+ Caminho Relativo
Buscar submódulos aninhados
Abrir Repositório do Submódulo
Caminho Relativo:
diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml
index 4558f716..7d5b932b 100644
--- a/src/Resources/Locales/ru_RU.axaml
+++ b/src/Resources/Locales/ru_RU.axaml
@@ -84,6 +84,9 @@
Показывать в виде списка файлов и каталогов
Показывать в виде списка путей
Показывать в виде дерева файловой системы
+ Изменить URL-адрес подмодуля
+ Подмодуль:
+ URL-адрес:
Переключить ветку
Переключение ревизии
Ревизия:
@@ -120,8 +123,8 @@
Сравнить c ГОЛОВОЙ (HEAD)
Сравнить с рабочим каталогом
Автор
+ Сообщение
Ревизор
- Информацию
SHA
Субъект
Пользовательское действие
@@ -208,10 +211,11 @@
Проверяемое значение:
Если установлено, то данное значение будет использоваться в аргументах командной строки
Описание:
- Используется в качестве заполнителя в текстовом поле/селекторе пути или всплывающей подсказки в флажке
По умолчанию:
Это каталог:
Метка:
+ Опции:
+ Используйте разделитель «|» для опций
Тип:
Рабочие пространства
Цвет
@@ -307,6 +311,7 @@
Увеличить количество видимых строк
ВЫБЕРИТЕ ФАЙЛ ДЛЯ ПРОСМОТРА ИЗМЕНЕНИЙ
Открыть в инструменте слияния
+ Каталог историй
Отклонить изменения
Все локальные изменения в рабочей копии.
Изменения:
@@ -472,6 +477,9 @@
Зафиксировать все изменения
Стратегия:
Цели:
+ Переместить подмодуль
+ Переместить в:
+ Подмодуль:
Переместить репозиторий в другую группу
Выбрать группу для:
Имя:
@@ -701,6 +709,11 @@
Пропустить эту версию
Обновление ПО
В настоящее время обновления недоступны.
+ Установить ветку подмодуля
+ Подмодуль:
+ Текущий:
+ Изменить в:
+ Не обязательно. Установить по умолчанию, когда пусто.
Отслеживать ветку
Ветка:
Снять основную ветку
@@ -739,18 +752,24 @@
РЕВИЗИИ:
ПОДМОДУЛИ
Добавить подмодули
- Копировать относительный путь
+ Ветка
+ Каталог
Удалить подмодуль
Извлечение вложенных подмодулей
+ Истории
+ Переместить в
Открыть подмодуль репозитория
Каталог:
Относительный путь для хранения подмодуля.
Удалить подмодуль
+ Установить ветку
+ Изменить URL-адрес
СОСТОЯНИЕ
изменён
не создан
ревизия изменена
не слита
+ Обновить
URL-адрес
ОК
Копировать имя метки
diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml
index 0e9dd4d1..d6f2ff44 100644
--- a/src/Resources/Locales/ta_IN.axaml
+++ b/src/Resources/Locales/ta_IN.axaml
@@ -102,7 +102,6 @@
கனி-பறி ...
தலையுடன் ஒப்பிடுக
பணிமரத்துடன் ஒப்பிடுக
- தகவலை
பாகொவ-வை
தனிப்பயன் செயல்
இங்கே ${0}$ ஐ ஊடாடும் வகையில் மறுதளம்
@@ -664,7 +663,7 @@
உறுதிமொழிகள்:
துணைத் தொகுதி
துணைத் தொகுதியைச் சேர்
- உறவு பாதையை நகலெடு
+ உறவு பாதை
உள்ளமைக்கப்பட்ட துணைத் தொகுதிகளை எடு
துணைத் தொகுதி களஞ்சியத்தைத் திற
உறவு பாதை:
diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml
index 16799bb6..393eea74 100644
--- a/src/Resources/Locales/uk_UA.axaml
+++ b/src/Resources/Locales/uk_UA.axaml
@@ -103,7 +103,6 @@
Cherry-pick ...
Порівняти з HEAD
Порівняти з робочим деревом
- Iнформацію
SHA
Спеціальна дія
Інтерактивно перебазувати ${0}$ сюди
@@ -669,7 +668,7 @@
КОМІТІВ:
ПІДМОДУЛІ
Додати підмодуль
- Копіювати відносний шлях
+ відносний шлях
Отримати вкладені підмодулі
Відкрити сховище підмодуля
Відносний шлях:
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 8e2eeef0..7fc02833 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -84,6 +84,9 @@
文件名+路径列表模式
全路径列表模式
文件目录树形结构模式
+ 修改子模块远程地址
+ 子模块 :
+ 远程地址 :
检出(checkout)分支
检出(checkout)提交
提交 :
@@ -120,8 +123,8 @@
与当前HEAD比较
与本地工作树比较
作者
+ 提交信息
提交者
- 简要信息
提交指纹
主题
自定义操作
@@ -208,10 +211,11 @@
启用时命令行参数 :
此CheckBox勾选后,该值会被应用于命令行参数
描述 :
- TextBox及Path Selector中用作Placeholder,CheckBox中用作ToolTip
默认值 :
目标是否是目录 :
名称 :
+ 选项列表 :
+ 选项之间请使用英文 '|' 作为分隔符
类型 :
工作区
颜色
@@ -307,6 +311,7 @@
增加可见的行数
请选择需要对比的文件
使用外部比对工具查看
+ 目录内容变更历史
放弃更改确认
所有本地址未提交的修改。
变更 :
@@ -472,6 +477,9 @@
提交变化
合并策略 :
目标列表 :
+ 移动子模块
+ 移动到 :
+ 子模块 :
调整仓库分组
请选择目标分组:
名称 :
@@ -701,6 +709,11 @@
忽略此版本
软件更新
当前已是最新版本。
+ 修改子模块追踪分支
+ 子模块 :
+ 当前追踪分支 :
+ 修改为 :
+ 可选。当不填写时,恢复默认追踪分支。
切换上游分支
本地分支 :
取消追踪
@@ -739,18 +752,24 @@
提交次数:
子模块
添加子模块
- 复制路径
+ 跟踪分支
+ 相对路径
取消初始化
拉取子孙模块
+ 变更历史
+ 移动
打开仓库
相对仓库路径 :
本地存放的相对路径。
- 删除子模块
+ 删除
+ 修改跟踪分支
+ 修改远程地址
状态
未提交修改
未初始化
SHA变更
未解决冲突
+ 更新
仓库
确 定
复制标签名
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index 732794fb..63273cb0 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -84,6 +84,9 @@
檔案名稱 + 路徑列表模式
全路徑列表模式
檔案目錄樹狀結構模式
+ 修改子模組的遠端網址
+ 子模組:
+ 遠端網址:
簽出 (checkout) 分支
簽出 (checkout) 提交
提交:
@@ -120,8 +123,8 @@
與目前 HEAD 比較
與本機工作區比較
作者
+ 提交訊息
提交者
- 摘要資訊
提交編號
標題
自訂動作
@@ -208,10 +211,11 @@
啟用時的指令行參數:
勾選 CheckBox 後,此值將用於命令列參數中
描述:
- 在 TextBox/PathSelector 中用作占位符,或在 CheckBox 中用作工具提示
預設值:
目標路徑是否為資料夾:
名稱:
+ 選項列表:
+ 請使用英文「|」符號分隔選項
類型:
工作區
顏色
@@ -307,6 +311,7 @@
增加可見的行數
請選擇需要對比的檔案
使用外部比對工具檢視
+ 目錄内容變更歷史
捨棄變更
所有本機未提交的變更。
變更:
@@ -472,6 +477,9 @@
提交變更
合併策略:
目標列表:
+ 移動子模組
+ 移動到:
+ 子模組:
調整存放庫分組
請選擇目標分組:
名稱:
@@ -701,6 +709,11 @@
忽略此版本
軟體更新
目前已是最新版本。
+ 設定子模組的追蹤分支
+ 子模組:
+ 目前追蹤分支:
+ 變更為:
+ 選購。為空時設定為預設值。
切換上游分支
本機分支:
取消設定上游分支
@@ -739,18 +752,24 @@
提交次數:
子模組
新增子模組
- 複製路徑
+ 追蹤分支
+ 相對路徑
取消初始化
提取子模組
+ 變更歷史
+ 移動
開啟存放庫
相對存放庫路徑:
本機存放的相對路徑。
- 刪除子模組
+ 刪除
+ 更改追蹤分支
+ 更改遠端網址
狀態
未提交變更
未初始化
SHA 變更
未解決的衝突
+ 更新
存放庫
確 定
複製標籤名稱
diff --git a/src/Resources/Styles.axaml b/src/Resources/Styles.axaml
index a20bec81..e328cf26 100644
--- a/src/Resources/Styles.axaml
+++ b/src/Resources/Styles.axaml
@@ -843,6 +843,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj
index 5205ae4f..8d76934c 100644
--- a/src/SourceGit.csproj
+++ b/src/SourceGit.csproj
@@ -40,6 +40,7 @@
+
diff --git a/src/ViewModels/AIAssistant.cs b/src/ViewModels/AIAssistant.cs
index 8756a30b..920fafcf 100644
--- a/src/ViewModels/AIAssistant.cs
+++ b/src/ViewModels/AIAssistant.cs
@@ -58,14 +58,14 @@ namespace SourceGit.ViewModels
IsGenerating = true;
_cancel = new CancellationTokenSource();
- Task.Run(() =>
+ Task.Run(async () =>
{
- new Commands.GenerateCommitMessage(_service, _repo.FullPath, _changes, _cancel.Token, message =>
+ await new Commands.GenerateCommitMessage(_service, _repo.FullPath, _changes, _cancel.Token, message =>
{
- Dispatcher.UIThread.Invoke(() => Text = message);
- }).Exec();
+ Dispatcher.UIThread.Post(() => Text = message);
+ }).ExecAsync().ConfigureAwait(false);
- Dispatcher.UIThread.Invoke(() => IsGenerating = false);
+ Dispatcher.UIThread.Post(() => IsGenerating = false);
}, _cancel.Token);
}
diff --git a/src/ViewModels/AddRemote.cs b/src/ViewModels/AddRemote.cs
index 37bbc43a..5a6c019f 100644
--- a/src/ViewModels/AddRemote.cs
+++ b/src/ViewModels/AddRemote.cs
@@ -87,7 +87,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding remote ...";
@@ -95,24 +95,27 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Add Remote");
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Remote(_repo.FullPath).Use(log).Add(_name, _url);
- if (succ)
- {
- new Commands.Config(_repo.FullPath).Use(log).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
- new Commands.Fetch(_repo.FullPath, _name, false, false).Use(log).Exec();
- }
+ var succ = await new Commands.Remote(_repo.FullPath)
+ .Use(log)
+ .AddAsync(_name, _url);
- log.Complete();
- CallUIThread(() =>
- {
- _repo.MarkFetched();
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
- return succ;
- });
+ if (succ)
+ {
+ await new Commands.Config(_repo.FullPath)
+ .Use(log)
+ .SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
+
+ await new Commands.Fetch(_repo.FullPath, _name, false, false)
+ .Use(log)
+ .RunAsync();
+ }
+
+ log.Complete();
+
+ _repo.MarkFetched();
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/AddSubmodule.cs b/src/ViewModels/AddSubmodule.cs
index 82a1f62a..313b2e8e 100644
--- a/src/ViewModels/AddSubmodule.cs
+++ b/src/ViewModels/AddSubmodule.cs
@@ -40,7 +40,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding submodule...";
@@ -59,14 +59,13 @@ namespace SourceGit.ViewModels
relativePath = Path.GetFileName(_url);
}
- return Task.Run(() =>
- {
- var succ = new Commands.Submodule(_repo.FullPath).Use(log).Add(_url, relativePath, Recursive);
- log.Complete();
+ var succ = await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .AddAsync(_url, relativePath, Recursive);
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/AddToIgnore.cs b/src/ViewModels/AddToIgnore.cs
index 74f7e3ec..d2a194f4 100644
--- a/src/ViewModels/AddToIgnore.cs
+++ b/src/ViewModels/AddToIgnore.cs
@@ -27,35 +27,28 @@ namespace SourceGit.ViewModels
StorageFile = Models.GitIgnoreFile.Supported[0];
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding Ignored File(s) ...";
- return Task.Run(() =>
+ var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir);
+ if (!File.Exists(file))
{
- var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir);
- if (!File.Exists(file))
- {
- File.WriteAllLines(file, [_pattern]);
- }
+ await File.WriteAllLinesAsync(file, [_pattern]);
+ }
+ else
+ {
+ var org = await File.ReadAllTextAsync(file);
+ if (!org.EndsWith('\n'))
+ await File.AppendAllLinesAsync(file, ["", _pattern]);
else
- {
- var org = File.ReadAllText(file);
- if (!org.EndsWith('\n'))
- File.AppendAllLines(file, ["", _pattern]);
- else
- File.AppendAllLines(file, [_pattern]);
- }
+ await File.AppendAllLinesAsync(file, [_pattern]);
+ }
- CallUIThread(() =>
- {
- _repo.MarkWorkingCopyDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
-
- return true;
- });
+ _repo.MarkWorkingCopyDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo;
diff --git a/src/ViewModels/AddWorktree.cs b/src/ViewModels/AddWorktree.cs
index a089a391..3c3d69ff 100644
--- a/src/ViewModels/AddWorktree.cs
+++ b/src/ViewModels/AddWorktree.cs
@@ -82,8 +82,7 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateWorktreePath(string path, ValidationContext ctx)
{
- var creator = ctx.ObjectInstance as AddWorktree;
- if (creator == null)
+ if (ctx.ObjectInstance is not AddWorktree creator)
return new ValidationResult("Missing runtime context to create branch!");
if (string.IsNullOrEmpty(path))
@@ -105,7 +104,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding worktree ...";
@@ -116,14 +115,13 @@ namespace SourceGit.ViewModels
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Worktree(_repo.FullPath).Use(log).Add(_path, branchName, _createNewBranch, tracking);
- log.Complete();
+ var succ = await new Commands.Worktree(_repo.FullPath)
+ .Use(log)
+ .AddAsync(_path, branchName, _createNewBranch, tracking);
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private Repository _repo = null;
diff --git a/src/ViewModels/Apply.cs b/src/ViewModels/Apply.cs
index c7f3c185..709a66fd 100644
--- a/src/ViewModels/Apply.cs
+++ b/src/ViewModels/Apply.cs
@@ -41,20 +41,21 @@ namespace SourceGit.ViewModels
return new ValidationResult($"File '{file}' can NOT be found!!!");
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Apply patch...";
var log = _repo.CreateLog("Apply Patch");
- return Task.Run(() =>
- {
- var succ = new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Use(log).Exec();
- log.Complete();
+ Use(log);
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ var succ = await new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null)
+ .Use(log)
+ .ExecAsync();
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/ApplyStash.cs b/src/ViewModels/ApplyStash.cs
index e7cd64e9..b21d6fe8 100644
--- a/src/ViewModels/ApplyStash.cs
+++ b/src/ViewModels/ApplyStash.cs
@@ -28,20 +28,26 @@ namespace SourceGit.ViewModels
Stash = stash;
}
- public override Task Sure()
+ public override async Task Sure()
{
+ _repo.SetWatcherEnabled(false);
ProgressDescription = $"Applying stash: {Stash.Name}";
var log = _repo.CreateLog("Apply Stash");
- return Task.Run(() =>
- {
- var succ = new Commands.Stash(_repo.FullPath).Use(log).Apply(Stash.Name, RestoreIndex);
- if (succ && DropAfterApply)
- new Commands.Stash(_repo.FullPath).Use(log).Drop(Stash.Name);
+ Use(log);
- log.Complete();
- return true;
- });
+ var succ = await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .ApplyAsync(Stash.Name, RestoreIndex);
+
+ if (succ && DropAfterApply)
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .DropAsync(Stash.Name);
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo;
diff --git a/src/ViewModels/Archive.cs b/src/ViewModels/Archive.cs
index a4a4f6eb..6f86357d 100644
--- a/src/ViewModels/Archive.cs
+++ b/src/ViewModels/Archive.cs
@@ -44,7 +44,7 @@ namespace SourceGit.ViewModels
BasedOn = tag;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Archiving ...";
@@ -52,20 +52,16 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Archive");
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Archive(_repo.FullPath, _revision, _saveFile).Use(log).Exec();
- log.Complete();
+ var succ = await new Commands.Archive(_repo.FullPath, _revision, _saveFile)
+ .Use(log)
+ .ExecAsync();
- CallUIThread(() =>
- {
- _repo.SetWatcherEnabled(true);
- if (succ)
- App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}");
- });
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
- return succ;
- });
+ if (succ)
+ App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}");
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/AssumeUnchangedManager.cs b/src/ViewModels/AssumeUnchangedManager.cs
index 68151448..8cd4a166 100644
--- a/src/ViewModels/AssumeUnchangedManager.cs
+++ b/src/ViewModels/AssumeUnchangedManager.cs
@@ -1,5 +1,4 @@
using System.Threading.Tasks;
-
using Avalonia.Collections;
using Avalonia.Threading;
@@ -14,19 +13,25 @@ namespace SourceGit.ViewModels
_repo = repo;
Files = new AvaloniaList();
- Task.Run(() =>
+ Task.Run(async () =>
{
- var collect = new Commands.QueryAssumeUnchangedFiles(_repo.FullPath).Result();
- Dispatcher.UIThread.Invoke(() => Files.AddRange(collect));
+ var collect = await new Commands.QueryAssumeUnchangedFiles(_repo.FullPath)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+ Dispatcher.UIThread.Post(() => Files.AddRange(collect));
});
}
- public void Remove(string file)
+ public async Task RemoveAsync(string file)
{
if (!string.IsNullOrEmpty(file))
{
var log = _repo.CreateLog("Remove Assume Unchanged File");
- new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec();
+
+ await new Commands.AssumeUnchanged(_repo.FullPath, file, false)
+ .Use(log)
+ .ExecAsync();
+
log.Complete();
Files.Remove(file);
}
diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs
index a189215a..affe40d9 100644
--- a/src/ViewModels/Blame.cs
+++ b/src/ViewModels/Blame.cs
@@ -2,9 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-
using Avalonia.Threading;
-
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
@@ -34,7 +32,7 @@ namespace SourceGit.ViewModels
public bool IsBinary
{
- get => _data != null && _data.IsBinary;
+ get => _data?.IsBinary ?? false;
}
public bool CanBack
@@ -65,7 +63,10 @@ namespace SourceGit.ViewModels
if (_commitMessages.TryGetValue(sha, out var msg))
return msg;
- msg = new Commands.QueryCommitFullMessage(_repo, sha).Result();
+ msg = new Commands.QueryCommitFullMessage(_repo, sha)
+ .GetResultAsync()
+ .Result;
+
_commitMessages[sha] = msg;
return msg;
}
@@ -132,11 +133,13 @@ namespace SourceGit.ViewModels
}
else
{
- Task.Run(() =>
+ Task.Run(async () =>
{
- var result = new Commands.QuerySingleCommit(_repo, commitSHA).Result();
+ var result = await new Commands.QuerySingleCommit(_repo, commitSHA)
+ .GetResultAsync()
+ .ConfigureAwait(false);
- Dispatcher.UIThread.Invoke(() =>
+ Dispatcher.UIThread.Post(() =>
{
if (!token.IsCancellationRequested)
{
@@ -147,11 +150,13 @@ namespace SourceGit.ViewModels
}, token);
}
- Task.Run(() =>
+ Task.Run(async () =>
{
- var result = new Commands.Blame(_repo, FilePath, commitSHA).Result();
+ var result = await new Commands.Blame(_repo, FilePath, commitSHA)
+ .ReadAsync()
+ .ConfigureAwait(false);
- Dispatcher.UIThread.Invoke(() =>
+ Dispatcher.UIThread.Post(() =>
{
if (!token.IsCancellationRequested)
Data = result;
diff --git a/src/ViewModels/BlockNavigation.cs b/src/ViewModels/BlockNavigation.cs
index 9a5a926c..4a51244c 100644
--- a/src/ViewModels/BlockNavigation.cs
+++ b/src/ViewModels/BlockNavigation.cs
@@ -70,9 +70,7 @@ namespace SourceGit.ViewModels
foreach (var line in lines)
{
lineIdx++;
- if (line.Type == Models.TextDiffLineType.Added ||
- line.Type == Models.TextDiffLineType.Deleted ||
- line.Type == Models.TextDiffLineType.None)
+ if (line.Type is Models.TextDiffLineType.Added or Models.TextDiffLineType.Deleted or Models.TextDiffLineType.None)
{
if (isNewBlock)
{
diff --git a/src/ViewModels/BranchCompare.cs b/src/ViewModels/BranchCompare.cs
index 64ceea1c..b2ecc3be 100644
--- a/src/ViewModels/BranchCompare.cs
+++ b/src/ViewModels/BranchCompare.cs
@@ -49,7 +49,7 @@ namespace SourceGit.ViewModels
{
if (SetProperty(ref _selectedChanges, value))
{
- if (value != null && value.Count == 1)
+ if (value is { Count: 1 })
DiffContext = new DiffContext(_repo, new Models.DiffOption(_based.Head, _to.Head, value[0]), _diffContext);
else
DiffContext = null;
@@ -63,9 +63,7 @@ namespace SourceGit.ViewModels
set
{
if (SetProperty(ref _searchFilter, value))
- {
RefreshVisible();
- }
}
}
@@ -127,13 +125,13 @@ namespace SourceGit.ViewModels
var diffWithMerger = new MenuItem();
diffWithMerger.Header = App.Text("DiffWithMerger");
diffWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
- diffWithMerger.Click += (_, ev) =>
+ diffWithMerger.Click += (sender, ev) =>
{
var toolType = Preferences.Instance.ExternalMergeToolType;
var toolPath = Preferences.Instance.ExternalMergeToolPath;
var opt = new Models.DiffOption(_based.Head, _to.Head, change);
- Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt));
+ _ = Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, opt);
ev.Handled = true;
};
menu.Items.Add(diffWithMerger);
@@ -156,9 +154,9 @@ namespace SourceGit.ViewModels
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyPath.Click += (_, ev) =>
+ copyPath.Click += async (_, ev) =>
{
- App.CopyText(change.Path);
+ await App.CopyTextAsync(change.Path);
ev.Handled = true;
};
menu.Items.Add(copyPath);
@@ -166,9 +164,9 @@ namespace SourceGit.ViewModels
var copyFullPath = new MenuItem();
copyFullPath.Header = App.Text("CopyFullPath");
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyFullPath.Click += (_, e) =>
+ copyFullPath.Click += async (_, e) =>
{
- App.CopyText(Native.OS.GetAbsPath(_repo, change.Path));
+ await App.CopyTextAsync(Native.OS.GetAbsPath(_repo, change.Path));
e.Handled = true;
};
menu.Items.Add(copyFullPath);
@@ -178,20 +176,28 @@ namespace SourceGit.ViewModels
private void Refresh()
{
- Task.Run(() =>
+ Task.Run(async () =>
{
if (_baseHead == null)
{
- var baseHead = new Commands.QuerySingleCommit(_repo, _based.Head).Result();
- var toHead = new Commands.QuerySingleCommit(_repo, _to.Head).Result();
- Dispatcher.UIThread.Invoke(() =>
+ var baseHead = await new Commands.QuerySingleCommit(_repo, _based.Head)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+
+ var toHead = await new Commands.QuerySingleCommit(_repo, _to.Head)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+
+ Dispatcher.UIThread.Post(() =>
{
BaseHead = baseHead;
ToHead = toHead;
});
}
- _changes = new Commands.CompareRevisions(_repo, _based.Head, _to.Head).Result();
+ _changes = await new Commands.CompareRevisions(_repo, _based.Head, _to.Head)
+ .ReadAsync()
+ .ConfigureAwait(false);
var visible = _changes;
if (!string.IsNullOrWhiteSpace(_searchFilter))
@@ -204,7 +210,15 @@ namespace SourceGit.ViewModels
}
}
- Dispatcher.UIThread.Invoke(() => VisibleChanges = visible);
+ Dispatcher.UIThread.Post(() =>
+ {
+ VisibleChanges = visible;
+
+ if (VisibleChanges.Count > 0)
+ SelectedChanges = [VisibleChanges[0]];
+ else
+ SelectedChanges = [];
+ });
});
}
diff --git a/src/ViewModels/BranchTreeNode.cs b/src/ViewModels/BranchTreeNode.cs
index dffbf671..1550e807 100644
--- a/src/ViewModels/BranchTreeNode.cs
+++ b/src/ViewModels/BranchTreeNode.cs
@@ -165,7 +165,7 @@ namespace SourceGit.ViewModels
return;
}
- var lastFolder = null as BranchTreeNode;
+ BranchTreeNode lastFolder = null;
var start = 0;
while (sepIdx != -1)
@@ -250,8 +250,7 @@ namespace SourceGit.ViewModels
{
if (r.Backend is Models.Branch)
return r.TimeToSort == l.TimeToSort ? Models.NumericSort.Compare(l.Name, r.Name) : r.TimeToSort.CompareTo(l.TimeToSort);
- else
- return 1;
+ return 1;
}
if (r.Backend is Models.Branch)
diff --git a/src/ViewModels/ChangeSubmoduleUrl.cs b/src/ViewModels/ChangeSubmoduleUrl.cs
new file mode 100644
index 00000000..f356234b
--- /dev/null
+++ b/src/ViewModels/ChangeSubmoduleUrl.cs
@@ -0,0 +1,60 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Threading.Tasks;
+
+namespace SourceGit.ViewModels
+{
+ public class ChangeSubmoduleUrl : Popup
+ {
+ public Models.Submodule Submodule
+ {
+ get;
+ }
+
+ [Required(ErrorMessage = "Url is required!!!")]
+ [CustomValidation(typeof(ChangeSubmoduleUrl), nameof(ValidateUrl))]
+ public string Url
+ {
+ get => _url;
+ set => SetProperty(ref _url, value, true);
+ }
+
+ public ChangeSubmoduleUrl(Repository repo, Models.Submodule submodule)
+ {
+ _repo = repo;
+ _url = submodule.URL;
+ Submodule = submodule;
+ }
+
+ public static ValidationResult ValidateUrl(string url, ValidationContext ctx)
+ {
+ if (!Models.Remote.IsValidURL(url))
+ return new ValidationResult("Invalid repository URL format");
+
+ return ValidationResult.Success;
+ }
+
+ public override async Task Sure()
+ {
+ if (_url.Equals(Submodule.URL, StringComparison.Ordinal))
+ return true;
+
+ _repo.SetWatcherEnabled(false);
+ ProgressDescription = "Change submodule's url...";
+
+ var log = _repo.CreateLog("Change Submodule's URL");
+ Use(log);
+
+ var succ = await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .SetURLAsync(Submodule.Path, _url);
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
+ }
+
+ private readonly Repository _repo;
+ private string _url;
+ }
+}
diff --git a/src/ViewModels/Checkout.cs b/src/ViewModels/Checkout.cs
index 45dcd9a4..ce6195b8 100644
--- a/src/ViewModels/Checkout.cs
+++ b/src/ViewModels/Checkout.cs
@@ -33,7 +33,7 @@ namespace SourceGit.ViewModels
DiscardLocalChanges = false;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout '{Branch}' ...";
@@ -41,71 +41,76 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Checkout '{Branch}'");
Use(log);
- var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
- return Task.Run(() =>
+ if (_repo.CurrentBranch is { IsDetachedHead: true })
{
- bool succ;
- var needPopStash = false;
-
- if (!_repo.ConfirmCheckoutBranch())
+ var refs = await new Commands.QueryRefsContainsCommit(_repo.FullPath, _repo.CurrentBranch.Head).GetResultAsync();
+ if (refs.Count == 0)
{
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- }
-
- if (DiscardLocalChanges)
- {
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, true);
- }
- else
- {
- var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
- if (changes > 0)
+ var msg = App.Text("Checkout.WarnLostCommits");
+ var shouldContinue = await App.AskConfirmAsync(msg, null);
+ if (!shouldContinue)
{
- succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
- if (!succ)
- {
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return false;
- }
+ _repo.SetWatcherEnabled(true);
+ return true;
+ }
+ }
+ }
- needPopStash = true;
+ var succ = false;
+ var needPopStash = false;
+
+ if (!DiscardLocalChanges)
+ {
+ var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).GetResultAsync();
+ if (changes > 0)
+ {
+ succ = await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PushAsync("CHECKOUT_AUTO_STASH");
+ if (!succ)
+ {
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return false;
}
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, false);
+ needPopStash = true;
+ }
+ }
+
+ succ = await new Commands.Checkout(_repo.FullPath)
+ .Use(log)
+ .BranchAsync(Branch, DiscardLocalChanges);
+
+ if (succ)
+ {
+ if (IsRecurseSubmoduleVisible && RecurseSubmodules)
+ {
+ var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).GetResultAsync();
+ if (submodules.Count > 0)
+ await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .UpdateAsync(submodules, true, true);
}
- if (succ)
- {
- if (updateSubmodules)
- {
- var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
- if (submodules.Count > 0)
- new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
- }
+ if (needPopStash)
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PopAsync("stash@{0}");
+ }
- if (needPopStash)
- new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
- }
+ log.Complete();
- log.Complete();
+ var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
+ if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included)
+ _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false);
- CallUIThread(() =>
- {
- ProgressDescription = "Waiting for branch updated...";
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
- var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
- if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included)
- _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false);
-
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
-
- Task.Delay(400).Wait();
- return succ;
- });
+ ProgressDescription = "Waiting for branch updated...";
+ await Task.Delay(400);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/CheckoutAndFastForward.cs b/src/ViewModels/CheckoutAndFastForward.cs
index 9ae931fe..205bbbd7 100644
--- a/src/ViewModels/CheckoutAndFastForward.cs
+++ b/src/ViewModels/CheckoutAndFastForward.cs
@@ -38,7 +38,7 @@ namespace SourceGit.ViewModels
RemoteBranch = remoteBranch;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout and Fast-Forward '{LocalBranch.Name}' ...";
@@ -46,70 +46,75 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Checkout and Fast-Forward '{LocalBranch.Name}' ...");
Use(log);
- var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
- return Task.Run(() =>
+ if (_repo.CurrentBranch is { IsDetachedHead: true })
{
- var succ = false;
- var needPopStash = false;
-
- if (!_repo.ConfirmCheckoutBranch())
+ var refs = await new Commands.QueryRefsContainsCommit(_repo.FullPath, _repo.CurrentBranch.Head).GetResultAsync();
+ if (refs.Count == 0)
{
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- }
-
- if (DiscardLocalChanges)
- {
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, true, true);
- }
- else
- {
- var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
- if (changes > 0)
+ var msg = App.Text("Checkout.WarnLostCommits");
+ var shouldContinue = await App.AskConfirmAsync(msg, null);
+ if (!shouldContinue)
{
- succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
- if (!succ)
- {
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return false;
- }
+ _repo.SetWatcherEnabled(true);
+ return true;
+ }
+ }
+ }
- needPopStash = true;
+ var succ = false;
+ var needPopStash = false;
+
+ if (!DiscardLocalChanges)
+ {
+ var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).GetResultAsync();
+ if (changes > 0)
+ {
+ succ = await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PushAsync("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
+ if (!succ)
+ {
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return false;
}
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, false, true);
+ needPopStash = true;
+ }
+ }
+
+ succ = await new Commands.Checkout(_repo.FullPath)
+ .Use(log)
+ .BranchAsync(LocalBranch.Name, RemoteBranch.Head, DiscardLocalChanges, true);
+
+ if (succ)
+ {
+ if (IsRecurseSubmoduleVisible && RecurseSubmodules)
+ {
+ var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).GetResultAsync();
+ if (submodules.Count > 0)
+ await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .UpdateAsync(submodules, true, true);
}
- if (succ)
- {
- if (updateSubmodules)
- {
- var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
- if (submodules.Count > 0)
- new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
- }
+ if (needPopStash)
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PopAsync("stash@{0}");
+ }
- if (needPopStash)
- new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
- }
+ log.Complete();
- log.Complete();
+ if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
+ _repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
- CallUIThread(() =>
- {
- ProgressDescription = "Waiting for branch updated...";
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
- if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
- _repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
-
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
-
- Task.Delay(400).Wait();
- return succ;
- });
+ ProgressDescription = "Waiting for branch updated...";
+ await Task.Delay(400);
+ return succ;
}
private Repository _repo;
diff --git a/src/ViewModels/CheckoutCommit.cs b/src/ViewModels/CheckoutCommit.cs
index f477538d..a77a7235 100644
--- a/src/ViewModels/CheckoutCommit.cs
+++ b/src/ViewModels/CheckoutCommit.cs
@@ -33,7 +33,7 @@ namespace SourceGit.ViewModels
DiscardLocalChanges = false;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout Commit '{Commit.SHA}' ...";
@@ -41,58 +41,67 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Checkout Commit");
Use(log);
- var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
- return Task.Run(() =>
+ if (_repo.CurrentBranch is { IsDetachedHead: true })
{
- bool succ;
- var needPop = false;
-
- if (!_repo.ConfirmCheckoutBranch())
+ var refs = await new Commands.QueryRefsContainsCommit(_repo.FullPath, _repo.CurrentBranch.Head).GetResultAsync();
+ if (refs.Count == 0)
{
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- }
-
- if (DiscardLocalChanges)
- {
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, true);
- }
- else
- {
- var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
- if (changes > 0)
+ var msg = App.Text("Checkout.WarnLostCommits");
+ var shouldContinue = await App.AskConfirmAsync(msg, null);
+ if (!shouldContinue)
{
- succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
- if (!succ)
- {
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return false;
- }
+ _repo.SetWatcherEnabled(true);
+ return true;
+ }
+ }
+ }
- needPop = true;
+ var succ = false;
+ var needPop = false;
+
+ if (!DiscardLocalChanges)
+ {
+ var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).GetResultAsync();
+ if (changes > 0)
+ {
+ succ = await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PushAsync("CHECKOUT_AUTO_STASH");
+ if (!succ)
+ {
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return false;
}
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, false);
+ needPop = true;
}
+ }
- if (succ)
+ succ = await new Commands.Checkout(_repo.FullPath)
+ .Use(log)
+ .CommitAsync(Commit.SHA, DiscardLocalChanges);
+
+ if (succ)
+ {
+ if (IsRecurseSubmoduleVisible && RecurseSubmodules)
{
- if (updateSubmodules)
- {
- var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
- if (submodules.Count > 0)
- new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
- }
-
- if (needPop)
- new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
+ var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).GetResultAsync();
+ if (submodules.Count > 0)
+ await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .UpdateAsync(submodules, true, true);
}
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ if (needPop)
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PopAsync("stash@{0}");
+ }
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/CherryPick.cs b/src/ViewModels/CherryPick.cs
index 2d929f3a..ca525e0a 100644
--- a/src/ViewModels/CherryPick.cs
+++ b/src/ViewModels/CherryPick.cs
@@ -63,7 +63,7 @@ namespace SourceGit.ViewModels
AutoCommit = true;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
@@ -72,31 +72,32 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Cherry-Pick");
Use(log);
- return Task.Run(() =>
+ if (IsMergeCommit)
{
- if (IsMergeCommit)
- {
- new Commands.CherryPick(
- _repo.FullPath,
- Targets[0].SHA,
- !AutoCommit,
- AppendSourceToMessage,
- $"-m {MainlineForMergeCommit + 1}").Use(log).Exec();
- }
- else
- {
- new Commands.CherryPick(
- _repo.FullPath,
- string.Join(' ', Targets.ConvertAll(c => c.SHA)),
- !AutoCommit,
- AppendSourceToMessage,
- string.Empty).Use(log).Exec();
- }
+ await new Commands.CherryPick(
+ _repo.FullPath,
+ Targets[0].SHA,
+ !AutoCommit,
+ AppendSourceToMessage,
+ $"-m {MainlineForMergeCommit + 1}")
+ .Use(log)
+ .ExecAsync();
+ }
+ else
+ {
+ await new Commands.CherryPick(
+ _repo.FullPath,
+ string.Join(' ', Targets.ConvertAll(c => c.SHA)),
+ !AutoCommit,
+ AppendSourceToMessage,
+ string.Empty)
+ .Use(log)
+ .ExecAsync();
+ }
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- });
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/Cleanup.cs b/src/ViewModels/Cleanup.cs
index 1fc39cb5..c8788d68 100644
--- a/src/ViewModels/Cleanup.cs
+++ b/src/ViewModels/Cleanup.cs
@@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Cleanup (GC & prune) ...";
@@ -17,13 +17,13 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Cleanup (GC & prune)");
Use(log);
- return Task.Run(() =>
- {
- new Commands.GC(_repo.FullPath).Use(log).Exec();
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- });
+ await new Commands.GC(_repo.FullPath)
+ .Use(log)
+ .ExecAsync();
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/ClearStashes.cs b/src/ViewModels/ClearStashes.cs
index d71bab31..6178d5ef 100644
--- a/src/ViewModels/ClearStashes.cs
+++ b/src/ViewModels/ClearStashes.cs
@@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Clear all stashes...";
@@ -17,13 +17,13 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Clear Stashes");
Use(log);
- return Task.Run(() =>
- {
- new Commands.Stash(_repo.FullPath).Use(log).Clear();
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- });
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .ClearAsync();
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/Clone.cs b/src/ViewModels/Clone.cs
index c6f09d24..b3aadb58 100644
--- a/src/ViewModels/Clone.cs
+++ b/src/ViewModels/Clone.cs
@@ -2,7 +2,6 @@
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading.Tasks;
-
using Avalonia.Threading;
namespace SourceGit.ViewModels
@@ -74,11 +73,11 @@ namespace SourceGit.ViewModels
{
var text = await App.GetClipboardTextAsync();
if (Models.Remote.IsValidURL(text))
- Dispatcher.UIThread.Invoke(() => Remote = text);
+ Dispatcher.UIThread.Post(() => Remote = text);
}
catch
{
- // ignore
+ // Ignore
}
});
}
@@ -97,79 +96,74 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
- public override Task Sure()
+ public override async Task Sure()
{
ProgressDescription = "Clone ...";
var log = new CommandLog("Clone");
Use(log);
- return Task.Run(() =>
+ var succ = await new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs)
+ .Use(log)
+ .ExecAsync();
+ if (succ)
+ return false;
+
+ var path = _parentFolder;
+ if (!string.IsNullOrEmpty(_local))
{
- var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs).Use(log);
- if (!cmd.Exec())
- return false;
+ path = Path.GetFullPath(Path.Combine(path, _local));
+ }
+ else
+ {
+ var name = Path.GetFileName(_remote)!;
+ if (name.EndsWith(".git", StringComparison.Ordinal))
+ name = name.Substring(0, name.Length - 4);
+ else if (name.EndsWith(".bundle", StringComparison.Ordinal))
+ name = name.Substring(0, name.Length - 7);
- var path = _parentFolder;
- if (!string.IsNullOrEmpty(_local))
+ path = Path.GetFullPath(Path.Combine(path, name));
+ }
+
+ if (!Directory.Exists(path))
+ {
+ App.RaiseException(_pageId, $"Folder '{path}' can NOT be found");
+ return false;
+ }
+
+ if (_useSSH && !string.IsNullOrEmpty(_sshKey))
+ {
+ await new Commands.Config(path)
+ .Use(log)
+ .SetAsync("remote.origin.sshkey", _sshKey);
+ }
+
+ if (InitAndUpdateSubmodules)
+ {
+ var submodules = await new Commands.QueryUpdatableSubmodules(path).GetResultAsync();
+ if (submodules.Count > 0)
+ await new Commands.Submodule(path)
+ .Use(log)
+ .UpdateAsync(submodules, true, true);
+ }
+
+ log.Complete();
+
+ var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);
+ var launcher = App.GetLauncher();
+ LauncherPage page = null;
+ foreach (var one in launcher.Pages)
+ {
+ if (one.Node.Id == _pageId)
{
- path = Path.GetFullPath(Path.Combine(path, _local));
+ page = one;
+ break;
}
- else
- {
- var name = Path.GetFileName(_remote)!;
- if (name.EndsWith(".git", StringComparison.Ordinal))
- name = name.Substring(0, name.Length - 4);
- else if (name.EndsWith(".bundle", StringComparison.Ordinal))
- name = name.Substring(0, name.Length - 7);
+ }
- path = Path.GetFullPath(Path.Combine(path, name));
- }
-
- if (!Directory.Exists(path))
- {
- CallUIThread(() =>
- {
- App.RaiseException(_pageId, $"Folder '{path}' can NOT be found");
- });
- return false;
- }
-
- if (_useSSH && !string.IsNullOrEmpty(_sshKey))
- {
- var config = new Commands.Config(path);
- config.Set("remote.origin.sshkey", _sshKey);
- }
-
- if (InitAndUpdateSubmodules)
- {
- var submodules = new Commands.QueryUpdatableSubmodules(path).Result();
- if (submodules.Count > 0)
- new Commands.Submodule(path).Use(log).Update(submodules, true, true);
- }
-
- log.Complete();
-
- CallUIThread(() =>
- {
- var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true);
- var launcher = App.GetLauncher();
- var page = null as LauncherPage;
- foreach (var one in launcher.Pages)
- {
- if (one.Node.Id == _pageId)
- {
- page = one;
- break;
- }
- }
-
- Welcome.Instance.Refresh();
- launcher.OpenRepositoryInTab(node, page);
- });
-
- return true;
- });
+ Welcome.Instance.Refresh();
+ launcher.OpenRepositoryInTab(node, page);
+ return true;
}
private string _pageId = string.Empty;
diff --git a/src/ViewModels/CommandLog.cs b/src/ViewModels/CommandLog.cs
index 896869cf..1accc226 100644
--- a/src/ViewModels/CommandLog.cs
+++ b/src/ViewModels/CommandLog.cs
@@ -51,36 +51,41 @@ namespace SourceGit.ViewModels
public void AppendLine(string line = null)
{
- var newline = line ?? string.Empty;
-
- Dispatcher.UIThread.Invoke(() =>
+ if (!Dispatcher.UIThread.CheckAccess())
{
+ Dispatcher.UIThread.Invoke(() => AppendLine(line));
+ }
+ else
+ {
+ var newline = line ?? string.Empty;
_builder.AppendLine(newline);
_onNewLineReceived?.Invoke(newline);
- });
+ }
}
public void Complete()
{
- IsComplete = true;
-
- Dispatcher.UIThread.Invoke(() =>
+ if (!Dispatcher.UIThread.CheckAccess())
{
- _content = _builder.ToString();
- _builder.Clear();
- _builder = null;
+ Dispatcher.UIThread.Invoke(Complete);
+ return;
+ }
- EndTime = DateTime.Now;
+ IsComplete = true;
+ EndTime = DateTime.Now;
- OnPropertyChanged(nameof(IsComplete));
+ _content = _builder.ToString();
+ _builder.Clear();
+ _builder = null;
- if (_onNewLineReceived != null)
- {
- var dumpHandlers = _onNewLineReceived.GetInvocationList();
- foreach (var d in dumpHandlers)
- _onNewLineReceived -= (Action)d;
- }
- });
+ OnPropertyChanged(nameof(IsComplete));
+
+ if (_onNewLineReceived != null)
+ {
+ var dumpHandlers = _onNewLineReceived.GetInvocationList();
+ foreach (var d in dumpHandlers)
+ _onNewLineReceived -= (Action)d;
+ }
}
private string _content = string.Empty;
diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs
index 54673ff2..7bdefe6b 100644
--- a/src/ViewModels/CommitDetail.cs
+++ b/src/ViewModels/CommitDetail.cs
@@ -17,14 +17,15 @@ namespace SourceGit.ViewModels
{
public int ActivePageIndex
{
- get => _repo.CommitDetailActivePageIndex;
+ get => _rememberActivePageIndex ? _repo.CommitDetailActivePageIndex : _activePageIndex;
set
{
- if (_repo.CommitDetailActivePageIndex != value)
- {
+ if (_rememberActivePageIndex)
_repo.CommitDetailActivePageIndex = value;
- OnPropertyChanged();
- }
+ else
+ _activePageIndex = value;
+
+ OnPropertyChanged();
}
}
@@ -139,9 +140,10 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _canOpenRevisionFileWithDefaultEditor, value);
}
- public CommitDetail(Repository repo)
+ public CommitDetail(Repository repo, bool rememberActivePageIndex)
{
_repo = repo;
+ _rememberActivePageIndex = rememberActivePageIndex;
WebLinks = Models.CommitLink.Get(repo.Remotes);
}
@@ -167,9 +169,11 @@ namespace SourceGit.ViewModels
_repo?.NavigateToCommit(commitSHA);
}
- public List GetRefsContainsThisCommit()
+ public async Task> GetRefsContainsThisCommitAsync()
{
- return new Commands.QueryRefsContainsCommit(_repo.FullPath, _commit.SHA).Result();
+ return await new Commands.QueryRefsContainsCommit(_repo.FullPath, _commit.SHA)
+ .GetResultAsync()
+ .ConfigureAwait(false);
}
public void ClearSearchChangeFilter()
@@ -187,93 +191,34 @@ namespace SourceGit.ViewModels
RevisionFileSearchSuggestion = null;
}
- public Models.Commit GetParent(string sha)
+ public async Task GetCommitAsync(string sha)
{
- return new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
+ return await new Commands.QuerySingleCommit(_repo.FullPath, sha)
+ .GetResultAsync()
+ .ConfigureAwait(false);
}
- public List GetRevisionFilesUnderFolder(string parentFolder)
+ public async Task> GetRevisionFilesUnderFolderAsync(string parentFolder)
{
- return new Commands.QueryRevisionObjects(_repo.FullPath, _commit.SHA, parentFolder).Result();
+ return await new Commands.QueryRevisionObjects(_repo.FullPath, _commit.SHA, parentFolder)
+ .GetResultAsync()
+ .ConfigureAwait(false);
}
- public void ViewRevisionFile(Models.Object file)
+ public async Task ViewRevisionFileAsync(Models.Object file)
{
- if (file == null)
- {
- ViewRevisionFilePath = string.Empty;
- ViewRevisionFileContent = null;
- CanOpenRevisionFileWithDefaultEditor = false;
- return;
- }
+ var obj = file ?? new Models.Object() { Path = string.Empty, Type = Models.ObjectType.None };
+ ViewRevisionFilePath = obj.Path;
- ViewRevisionFilePath = file.Path;
-
- switch (file.Type)
+ switch (obj.Type)
{
case Models.ObjectType.Blob:
CanOpenRevisionFileWithDefaultEditor = true;
- Task.Run(() =>
- {
- var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
- if (isBinary)
- {
- var imgDecoder = ImageSource.GetDecoder(file.Path);
- if (imgDecoder != Models.ImageDecoder.None)
- {
- var source = ImageSource.FromRevision(_repo.FullPath, _commit.SHA, file.Path, imgDecoder);
- var image = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size);
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image);
- }
- else
- {
- var size = new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).Result();
- var binary = new Models.RevisionBinaryFile() { Size = size };
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = binary);
- }
-
- return;
- }
-
- var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
- var content = new StreamReader(contentStream).ReadToEnd();
- var lfs = Models.LFSObject.Parse(content);
- if (lfs != null)
- {
- var imgDecoder = ImageSource.GetDecoder(file.Path);
- if (imgDecoder != Models.ImageDecoder.None)
- {
- var combined = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = combined);
- }
- else
- {
- var rlfs = new Models.RevisionLFSObject() { Object = lfs };
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = rlfs);
- }
- }
- else
- {
- var txt = new Models.RevisionTextFile() { FileName = file.Path, Content = content };
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = txt);
- }
- });
+ await SetViewingBlobAsync(obj);
break;
case Models.ObjectType.Commit:
CanOpenRevisionFileWithDefaultEditor = false;
- Task.Run(() =>
- {
- var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
- var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
- var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result() : null;
- var module = new Models.RevisionSubmodule()
- {
- Commit = commit ?? new Models.Commit() { SHA = _commit.SHA },
- FullMessage = new Models.CommitFullMessage { Message = message }
- };
-
- Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = module);
- });
+ await SetViewingCommitAsync(obj);
break;
default:
CanOpenRevisionFileWithDefaultEditor = false;
@@ -282,40 +227,27 @@ namespace SourceGit.ViewModels
}
}
- public Task OpenRevisionFileWithDefaultEditor(string file)
+ public async Task OpenRevisionFileWithDefaultEditorAsync(string file)
{
- return Task.Run(() =>
- {
- var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file);
- var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
- var fileExt = Path.GetExtension(fullPath) ?? "";
- var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
+ var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file);
+ var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
+ var fileExt = Path.GetExtension(fullPath) ?? "";
+ var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
- Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file, tmpFile);
- Native.OS.OpenWithDefaultEditor(tmpFile);
- });
+ await Commands.SaveRevisionFile
+ .RunAsync(_repo.FullPath, _commit.SHA, file, tmpFile)
+ .ConfigureAwait(false);
+
+ Native.OS.OpenWithDefaultEditor(tmpFile);
}
- public ContextMenu CreateChangeContextMenu(Models.Change change)
+ public ContextMenu CreateChangeContextMenuByFolder(ChangeTreeNode node, List changes)
{
- var diffWithMerger = new MenuItem();
- diffWithMerger.Header = App.Text("DiffWithMerger");
- diffWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
- diffWithMerger.Click += (_, ev) =>
- {
- var toolType = Preferences.Instance.ExternalMergeToolType;
- var toolPath = Preferences.Instance.ExternalMergeToolPath;
- var opt = new Models.DiffOption(_commit, change);
-
- Task.Run(() => Commands.MergeTool.OpenForDiff(_repo.FullPath, toolType, toolPath, opt));
- ev.Handled = true;
- };
-
- var fullPath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
+ var fullPath = Native.OS.GetAbsPath(_repo.FullPath, node.FullPath);
var explore = new MenuItem();
explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
- explore.IsEnabled = File.Exists(fullPath);
+ explore.IsEnabled = Directory.Exists(fullPath);
explore.Click += (_, ev) =>
{
Native.OS.OpenInFileManager(fullPath, true);
@@ -323,21 +255,11 @@ namespace SourceGit.ViewModels
};
var history = new MenuItem();
- history.Header = App.Text("FileHistory");
+ history.Header = App.Text("DirHistories");
history.Icon = App.CreateMenuIcon("Icons.Histories");
history.Click += (_, ev) =>
{
- App.ShowWindow(new FileHistories(_repo, change.Path, _commit.SHA), false);
- ev.Handled = true;
- };
-
- var blame = new MenuItem();
- blame.Header = App.Text("Blame");
- blame.Icon = App.CreateMenuIcon("Icons.Blame");
- blame.IsEnabled = change.Index != Models.ChangeState.Deleted;
- blame.Click += (_, ev) =>
- {
- App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit), false);
+ App.ShowWindow(new DirHistories(_repo, node.FullPath, _commit.SHA));
ev.Handled = true;
};
@@ -360,7 +282,109 @@ namespace SourceGit.ViewModels
if (storageFile != null)
{
var saveTo = storageFile.Path.LocalPath;
- var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo.FullPath, [change], baseRevision, _commit.SHA, saveTo));
+ var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo);
+ if (succ)
+ App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
+ }
+
+ e.Handled = true;
+ };
+
+ var copyPath = new MenuItem();
+ copyPath.Header = App.Text("CopyPath");
+ copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
+ copyPath.Click += async (_, ev) =>
+ {
+ await App.CopyTextAsync(node.FullPath);
+ ev.Handled = true;
+ };
+
+ var copyFullPath = new MenuItem();
+ copyFullPath.Header = App.Text("CopyFullPath");
+ copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
+ copyFullPath.Click += async (_, e) =>
+ {
+ await App.CopyTextAsync(fullPath);
+ e.Handled = true;
+ };
+
+ var menu = new ContextMenu();
+ menu.Items.Add(explore);
+ menu.Items.Add(new MenuItem { Header = "-" });
+ menu.Items.Add(history);
+ menu.Items.Add(patch);
+ menu.Items.Add(new MenuItem { Header = "-" });
+ menu.Items.Add(copyPath);
+ menu.Items.Add(copyFullPath);
+
+ return menu;
+ }
+
+ public ContextMenu CreateChangeContextMenu(Models.Change change)
+ {
+ var diffWithMerger = new MenuItem();
+ diffWithMerger.Header = App.Text("DiffWithMerger");
+ diffWithMerger.Icon = App.CreateMenuIcon("Icons.OpenWith");
+ diffWithMerger.Click += (sender, ev) =>
+ {
+ var toolType = Preferences.Instance.ExternalMergeToolType;
+ var toolPath = Preferences.Instance.ExternalMergeToolPath;
+ var opt = new Models.DiffOption(_commit, change);
+
+ _ = Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt);
+ ev.Handled = true;
+ };
+
+ var fullPath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
+ var explore = new MenuItem();
+ explore.Header = App.Text("RevealFile");
+ explore.Icon = App.CreateMenuIcon("Icons.Explore");
+ explore.IsEnabled = File.Exists(fullPath);
+ explore.Click += (_, ev) =>
+ {
+ Native.OS.OpenInFileManager(fullPath, true);
+ ev.Handled = true;
+ };
+
+ var history = new MenuItem();
+ history.Header = App.Text("FileHistory");
+ history.Icon = App.CreateMenuIcon("Icons.Histories");
+ history.Click += (_, ev) =>
+ {
+ App.ShowWindow(new FileHistories(_repo, change.Path, _commit.SHA));
+ ev.Handled = true;
+ };
+
+ var blame = new MenuItem();
+ blame.Header = App.Text("Blame");
+ blame.Icon = App.CreateMenuIcon("Icons.Blame");
+ blame.IsEnabled = change.Index != Models.ChangeState.Deleted;
+ blame.Click += (_, ev) =>
+ {
+ App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit));
+ ev.Handled = true;
+ };
+
+ var patch = new MenuItem();
+ patch.Header = App.Text("FileCM.SaveAsPatch");
+ patch.Icon = App.CreateMenuIcon("Icons.Diff");
+ patch.Click += async (_, e) =>
+ {
+ var storageProvider = App.GetStorageProvider();
+ if (storageProvider == null)
+ return;
+
+ var options = new FilePickerSaveOptions();
+ options.Title = App.Text("FileCM.SaveAsPatch");
+ options.DefaultExtension = ".patch";
+ options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
+
+ var baseRevision = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0];
+ var storageFile = await storageProvider.SaveFilePickerAsync(options);
+ if (storageFile != null)
+ {
+ var saveTo = storageFile.Path.LocalPath;
+ var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, [change], baseRevision, _commit.SHA, saveTo);
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@@ -384,7 +408,7 @@ namespace SourceGit.ViewModels
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += async (_, ev) =>
{
- await ResetToThisRevision(change.Path);
+ await ResetToThisRevisionAsync(change.Path);
ev.Handled = true;
};
@@ -394,7 +418,7 @@ namespace SourceGit.ViewModels
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += async (_, ev) =>
{
- await ResetToParentRevision(change);
+ await ResetToParentRevisionAsync(change);
ev.Handled = true;
};
@@ -408,18 +432,18 @@ namespace SourceGit.ViewModels
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyPath.Click += (_, ev) =>
+ copyPath.Click += async (_, ev) =>
{
- App.CopyText(change.Path);
+ await App.CopyTextAsync(change.Path);
ev.Handled = true;
};
var copyFullPath = new MenuItem();
copyFullPath.Header = App.Text("CopyFullPath");
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyFullPath.Click += (_, e) =>
+ copyFullPath.Click += async (_, e) =>
{
- App.CopyText(fullPath);
+ await App.CopyTextAsync(fullPath);
e.Handled = true;
};
@@ -428,8 +452,61 @@ namespace SourceGit.ViewModels
return menu;
}
+ public ContextMenu CreateRevisionFileContextMenuByFolder(string path)
+ {
+ var fullPath = Native.OS.GetAbsPath(_repo.FullPath, path);
+ var explore = new MenuItem();
+ explore.Header = App.Text("RevealFile");
+ explore.Icon = App.CreateMenuIcon("Icons.Explore");
+ explore.IsEnabled = Directory.Exists(fullPath);
+ explore.Click += (_, ev) =>
+ {
+ Native.OS.OpenInFileManager(fullPath, true);
+ ev.Handled = true;
+ };
+
+ var history = new MenuItem();
+ history.Header = App.Text("DirHistories");
+ history.Icon = App.CreateMenuIcon("Icons.Histories");
+ history.Click += (_, ev) =>
+ {
+ App.ShowWindow(new DirHistories(_repo, path, _commit.SHA));
+ ev.Handled = true;
+ };
+
+ var copyPath = new MenuItem();
+ copyPath.Header = App.Text("CopyPath");
+ copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
+ copyPath.Click += async (_, ev) =>
+ {
+ await App.CopyTextAsync(path);
+ ev.Handled = true;
+ };
+
+ var copyFullPath = new MenuItem();
+ copyFullPath.Header = App.Text("CopyFullPath");
+ copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
+ copyFullPath.Click += async (_, e) =>
+ {
+ await App.CopyTextAsync(fullPath);
+ e.Handled = true;
+ };
+
+ var menu = new ContextMenu();
+ menu.Items.Add(explore);
+ menu.Items.Add(new MenuItem() { Header = "-" });
+ menu.Items.Add(history);
+ menu.Items.Add(new MenuItem() { Header = "-" });
+ menu.Items.Add(copyPath);
+ menu.Items.Add(copyFullPath);
+ return menu;
+ }
+
public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
{
+ if (file.Type == Models.ObjectType.Tree)
+ return CreateRevisionFileContextMenuByFolder(file.Path);
+
var menu = new ContextMenu();
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file.Path);
var explore = new MenuItem();
@@ -448,7 +525,7 @@ namespace SourceGit.ViewModels
openWith.IsEnabled = file.Type == Models.ObjectType.Blob;
openWith.Click += async (_, ev) =>
{
- await OpenRevisionFileWithDefaultEditor(file.Path);
+ await OpenRevisionFileWithDefaultEditorAsync(file.Path);
ev.Handled = true;
};
@@ -471,7 +548,10 @@ namespace SourceGit.ViewModels
var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path)!);
- await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo));
+
+ await Commands.SaveRevisionFile
+ .RunAsync(_repo.FullPath, _commit.SHA, file.Path, saveTo)
+ .ConfigureAwait(false);
}
}
catch (Exception e)
@@ -492,7 +572,7 @@ namespace SourceGit.ViewModels
history.Icon = App.CreateMenuIcon("Icons.Histories");
history.Click += (_, ev) =>
{
- App.ShowWindow(new FileHistories(_repo, file.Path, _commit.SHA), false);
+ App.ShowWindow(new FileHistories(_repo, file.Path, _commit.SHA));
ev.Handled = true;
};
@@ -502,7 +582,7 @@ namespace SourceGit.ViewModels
blame.IsEnabled = file.Type == Models.ObjectType.Blob;
blame.Click += (_, ev) =>
{
- App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit), false);
+ App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit));
ev.Handled = true;
};
@@ -517,7 +597,7 @@ namespace SourceGit.ViewModels
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += async (_, ev) =>
{
- await ResetToThisRevision(file.Path);
+ await ResetToThisRevisionAsync(file.Path);
ev.Handled = true;
};
@@ -528,7 +608,7 @@ namespace SourceGit.ViewModels
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += async (_, ev) =>
{
- await ResetToParentRevision(change);
+ await ResetToParentRevisionAsync(change);
ev.Handled = true;
};
@@ -542,18 +622,18 @@ namespace SourceGit.ViewModels
var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath");
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyPath.Click += (_, ev) =>
+ copyPath.Click += async (_, ev) =>
{
- App.CopyText(file.Path);
+ await App.CopyTextAsync(file.Path);
ev.Handled = true;
};
var copyFullPath = new MenuItem();
copyFullPath.Header = App.Text("CopyFullPath");
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
- copyFullPath.Click += (_, e) =>
+ copyFullPath.Click += async (_, e) =>
{
- App.CopyText(fullPath);
+ await App.CopyTextAsync(fullPath);
e.Handled = true;
};
@@ -585,39 +665,51 @@ namespace SourceGit.ViewModels
_cancellationSource = new CancellationTokenSource();
var token = _cancellationSource.Token;
- Task.Run(() =>
+ Task.Run(async () =>
{
- var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
- var inlines = ParseInlinesInMessage(message);
+ var message = await new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+ var inlines = await ParseInlinesInMessageAsync(message);
if (!token.IsCancellationRequested)
- Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines });
+ Dispatcher.UIThread.Post(() =>
+ {
+ FullMessage = new Models.CommitFullMessage
+ {
+ Message = message,
+ Inlines = inlines
+ };
+ });
}, token);
- Task.Run(() =>
+ Task.Run(async () =>
{
- var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
+ var signInfo = await new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+
if (!token.IsCancellationRequested)
- Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
+ Dispatcher.UIThread.Post(() => SignInfo = signInfo);
}, token);
if (Preferences.Instance.ShowChildren)
{
- Task.Run(() =>
+ Task.Run(async () =>
{
var max = Preferences.Instance.MaxHistoryCommits;
var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token };
- var children = cmd.Result();
+ var children = await cmd.GetResultAsync().ConfigureAwait(false);
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Post(() => Children = children);
}, token);
}
- Task.Run(() =>
+ Task.Run(async () =>
{
var parent = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0];
var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token };
- var changes = cmd.Result();
+ var changes = await cmd.ReadAsync().ConfigureAwait(false);
var visible = changes;
if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
{
@@ -638,12 +730,14 @@ namespace SourceGit.ViewModels
if (visible.Count == 0)
SelectedChanges = null;
+ else
+ SelectedChanges = [VisibleChanges[0]];
});
}
}, token);
}
- private Models.InlineElementCollector ParseInlinesInMessage(string message)
+ private async Task ParseInlinesInMessageAsync(string message)
{
var inlines = new Models.InlineElementCollector();
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
@@ -682,7 +776,7 @@ namespace SourceGit.ViewModels
continue;
var sha = match.Groups[1].Value;
- var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, sha).Result();
+ var isCommitSHA = await new Commands.IsCommitSHA(_repo.FullPath, sha).GetResultAsync().ConfigureAwait(false);
if (isCommitSHA)
inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha));
}
@@ -734,7 +828,7 @@ namespace SourceGit.ViewModels
lfsLock.Click += async (_, e) =>
{
var log = _repo.CreateLog("Lock LFS file");
- var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(_repo.Remotes[0].Name, path, log));
+ var succ = await new Commands.LFS(_repo.FullPath).LockAsync(_repo.Remotes[0].Name, path, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
@@ -752,7 +846,7 @@ namespace SourceGit.ViewModels
lockRemote.Click += async (_, e) =>
{
var log = _repo.CreateLog("Lock LFS file");
- var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(remoteName, path, log));
+ var succ = await new Commands.LFS(_repo.FullPath).LockAsync(remoteName, path, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
@@ -772,7 +866,7 @@ namespace SourceGit.ViewModels
lfsUnlock.Click += async (_, e) =>
{
var log = _repo.CreateLog("Unlock LFS file");
- var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(_repo.Remotes[0].Name, path, false, log));
+ var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(_repo.Remotes[0].Name, path, false, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
@@ -790,7 +884,7 @@ namespace SourceGit.ViewModels
unlockRemote.Click += async (_, e) =>
{
var log = _repo.CreateLog("Unlock LFS file");
- var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(remoteName, path, false, log));
+ var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(remoteName, path, false, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
@@ -818,10 +912,13 @@ namespace SourceGit.ViewModels
var sha = Commit.SHA;
_requestingRevisionFiles = true;
- Task.Run(() =>
+ Task.Run(async () =>
{
- var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result();
- Dispatcher.UIThread.Invoke(() =>
+ var files = await new Commands.QueryRevisionFileNames(_repo.FullPath, sha)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+
+ Dispatcher.UIThread.Post(() =>
{
if (sha == Commit.SHA && _requestingRevisionFiles)
{
@@ -862,29 +959,83 @@ namespace SourceGit.ViewModels
RevisionFileSearchSuggestion = suggestion;
}
- private Task ResetToThisRevision(string path)
+ private async Task SetViewingBlobAsync(Models.Object file)
+ {
+ var isBinary = await new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).GetResultAsync();
+ if (isBinary)
+ {
+ var imgDecoder = ImageSource.GetDecoder(file.Path);
+ if (imgDecoder != Models.ImageDecoder.None)
+ {
+ var source = await ImageSource.FromRevisionAsync(_repo.FullPath, _commit.SHA, file.Path, imgDecoder);
+ ViewRevisionFileContent = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size);
+ }
+ else
+ {
+ var size = await new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).GetResultAsync();
+ ViewRevisionFileContent = new Models.RevisionBinaryFile() { Size = size };
+ }
+
+ return;
+ }
+
+ var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _commit.SHA, file.Path);
+ var content = await new StreamReader(contentStream).ReadToEndAsync();
+ var lfs = Models.LFSObject.Parse(content);
+ if (lfs != null)
+ {
+ var imgDecoder = ImageSource.GetDecoder(file.Path);
+ if (imgDecoder != Models.ImageDecoder.None)
+ ViewRevisionFileContent = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
+ else
+ ViewRevisionFileContent = new Models.RevisionLFSObject() { Object = lfs };
+ }
+ else
+ {
+ ViewRevisionFileContent = new Models.RevisionTextFile() { FileName = file.Path, Content = content };
+ }
+ }
+
+ private async Task SetViewingCommitAsync(Models.Object file)
+ {
+ var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
+ var commit = await new Commands.QuerySingleCommit(submoduleRoot, file.SHA).GetResultAsync();
+ if (commit == null)
+ {
+ ViewRevisionFileContent = new Models.RevisionSubmodule()
+ {
+ Commit = new Models.Commit() { SHA = file.SHA },
+ FullMessage = new Models.CommitFullMessage()
+ };
+ }
+ else
+ {
+ var message = await new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).GetResultAsync();
+ ViewRevisionFileContent = new Models.RevisionSubmodule()
+ {
+ Commit = commit,
+ FullMessage = new Models.CommitFullMessage { Message = message }
+ };
+ }
+ }
+
+ private async Task ResetToThisRevisionAsync(string path)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
- return Task.Run(() =>
- {
- new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(path, $"{_commit.SHA}");
- log.Complete();
- });
+ await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(path, $"{_commit.SHA}");
+ log.Complete();
}
- private Task ResetToParentRevision(Models.Change change)
+ private async Task ResetToParentRevisionAsync(Models.Change change)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
- return Task.Run(() =>
- {
- if (change.Index == Models.ChangeState.Renamed)
- new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
+ if (change.Index == Models.ChangeState.Renamed)
+ await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(change.OriginalPath, $"{_commit.SHA}~1");
- new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
- log.Complete();
- });
+ await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(change.Path, $"{_commit.SHA}~1");
+ log.Complete();
}
[GeneratedRegex(@"\b(https?://|ftp://)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]")]
@@ -894,6 +1045,8 @@ namespace SourceGit.ViewModels
private static partial Regex REG_SHA_FORMAT();
private Repository _repo = null;
+ private bool _rememberActivePageIndex = true;
+ private int _activePageIndex = 0;
private Models.Commit _commit = null;
private Models.CommitFullMessage _fullMessage = null;
private Models.CommitSignInfo _signInfo = null;
diff --git a/src/ViewModels/ConfigureCustomActionControls.cs b/src/ViewModels/ConfigureCustomActionControls.cs
index f0588af7..abe992ea 100644
--- a/src/ViewModels/ConfigureCustomActionControls.cs
+++ b/src/ViewModels/ConfigureCustomActionControls.cs
@@ -23,7 +23,12 @@ namespace SourceGit.ViewModels
public void Add()
{
- var added = new Models.CustomActionControl() { Type = Models.CustomActionControlType.TextBox };
+ var added = new Models.CustomActionControl()
+ {
+ Label = "Unnamed",
+ Type = Models.CustomActionControlType.TextBox
+ };
+
Controls.Add(added);
Edit = added;
}
diff --git a/src/ViewModels/ConfigureWorkspace.cs b/src/ViewModels/ConfigureWorkspace.cs
index 5be066ae..638caf5d 100644
--- a/src/ViewModels/ConfigureWorkspace.cs
+++ b/src/ViewModels/ConfigureWorkspace.cs
@@ -17,7 +17,7 @@ namespace SourceGit.ViewModels
set
{
if (SetProperty(ref _selected, value))
- CanDeleteSelected = value != null && !value.IsActive;
+ CanDeleteSelected = value is { IsActive: false };
}
}
diff --git a/src/ViewModels/Confirm.cs b/src/ViewModels/Confirm.cs
deleted file mode 100644
index ecbda72c..00000000
--- a/src/ViewModels/Confirm.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-
-namespace SourceGit.ViewModels
-{
- public class Confirm
- {
- public string Message
- {
- get;
- private set;
- }
-
- public Confirm(string message, Action onSure, Action onCancel = null)
- {
- Message = message;
- _onSure = onSure;
- _onCancel = onCancel;
- }
-
- public void Done(bool isSure)
- {
- if (isSure)
- _onSure?.Invoke();
- else
- _onCancel?.Invoke();
- }
-
- private Action _onSure;
- private Action _onCancel;
- }
-}
diff --git a/src/ViewModels/Conflict.cs b/src/ViewModels/Conflict.cs
index bf93b5bc..585fee0b 100644
--- a/src/ViewModels/Conflict.cs
+++ b/src/ViewModels/Conflict.cs
@@ -19,7 +19,7 @@ namespace SourceGit.ViewModels
{
Name = branch.Name;
Head = branch.Head;
- Revision = new Commands.QuerySingleCommit(repo.FullPath, branch.Head).Result() ?? new Models.Commit() { SHA = branch.Head };
+ Revision = new Commands.QuerySingleCommit(repo.FullPath, branch.Head).GetResultAsync().Result ?? new Models.Commit() { SHA = branch.Head };
}
}
@@ -65,42 +65,39 @@ namespace SourceGit.ViewModels
_change = change;
var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null;
- if (!isSubmodule && (_change.ConflictReason == Models.ConflictReason.BothAdded || _change.ConflictReason == Models.ConflictReason.BothModified))
+ if (!isSubmodule && (_change.ConflictReason is Models.ConflictReason.BothAdded or Models.ConflictReason.BothModified))
{
CanUseExternalMergeTool = true;
- IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).Result();
+ IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).GetResultAsync().Result;
}
- var context = wc.InProgressContext;
- if (context is CherryPickInProgress cherryPick)
+ switch (wc.InProgressContext)
{
- Theirs = cherryPick.Head;
- Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
- }
- else if (context is RebaseInProgress rebase)
- {
- var b = repo.Branches.Find(x => x.IsLocal && x.Name == rebase.HeadName);
- if (b != null)
- Theirs = new ConflictSourceBranch(b.Name, b.Head, rebase.StoppedAt);
- else
- Theirs = new ConflictSourceBranch(rebase.HeadName, rebase.StoppedAt?.SHA ?? "----------", rebase.StoppedAt);
+ case CherryPickInProgress cherryPick:
+ Theirs = cherryPick.Head;
+ Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
+ break;
+ case RebaseInProgress rebase:
+ var b = repo.Branches.Find(x => x.IsLocal && x.Name == rebase.HeadName);
+ if (b != null)
+ Theirs = new ConflictSourceBranch(b.Name, b.Head, rebase.StoppedAt);
+ else
+ Theirs = new ConflictSourceBranch(rebase.HeadName, rebase.StoppedAt?.SHA ?? "----------", rebase.StoppedAt);
- Mine = rebase.Onto;
- }
- else if (context is RevertInProgress revert)
- {
- Theirs = revert.Head;
- Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
- }
- else if (context is MergeInProgress merge)
- {
- Theirs = merge.Source;
- Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
- }
- else
- {
- Theirs = "Stash or Patch";
- Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
+ Mine = rebase.Onto;
+ break;
+ case RevertInProgress revert:
+ Theirs = revert.Head;
+ Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
+ break;
+ case MergeInProgress merge:
+ Theirs = merge.Source;
+ Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
+ break;
+ default:
+ Theirs = "Stash or Patch";
+ Mine = new ConflictSourceBranch(repo, repo.CurrentBranch);
+ break;
}
}
diff --git a/src/ViewModels/ConventionalCommitMessageBuilder.cs b/src/ViewModels/ConventionalCommitMessageBuilder.cs
index 8faabe86..5eb9494c 100644
--- a/src/ViewModels/ConventionalCommitMessageBuilder.cs
+++ b/src/ViewModels/ConventionalCommitMessageBuilder.cs
@@ -72,10 +72,9 @@ namespace SourceGit.ViewModels
builder.Append(")");
}
- if (string.IsNullOrEmpty(_breakingChanges))
- builder.Append(": ");
- else
- builder.Append("!: ");
+ if (!string.IsNullOrEmpty(_breakingChanges))
+ builder.Append("!");
+ builder.Append(": ");
builder.Append(_description);
builder.Append("\n\n");
diff --git a/src/ViewModels/CreateBranch.cs b/src/ViewModels/CreateBranch.cs
index 6e01eb39..07080d7e 100644
--- a/src/ViewModels/CreateBranch.cs
+++ b/src/ViewModels/CreateBranch.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel.DataAnnotations;
+using System;
+using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
namespace SourceGit.ViewModels
@@ -67,12 +68,10 @@ namespace SourceGit.ViewModels
public CreateBranch(Repository repo, Models.Branch branch)
{
_repo = repo;
- _baseOnRevision = branch.IsDetachedHead ? branch.Head : branch.FullName;
+ _baseOnRevision = branch.Head;
if (!branch.IsLocal && repo.Branches.Find(x => x.IsLocal && x.Name == branch.Name) == null)
- {
Name = branch.Name;
- }
BasedOn = branch;
DiscardLocalChanges = false;
@@ -102,123 +101,122 @@ namespace SourceGit.ViewModels
{
if (!creator._allowOverwrite)
{
- var fixedName = creator.FixName(name);
+ var fixedName = Models.Branch.FixName(name);
foreach (var b in creator._repo.Branches)
{
- if (b.FriendlyName == fixedName)
+ if (b.FriendlyName.Equals(fixedName, StringComparison.Ordinal))
return new ValidationResult("A branch with same name already exists!");
}
}
return ValidationResult.Success;
}
- else
- {
- return new ValidationResult("Missing runtime context to create branch!");
- }
+
+ return new ValidationResult("Missing runtime context to create branch!");
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
- var fixedName = FixName(_name);
+ var fixedName = Models.Branch.FixName(_name);
var log = _repo.CreateLog($"Create Branch '{fixedName}'");
Use(log);
- var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
- return Task.Run(() =>
+ if (CheckoutAfterCreated)
{
- bool succ;
-
- if (CheckoutAfterCreated && !_repo.ConfirmCheckoutBranch())
+ if (_repo.CurrentBranch is { IsDetachedHead: true } && !_repo.CurrentBranch.Head.Equals(_baseOnRevision, StringComparison.Ordinal))
{
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return true;
- }
-
- if (CheckoutAfterCreated && !_repo.IsBare)
- {
- var needPopStash = false;
- if (DiscardLocalChanges)
+ var refs = await new Commands.QueryRefsContainsCommit(_repo.FullPath, _repo.CurrentBranch.Head).GetResultAsync();
+ if (refs.Count == 0)
{
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true, _allowOverwrite);
- }
- else
- {
- var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
- if (changes > 0)
+ var msg = App.Text("Checkout.WarnLostCommits");
+ var shouldContinue = await App.AskConfirmAsync(msg, null);
+ if (!shouldContinue)
{
- succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
- if (!succ)
- {
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return false;
- }
+ _repo.SetWatcherEnabled(true);
+ return true;
+ }
+ }
+ }
+ }
- needPopStash = true;
+ bool succ;
+ if (CheckoutAfterCreated && !_repo.IsBare)
+ {
+ var needPopStash = false;
+ if (!DiscardLocalChanges)
+ {
+ var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).GetResultAsync();
+ if (changes > 0)
+ {
+ succ = await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PushAsync("CREATE_BRANCH_AUTO_STASH");
+ if (!succ)
+ {
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return false;
}
- succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false, _allowOverwrite);
- }
-
- if (succ)
- {
- if (updateSubmodules)
- {
- var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
- if (submodules.Count > 0)
- new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
- }
-
- if (needPopStash)
- new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
+ needPopStash = true;
}
}
- else
- {
- succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
- }
- log.Complete();
+ succ = await new Commands.Checkout(_repo.FullPath)
+ .Use(log)
+ .BranchAsync(fixedName, _baseOnRevision, DiscardLocalChanges, _allowOverwrite);
- CallUIThread(() =>
+ if (succ)
{
- if (succ && CheckoutAfterCreated)
+ if (IsRecurseSubmoduleVisible && RecurseSubmodules)
{
- var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" };
- if (BasedOn is Models.Branch based && !based.IsLocal)
- fake.Upstream = based.FullName;
-
- var folderEndIdx = fake.FullName.LastIndexOf('/');
- if (folderEndIdx > 10)
- _repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx));
-
- if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
- _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
-
- ProgressDescription = "Waiting for branch updated...";
+ var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).GetResultAsync();
+ if (submodules.Count > 0)
+ await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .UpdateAsync(submodules, true, true);
}
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
+ if (needPopStash)
+ await new Commands.Stash(_repo.FullPath)
+ .Use(log)
+ .PopAsync("stash@{0}");
+ }
+ }
+ else
+ {
+ succ = await Commands.Branch.CreateAsync(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
+ }
- if (CheckoutAfterCreated)
- Task.Delay(400).Wait();
+ log.Complete();
- return true;
- });
- }
+ if (succ && CheckoutAfterCreated)
+ {
+ var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" };
+ if (BasedOn is Models.Branch { IsLocal: false } based)
+ fake.Upstream = based.FullName;
- private string FixName(string name)
- {
- if (!name.Contains(' '))
- return name;
+ var folderEndIdx = fake.FullName.LastIndexOf('/');
+ if (folderEndIdx > 10)
+ _repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx));
- var parts = name.Split(' ', System.StringSplitOptions.RemoveEmptyEntries);
- return string.Join("-", parts);
+ if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
+ _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
+
+ }
+
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
+
+ if (CheckoutAfterCreated)
+ {
+ ProgressDescription = "Waiting for branch updated...";
+ await Task.Delay(400);
+ }
+
+ return true;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/CreateGroup.cs b/src/ViewModels/CreateGroup.cs
index fb0218f0..eb8ef2b5 100644
--- a/src/ViewModels/CreateGroup.cs
+++ b/src/ViewModels/CreateGroup.cs
@@ -29,7 +29,7 @@ namespace SourceGit.ViewModels
}, _parent, true);
Welcome.Instance.Refresh();
- return null;
+ return Task.FromResult(true);
}
private readonly RepositoryNode _parent = null;
diff --git a/src/ViewModels/CreateTag.cs b/src/ViewModels/CreateTag.cs
index d3cd512b..85e2b973 100644
--- a/src/ViewModels/CreateTag.cs
+++ b/src/ViewModels/CreateTag.cs
@@ -51,7 +51,7 @@ namespace SourceGit.ViewModels
_basedOn = branch.Head;
BasedOn = branch;
- SignTag = new Commands.Config(repo.FullPath).Get("tag.gpgsign").Equals("true", StringComparison.OrdinalIgnoreCase);
+ SignTag = new Commands.Config(repo.FullPath).GetAsync("tag.gpgsign").Result.Equals("true", StringComparison.OrdinalIgnoreCase);
}
public CreateTag(Repository repo, Models.Commit commit)
@@ -60,7 +60,7 @@ namespace SourceGit.ViewModels
_basedOn = commit.SHA;
BasedOn = commit;
- SignTag = new Commands.Config(repo.FullPath).Get("tag.gpgsign").Equals("true", StringComparison.OrdinalIgnoreCase);
+ SignTag = new Commands.Config(repo.FullPath).GetAsync("tag.gpgsign").Result.Equals("true", StringComparison.OrdinalIgnoreCase);
}
public static ValidationResult ValidateTagName(string name, ValidationContext ctx)
@@ -74,7 +74,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Create tag...";
@@ -83,24 +83,23 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Create Tag");
Use(log);
- return Task.Run(() =>
+ bool succ;
+ if (_annotated)
+ succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log);
+ else
+ succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, log);
+
+ if (succ && remotes != null)
{
- bool succ;
- if (_annotated)
- succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log);
- else
- succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, log);
+ foreach (var remote in remotes)
+ await new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false)
+ .Use(log)
+ .RunAsync();
+ }
- if (succ && remotes != null)
- {
- foreach (var remote in remotes)
- new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Use(log).Exec();
- }
-
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/CustomActionContextMenuLabel.cs b/src/ViewModels/CustomActionContextMenuLabel.cs
new file mode 100644
index 00000000..82804f09
--- /dev/null
+++ b/src/ViewModels/CustomActionContextMenuLabel.cs
@@ -0,0 +1,8 @@
+namespace SourceGit.ViewModels
+{
+ public class CustomActionContextMenuLabel(string name, bool isGlobal)
+ {
+ public string Name { get; set; } = name;
+ public bool IsGlobal { get; set; } = isGlobal;
+ }
+}
diff --git a/src/ViewModels/DeinitSubmodule.cs b/src/ViewModels/DeinitSubmodule.cs
index a96a65d0..1769ef80 100644
--- a/src/ViewModels/DeinitSubmodule.cs
+++ b/src/ViewModels/DeinitSubmodule.cs
@@ -23,7 +23,7 @@ namespace SourceGit.ViewModels
Force = false;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "De-initialize Submodule";
@@ -31,13 +31,13 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("De-initialize Submodule");
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Submodule(_repo.FullPath).Use(log).Deinit(Submodule, false);
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ var succ = await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .DeinitAsync(Submodule, false);
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private Repository _repo;
diff --git a/src/ViewModels/DeleteBranch.cs b/src/ViewModels/DeleteBranch.cs
index 4decdb40..0c8ee154 100644
--- a/src/ViewModels/DeleteBranch.cs
+++ b/src/ViewModels/DeleteBranch.cs
@@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
}
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting branch...";
@@ -47,29 +47,22 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Branch");
Use(log);
- return Task.Run(() =>
+ if (Target.IsLocal)
{
- if (Target.IsLocal)
- {
- Commands.Branch.DeleteLocal(_repo.FullPath, Target.Name, log);
+ await Commands.Branch.DeleteLocalAsync(_repo.FullPath, Target.Name, log);
+ if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
+ await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
+ }
+ else
+ {
+ await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, Target.Remote, Target.Name, log);
+ }
- if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
- Commands.Branch.DeleteRemote(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
- }
- else
- {
- Commands.Branch.DeleteRemote(_repo.FullPath, Target.Remote, Target.Name, log);
- }
+ log.Complete();
- log.Complete();
-
- CallUIThread(() =>
- {
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
- return true;
- });
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/DeleteMultipleBranches.cs b/src/ViewModels/DeleteMultipleBranches.cs
index b40ff223..e8ca45ab 100644
--- a/src/ViewModels/DeleteMultipleBranches.cs
+++ b/src/ViewModels/DeleteMultipleBranches.cs
@@ -17,7 +17,7 @@ namespace SourceGit.ViewModels
Targets = branches;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting multiple branches...";
@@ -25,29 +25,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Multiple Branches");
Use(log);
- return Task.Run(() =>
+ if (_isLocal)
{
- if (_isLocal)
- {
- foreach (var target in Targets)
- Commands.Branch.DeleteLocal(_repo.FullPath, target.Name, log);
- }
- else
- {
- foreach (var target in Targets)
- Commands.Branch.DeleteRemote(_repo.FullPath, target.Remote, target.Name, log);
- }
+ foreach (var target in Targets)
+ await Commands.Branch.DeleteLocalAsync(_repo.FullPath, target.Name, log);
+ }
+ else
+ {
+ foreach (var target in Targets)
+ await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, target.Remote, target.Name, log);
+ }
- log.Complete();
-
- CallUIThread(() =>
- {
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
-
- return true;
- });
+ log.Complete();
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return true;
}
private Repository _repo = null;
diff --git a/src/ViewModels/DeleteRemote.cs b/src/ViewModels/DeleteRemote.cs
index faf7c8a9..595a7d52 100644
--- a/src/ViewModels/DeleteRemote.cs
+++ b/src/ViewModels/DeleteRemote.cs
@@ -16,7 +16,7 @@ namespace SourceGit.ViewModels
Remote = remote;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting remote ...";
@@ -24,18 +24,14 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Remote");
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Remote(_repo.FullPath).Use(log).Delete(Remote.Name);
- log.Complete();
+ var succ = await new Commands.Remote(_repo.FullPath)
+ .Use(log)
+ .DeleteAsync(Remote.Name);
- CallUIThread(() =>
- {
- _repo.MarkBranchesDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
- return succ;
- });
+ log.Complete();
+ _repo.MarkBranchesDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/DeleteRepositoryNode.cs b/src/ViewModels/DeleteRepositoryNode.cs
index 38e03d9f..59ef60ea 100644
--- a/src/ViewModels/DeleteRepositoryNode.cs
+++ b/src/ViewModels/DeleteRepositoryNode.cs
@@ -18,7 +18,7 @@ namespace SourceGit.ViewModels
{
Preferences.Instance.RemoveNode(Node, true);
Welcome.Instance.Refresh();
- return null;
+ return Task.FromResult(true);
}
}
}
diff --git a/src/ViewModels/DeleteSubmodule.cs b/src/ViewModels/DeleteSubmodule.cs
index 239c7d31..34a77c6e 100644
--- a/src/ViewModels/DeleteSubmodule.cs
+++ b/src/ViewModels/DeleteSubmodule.cs
@@ -16,7 +16,7 @@ namespace SourceGit.ViewModels
Submodule = submodule;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting submodule ...";
@@ -24,13 +24,13 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Submodule");
Use(log);
- return Task.Run(() =>
- {
- var succ = new Commands.Submodule(_repo.FullPath).Use(log).Delete(Submodule);
- log.Complete();
- CallUIThread(() => _repo.SetWatcherEnabled(true));
- return succ;
- });
+ var succ = await new Commands.Submodule(_repo.FullPath)
+ .Use(log)
+ .DeleteAsync(Submodule);
+
+ log.Complete();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/DeleteTag.cs b/src/ViewModels/DeleteTag.cs
index f7de6341..b283a837 100644
--- a/src/ViewModels/DeleteTag.cs
+++ b/src/ViewModels/DeleteTag.cs
@@ -22,7 +22,7 @@ namespace SourceGit.ViewModels
Target = tag;
}
- public override Task Sure()
+ public override async Task Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Deleting tag '{Target.Name}' ...";
@@ -31,24 +31,19 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Tag");
Use(log);
- return Task.Run(() =>
+ var succ = await Commands.Tag.DeleteAsync(_repo.FullPath, Target.Name, log);
+ if (succ)
{
- var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, log);
- if (succ)
- {
- foreach (var r in remotes)
- new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true).Use(log).Exec();
- }
+ foreach (var r in remotes)
+ await new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true)
+ .Use(log)
+ .RunAsync();
+ }
- log.Complete();
-
- CallUIThread(() =>
- {
- _repo.MarkTagsDirtyManually();
- _repo.SetWatcherEnabled(true);
- });
- return succ;
- });
+ log.Complete();
+ _repo.MarkTagsDirtyManually();
+ _repo.SetWatcherEnabled(true);
+ return succ;
}
private readonly Repository _repo = null;
diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs
index 9bb3c710..5b772fc8 100644
--- a/src/ViewModels/DiffContext.cs
+++ b/src/ViewModels/DiffContext.cs
@@ -97,7 +97,7 @@ namespace SourceGit.ViewModels
{
var toolType = Preferences.Instance.ExternalMergeToolType;
var toolPath = Preferences.Instance.ExternalMergeToolPath;
- Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, _option));
+ Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, _option));
}
private void LoadDiffContent()
@@ -109,18 +109,22 @@ namespace SourceGit.ViewModels
return;
}
- Task.Run(() =>
+ Task.Run(async () =>
{
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
- var latest = new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).Result();
+
+ var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace)
+ .ReadAsync()
+ .ConfigureAwait(false);
+
var info = new Info(_option, numLines, ignoreWhitespace, latest);
if (_info != null && info.IsSame(_info))
return;
_info = info;
- var rs = null as object;
+ object rs = null;
if (latest.TextDiff != null)
{
var count = latest.TextDiff.Lines.Count;
@@ -141,9 +145,9 @@ namespace SourceGit.ViewModels
var sha = line.Content.Substring(18);
if (line.Type == Models.TextDiffLineType.Added)
- submoduleDiff.New = QuerySubmoduleRevision(submoduleRoot, sha);
+ submoduleDiff.New = await QuerySubmoduleRevisionAsync(submoduleRoot, sha).ConfigureAwait(false);
else if (line.Type == Models.TextDiffLineType.Deleted)
- submoduleDiff.Old = QuerySubmoduleRevision(submoduleRoot, sha);
+ submoduleDiff.Old = await QuerySubmoduleRevisionAsync(submoduleRoot, sha).ConfigureAwait(false);
}
if (isSubmodule)
@@ -167,8 +171,8 @@ namespace SourceGit.ViewModels
if (_option.Revisions.Count == 2)
{
- var oldImage = ImageSource.FromRevision(_repo, _option.Revisions[0], oldPath, imgDecoder);
- var newImage = ImageSource.FromRevision(_repo, _option.Revisions[1], _option.Path, imgDecoder);
+ var oldImage = await ImageSource.FromRevisionAsync(_repo, _option.Revisions[0], oldPath, imgDecoder).ConfigureAwait(false);
+ var newImage = await ImageSource.FromRevisionAsync(_repo, _option.Revisions[1], _option.Path, imgDecoder).ConfigureAwait(false);
imgDiff.Old = oldImage.Bitmap;
imgDiff.OldFileSize = oldImage.Size;
imgDiff.New = newImage.Bitmap;
@@ -178,7 +182,7 @@ namespace SourceGit.ViewModels
{
if (!oldPath.Equals("/dev/null", StringComparison.Ordinal))
{
- var oldImage = ImageSource.FromRevision(_repo, "HEAD", oldPath, imgDecoder);
+ var oldImage = await ImageSource.FromRevisionAsync(_repo, "HEAD", oldPath, imgDecoder).ConfigureAwait(false);
imgDiff.Old = oldImage.Bitmap;
imgDiff.OldFileSize = oldImage.Size;
}
@@ -186,7 +190,7 @@ namespace SourceGit.ViewModels
var fullPath = Path.Combine(_repo, _option.Path);
if (File.Exists(fullPath))
{
- var newImage = ImageSource.FromFile(fullPath, imgDecoder);
+ var newImage = await ImageSource.FromFileAsync(fullPath, imgDecoder).ConfigureAwait(false);
imgDiff.New = newImage.Bitmap;
imgDiff.NewFileSize = newImage.Size;
}
@@ -199,13 +203,13 @@ namespace SourceGit.ViewModels
var binaryDiff = new Models.BinaryDiff();
if (_option.Revisions.Count == 2)
{
- binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).Result();
- binaryDiff.NewSize = new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).Result();
+ binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).GetResultAsync().ConfigureAwait(false);
+ binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).GetResultAsync().ConfigureAwait(false);
}
else
{
var fullPath = Path.Combine(_repo, _option.Path);
- binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, "HEAD").Result();
+ binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").GetResultAsync().ConfigureAwait(false);
binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0;
}
rs = binaryDiff;
@@ -236,13 +240,13 @@ namespace SourceGit.ViewModels
});
}
- private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha)
+ private async Task QuerySubmoduleRevisionAsync(string repo, string sha)
{
- var commit = new Commands.QuerySingleCommit(repo, sha).Result();
+ var commit = await new Commands.QuerySingleCommit(repo, sha).GetResultAsync().ConfigureAwait(false);
if (commit == null)
return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha } };
- var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
+ var body = await new Commands.QueryCommitFullMessage(repo, sha).GetResultAsync().ConfigureAwait(false);
return new Models.RevisionSubmodule()
{
Commit = commit,
diff --git a/src/ViewModels/DirHistories.cs b/src/ViewModels/DirHistories.cs
new file mode 100644
index 00000000..6b4aa039
--- /dev/null
+++ b/src/ViewModels/DirHistories.cs
@@ -0,0 +1,94 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Avalonia.Threading;
+using CommunityToolkit.Mvvm.ComponentModel;
+
+namespace SourceGit.ViewModels
+{
+ public class DirHistories : ObservableObject
+ {
+ public string Title
+ {
+ get;
+ }
+
+ public bool IsLoading
+ {
+ get => _isLoading;
+ private set => SetProperty(ref _isLoading, value);
+ }
+
+ public List Commits
+ {
+ get => _commits;
+ private set => SetProperty(ref _commits, value);
+ }
+
+ public Models.Commit SelectedCommit
+ {
+ get => _selectedCommit;
+ set
+ {
+ if (SetProperty(ref _selectedCommit, value))
+ Detail.Commit = value;
+ }
+ }
+
+ public CommitDetail Detail
+ {
+ get => _detail;
+ private set => SetProperty(ref _detail, value);
+ }
+
+ public DirHistories(Repository repo, string dir, string revision = null)
+ {
+ if (!string.IsNullOrEmpty(revision))
+ Title = $"{dir} @ {revision}";
+ else
+ Title = dir;
+
+ _repo = repo;
+ _detail = new CommitDetail(repo, false);
+ _detail.SearchChangeFilter = dir;
+
+ Task.Run(async () =>
+ {
+ var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision ?? string.Empty} -- \"{dir}\"", false)
+ .GetResultAsync()
+ .ConfigureAwait(false);
+
+ Dispatcher.UIThread.Post(() =>
+ {
+ Commits = commits;
+ IsLoading = false;
+
+ if (commits.Count > 0)
+ SelectedCommit = commits[0];
+ });
+ });
+ }
+
+ public void NavigateToCommit(Models.Commit commit)
+ {
+ _repo.NavigateToCommit(commit.SHA);
+ }
+
+ public string GetCommitFullMessage(Models.Commit commit)
+ {
+ var sha = commit.SHA;
+ if (_cachedCommitFullMessage.TryGetValue(sha, out var msg))
+ return msg;
+
+ msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).GetResultAsync().Result;
+ _cachedCommitFullMessage[sha] = msg;
+ return msg;
+ }
+
+ private Repository _repo = null;
+ private bool _isLoading = true;
+ private List _commits = [];
+ private Models.Commit _selectedCommit = null;
+ private CommitDetail _detail = null;
+ private Dictionary _cachedCommitFullMessage = new();
+ }
+}
diff --git a/src/ViewModels/Discard.cs b/src/ViewModels/Discard.cs
index 7619635c..1fcda904 100644
--- a/src/ViewModels/Discard.cs
+++ b/src/ViewModels/Discard.cs
@@ -56,7 +56,7 @@ namespace SourceGit.ViewModels
Mode = new DiscardMultipleFiles() { Count = _changes.Count };
}
- public override Task Sure()
+ public override async Task