diff --git a/src/Commands/Fetch.cs b/src/Commands/Fetch.cs index 9dc95767..4bf156f9 100644 --- a/src/Commands/Fetch.cs +++ b/src/Commands/Fetch.cs @@ -29,6 +29,22 @@ namespace SourceGit.Commands { AutoFetch.MarkFetched(repo); } + public Fetch(string repo, string remote, string localBranch, string remoteBranch, Action outputHandler) { + Cwd = repo; + TraitErrorAsOutput = true; + + var sshKey = new Config(repo).Get($"remote.{remote}.sshkey"); + if (!string.IsNullOrEmpty(sshKey)) { + Envs.Add("GIT_SSH_COMMAND", $"ssh -i '{sshKey}'"); + Args = ""; + } else { + Args = "-c credential.helper=manager-core "; + } + + Args += $"fetch --progress --verbose {remote} {remoteBranch}:{localBranch}"; + handler = outputHandler; + } + public override void OnReadline(string line) { handler?.Invoke(line); } diff --git a/src/Views/Popups/FastForwardWithoutCheckout.xaml b/src/Views/Popups/FastForwardWithoutCheckout.xaml new file mode 100644 index 00000000..e7b36ec7 --- /dev/null +++ b/src/Views/Popups/FastForwardWithoutCheckout.xaml @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/src/Views/Popups/FastForwardWithoutCheckout.xaml.cs b/src/Views/Popups/FastForwardWithoutCheckout.xaml.cs new file mode 100644 index 00000000..37efa5b5 --- /dev/null +++ b/src/Views/Popups/FastForwardWithoutCheckout.xaml.cs @@ -0,0 +1,46 @@ +using System.Threading.Tasks; + +namespace SourceGit.Views.Popups { + /// + /// 对于不是当前分支的本地分支,Fast-Forward + /// + public partial class FastForwardWithoutCheckout : Controls.PopupWidget { + private string repo = null; + private string remote = null; + private string localBranch = null; + private string remoteBranch = null; + private bool isValid = false; + + public FastForwardWithoutCheckout(string repo, string branch, string upstream) { + int idx = upstream.IndexOf('/'); + if (idx < 0 || idx == upstream.Length - 1) { + Models.Exception.Raise($"Invalid upstream: {upstream}"); + return; + } + + this.repo = repo; + this.remote = upstream.Substring(0, idx); + this.localBranch = branch; + this.remoteBranch = upstream.Substring(idx+1); + this.isValid = true; + + InitializeComponent(); + } + + public override string GetTitle() { + return App.Text("Fetch.Title"); + } + + public override Task Start() { + return Task.Run(() => { + if (isValid) { + Models.Watcher.SetEnabled(repo, false); + new Commands.Fetch(repo, remote, localBranch, remoteBranch, UpdateProgress).Exec(); + Models.Watcher.SetEnabled(repo, true); + } + + return true; + }); + } + } +} diff --git a/src/Views/Widgets/Dashboard.xaml.cs b/src/Views/Widgets/Dashboard.xaml.cs index 0a17f8bc..02fe2ba6 100644 --- a/src/Views/Widgets/Dashboard.xaml.cs +++ b/src/Views/Widgets/Dashboard.xaml.cs @@ -654,7 +654,7 @@ namespace SourceGit.Views.Widgets { var upstream = branch.Upstream.Substring(13); var fastForward = new MenuItem(); fastForward.Header = App.Text("BranchCM.FastForward", upstream); - fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus); + fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0; fastForward.Click += (o, e) => { new Popups.Merge(repo.Path, upstream, branch.Name).ShowAndStart(); e.Handled = true; @@ -683,6 +683,21 @@ namespace SourceGit.Views.Widgets { e.Handled = true; }; menu.Items.Add(checkout); + + if (!string.IsNullOrEmpty(branch.Upstream)) { + var upstream = branch.Upstream.Substring(13); + var fastForward = new MenuItem(); + fastForward.Header = App.Text("BranchCM.FastForward", upstream); + fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0; + fastForward.Click += (o, e) => { + new Popups.FastForwardWithoutCheckout(repo.Path, branch.Name, upstream).ShowAndStart(); + e.Handled = true; + }; + + menu.Items.Add(new Separator()); + menu.Items.Add(fastForward); + } + menu.Items.Add(new Separator()); menu.Items.Add(push);