mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-06-16 16:05:00 +00:00
feature: when trying to checkout a local branch from its tracking upstream and it is behind the upstream, show Checkout & Fast-Forward
popup
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
parent
6c04f5390a
commit
7d0536d94b
8 changed files with 203 additions and 6 deletions
|
@ -86,6 +86,8 @@
|
|||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash & Reapply</x:String>
|
||||
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">Checkout & Fast-Forward</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">Fast-Forward to:</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
|
||||
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit(s):</x:String>
|
||||
|
|
|
@ -90,6 +90,8 @@
|
|||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
|
||||
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 :</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">检出分支并快进</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">上游分支 :</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String>
|
||||
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表 :</x:String>
|
||||
|
|
|
@ -90,6 +90,8 @@
|
|||
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
|
||||
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String>
|
||||
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward" xml:space="preserve">簽出分支並快轉</x:String>
|
||||
<x:String x:Key="Text.Checkout.WithFastForward.Upstream" xml:space="preserve">上游分支 :</x:String>
|
||||
<x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String>
|
||||
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String>
|
||||
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">提交列表:</x:String>
|
||||
|
|
111
src/ViewModels/CheckoutAndFastForward.cs
Normal file
111
src/ViewModels/CheckoutAndFastForward.cs
Normal file
|
@ -0,0 +1,111 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class CheckoutAndFastForward : Popup
|
||||
{
|
||||
public Models.Branch LocalBranch
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public Models.Branch RemoteBrach
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public bool DiscardLocalChanges
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool IsRecurseSubmoduleVisible
|
||||
{
|
||||
get => _repo.Submodules.Count > 0;
|
||||
}
|
||||
|
||||
public bool RecurseSubmodules
|
||||
{
|
||||
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
|
||||
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
|
||||
}
|
||||
|
||||
public CheckoutAndFastForward(Repository repo, Models.Branch localBranch, Models.Branch remoteBranch)
|
||||
{
|
||||
_repo = repo;
|
||||
LocalBranch = localBranch;
|
||||
RemoteBrach = remoteBranch;
|
||||
}
|
||||
|
||||
public override Task<bool> Sure()
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
ProgressDescription = $"Checkout and Fast-Forward '{LocalBranch.Name}' ...";
|
||||
|
||||
var log = _repo.CreateLog($"Checkout and Fast-Forward '{LocalBranch.Name}' ...");
|
||||
Use(log);
|
||||
|
||||
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var succ = false;
|
||||
var needPopStash = false;
|
||||
|
||||
if (DiscardLocalChanges)
|
||||
{
|
||||
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBrach.Head, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
|
||||
if (changes > 0)
|
||||
{
|
||||
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
|
||||
if (!succ)
|
||||
{
|
||||
log.Complete();
|
||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||
return false;
|
||||
}
|
||||
|
||||
needPopStash = true;
|
||||
}
|
||||
|
||||
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBrach.Head, false, 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)
|
||||
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
|
||||
}
|
||||
|
||||
log.Complete();
|
||||
|
||||
CallUIThread(() =>
|
||||
{
|
||||
ProgressDescription = "Waiting for branch updated...";
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
private Repository _repo;
|
||||
}
|
||||
}
|
|
@ -236,11 +236,13 @@ namespace SourceGit.ViewModels
|
|||
var remoteBranch = _repo.Branches.Find(x => x.FriendlyName == d.Name);
|
||||
if (remoteBranch != null)
|
||||
{
|
||||
// If there's a local branch that is tracking on this remote branch and it does not ahead of
|
||||
// its upstream, show `Create and Fast-Forward` popup.
|
||||
var localBranch = _repo.Branches.Find(x => x.IsLocal && x.Upstream == remoteBranch.FullName);
|
||||
if (localBranch != null)
|
||||
if (localBranch is { TrackStatus: { Ahead: { Count: 0 } } })
|
||||
{
|
||||
if (!localBranch.IsCurrent)
|
||||
_repo.CheckoutBranch(localBranch);
|
||||
if (_repo.CanCreatePopup())
|
||||
_repo.ShowPopup(new CheckoutAndFastForward(_repo, localBranch, remoteBranch));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1316,7 +1316,7 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
if (branch.IsLocal)
|
||||
{
|
||||
var worktree = _worktrees.Find(x => x.Branch == branch.FullName);
|
||||
var worktree = _worktrees.Find(x => x.Branch.Equals(branch.FullName, StringComparison.Ordinal));
|
||||
if (worktree != null)
|
||||
{
|
||||
OpenWorktree(worktree);
|
||||
|
@ -1341,9 +1341,13 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
foreach (var b in _branches)
|
||||
{
|
||||
if (b.IsLocal && b.Upstream == branch.FullName)
|
||||
if (b.IsLocal &&
|
||||
b.Upstream.Equals(branch.FullName, StringComparison.Ordinal) &&
|
||||
b.TrackStatus.Ahead.Count == 0)
|
||||
{
|
||||
if (!b.IsCurrent)
|
||||
if (b.TrackStatus.Behind.Count > 0)
|
||||
ShowPopup(new CheckoutAndFastForward(this, b, branch));
|
||||
else if (!b.IsCurrent)
|
||||
CheckoutBranch(b);
|
||||
|
||||
return;
|
||||
|
|
62
src/Views/CheckoutAndFastForward.axaml
Normal file
62
src/Views/CheckoutAndFastForward.axaml
Normal file
|
@ -0,0 +1,62 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CheckoutAndFastForward"
|
||||
x:DataType="vm:CheckoutAndFastForward">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<TextBlock FontSize="18"
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.Checkout.WithFastForward}"/>
|
||||
|
||||
<Grid Margin="0,16,0,0" ColumnDefinitions="140,*">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32"/>
|
||||
<RowDefinition Height="32"/>
|
||||
<RowDefinition Height="Auto" MinHeight="32"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Checkout.Target}"/>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
|
||||
<Path Width="14" Height="14" Margin="4,0" Data="{StaticResource Icons.Branch}"/>
|
||||
<TextBlock Text="{Binding LocalBranch.Name}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Checkout.WithFastForward.Upstream}"/>
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
|
||||
<Path Width="14" Height="14" Margin="4,0" Data="{StaticResource Icons.Branch}"/>
|
||||
<TextBlock Text="{Binding RemoteBrach.FriendlyName}"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"
|
||||
Text="{DynamicResource Text.Checkout.LocalChanges}"/>
|
||||
<WrapPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<RadioButton GroupName="LocalChanges"
|
||||
Margin="0,0,8,0"
|
||||
Content="{DynamicResource Text.Checkout.LocalChanges.StashAndReply}"
|
||||
IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/>
|
||||
<RadioButton GroupName="LocalChanges"
|
||||
Content="{DynamicResource Text.Checkout.LocalChanges.Discard}"/>
|
||||
</WrapPanel>
|
||||
|
||||
<CheckBox Grid.Row="3" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
|
||||
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
|
||||
IsVisible="{Binding IsRecurseSubmoduleVisible}"
|
||||
ToolTip.Tip="--recurse-submodules"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
12
src/Views/CheckoutAndFastForward.axaml.cs
Normal file
12
src/Views/CheckoutAndFastForward.axaml.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CheckoutAndFastForward : UserControl
|
||||
{
|
||||
public CheckoutAndFastForward()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue