fix: running git command in UIThread via context menu entry blocks whole app (#1384)
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo 2025-06-03 23:36:15 +08:00
parent d85f82e171
commit c2187edbe9
No known key found for this signature in database
4 changed files with 37 additions and 24 deletions

View file

@ -56,7 +56,7 @@ namespace SourceGit.ViewModels
{
get;
private set;
} = [];
}
public List<string> Children
{
@ -426,12 +426,12 @@ namespace SourceGit.ViewModels
var openWith = new MenuItem();
openWith.Header = App.Text("OpenWith");
openWith.Icon = App.CreateMenuIcon("Icons.OpenWith");
openWith.Click += (_, ev) =>
openWith.Click += async (_, ev) =>
{
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile);
await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, tmpFile));
Native.OS.OpenWithDefaultEditor(tmpFile);
ev.Handled = true;
};
@ -453,9 +453,9 @@ namespace SourceGit.ViewModels
if (selected.Count == 1)
{
var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString();
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path));
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo);
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var saveTo = Path.Combine(folderPath, Path.GetFileName(file.Path)!);
await Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo));
}
}
catch (Exception e)

View file

@ -47,9 +47,9 @@ namespace SourceGit.ViewModels
RefreshViewContent();
}
public void ResetToSelectedRevision()
public Task<bool> ResetToSelectedRevision()
{
new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}");
return Task.Run(() => new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}"));
}
private void RefreshViewContent()
@ -84,7 +84,7 @@ namespace SourceGit.ViewModels
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
var fileSize = stream.Length;
var bitmap = fileSize > 0 ? new Bitmap(stream) : null;
var imageType = Path.GetExtension(_file).TrimStart('.').ToUpper(CultureInfo.CurrentCulture);
var imageType = Path.GetExtension(_file)!.TrimStart('.').ToUpper(CultureInfo.CurrentCulture);
var image = new Models.RevisionImageFile() { Image = bitmap, FileSize = fileSize, ImageType = imageType };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
}
@ -103,7 +103,7 @@ namespace SourceGit.ViewModels
var matchLFS = REG_LFS_FORMAT().Match(content);
if (matchLFS.Success)
{
var lfs = new Models.RevisionLFSObject() { Object = new Models.LFSObject() };
var lfs = new Models.RevisionLFSObject() { Object = new() };
lfs.Object.Oid = matchLFS.Groups[1].Value;
lfs.Object.Size = long.Parse(matchLFS.Groups[2].Value);
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, lfs));
@ -156,15 +156,12 @@ namespace SourceGit.ViewModels
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
private static partial Regex REG_LFS_FORMAT();
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
{
".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"
};
private static readonly HashSet<string> IMG_EXTS = [".ico", ".bmp", ".jpg", ".png", ".jpeg", ".webp"];
private Repository _repo = null;
private string _file = null;
private Models.Commit _revision = null;
private bool _isDiffMode = true;
private bool _isDiffMode = false;
private object _viewContent = null;
}
@ -265,7 +262,6 @@ namespace SourceGit.ViewModels
public FileHistories(Repository repo, string file, string commit = null)
{
_repo = repo;
_file = file;
Task.Run(() =>
{
@ -288,10 +284,10 @@ namespace SourceGit.ViewModels
switch (SelectedCommits.Count)
{
case 1:
ViewContent = new FileHistoriesSingleRevision(_repo, _file, SelectedCommits[0], _prevIsDiffMode);
ViewContent = new FileHistoriesSingleRevision(_repo, file, SelectedCommits[0], _prevIsDiffMode);
break;
case 2:
ViewContent = new FileHistoriesCompareRevisions(_repo, _file, SelectedCommits[0], SelectedCommits[1]);
ViewContent = new FileHistoriesCompareRevisions(_repo, file, SelectedCommits[0], SelectedCommits[1]);
break;
default:
ViewContent = SelectedCommits.Count;
@ -317,11 +313,10 @@ namespace SourceGit.ViewModels
}
private readonly Repository _repo = null;
private readonly string _file = null;
private bool _isLoading = true;
private bool _prevIsDiffMode = true;
private List<Models.Commit> _commits = null;
private Dictionary<string, string> _fullCommitMessages = new Dictionary<string, string>();
private Dictionary<string, string> _fullCommitMessages = new();
private object _viewContent = null;
}
}

View file

@ -234,10 +234,28 @@ namespace SourceGit.ViewModels
var resetToThisRevision = new MenuItem();
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += (_, ev) =>
resetToThisRevision.Click += async (_, ev) =>
{
var log = _repo.CreateLog($"Reset File to '{_selectedStash.SHA}'");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_selectedStash.SHA}");
await Task.Run(() =>
{
if (_untracked.Contains(change))
{
Commands.SaveRevisionFile.Run(_repo.FullPath, _selectedStash.Parents[2], change.Path, fullPath);
}
else if (change.Index == Models.ChangeState.Added)
{
Commands.SaveRevisionFile.Run(_repo.FullPath, _selectedStash.SHA, change.Path, fullPath);
}
else
{
new Commands.Checkout(_repo.FullPath)
.Use(log)
.FileWithRevision(change.Path, $"{_selectedStash.SHA}");
}
});
log.Complete();
ev.Handled = true;
};

View file

@ -25,11 +25,11 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
private async void OnResetToSelectedRevision(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: ViewModels.FileHistoriesSingleRevision single })
{
single.ResetToSelectedRevision();
await single.ResetToSelectedRevision();
NotifyDonePanel.IsVisible = true;
}