refactor: re-implement git stash apply

* supports `--index` option
* add an option to drop selected stash after applying
* remove `Pop` context menu for stash

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-02-06 16:33:55 +08:00
parent dbb1df5f8b
commit 7089f29b85
No known key found for this signature in database
9 changed files with 121 additions and 22 deletions

View file

@ -73,27 +73,22 @@ namespace SourceGit.Commands
return Exec(); return Exec();
} }
public bool Apply(string name = null) public bool Apply(string name, bool restoreIndex)
{ {
Args = "stash apply -q"; var opts = restoreIndex ? "--index" : string.Empty;
if (!string.IsNullOrEmpty(name)) Args = $"stash apply -q {opts} \"{name}\"";
Args += $" \"{name}\"";
return Exec(); return Exec();
} }
public bool Pop(string name = null) public bool Pop(string name)
{ {
Args = "stash pop -q"; Args = $"stash pop -q \"{name}\"";
if (!string.IsNullOrEmpty(name))
Args += $" \"{name}\"";
return Exec(); return Exec();
} }
public bool Drop(string name = null) public bool Drop(string name)
{ {
Args = "stash drop -q"; Args = $"stash drop -q \"{name}\"";
if (!string.IsNullOrEmpty(name))
Args += $" \"{name}\"";
return Exec(); return Exec();
} }

View file

@ -34,6 +34,10 @@
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String> <x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Outputs warnings for a few such errors, but applies</x:String> <x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Outputs warnings for a few such errors, but applies</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">Whitespace:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">Apply Stash</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">Delete after applying</x:String>
<x:String x:Key="Text.ApplyStash.RestoreIndex" xml:space="preserve">Reinstate the index's changes</x:String>
<x:String x:Key="Text.ApplyStash.Stash" xml:space="preserve">Stash:</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Archive...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">Archive...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Save Archive To:</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">Save Archive To:</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Select archive file path</x:String> <x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Select archive file path</x:String>

View file

@ -37,6 +37,10 @@
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String> <x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">应用补丁,输出关于空白符的警告</x:String> <x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">应用补丁,输出关于空白符的警告</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">空白符号处理 </x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">空白符号处理 </x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">应用贮藏</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">在成功应用后丢弃该贮藏</x:String>
<x:String x:Key="Text.ApplyStash.RestoreIndex" xml:space="preserve">恢复索引中已暂存的变化</x:String>
<x:String x:Key="Text.ApplyStash.Stash" xml:space="preserve">已选贮藏 </x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">存档(archive) ...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">存档(archive) ...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">存档文件路径:</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">存档文件路径:</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">选择存档文件的存放路径</x:String> <x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">选择存档文件的存放路径</x:String>

View file

@ -37,6 +37,10 @@
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String> <x:String x:Key="Text.Apply.Warn" xml:space="preserve">警告</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">套用修補檔,輸出關於空白字元的警告</x:String> <x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">套用修補檔,輸出關於空白字元的警告</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">空白字元處理:</x:String> <x:String x:Key="Text.Apply.WS" xml:space="preserve">空白字元處理:</x:String>
<x:String x:Key="Text.ApplyStash" xml:space="preserve">套用擱置</x:String>
<x:String x:Key="Text.ApplyStash.DropAfterApply" xml:space="preserve">在成功套用后捨棄擱置</x:String>
<x:String x:Key="Text.ApplyStash.RestoreIndex" xml:space="preserve">恢復索引中已暫存的變更</x:String>
<x:String x:Key="Text.ApplyStash.Stash" xml:space="preserve">已選擇擱置 </x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">封存 (archive)...</x:String> <x:String x:Key="Text.Archive" xml:space="preserve">封存 (archive)...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">封存檔案路徑:</x:String> <x:String x:Key="Text.Archive.File" xml:space="preserve">封存檔案路徑:</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">選擇封存檔案的儲存路徑</x:String> <x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">選擇封存檔案的儲存路徑</x:String>

View file

@ -0,0 +1,48 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class ApplyStash : Popup
{
public Models.Stash Stash
{
get;
private set;
}
public bool RestoreIndex
{
get;
set;
} = true;
public bool DropAfterApply
{
get;
set;
} = false;
public ApplyStash(string repo, Models.Stash stash)
{
_repo = repo;
Stash = stash;
View = new Views.ApplyStash() { DataContext = this };
}
public override Task<bool> Sure()
{
ProgressDescription = $"Applying stash: {Stash.Name}";
return Task.Run(() =>
{
var succ = new Commands.Stash(_repo).Apply(Stash.Name, RestoreIndex);
if (succ && DropAfterApply)
new Commands.Stash(_repo).Drop(Stash.Name);
return true;
});
}
private readonly string _repo;
}
}

View file

@ -91,7 +91,7 @@ namespace SourceGit.ViewModels
} }
if (AutoRestore && succ) if (AutoRestore && succ)
succ = new Commands.Stash(_repo.FullPath).Apply(); succ = new Commands.Stash(_repo.FullPath).Apply("stash@{0}", true);
CallUIThread(() => CallUIThread(() =>
{ {

View file

@ -141,15 +141,9 @@ namespace SourceGit.ViewModels
apply.Header = App.Text("StashCM.Apply"); apply.Header = App.Text("StashCM.Apply");
apply.Click += (_, ev) => apply.Click += (_, ev) =>
{ {
Task.Run(() => new Commands.Stash(_repo.FullPath).Apply(stash.Name)); if (_repo.CanCreatePopup())
ev.Handled = true; _repo.ShowPopup(new ApplyStash(_repo.FullPath, stash));
};
var pop = new MenuItem();
pop.Header = App.Text("StashCM.Pop");
pop.Click += (_, ev) =>
{
Task.Run(() => new Commands.Stash(_repo.FullPath).Pop(stash.Name));
ev.Handled = true; ev.Handled = true;
}; };
@ -165,7 +159,6 @@ namespace SourceGit.ViewModels
var menu = new ContextMenu(); var menu = new ContextMenu();
menu.Items.Add(apply); menu.Items.Add(apply);
menu.Items.Add(pop);
menu.Items.Add(drop); menu.Items.Add(drop);
return menu; return menu;
} }

View file

@ -0,0 +1,38 @@
<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:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ApplyStash"
x:DataType="vm:ApplyStash">
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.ApplyStash}"/>
<Grid Margin="0,16,8,0" RowDefinitions="32,32,32" ColumnDefinitions="100,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.ApplyStash.Stash}"/>
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
<Path Width="12" Height="12" Margin="2,0,8,0"
HorizontalAlignment="Left" VerticalAlignment="Center"
Data="{StaticResource Icons.Stashes}"/>
<TextBlock VerticalAlignment="Center" Classes="primary" Text="{Binding Stash.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
<TextBlock VerticalAlignment="Center" Text="{Binding Stash.Message}" Margin="8,0,0,0"/>
</StackPanel>
<CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.ApplyStash.RestoreIndex}"
IsChecked="{Binding RestoreIndex, Mode=TwoWay}"
ToolTip.Tip="--index"/>
<CheckBox Grid.Row="2" Grid.Column="1"
Content="{DynamicResource Text.ApplyStash.DropAfterApply}"
IsChecked="{Binding DropAfterApply, Mode=TwoWay}"/>
</Grid>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,13 @@
using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class ApplyStash : UserControl
{
public ApplyStash()
{
InitializeComponent();
}
}
}