From 53bcafa5ed072a3fe2cb9def11c1d061f05d1e8c Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 1 Apr 2024 21:27:08 +0800 Subject: [PATCH] refactor: ux for in progress action (cherry-pick/rebase/revert/merge) --- src/SourceGit/Resources/Locales.Designer.cs | 45 ++++- src/SourceGit/Resources/Locales.en.resx | 15 +- src/SourceGit/Resources/Locales.resx | 15 +- src/SourceGit/Resources/Locales.zh.resx | 15 +- .../ViewModels/InProgressContexts.cs | 89 ++++++++++ src/SourceGit/ViewModels/Repository.cs | 159 +++++++----------- src/SourceGit/Views/Repository.axaml | 28 ++- 7 files changed, 243 insertions(+), 123 deletions(-) create mode 100644 src/SourceGit/ViewModels/InProgressContexts.cs diff --git a/src/SourceGit/Resources/Locales.Designer.cs b/src/SourceGit/Resources/Locales.Designer.cs index a9fd97f6..8188bc8f 100644 --- a/src/SourceGit/Resources/Locales.Designer.cs +++ b/src/SourceGit/Resources/Locales.Designer.cs @@ -942,15 +942,6 @@ namespace SourceGit.Resources { } } - /// - /// Looks up a localized string similar to Conflict detected! Press 'Abort' to restore original HEAD.. - /// - public static string Text_Conflict_Tip { - get { - return ResourceManager.GetString("Text.Conflict.Tip", resourceCulture); - } - } - /// /// Looks up a localized string similar to Copy. /// @@ -2049,6 +2040,42 @@ namespace SourceGit.Resources { } } + /// + /// Looks up a localized string similar to Cherry-Pick in progress. Press 'Abort' to restore original HEAD.. + /// + public static string Text_InProgress_CherryPick { + get { + return ResourceManager.GetString("Text.InProgress.CherryPick", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Merge request in progress. Press 'Abort' to restore original HEAD.. + /// + public static string Text_InProgress_Merge { + get { + return ResourceManager.GetString("Text.InProgress.Merge", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rebase in progress. Press 'Abort' to restore original HEAD.. + /// + public static string Text_InProgress_Rebase { + get { + return ResourceManager.GetString("Text.InProgress.Rebase", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Revert in progress. Press 'Abort' to restore original HEAD.. + /// + public static string Text_InProgress_Revert { + get { + return ResourceManager.GetString("Text.InProgress.Revert", resourceCulture); + } + } + /// /// Looks up a localized string similar to Source Git. /// diff --git a/src/SourceGit/Resources/Locales.en.resx b/src/SourceGit/Resources/Locales.en.resx index 60b75f55..7110409d 100644 --- a/src/SourceGit/Resources/Locales.en.resx +++ b/src/SourceGit/Resources/Locales.en.resx @@ -1161,9 +1161,6 @@ INCLUDE UNTRACKED FILES - - Conflict detected! Press 'Abort' to restore original HEAD. - Clear Stashes @@ -1338,4 +1335,16 @@ • Source code can be found at + + Cherry-Pick in progress. Press 'Abort' to restore original HEAD. + + + Rebase in progress. Press 'Abort' to restore original HEAD. + + + Revert in progress. Press 'Abort' to restore original HEAD. + + + Merge request in progress. Press 'Abort' to restore original HEAD. + \ No newline at end of file diff --git a/src/SourceGit/Resources/Locales.resx b/src/SourceGit/Resources/Locales.resx index d5610a76..9c68815d 100644 --- a/src/SourceGit/Resources/Locales.resx +++ b/src/SourceGit/Resources/Locales.resx @@ -1161,9 +1161,6 @@ INCLUDE UNTRACKED FILES - - Conflict detected! Press 'Abort' to restore original HEAD. - Clear Stashes @@ -1338,4 +1335,16 @@ • Source code can be found at + + Cherry-Pick in progress. Press 'Abort' to restore original HEAD. + + + Rebase in progress. Press 'Abort' to restore original HEAD. + + + Revert in progress. Press 'Abort' to restore original HEAD. + + + Merge request in progress. Press 'Abort' to restore original HEAD. + \ No newline at end of file diff --git a/src/SourceGit/Resources/Locales.zh.resx b/src/SourceGit/Resources/Locales.zh.resx index 50f3cc11..e960254c 100644 --- a/src/SourceGit/Resources/Locales.zh.resx +++ b/src/SourceGit/Resources/Locales.zh.resx @@ -1158,9 +1158,6 @@ 显示未跟踪文件 - - 检测到本地冲突! 点击【终止合并】回滚到合并操作前的状态。 - 丢弃贮藏确认 @@ -1338,4 +1335,16 @@ 在 Fleet 中打开 + + 挑选(Cherry-Pick)操作进行中。点击【终止】回滚到操作前的状态。 + + + 变基(Rebase)操作进行中。点击【终止】回滚到操作前的状态。 + + + 回滚提交操作进行中。点击【终止】回滚到操作前的状态。 + + + 合并操作进行中。点击【终止】回滚到操作前的状态。 + \ No newline at end of file diff --git a/src/SourceGit/ViewModels/InProgressContexts.cs b/src/SourceGit/ViewModels/InProgressContexts.cs new file mode 100644 index 00000000..e38cab13 --- /dev/null +++ b/src/SourceGit/ViewModels/InProgressContexts.cs @@ -0,0 +1,89 @@ +using System.IO; + +namespace SourceGit.ViewModels +{ + public abstract class InProgressContext + { + public string Repository + { + get; + set; + } + + public string Cmd + { + get; + set; + } + + public InProgressContext(string repo, string cmd) + { + Repository = repo; + Cmd = cmd; + } + + public void Abort() + { + new Commands.Command() + { + WorkingDirectory = Repository, + Context = Repository, + Args = $"{Cmd} --abort", + }.Exec(); + } + + public virtual bool Continue() + { + return new Commands.Command() + { + WorkingDirectory = Repository, + Context = Repository, + Args = $"-c core.editor=true {Cmd} --continue", + }.Exec(); + } + } + + public class CherryPickInProgress : InProgressContext + { + public CherryPickInProgress(string repo) : base(repo, "cherry-pick") { } + } + + public class RebaseInProgress : InProgressContext + { + public RebaseInProgress(Repository repo) : base(repo.FullPath, "rebase") + { + _gitDir = repo.GitDir; + } + + public override bool Continue() + { + var succ = base.Continue(); + if (succ) + { + var rebaseMergeHead = Path.Combine(_gitDir, "REBASE_HEAD"); + var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); + var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply"); + if (File.Exists(rebaseMergeHead)) + File.Delete(rebaseMergeHead); + if (Directory.Exists(rebaseMergeFolder)) + Directory.Delete(rebaseMergeFolder); + if (Directory.Exists(rebaseApplyFolder)) + Directory.Delete(rebaseApplyFolder); + } + + return succ; + } + + private string _gitDir; + } + + public class RevertInProgress : InProgressContext + { + public RevertInProgress(string repo) : base(repo, "revert") { } + } + + public class MergeInProgress : InProgressContext + { + public MergeInProgress(string repo) : base(repo, "merge") { } + } +} diff --git a/src/SourceGit/ViewModels/Repository.cs b/src/SourceGit/ViewModels/Repository.cs index da886362..bdc2291f 100644 --- a/src/SourceGit/ViewModels/Repository.cs +++ b/src/SourceGit/ViewModels/Repository.cs @@ -141,20 +141,6 @@ namespace SourceGit.ViewModels get => _stashesPage == null ? 0 : _stashesPage.Count; } - [JsonIgnore] - public bool IsConflictBarVisible - { - get => _isConflictBarVisible; - private set => SetProperty(ref _isConflictBarVisible, value); - } - - [JsonIgnore] - public bool HasUnsolvedConflict - { - get => _hasUnsolvedConflict; - private set => SetProperty(ref _hasUnsolvedConflict, value); - } - [JsonIgnore] public bool CanCommitWithPush { @@ -219,6 +205,20 @@ namespace SourceGit.ViewModels set => SetProperty(ref _isSubmoduleGroupExpanded, value); } + [JsonIgnore] + public InProgressContext InProgressContext + { + get => _inProgressContext; + private set => SetProperty(ref _inProgressContext, value); + } + + [JsonIgnore] + public bool HasUnsolvedConflicts + { + get => _hasUnsolvedConflicts; + private set => SetProperty(ref _hasUnsolvedConflicts, value); + } + public void Open() { _watcher = new Models.Watcher(this); @@ -227,8 +227,8 @@ namespace SourceGit.ViewModels _stashesPage = new StashesPage(this); _selectedView = _histories; _selectedViewIndex = 0; - _isConflictBarVisible = false; - _hasUnsolvedConflict = false; + _inProgressContext = null; + _hasUnsolvedConflicts = false; Task.Run(() => { @@ -262,6 +262,9 @@ namespace SourceGit.ViewModels _isTagGroupExpanded = false; _isSubmoduleGroupExpanded = false; + _inProgressContext = null; + _hasUnsolvedConflicts = false; + _remotes.Clear(); _branches.Clear(); _localBranchTrees.Clear(); @@ -450,90 +453,34 @@ namespace SourceGit.ViewModels public async void ContinueMerge() { - var cherryPickMerge = Path.Combine(_gitDir, "CHERRY_PICK_HEAD"); - var rebaseMerge = Path.Combine(_gitDir, "REBASE_HEAD"); - var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); - var revertMerge = Path.Combine(_gitDir, "REVERT_HEAD"); - var otherMerge = Path.Combine(_gitDir, "MERGE_HEAD"); - - var mode = ""; - if (File.Exists(cherryPickMerge)) + if (_inProgressContext != null) { - mode = "cherry-pick"; - } - else if (File.Exists(rebaseMerge) && Directory.Exists(rebaseMergeFolder)) - { - mode = "rebase"; - } - else if (File.Exists(revertMerge)) - { - mode = "revert"; - } - else if (File.Exists(otherMerge)) - { - mode = "merge"; + SetWatcherEnabled(false); + var succ = await Task.Run(_inProgressContext.Continue); + if (succ && _workingCopy != null) + { + _workingCopy.CommitMessage = string.Empty; + } + SetWatcherEnabled(true); } else { MarkWorkingCopyDirtyManually(); - return; - } - - var cmd = new Commands.Command(); - cmd.WorkingDirectory = _fullpath; - cmd.Context = _fullpath; - cmd.Args = $"-c core.editor=true {mode} --continue"; - - SetWatcherEnabled(false); - var succ = await Task.Run(cmd.Exec); - SetWatcherEnabled(true); - - if (succ) - { - if (_workingCopy != null) - _workingCopy.CommitMessage = string.Empty; - - if (mode == "rebase") - { - if (File.Exists(rebaseMerge)) - File.Delete(rebaseMerge); - if (Directory.Exists(rebaseMergeFolder)) - Directory.Delete(rebaseMergeFolder); - } } } public async void AbortMerge() { - var cmd = new Commands.Command(); - cmd.WorkingDirectory = _fullpath; - cmd.Context = _fullpath; - - if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD"))) + if (_inProgressContext != null) { - cmd.Args = "cherry-pick --abort"; - } - else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD"))) - { - cmd.Args = "rebase --abort"; - } - else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD"))) - { - cmd.Args = "revert --abort"; - } - else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD"))) - { - cmd.Args = "merge --abort"; + SetWatcherEnabled(false); + await Task.Run(_inProgressContext.Abort); + SetWatcherEnabled(true); } else { MarkWorkingCopyDirtyManually(); - return; } - - SetWatcherEnabled(false); - await Task.Run(cmd.Exec); - SetWatcherEnabled(true); } public void RefreshBranches() @@ -622,30 +569,39 @@ namespace SourceGit.ViewModels { var changes = new Commands.QueryLocalChanges(FullPath, _includeUntracked).Result(); var hasUnsolvedConflict = _workingCopy.SetData(changes); + var inProgress = null as InProgressContext; - var cherryPickMerge = Path.Combine(_gitDir, "CHERRY_PICK_HEAD"); - var rebaseMerge = Path.Combine(_gitDir, "REBASE_HEAD"); var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge"); - var revertMerge = Path.Combine(_gitDir, "REVERT_HEAD"); - var otherMerge = Path.Combine(_gitDir, "MERGE_HEAD"); - var runningMerge = (File.Exists(cherryPickMerge) || - (File.Exists(rebaseMerge) && Directory.Exists(rebaseMergeFolder)) || - File.Exists(revertMerge) || - File.Exists(otherMerge)); - - if (!runningMerge) + var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply"); + if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD"))) + { + inProgress = new CherryPickInProgress(_fullpath); + } + else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(rebaseMergeFolder)) + { + inProgress = new RebaseInProgress(this); + } + else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD"))) + { + inProgress = new RevertInProgress(_fullpath); + } + else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD"))) + { + inProgress = new MergeInProgress(_fullpath); + } + else { if (Directory.Exists(rebaseMergeFolder)) Directory.Delete(rebaseMergeFolder, true); - var applyFolder = Path.Combine(_gitDir, "rebase-apply"); - if (Directory.Exists(applyFolder)) - Directory.Delete(applyFolder, true); + + if (Directory.Exists(rebaseApplyFolder)) + Directory.Delete(rebaseApplyFolder, true); } Dispatcher.UIThread.Invoke(() => { - IsConflictBarVisible = runningMerge; - HasUnsolvedConflict = hasUnsolvedConflict; + InProgressContext = inProgress; + HasUnsolvedConflicts = hasUnsolvedConflict; OnPropertyChanged(nameof(WorkingCopyChangesCount)); }); } @@ -1359,9 +1315,10 @@ namespace SourceGit.ViewModels private List _remoteBranchTrees = new List(); private List _tags = new List(); private List _submodules = new List(); - private bool _isConflictBarVisible = false; - private bool _hasUnsolvedConflict = false; private bool _canCommitWithPush = false; private bool _includeUntracked = true; + + private InProgressContext _inProgressContext = null; + private bool _hasUnsolvedConflicts = false; } } diff --git a/src/SourceGit/Views/Repository.axaml b/src/SourceGit/Views/Repository.axaml index 0bd58201..95b26522 100644 --- a/src/SourceGit/Views/Repository.axaml +++ b/src/SourceGit/Views/Repository.axaml @@ -463,15 +463,35 @@ BorderBrush="{DynamicResource Brush.Border0}"/> - - - + + + + + + + + + + + + + + + + + + + + + + -