diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs index 8c0fd5051..f88fd51e2 100644 --- a/src/Commands/LFS.cs +++ b/src/Commands/LFS.cs @@ -93,5 +93,23 @@ public async Task UnlockAsync(string remote, string file, bool force) Args = builder.ToString(); return await ExecAsync().ConfigureAwait(false); } + + public async Task UnlockAsync(string remote, List 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); + } } } diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index e204baac0..2a7ae2c0d 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -441,6 +441,8 @@ No Locked Files Lock Show only my locks + Are you sure you want to unlock all your locked files? + Unlock all of my locks LFS Locks Unlock Force Unlock diff --git a/src/ViewModels/LFSLocks.cs b/src/ViewModels/LFSLocks.cs index 9e937086c..b2a415183 100644 --- a/src/ViewModels/LFSLocks.cs +++ b/src/ViewModels/LFSLocks.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; +using SourceGit.Models; namespace SourceGit.ViewModels { @@ -72,6 +73,32 @@ public async Task UnlockAsync(Models.LFSLock lfsLock, bool force) IsLoading = false; } + public async Task UnlockAllMyLocksAsync(bool force = false) + { + if (_isLoading) + return; + + IsLoading = true; + + List 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(); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 5ca5ca82b..1bc369df8 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -738,6 +738,20 @@ public async Task UnlockLFSFileAsync(string remote, string path, bool forc return succ; } + public async Task UnlockLFSFilesAsync(string remote, List 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); diff --git a/src/Views/LFSLocks.axaml b/src/Views/LFSLocks.axaml index e05572f76..c41f9845e 100644 --- a/src/Views/LFSLocks.axaml +++ b/src/Views/LFSLocks.axaml @@ -38,18 +38,34 @@ - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/Views/LFSLocks.axaml.cs b/src/Views/LFSLocks.axaml.cs index fe77a3361..522dcc8d1 100644 --- a/src/Views/LFSLocks.axaml.cs +++ b/src/Views/LFSLocks.axaml.cs @@ -26,5 +26,27 @@ private async void OnForceUnlockButtonClicked(object sender, RoutedEventArgs e) 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(this); + if (result) + { + await vm.UnlockAllMyLocksAsync(true); + } + } + + e.Handled = true; + } } }