mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-21 13:20:30 +08:00
refactor: use async methods to commit changes
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -158,13 +158,12 @@ namespace SourceGit
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<bool> AskConfirmAsync(string message, Action onSure)
|
||||
public static async Task<bool> AskConfirmAsync(string message)
|
||||
{
|
||||
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
|
||||
{
|
||||
var confirm = new Views.Confirm();
|
||||
confirm.Message.Text = message;
|
||||
confirm.OnSure = onSure;
|
||||
return await confirm.ShowDialog<bool>(owner);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@ namespace SourceGit.Models
|
||||
ByContent,
|
||||
}
|
||||
|
||||
public enum CommitCheckPassed
|
||||
{
|
||||
None = 0,
|
||||
DetachedHead,
|
||||
Filter,
|
||||
FileCount,
|
||||
}
|
||||
|
||||
public class Commit
|
||||
{
|
||||
// As retrieved by: git mktree </dev/null
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace SourceGit.ViewModels
|
||||
if (refs.Count == 0)
|
||||
{
|
||||
var msg = App.Text("Checkout.WarnLostCommits");
|
||||
var shouldContinue = await App.AskConfirmAsync(msg, null);
|
||||
var shouldContinue = await App.AskConfirmAsync(msg);
|
||||
if (!shouldContinue)
|
||||
{
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace SourceGit.ViewModels
|
||||
if (refs.Count == 0)
|
||||
{
|
||||
var msg = App.Text("Checkout.WarnLostCommits");
|
||||
var shouldContinue = await App.AskConfirmAsync(msg, null);
|
||||
var shouldContinue = await App.AskConfirmAsync(msg);
|
||||
if (!shouldContinue)
|
||||
{
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace SourceGit.ViewModels
|
||||
if (refs.Count == 0)
|
||||
{
|
||||
var msg = App.Text("Checkout.WarnLostCommits");
|
||||
var shouldContinue = await App.AskConfirmAsync(msg, null);
|
||||
var shouldContinue = await App.AskConfirmAsync(msg);
|
||||
if (!shouldContinue)
|
||||
{
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
@@ -16,23 +16,25 @@ namespace SourceGit.ViewModels
|
||||
private set;
|
||||
}
|
||||
|
||||
public ConfirmEmptyCommit(bool hasLocalChanges, Action<bool> onSure)
|
||||
public ConfirmEmptyCommit(WorkingCopy wc, bool autoPush, int unstagedCount)
|
||||
{
|
||||
HasLocalChanges = hasLocalChanges;
|
||||
Message = App.Text(hasLocalChanges ? "ConfirmEmptyCommit.WithLocalChanges" : "ConfirmEmptyCommit.NoLocalChanges");
|
||||
_onSure = onSure;
|
||||
_wc = wc;
|
||||
_autoPush = autoPush;
|
||||
HasLocalChanges = unstagedCount > 0;
|
||||
Message = App.Text(HasLocalChanges ? "ConfirmEmptyCommit.WithLocalChanges" : "ConfirmEmptyCommit.NoLocalChanges");
|
||||
}
|
||||
|
||||
public void StageAllThenCommit()
|
||||
public async Task StageAllThenCommitAsync()
|
||||
{
|
||||
_onSure?.Invoke(true);
|
||||
await _wc.CommitAsync(true, _autoPush, Models.CommitCheckPassed.FileCount);
|
||||
}
|
||||
|
||||
public void Continue()
|
||||
public async Task ContinueAsync()
|
||||
{
|
||||
_onSure?.Invoke(false);
|
||||
await _wc.CommitAsync(false, _autoPush, Models.CommitCheckPassed.FileCount);
|
||||
}
|
||||
|
||||
private Action<bool> _onSure;
|
||||
private readonly WorkingCopy _wc;
|
||||
private readonly bool _autoPush;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace SourceGit.ViewModels
|
||||
if (refs.Count == 0)
|
||||
{
|
||||
var msg = App.Text("Checkout.WarnLostCommits");
|
||||
var shouldContinue = await App.AskConfirmAsync(msg, null);
|
||||
var shouldContinue = await App.AskConfirmAsync(msg);
|
||||
if (!shouldContinue)
|
||||
{
|
||||
_repo.SetWatcherEnabled(true);
|
||||
|
||||
@@ -606,19 +606,86 @@ namespace SourceGit.ViewModels
|
||||
CommitMessage = tmpl.Apply(_repo.CurrentBranch, _staged);
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
public async Task CommitAsync(bool autoStage, bool autoPush, Models.CommitCheckPassed checkPassed = Models.CommitCheckPassed.None)
|
||||
{
|
||||
DoCommit(false, false);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
return;
|
||||
|
||||
public void CommitWithAutoStage()
|
||||
{
|
||||
DoCommit(true, false);
|
||||
}
|
||||
if (!_repo.CanCreatePopup())
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has an unfinished job! Please wait!");
|
||||
return;
|
||||
}
|
||||
|
||||
public void CommitWithPush()
|
||||
{
|
||||
DoCommit(false, true);
|
||||
if (autoStage && HasUnsolvedConflicts)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has unsolved conflict(s). Auto-stage and commit is disabled!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_repo.CurrentBranch is { IsDetachedHead: true } && checkPassed < Models.CommitCheckPassed.DetachedHead)
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithDetachedHead");
|
||||
var sure = await App.AskConfirmAsync(msg);
|
||||
if (sure)
|
||||
await CommitAsync(autoStage, autoPush, Models.CommitCheckPassed.DetachedHead);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && checkPassed < Models.CommitCheckPassed.Filter)
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count);
|
||||
var sure = await App.AskConfirmAsync(msg);
|
||||
if (sure)
|
||||
await CommitAsync(autoStage, autoPush, Models.CommitCheckPassed.Filter);
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkPassed < Models.CommitCheckPassed.FileCount && !_useAmend)
|
||||
{
|
||||
if ((!autoStage && _staged.Count == 0) || (autoStage && _cached.Count == 0))
|
||||
{
|
||||
await App.ShowDialog(new ConfirmEmptyCommit(this, autoPush, _cached.Count));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IsCommitting = true;
|
||||
_repo.Settings.PushCommitMessage(_commitMessage);
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
||||
var signOff = _repo.Settings.EnableSignOffForCommit;
|
||||
var log = _repo.CreateLog("Commit");
|
||||
var succ = true;
|
||||
if (autoStage && _unstaged.Count > 0)
|
||||
succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).ExecAsync().ConfigureAwait(false);
|
||||
|
||||
if (succ)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).RunAsync().ConfigureAwait(false);
|
||||
|
||||
log.Complete();
|
||||
|
||||
if (succ)
|
||||
{
|
||||
CommitMessage = string.Empty;
|
||||
UseAmend = false;
|
||||
if (autoPush && _repo.Remotes.Count > 0)
|
||||
{
|
||||
Models.Branch pushBranch = null;
|
||||
if (_repo.CurrentBranch == null)
|
||||
{
|
||||
var currentBranchName = await new Commands.QueryCurrentBranch(_repo.FullPath).GetResultAsync();
|
||||
pushBranch = new Models.Branch() { Name = currentBranchName };
|
||||
}
|
||||
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowAndStartPopup(new Push(_repo, pushBranch));
|
||||
}
|
||||
}
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
}
|
||||
|
||||
private List<Models.Change> GetVisibleChanges(List<Models.Change> changes)
|
||||
@@ -745,102 +812,6 @@ namespace SourceGit.ViewModels
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
|
||||
}
|
||||
|
||||
private void DoCommit(bool autoStage, bool autoPush, CommitCheckPassed checkPassed = CommitCheckPassed.None)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_commitMessage))
|
||||
return;
|
||||
|
||||
if (!_repo.CanCreatePopup())
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has an unfinished job! Please wait!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoStage && HasUnsolvedConflicts)
|
||||
{
|
||||
App.RaiseException(_repo.FullPath, "Repository has unsolved conflict(s). Auto-stage and commit is disabled!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_repo.CurrentBranch is { IsDetachedHead: true } && checkPassed < CommitCheckPassed.DetachedHead)
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithDetachedHead");
|
||||
_ = App.AskConfirmAsync(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.DetachedHead));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && checkPassed < CommitCheckPassed.Filter)
|
||||
{
|
||||
var msg = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count);
|
||||
_ = App.AskConfirmAsync(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.Filter));
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkPassed < CommitCheckPassed.FileCount && !_useAmend)
|
||||
{
|
||||
if ((!autoStage && _staged.Count == 0) || (autoStage && _cached.Count == 0))
|
||||
{
|
||||
_ = App.ShowDialog(new ConfirmEmptyCommit(_cached.Count > 0, stageAll => DoCommit(stageAll, autoPush, CommitCheckPassed.FileCount)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
IsCommitting = true;
|
||||
_repo.Settings.PushCommitMessage(_commitMessage);
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
||||
var signOff = _repo.Settings.EnableSignOffForCommit;
|
||||
var log = _repo.CreateLog("Commit");
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var succ = true;
|
||||
if (autoStage && _unstaged.Count > 0)
|
||||
succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).ExecAsync().ConfigureAwait(false);
|
||||
|
||||
if (succ)
|
||||
succ = await new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).RunAsync().ConfigureAwait(false);
|
||||
|
||||
log.Complete();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (succ)
|
||||
{
|
||||
CommitMessage = string.Empty;
|
||||
UseAmend = false;
|
||||
if (autoPush && _repo.Remotes.Count > 0)
|
||||
PushAfterCommit();
|
||||
}
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void PushAfterCommit()
|
||||
{
|
||||
if (_repo.CurrentBranch == null)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var currentBranchName = await new Commands.QueryCurrentBranch(_repo.FullPath).GetResultAsync();
|
||||
var tmp = new Models.Branch() { Name = currentBranchName };
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowAndStartPopup(new Push(_repo, tmp));
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (_repo.CanCreatePopup())
|
||||
{
|
||||
_repo.ShowAndStartPopup(new Push(_repo, null));
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsChanged(List<Models.Change> old, List<Models.Change> cur)
|
||||
{
|
||||
if (old.Count != cur.Count)
|
||||
@@ -857,14 +828,6 @@ namespace SourceGit.ViewModels
|
||||
return false;
|
||||
}
|
||||
|
||||
private enum CommitCheckPassed
|
||||
{
|
||||
None = 0,
|
||||
DetachedHead,
|
||||
Filter,
|
||||
FileCount,
|
||||
}
|
||||
|
||||
private Repository _repo = null;
|
||||
private bool _isLoadingData = false;
|
||||
private bool _isStaging = false;
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
using System;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Confirm : ChromelessWindow
|
||||
{
|
||||
public Action OnSure
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Confirm()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -18,7 +11,6 @@ namespace SourceGit.Views
|
||||
|
||||
private void Sure(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
OnSure?.Invoke();
|
||||
Close(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,15 +9,19 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void StageAllThenCommit(object _1, RoutedEventArgs _2)
|
||||
private async void StageAllThenCommit(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
(DataContext as ViewModels.ConfirmEmptyCommit)?.StageAllThenCommit();
|
||||
if (DataContext is ViewModels.ConfirmEmptyCommit vm)
|
||||
await vm.StageAllThenCommitAsync();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Continue(object _1, RoutedEventArgs _2)
|
||||
private async void Continue(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
(DataContext as ViewModels.ConfirmEmptyCommit)?.Continue();
|
||||
if (DataContext is ViewModels.ConfirmEmptyCommit vm)
|
||||
await vm.ContinueAsync();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@
|
||||
<SplitButton.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem Header="{DynamicResource Text.WorkingCopy.CommitToEdit}"
|
||||
Command="{Binding Commit}"
|
||||
Click="OnCommit"
|
||||
IsEnabled="{Binding CommitMessage, Converter={x:Static c:StringConverters.IsNotNullOrWhitespace}}"/>
|
||||
</MenuFlyout>
|
||||
</SplitButton.Flyout>
|
||||
@@ -307,7 +307,7 @@
|
||||
Height="28"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,0"
|
||||
Command="{Binding Commit}"
|
||||
Click="OnCommit"
|
||||
HotKey="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"
|
||||
IsVisible="{Binding InProgressContext, Converter={x:Static ObjectConverters.IsNull}}"
|
||||
ToolTip.Placement="Top"
|
||||
@@ -337,7 +337,7 @@
|
||||
<Button Grid.Column="5"
|
||||
Width="0" Height="0"
|
||||
Background="Transparent"
|
||||
Command="{Binding CommitWithAutoStage}"
|
||||
Click="OnCommitWithAutoStage"
|
||||
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}">
|
||||
<Button.IsEnabled>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
@@ -353,7 +353,7 @@
|
||||
Height="28"
|
||||
Margin="8,0,0,0"
|
||||
Padding="8,0"
|
||||
Command="{Binding CommitWithPush}"
|
||||
Click="OnCommitWithPush"
|
||||
HotKey="{OnPlatform Ctrl+Alt+Enter, macOS=⌘+Alt+Enter}"
|
||||
ToolTip.Tip="{OnPlatform Ctrl+Alt+Enter, macOS=⌘+⌥+Enter}"
|
||||
ToolTip.Placement="Top"
|
||||
|
||||
@@ -193,6 +193,30 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnCommit(object _, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.WorkingCopy vm)
|
||||
await vm.CommitAsync(false, false);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnCommitWithAutoStage(object _, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.WorkingCopy vm)
|
||||
await vm.CommitAsync(true, false);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnCommitWithPush(object _, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.WorkingCopy vm)
|
||||
await vm.CommitAsync(false, true);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private ContextMenu CreateContextMenuForUnstagedChanges(ViewModels.WorkingCopy vm, string selectedSingleFolder)
|
||||
{
|
||||
var repo = vm.Repository;
|
||||
|
||||
Reference in New Issue
Block a user