From 1442dcfe0012aaf2d53ce16dc19b463a08a45d59 Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 29 Oct 2024 09:59:13 +0800 Subject: [PATCH] feature: allow fetch the latest remote changes into local branch which is not current branch (#617) Signed-off-by: leo --- src/Commands/Fetch.cs | 10 ++++++++ src/Resources/Locales/en_US.axaml | 1 + src/Resources/Locales/zh_CN.axaml | 1 + src/Resources/Locales/zh_TW.axaml | 1 + src/ViewModels/FetchInto.cs | 42 +++++++++++++++++++++++++++++++ src/ViewModels/Repository.cs | 16 ++++++++++-- src/Views/FetchInto.axaml | 21 ++++++++++++++++ src/Views/FetchInto.axaml.cs | 12 +++++++++ 8 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/ViewModels/FetchInto.cs create mode 100644 src/Views/FetchInto.axaml create mode 100644 src/Views/FetchInto.axaml.cs diff --git a/src/Commands/Fetch.cs b/src/Commands/Fetch.cs index ea4e54bf..25c499fd 100644 --- a/src/Commands/Fetch.cs +++ b/src/Commands/Fetch.cs @@ -21,6 +21,16 @@ namespace SourceGit.Commands Args += remote; } + public Fetch(string repo, Models.Branch local, Models.Branch remote, Action outputHandler) + { + _outputHandler = outputHandler; + WorkingDirectory = repo; + Context = repo; + TraitErrorAsOutput = true; + SSHKey = new Config(repo).Get($"remote.{remote.Remote}.sshkey"); + Args = $"fetch --progress --verbose {remote.Remote} {remote.Name}:{local.Name}"; + } + protected override void OnReadline(string line) { _outputHandler?.Invoke(line); diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 16056b22..b2e0ef8d 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -55,6 +55,7 @@ Delete selected {0} branches Discard all changes Fast-Forward to ${0}$ + Fetch ${0}$ into ${1}$... Git Flow - Finish ${0}$ Merge ${0}$ into ${1}$... Pull ${0}$ diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 2e8e8843..333dbd06 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -58,6 +58,7 @@ 删除选中的 {0} 个分支 放弃所有更改 快进(fast-forward)到 ${0}$ + 拉取(fetch) ${0}$ 至 ${1}$... GIT工作流 - 完成 ${0}$ 合并 ${0}$ 到 ${1}$... 拉回(pull) ${0}$ diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 5f771da8..06f9bba4 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -58,6 +58,7 @@ 刪除所選的 {0} 個分支 捨棄所有變更 快轉 (fast-forward) 到 ${0}$ + 提取(fetch) ${0}$ 至 ${1}$... Git 工作流 - 完成 ${0}$ 合併 ${0}$ 到 ${1}$... 拉取 (pull) ${0}$ diff --git a/src/ViewModels/FetchInto.cs b/src/ViewModels/FetchInto.cs new file mode 100644 index 00000000..a52b1cd6 --- /dev/null +++ b/src/ViewModels/FetchInto.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; + +namespace SourceGit.ViewModels +{ + public class FetchInto : Popup + { + public Models.Branch Local + { + get; + private set; + } + + public Models.Branch Upstream + { + get; + private set; + } + + public FetchInto(Repository repo, Models.Branch local, Models.Branch upstream) + { + _repo = repo; + Local = local; + Upstream = upstream; + View = new Views.FetchInto() { DataContext = this }; + } + + public override Task Sure() + { + _repo.SetWatcherEnabled(false); + ProgressDescription = "Fast-Forward ..."; + + return Task.Run(() => + { + new Commands.Fetch(_repo.FullPath, Local, Upstream, SetProgressDescription).Exec(); + CallUIThread(() => _repo.SetWatcherEnabled(true)); + return true; + }); + } + + private readonly Repository _repo = null; + } +} diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 8f6e1f88..9708f1e2 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1354,6 +1354,7 @@ namespace SourceGit.ViewModels e.Handled = true; }; menu.Items.Add(checkout); + menu.Items.Add(new MenuItem() { Header = "-" }); var worktree = _worktrees.Find(x => x.Branch == branch.FullName); var upstream = _branches.Find(x => x.FullName == branch.Upstream); @@ -1370,11 +1371,22 @@ namespace SourceGit.ViewModels e.Handled = true; }; - menu.Items.Add(new MenuItem() { Header = "-" }); + var fetchInto = new MenuItem(); + fetchInto.Header = new Views.NameHighlightedTextBlock("BranchCM.FetchInto", upstream.FriendlyName, branch.Name); + fetchInto.Icon = App.CreateMenuIcon("Icons.Fetch"); + fetchInto.IsEnabled = branch.TrackStatus.Ahead.Count == 0; + fetchInto.Click += (_, e) => + { + if (PopupHost.CanCreatePopup()) + PopupHost.ShowAndStartPopup(new FetchInto(this, branch, upstream)); + e.Handled = true; + }; + menu.Items.Add(fastForward); + menu.Items.Add(new MenuItem() { Header = "-" }); + menu.Items.Add(fetchInto); } - menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(push); var merge = new MenuItem(); diff --git a/src/Views/FetchInto.axaml b/src/Views/FetchInto.axaml new file mode 100644 index 00000000..4a0c0966 --- /dev/null +++ b/src/Views/FetchInto.axaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/src/Views/FetchInto.axaml.cs b/src/Views/FetchInto.axaml.cs new file mode 100644 index 00000000..c61c052e --- /dev/null +++ b/src/Views/FetchInto.axaml.cs @@ -0,0 +1,12 @@ +using Avalonia.Controls; + +namespace SourceGit.Views +{ + public partial class FetchInto : UserControl + { + public FetchInto() + { + InitializeComponent(); + } + } +}