feature: unlock all locks (Git LFS) (#1890)

* Add "Unlock all my locks" functionality to LFS Locks

* Add confirmation dialog for "Unlock all my locks" in LFS Locks

* Remove trailing whitespaces across LFS-related files
This commit is contained in:
Mat
2025-11-03 03:28:38 +01:00
committed by GitHub
parent 8aafc47811
commit 691686cbd6
6 changed files with 111 additions and 12 deletions

View File

@@ -93,5 +93,23 @@ namespace SourceGit.Commands
Args = builder.ToString();
return await ExecAsync().ConfigureAwait(false);
}
public async Task<bool> UnlockAsync(string remote, List<string> files, bool force)
{
var builder = new StringBuilder();
builder
.Append("lfs unlock --remote=")
.Append(remote)
.Append(force ? " -f " : " ");
foreach (string file in files)
{
builder.Append(file.Quoted());
builder.Append(" ");
}
Args = builder.ToString();
return await ExecAsync().ConfigureAwait(false);
}
}
}

View File

@@ -441,6 +441,8 @@
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No Locked Files</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Lock</x:String>
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Show only my locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAll.Confirm" xml:space="preserve">Are you sure you want to unlock all your locked files?</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks" xml:space="preserve">Unlock all of my locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Unlock</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Force Unlock</x:String>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using SourceGit.Models;
namespace SourceGit.ViewModels
{
@@ -72,6 +73,32 @@ namespace SourceGit.ViewModels
IsLoading = false;
}
public async Task UnlockAllMyLocksAsync(bool force = false)
{
if (_isLoading)
return;
IsLoading = true;
List<string> myLocks = [];
foreach (LFSLock lfsLock in _cachedLocks)
{
if (lfsLock.Owner.Name.Equals(_userName, StringComparison.Ordinal))
{
myLocks.Add(lfsLock.Path);
}
}
bool succ = await _repo.UnlockLFSFilesAsync(_remote, myLocks, force, false);
if (succ)
{
_cachedLocks.RemoveAll(lfsLock => lfsLock.Owner.Name.Equals(_userName, StringComparison.Ordinal));
UpdateVisibleLocks();
}
IsLoading = false;
}
private void UpdateVisibleLocks()
{
var visible = new List<Models.LFSLock>();

View File

@@ -738,6 +738,20 @@ namespace SourceGit.ViewModels
return succ;
}
public async Task<bool> UnlockLFSFilesAsync(string remote, List<string> paths, bool force, bool notify)
{
CommandLog log = CreateLog("Unlock LFS File");
bool succ = await new Commands.LFS(FullPath)
.Use(log)
.UnlockAsync(remote, paths, force);
if (succ && notify)
App.SendNotification(FullPath, $"Unlocked {paths.Count} files successfully!");
log.Complete();
return succ;
}
public CommandLog CreateLog(string name)
{
var log = new CommandLog(name);

View File

@@ -38,18 +38,34 @@
</Grid>
<!-- Filter and Unlock All -->
<CheckBox Grid.Row="1"
Margin="8,0,0,0"
Content="{DynamicResource Text.GitLFS.Locks.OnlyMine}"
IsChecked="{Binding ShowOnlyMyLocks, Mode=TwoWay}"
VerticalAlignment="Center">
<CheckBox.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName"/>
<Binding Path="!IsLoading"/>
</MultiBinding>
</CheckBox.IsEnabled>
</CheckBox>
<StackPanel Grid.Row="1"
HorizontalAlignment="Left"
Orientation="Horizontal">
<CheckBox Margin="8,0,4,0"
Content="{DynamicResource Text.GitLFS.Locks.OnlyMine}"
IsChecked="{Binding ShowOnlyMyLocks, Mode=TwoWay}"
VerticalAlignment="Center">
<CheckBox.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</CheckBox.IsEnabled>
</CheckBox>
<Button Margin="4,0,4,0"
Content="{DynamicResource Text.GitLFS.Locks.UnlockAllMyLocks}"
Click="OnUnlockAllMyLocksButtonClicked">
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</Button.IsEnabled>
</Button>
</StackPanel>
<!-- Locked Files -->
<Grid Grid.Row="2">

View File

@@ -26,5 +26,27 @@ namespace SourceGit.Views
e.Handled = true;
}
private async void OnUnlockAllMyLocksButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.LFSLocks vm)
{
Confirm dialog = new()
{
Message =
{
Text = App.Text("GitLFS.Locks.UnlockAll.Confirm")
}
};
bool result = await dialog.ShowDialog<bool>(this);
if (result)
{
await vm.UnlockAllMyLocksAsync(true);
}
}
e.Handled = true;
}
}
}