diff --git a/src/App.Commands.cs b/src/App.Commands.cs index 22e9fb51..a3a7267a 100644 --- a/src/App.Commands.cs +++ b/src/App.Commands.cs @@ -43,16 +43,16 @@ namespace SourceGit public static readonly Command OpenAboutCommand = new Command(_ => ShowWindow(new Views.About(), false)); public static readonly Command CheckForUpdateCommand = new Command(_ => (Current as App)?.Check4Update(true)); public static readonly Command QuitCommand = new Command(_ => Quit(0)); - public static readonly Command CopyTextBlockCommand = new Command(p => + public static readonly Command CopyTextBlockCommand = new Command(async p => { var textBlock = p as TextBlock; if (textBlock == null) return; if (textBlock.Inlines is { Count: > 0 } inlines) - CopyText(inlines.Text); + await CopyTextAsync(inlines.Text); else if (!string.IsNullOrEmpty(textBlock.Text)) - CopyText(textBlock.Text); + await CopyTextAsync(textBlock.Text); }); } } diff --git a/src/App.axaml.cs b/src/App.axaml.cs index b7555da7..13eadfa4 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -146,6 +146,18 @@ namespace SourceGit } } + public static async Task AskConfirmAsync(string message, Action onSure) + { + if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner }) + { + var confirm = new Views.Confirm(); + confirm.Message.Text = message; + return await confirm.ShowDialog(owner); + } + + return false; + } + public static void RaiseException(string context, string message) { if (Current is App { _launcher: not null } app) @@ -281,7 +293,7 @@ namespace SourceGit } } - public static async void CopyText(string data) + public static async Task CopyTextAsync(string data) { if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow.Clipboard: { } clipboard }) await clipboard.SetTextAsync(data ?? ""); @@ -571,7 +583,7 @@ namespace SourceGit { if (!string.IsNullOrEmpty(repo) && Directory.Exists(repo)) { - var test = new Commands.QueryRepositoryRootPath(repo).ReadToEnd(); + var test = new Commands.QueryRepositoryRootPath(repo).GetResultAsync().Result; if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut)) { Dispatcher.UIThread.Invoke(() => diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs index 7613cd52..aadbb2db 100644 --- a/src/Commands/Blame.cs +++ b/src/Commands/Blame.cs @@ -20,9 +20,9 @@ namespace SourceGit.Commands _result.File = file; } - public async Task ResultAsync() + public async Task ReadAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return _result; diff --git a/src/Commands/Branch.cs b/src/Commands/Branch.cs index e920413f..1927bae5 100644 --- a/src/Commands/Branch.cs +++ b/src/Commands/Branch.cs @@ -5,24 +5,6 @@ namespace SourceGit.Commands { public static class Branch { - public static string ShowCurrent(string repo) - { - var cmd = new Command(); - cmd.WorkingDirectory = repo; - cmd.Context = repo; - cmd.Args = "branch --show-current"; - return cmd.ReadToEnd().StdOut.Trim(); - } - - public static async Task ShowCurrentAsync(string repo) - { - var cmd = new Command(); - cmd.WorkingDirectory = repo; - cmd.Context = repo; - cmd.Args = "branch --show-current"; - return (await cmd.ReadToEndAsync()).StdOut.Trim(); - } - public static async Task CreateAsync(string repo, string name, string basedOn, bool force, Models.ICommandLog log) { var builder = new StringBuilder(); @@ -38,7 +20,7 @@ namespace SourceGit.Commands cmd.Context = repo; cmd.Args = builder.ToString(); cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task RenameAsync(string repo, string name, string to, Models.ICommandLog log) @@ -48,7 +30,7 @@ namespace SourceGit.Commands cmd.Context = repo; cmd.Args = $"branch -M {name} {to}"; cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task SetUpstreamAsync(string repo, string name, string upstream, Models.ICommandLog log) @@ -63,7 +45,7 @@ namespace SourceGit.Commands else cmd.Args = $"branch {name} -u {upstream}"; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task DeleteLocalAsync(string repo, string name, Models.ICommandLog log) @@ -73,21 +55,21 @@ namespace SourceGit.Commands cmd.Context = repo; cmd.Args = $"branch -D {name}"; cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task DeleteRemoteAsync(string repo, string remote, string name, Models.ICommandLog log) { - bool exists = await new Remote(repo).HasBranchAsync(remote, name); + bool exists = await new Remote(repo).HasBranchAsync(remote, name).ConfigureAwait(false); if (exists) - return await new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.ExecAsync(); + return await new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.ExecAsync().ConfigureAwait(false); var cmd = new Command(); cmd.WorkingDirectory = repo; cmd.Context = repo; cmd.Args = $"branch -D -r {remote}/{name}"; cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/Checkout.cs b/src/Commands/Checkout.cs index 87186b74..1aeff870 100644 --- a/src/Commands/Checkout.cs +++ b/src/Commands/Checkout.cs @@ -21,7 +21,7 @@ namespace SourceGit.Commands builder.Append(branch); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task BranchAsync(string branch, string basedOn, bool force, bool allowOverwrite) @@ -36,14 +36,14 @@ namespace SourceGit.Commands builder.Append(basedOn); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task CommitAsync(string commitId, bool force) { var option = force ? "--force" : string.Empty; Args = $"checkout {option} --detach --progress {commitId}"; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task UseTheirsAsync(List files) @@ -57,7 +57,7 @@ namespace SourceGit.Commands builder.Append("\""); } Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task UseMineAsync(List files) @@ -72,13 +72,13 @@ namespace SourceGit.Commands } Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task FileWithRevisionAsync(string file, string revision) { Args = $"checkout --no-overlay {revision} -- \"{file}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 2beefc9f..24ebdbb6 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -10,11 +10,13 @@ namespace SourceGit.Commands { public partial class Command { - public class ReadToEndResult + public class Result { public bool IsSuccess { get; set; } = false; - public string StdOut { get; set; } = ""; - public string StdErr { get; set; } = ""; + public string StdOut { get; set; } = string.Empty; + public string StdErr { get; set; } = string.Empty; + + public static Result Failed(string reason) => new Result() { StdErr = reason }; } public enum EditorType @@ -25,46 +27,16 @@ namespace SourceGit.Commands } public string Context { get; set; } = string.Empty; - public CancellationToken CancellationToken { get; set; } = CancellationToken.None; public string WorkingDirectory { get; set; } = null; - public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode + public EditorType Editor { get; set; } = EditorType.CoreEditor; public string SSHKey { get; set; } = string.Empty; public string Args { get; set; } = string.Empty; + + // Only used in `ExecAsync` mode. + public CancellationToken CancellationToken { get; set; } = CancellationToken.None; public bool RaiseError { get; set; } = true; public Models.ICommandLog Log { get; set; } = null; - public ReadToEndResult ReadToEnd() - { - var start = CreateGitStartInfo(); - var proc = new Process() { StartInfo = start }; - - try - { - proc.Start(); - } - catch (Exception e) - { - return new ReadToEndResult() - { - IsSuccess = false, - StdOut = string.Empty, - StdErr = e.Message, - }; - } - - var rs = new ReadToEndResult() - { - StdOut = proc.StandardOutput.ReadToEnd(), - StdErr = proc.StandardError.ReadToEnd(), - }; - - proc.WaitForExit(); - rs.IsSuccess = proc.ExitCode == 0; - proc.Close(); - - return rs; - } - public async Task ExecAsync() { Log?.AppendLine($"$ git {Args}\n"); @@ -107,7 +79,15 @@ namespace SourceGit.Commands proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); - await proc.WaitForExitAsync(CancellationToken); + + try + { + await proc.WaitForExitAsync(CancellationToken).ConfigureAwait(false); + } + catch (Exception e) + { + HandleOutput(e.Message, errs); + } if (dummy != null) { @@ -136,7 +116,7 @@ namespace SourceGit.Commands return true; } - public async Task ReadToEndAsync() + protected async Task ReadToEndAsync() { var start = CreateGitStartInfo(); var proc = new Process() { StartInfo = start }; @@ -147,24 +127,16 @@ namespace SourceGit.Commands } catch (Exception e) { - return new ReadToEndResult() - { - IsSuccess = false, - StdOut = string.Empty, - StdErr = e.Message, - }; + return Result.Failed(e.Message); } - var rs = new ReadToEndResult() - { - StdOut = await proc.StandardOutput.ReadToEndAsync(CancellationToken), - StdErr = await proc.StandardError.ReadToEndAsync(CancellationToken), - }; + var rs = new Result() { IsSuccess = true }; + rs.StdOut = await proc.StandardOutput.ReadToEndAsync().ConfigureAwait(false); + rs.StdErr = await proc.StandardError.ReadToEndAsync().ConfigureAwait(false); + await proc.WaitForExitAsync().ConfigureAwait(false); - await proc.WaitForExitAsync(CancellationToken); rs.IsSuccess = proc.ExitCode == 0; proc.Close(); - return rs; } diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs index 453afbc8..02c4ba89 100644 --- a/src/Commands/Commit.cs +++ b/src/Commands/Commit.cs @@ -8,7 +8,7 @@ namespace SourceGit.Commands public Commit(string repo, string message, bool signOff, bool amend, bool resetAuthor) { _tmpFile = Path.GetTempFileName(); - File.WriteAllText(_tmpFile, message); + _message = message; WorkingDirectory = repo; Context = repo; @@ -21,20 +21,20 @@ namespace SourceGit.Commands public async Task RunAsync() { - var succ = await ExecAsync(); - try { + await File.WriteAllTextAsync(_tmpFile, _message).ConfigureAwait(false); + var succ = await ExecAsync().ConfigureAwait(false); File.Delete(_tmpFile); + return succ; } catch { - // Ignore + return false; } - - return succ; } - private readonly string _tmpFile; + private readonly string _tmpFile = string.Empty; + private readonly string _message = string.Empty; } } diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs index 5530b919..634d98c9 100644 --- a/src/Commands/CompareRevisions.cs +++ b/src/Commands/CompareRevisions.cs @@ -30,35 +30,22 @@ namespace SourceGit.Commands Args = $"diff --name-status {based} {end} -- \"{path}\""; } - public List Result() + public async Task> ReadAsync() { - var rs = ReadToEnd(); + var changes = new List(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) - return _changes; + return changes; var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) - ParseLine(line); + ParseLine(changes, line); - _changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); - return _changes; + changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); + return changes; } - public async Task> ResultAsync() - { - var rs = await ReadToEndAsync(); - if (!rs.IsSuccess) - return _changes; - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - ParseLine(line); - - _changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); - return _changes; - } - - private void ParseLine(string line) + private void ParseLine(List outs, string line) { var match = REG_FORMAT().Match(line); if (!match.Success) @@ -68,7 +55,7 @@ namespace SourceGit.Commands { var renamed = new Models.Change() { Path = match.Groups[1].Value }; renamed.Set(Models.ChangeState.Renamed); - _changes.Add(renamed); + outs.Add(renamed); } return; @@ -81,23 +68,21 @@ namespace SourceGit.Commands { case 'M': change.Set(Models.ChangeState.Modified); - _changes.Add(change); + outs.Add(change); break; case 'A': change.Set(Models.ChangeState.Added); - _changes.Add(change); + outs.Add(change); break; case 'D': change.Set(Models.ChangeState.Deleted); - _changes.Add(change); + outs.Add(change); break; case 'C': change.Set(Models.ChangeState.Copied); - _changes.Add(change); + outs.Add(change); break; } } - - private readonly List _changes = new List(); } } diff --git a/src/Commands/Config.cs b/src/Commands/Config.cs index 3e0516c5..78057b22 100644 --- a/src/Commands/Config.cs +++ b/src/Commands/Config.cs @@ -18,45 +18,13 @@ namespace SourceGit.Commands Context = repository; _isLocal = true; } - - RaiseError = false; } - public Dictionary ListAll() + public async Task> ReadAllAsync() { Args = "config -l"; - var output = ReadToEnd(); - var rs = new Dictionary(); - if (output.IsSuccess) - { - var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var idx = line.IndexOf('=', StringComparison.Ordinal); - if (idx != -1) - { - var key = line.Substring(0, idx).Trim(); - var val = line.Substring(idx + 1).Trim(); - rs[key] = val; - } - } - } - - return rs; - } - - public string Get(string key) - { - Args = $"config {key}"; - return ReadToEnd().StdOut.Trim(); - } - - public async Task> ListAllAsync() - { - Args = "config -l"; - - var output = await ReadToEndAsync(); + var output = await ReadToEndAsync().ConfigureAwait(false); var rs = new Dictionary(); if (output.IsSuccess) { @@ -79,7 +47,9 @@ namespace SourceGit.Commands public async Task GetAsync(string key) { Args = $"config {key}"; - return (await ReadToEndAsync()).StdOut.Trim(); + + var rs = await ReadToEndAsync().ConfigureAwait(false); + return rs.StdOut.Trim(); } public async Task SetAsync(string key, string value, bool allowEmpty = false) @@ -91,7 +61,7 @@ namespace SourceGit.Commands else Args = $"config {scope} {key} \"{value}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } private bool _isLocal = false; diff --git a/src/Commands/CountLocalChangesWithoutUntracked.cs b/src/Commands/CountLocalChangesWithoutUntracked.cs index b59368bf..769d732e 100644 --- a/src/Commands/CountLocalChangesWithoutUntracked.cs +++ b/src/Commands/CountLocalChangesWithoutUntracked.cs @@ -12,9 +12,9 @@ namespace SourceGit.Commands Args = "--no-optional-locks status -uno --ignore-submodules=all --porcelain"; } - public async Task ResultAsync() + public async Task GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (rs.IsSuccess) { var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs index d56e21bd..0279f56f 100644 --- a/src/Commands/Diff.cs +++ b/src/Commands/Diff.cs @@ -36,9 +36,9 @@ namespace SourceGit.Commands Args = $"diff --no-ext-diff --patch --unified={unified} {opt}"; } - public async Task ResultAsync() + public async Task ReadAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var start = 0; var end = rs.StdOut.IndexOf('\n', start); while (end > 0) diff --git a/src/Commands/Discard.cs b/src/Commands/Discard.cs index 6f5a1eb7..73899d52 100644 --- a/src/Commands/Discard.cs +++ b/src/Commands/Discard.cs @@ -15,7 +15,7 @@ namespace SourceGit.Commands /// public static async Task AllAsync(string repo, bool includeIgnored, Models.ICommandLog log) { - var changes = await new QueryLocalChanges(repo).ResultAsync(); + var changes = await new QueryLocalChanges(repo).GetResultAsync().ConfigureAwait(false); try { foreach (var c in changes) @@ -38,10 +38,10 @@ namespace SourceGit.Commands App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}"); } - await new Reset(repo, "HEAD", "--hard") { Log = log }.ExecAsync(); + await new Reset(repo, "HEAD", "--hard") { Log = log }.ExecAsync().ConfigureAwait(false); if (includeIgnored) - await new Clean(repo) { Log = log }.ExecAsync(); + await new Clean(repo) { Log = log }.ExecAsync().ConfigureAwait(false); } /// @@ -80,8 +80,8 @@ namespace SourceGit.Commands if (restores.Count > 0) { var pathSpecFile = Path.GetTempFileName(); - await File.WriteAllLinesAsync(pathSpecFile, restores); - await new Restore(repo, pathSpecFile, false) { Log = log }.ExecAsync(); + await File.WriteAllLinesAsync(pathSpecFile, restores).ConfigureAwait(false); + await new Restore(repo, pathSpecFile, false) { Log = log }.ExecAsync().ConfigureAwait(false); File.Delete(pathSpecFile); } } diff --git a/src/Commands/Fetch.cs b/src/Commands/Fetch.cs index edf2a6dd..d25cc80c 100644 --- a/src/Commands/Fetch.cs +++ b/src/Commands/Fetch.cs @@ -1,12 +1,15 @@ -namespace SourceGit.Commands +using System.Threading.Tasks; + +namespace SourceGit.Commands { public class Fetch : Command { public Fetch(string repo, string remote, bool noTags, bool force) { + _remoteKey = $"remote.{remote}.sshkey"; + WorkingDirectory = repo; Context = repo; - SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); Args = "fetch --progress --verbose "; if (noTags) @@ -18,14 +21,24 @@ Args += "--force "; Args += remote; + } public Fetch(string repo, Models.Branch local, Models.Branch remote) { + _remoteKey = $"remote.{remote.Remote}.sshkey"; + WorkingDirectory = repo; Context = repo; - SSHKey = new Config(repo).Get($"remote.{remote.Remote}.sshkey"); Args = $"fetch --progress --verbose {remote.Remote} {remote.Name}:{local.Name}"; } + + public async Task RunAsync() + { + SSHKey = await new Config(WorkingDirectory).GetAsync(_remoteKey).ConfigureAwait(false); + return await ExecAsync().ConfigureAwait(false); + } + + private readonly string _remoteKey; } } diff --git a/src/Commands/GenerateCommitMessage.cs b/src/Commands/GenerateCommitMessage.cs index 2292a56a..9b6fc4ff 100644 --- a/src/Commands/GenerateCommitMessage.cs +++ b/src/Commands/GenerateCommitMessage.cs @@ -19,6 +19,11 @@ namespace SourceGit.Commands Context = repo; Args = $"diff --diff-algorithm=minimal {opt}"; } + + public async Task ReadAsync() + { + return await ReadToEndAsync().ConfigureAwait(false); + } } public GenerateCommitMessage(Models.OpenAIService service, string repo, List changes, CancellationToken cancelToken, Action onResponse) @@ -46,7 +51,7 @@ namespace SourceGit.Commands responseBuilder.Append("- "); summaryBuilder.Append("- "); - var rs = await new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEndAsync(); + var rs = await new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadAsync(); if (rs.IsSuccess) { await _service.ChatAsync( diff --git a/src/Commands/GitFlow.cs b/src/Commands/GitFlow.cs index 36a4cd0b..1f492b89 100644 --- a/src/Commands/GitFlow.cs +++ b/src/Commands/GitFlow.cs @@ -8,21 +8,21 @@ namespace SourceGit.Commands public static async Task InitAsync(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log) { var config = new Config(repo); - await config.SetAsync("gitflow.branch.master", master); - await config.SetAsync("gitflow.branch.develop", develop); - await config.SetAsync("gitflow.prefix.feature", feature); - await config.SetAsync("gitflow.prefix.bugfix", "bugfix/"); - await config.SetAsync("gitflow.prefix.release", release); - await config.SetAsync("gitflow.prefix.hotfix", hotfix); - await config.SetAsync("gitflow.prefix.support", "support/"); - await config.SetAsync("gitflow.prefix.versiontag", version, true); + await config.SetAsync("gitflow.branch.master", master).ConfigureAwait(false); + await config.SetAsync("gitflow.branch.develop", develop).ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.feature", feature).ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.bugfix", "bugfix/").ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.release", release).ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.hotfix", hotfix).ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.support", "support/").ConfigureAwait(false); + await config.SetAsync("gitflow.prefix.versiontag", version, true).ConfigureAwait(false); var init = new Command(); init.WorkingDirectory = repo; init.Context = repo; init.Args = "flow init -d"; init.Log = log; - return await init.ExecAsync(); + return await init.ExecAsync().ConfigureAwait(false); } public static async Task StartAsync(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log) @@ -48,7 +48,7 @@ namespace SourceGit.Commands } start.Log = log; - return await start.ExecAsync(); + return await start.ExecAsync().ConfigureAwait(false); } public static async Task FinishAsync(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log) @@ -86,7 +86,7 @@ namespace SourceGit.Commands finish.Context = repo; finish.Args = builder.ToString(); finish.Log = log; - return await finish.ExecAsync(); + return await finish.ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/IsBareRepository.cs b/src/Commands/IsBareRepository.cs index 2b67a5e3..98b127ce 100644 --- a/src/Commands/IsBareRepository.cs +++ b/src/Commands/IsBareRepository.cs @@ -11,25 +11,14 @@ namespace SourceGit.Commands Args = "rev-parse --is-bare-repository"; } - public bool Result() + public async Task GetResultAsync() { if (!Directory.Exists(Path.Combine(WorkingDirectory, "refs")) || !Directory.Exists(Path.Combine(WorkingDirectory, "objects")) || !File.Exists(Path.Combine(WorkingDirectory, "HEAD"))) return false; - var rs = ReadToEnd(); - return rs.IsSuccess && rs.StdOut.Trim() == "true"; - } - - public async Task ResultAsync() - { - if (!Directory.Exists(Path.Combine(WorkingDirectory, "refs")) || - !Directory.Exists(Path.Combine(WorkingDirectory, "objects")) || - !File.Exists(Path.Combine(WorkingDirectory, "HEAD"))) - return false; - - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); return rs.IsSuccess && rs.StdOut.Trim() == "true"; } } diff --git a/src/Commands/IsBinary.cs b/src/Commands/IsBinary.cs index f540a71a..5c3e5673 100644 --- a/src/Commands/IsBinary.cs +++ b/src/Commands/IsBinary.cs @@ -16,9 +16,10 @@ namespace SourceGit.Commands RaiseError = false; } - public async Task ResultAsync() + public async Task GetResultAsync() { - return REG_TEST().IsMatch((await ReadToEndAsync()).StdOut); + var rs = await ReadToEndAsync().ConfigureAwait(false); + return REG_TEST().IsMatch(rs.StdOut.Trim()); } } } diff --git a/src/Commands/IsCommitSHA.cs b/src/Commands/IsCommitSHA.cs index 5ebba6cb..dcf9b1a9 100644 --- a/src/Commands/IsCommitSHA.cs +++ b/src/Commands/IsCommitSHA.cs @@ -10,9 +10,9 @@ namespace SourceGit.Commands Args = $"cat-file -t {hash}"; } - public async Task ResultAsync() + public async Task GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); return rs.IsSuccess && rs.StdOut.Trim().Equals("commit"); } } diff --git a/src/Commands/IsConflictResolved.cs b/src/Commands/IsConflictResolved.cs index f986c325..2d53766a 100644 --- a/src/Commands/IsConflictResolved.cs +++ b/src/Commands/IsConflictResolved.cs @@ -13,14 +13,10 @@ namespace SourceGit.Commands Args = $"diff -a --ignore-cr-at-eol --check {opt}"; } - public bool Result() + public async Task GetResultAsync() { - return ReadToEnd().IsSuccess; - } - - public async Task ResultAsync() - { - return (await ReadToEndAsync()).IsSuccess; + var rs = await ReadToEndAsync().ConfigureAwait(false); + return rs.IsSuccess; } } } diff --git a/src/Commands/IsLFSFiltered.cs b/src/Commands/IsLFSFiltered.cs index 171f6e9b..ee716761 100644 --- a/src/Commands/IsLFSFiltered.cs +++ b/src/Commands/IsLFSFiltered.cs @@ -20,15 +20,9 @@ namespace SourceGit.Commands RaiseError = false; } - public bool Result() + public async Task GetResultAsync() { - var rs = ReadToEnd(); - return rs.IsSuccess && rs.StdOut.Contains("filter\0lfs"); - } - - public async Task ResultAsync() - { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); return rs.IsSuccess && rs.StdOut.Contains("filter\0lfs"); } } diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs index b168a1e4..30f06e5f 100644 --- a/src/Commands/LFS.cs +++ b/src/Commands/LFS.cs @@ -20,6 +20,11 @@ namespace SourceGit.Commands Args = args; Log = log; } + + public async Task ReadAsync() + { + return await ReadToEndAsync().ConfigureAwait(false); + } } public LFS(string repo) @@ -39,40 +44,40 @@ namespace SourceGit.Commands public async Task InstallAsync(Models.ICommandLog log) { - return await new SubCmd(_repo, "lfs install --local", log).ExecAsync(); + return await new SubCmd(_repo, "lfs install --local", log).ExecAsync().ConfigureAwait(false); } public async Task TrackAsync(string pattern, bool isFilenameMode, Models.ICommandLog log) { var opt = isFilenameMode ? "--filename" : ""; - return await new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).ExecAsync(); + return await new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).ExecAsync().ConfigureAwait(false); } public async Task FetchAsync(string remote, Models.ICommandLog log) { - await new SubCmd(_repo, $"lfs fetch {remote}", log).ExecAsync(); + await new SubCmd(_repo, $"lfs fetch {remote}", log).ExecAsync().ConfigureAwait(false); } public async Task PullAsync(string remote, Models.ICommandLog log) { - await new SubCmd(_repo, $"lfs pull {remote}", log).ExecAsync(); + await new SubCmd(_repo, $"lfs pull {remote}", log).ExecAsync().ConfigureAwait(false); } public async Task PushAsync(string remote, Models.ICommandLog log) { - await new SubCmd(_repo, $"lfs push {remote}", log).ExecAsync(); + await new SubCmd(_repo, $"lfs push {remote}", log).ExecAsync().ConfigureAwait(false); } public async Task PruneAsync(Models.ICommandLog log) { - await new SubCmd(_repo, "lfs prune", log).ExecAsync(); + await new SubCmd(_repo, "lfs prune", log).ExecAsync().ConfigureAwait(false); } - public async Task> LocksAsync(string remote) + public async Task> GetLocksAsync(string remote) { var locks = new List(); var cmd = new SubCmd(_repo, $"lfs locks --remote={remote}", null); - var rs = await cmd.ReadToEndAsync(); + var rs = await cmd.ReadAsync().ConfigureAwait(false); if (rs.IsSuccess) { var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); @@ -96,19 +101,19 @@ namespace SourceGit.Commands public async Task LockAsync(string remote, string file, Models.ICommandLog log) { - return await new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).ExecAsync(); + return await new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).ExecAsync().ConfigureAwait(false); } public async Task UnlockAsync(string remote, string file, bool force, Models.ICommandLog log) { var opt = force ? "-f" : ""; - return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).ExecAsync(); + return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).ExecAsync().ConfigureAwait(false); } public async Task UnlockAsync(string remote, long id, bool force, Models.ICommandLog log) { var opt = force ? "-f" : ""; - return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).ExecAsync(); + return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).ExecAsync().ConfigureAwait(false); } private readonly string _repo; diff --git a/src/Commands/MergeTool.cs b/src/Commands/MergeTool.cs index 80617885..7cf0a22c 100644 --- a/src/Commands/MergeTool.cs +++ b/src/Commands/MergeTool.cs @@ -18,7 +18,7 @@ namespace SourceGit.Commands if (toolType == 0) { cmd.Args = $"mergetool {fileArg}"; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } if (!File.Exists(toolPath)) @@ -35,7 +35,7 @@ namespace SourceGit.Commands } cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit {fileArg}"; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task OpenForDiffAsync(string repo, int toolType, string toolPath, Models.DiffOption option) @@ -65,7 +65,7 @@ namespace SourceGit.Commands } cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}"; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/Pull.cs b/src/Commands/Pull.cs index 698fbfce..93896c75 100644 --- a/src/Commands/Pull.cs +++ b/src/Commands/Pull.cs @@ -1,12 +1,15 @@ -namespace SourceGit.Commands +using System.Threading.Tasks; + +namespace SourceGit.Commands { public class Pull : Command { public Pull(string repo, string remote, string branch, bool useRebase) { + _remote = remote; + WorkingDirectory = repo; Context = repo; - SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); Args = "pull --verbose --progress "; if (useRebase) @@ -14,5 +17,13 @@ Args += $"{remote} {branch}"; } + + public async Task RunAsync() + { + SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{_remote}.sshkey").ConfigureAwait(false); + return await ExecAsync().ConfigureAwait(false); + } + + private readonly string _remote; } } diff --git a/src/Commands/Push.cs b/src/Commands/Push.cs index 8a5fe33c..b822af46 100644 --- a/src/Commands/Push.cs +++ b/src/Commands/Push.cs @@ -1,12 +1,15 @@ -namespace SourceGit.Commands +using System.Threading.Tasks; + +namespace SourceGit.Commands { public class Push : Command { public Push(string repo, string local, string remote, string remoteBranch, bool withTags, bool checkSubmodules, bool track, bool force) { + _remote = remote; + WorkingDirectory = repo; Context = repo; - SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); Args = "push --progress --verbose "; if (withTags) @@ -23,9 +26,10 @@ public Push(string repo, string remote, string refname, bool isDelete) { + _remote = remote; + WorkingDirectory = repo; Context = repo; - SSHKey = new Config(repo).Get($"remote.{remote}.sshkey"); Args = "push "; if (isDelete) @@ -33,5 +37,13 @@ Args += $"{remote} {refname}"; } + + public async Task RunAsync() + { + SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{_remote}.sshkey").ConfigureAwait(false); + return await ExecAsync().ConfigureAwait(false); + } + + private readonly string _remote; } } diff --git a/src/Commands/QueryAssumeUnchangedFiles.cs b/src/Commands/QueryAssumeUnchangedFiles.cs index 0d13e51a..0fa0f8d0 100644 --- a/src/Commands/QueryAssumeUnchangedFiles.cs +++ b/src/Commands/QueryAssumeUnchangedFiles.cs @@ -17,10 +17,10 @@ namespace SourceGit.Commands RaiseError = false; } - public async Task> ResultAsync() + public async Task> GetResultAsync() { var outs = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs index 653d1cc8..e8a8372b 100644 --- a/src/Commands/QueryBranches.cs +++ b/src/Commands/QueryBranches.cs @@ -18,54 +18,10 @@ namespace SourceGit.Commands Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\""; } - public List Result(out int localBranchesCount) - { - localBranchesCount = 0; - - var branches = new List(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return branches; - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - var remoteHeads = new Dictionary(); - foreach (var line in lines) - { - var b = ParseLine(line); - if (b != null) - { - branches.Add(b); - if (!b.IsLocal) - remoteHeads.Add(b.FullName, b.Head); - else - localBranchesCount++; - } - } - - foreach (var b in branches) - { - if (b.IsLocal && !string.IsNullOrEmpty(b.Upstream)) - { - if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead)) - { - b.IsUpstreamGone = false; - b.TrackStatus ??= new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result(); - } - else - { - b.IsUpstreamGone = true; - b.TrackStatus ??= new Models.BranchTrackStatus(); - } - } - } - - return branches; - } - - public async Task> ResultAsync() + public async Task> GetResultAsync() { var branches = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return branches; @@ -89,7 +45,7 @@ namespace SourceGit.Commands if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead)) { b.IsUpstreamGone = false; - b.TrackStatus ??= await new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).ResultAsync(); + b.TrackStatus ??= await new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).GetResultAsync().ConfigureAwait(false); } else { diff --git a/src/Commands/QueryCommitChildren.cs b/src/Commands/QueryCommitChildren.cs index f4b04996..6af0abb7 100644 --- a/src/Commands/QueryCommitChildren.cs +++ b/src/Commands/QueryCommitChildren.cs @@ -14,9 +14,9 @@ namespace SourceGit.Commands Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path ^{commit}"; } - public async Task> ResultAsync() + public async Task> GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var outs = new List(); if (rs.IsSuccess) { diff --git a/src/Commands/QueryCommitFullMessage.cs b/src/Commands/QueryCommitFullMessage.cs index f0788c1f..07b77f2e 100644 --- a/src/Commands/QueryCommitFullMessage.cs +++ b/src/Commands/QueryCommitFullMessage.cs @@ -11,20 +11,10 @@ namespace SourceGit.Commands Args = $"show --no-show-signature --format=%B -s {sha}"; } - public string Result() + public async Task GetResultAsync() { - var rs = ReadToEnd(); - if (rs.IsSuccess) - return rs.StdOut.TrimEnd(); - return string.Empty; - } - - public async Task ResultAsync() - { - var rs = await ReadToEndAsync(); - if (rs.IsSuccess) - return rs.StdOut.TrimEnd(); - return string.Empty; + var rs = await ReadToEndAsync().ConfigureAwait(false); + return rs.IsSuccess ? rs.StdOut.TrimEnd() : string.Empty; } } } diff --git a/src/Commands/QueryCommitSignInfo.cs b/src/Commands/QueryCommitSignInfo.cs index 312e9e1d..179e4cdd 100644 --- a/src/Commands/QueryCommitSignInfo.cs +++ b/src/Commands/QueryCommitSignInfo.cs @@ -14,9 +14,9 @@ namespace SourceGit.Commands Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}"; } - public async Task ResultAsync() + public async Task GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return null; diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index b72c88af..5e7ef4e6 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -57,9 +57,9 @@ namespace SourceGit.Commands _findFirstMerged = false; } - public List Result() + public async Task> GetResultAsync() { - var rs = ReadToEnd(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return _commits; @@ -111,7 +111,7 @@ namespace SourceGit.Commands _current.Subject = rs.StdOut.Substring(start); if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0) - MarkFirstMerged(); + await MarkFirstMergedAsync().ConfigureAwait(false); return _commits; } @@ -124,90 +124,11 @@ namespace SourceGit.Commands _current.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries)); } - private void MarkFirstMerged() - { - Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\""; - - var rs = ReadToEnd(); - var shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - if (shas.Length == 0) - return; - - var set = new HashSet(shas); - foreach (var c in _commits) - { - if (set.Contains(c.SHA)) - { - c.IsMerged = true; - break; - } - } - } - - public async Task> ResultAsync() - { - var rs = await ReadToEndAsync(); - if (!rs.IsSuccess) - return _commits; - - var nextPartIdx = 0; - var start = 0; - var end = rs.StdOut.IndexOf('\n', start); - while (end > 0) - { - var line = rs.StdOut.Substring(start, end - start); - switch (nextPartIdx) - { - case 0: - _current = new Models.Commit() { SHA = line }; - _commits.Add(_current); - break; - case 1: - ParseParent(line); - break; - case 2: - _current.ParseDecorators(line); - if (_current.IsMerged && !_isHeadFounded) - _isHeadFounded = true; - break; - case 3: - _current.Author = Models.User.FindOrAdd(line); - break; - case 4: - _current.AuthorTime = ulong.Parse(line); - break; - case 5: - _current.Committer = Models.User.FindOrAdd(line); - break; - case 6: - _current.CommitterTime = ulong.Parse(line); - break; - case 7: - _current.Subject = line; - nextPartIdx = -1; - break; - } - - nextPartIdx++; - - start = end + 1; - end = rs.StdOut.IndexOf('\n', start); - } - - if (start < rs.StdOut.Length) - _current.Subject = rs.StdOut.Substring(start); - - if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0) - await MarkFirstMergedAsync(); - - return _commits; - } - private async Task MarkFirstMergedAsync() { Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\""; - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); if (shas.Length == 0) return; diff --git a/src/Commands/QueryCommitsForInteractiveRebase.cs b/src/Commands/QueryCommitsForInteractiveRebase.cs index 273a6bcf..0093d136 100644 --- a/src/Commands/QueryCommitsForInteractiveRebase.cs +++ b/src/Commands/QueryCommitsForInteractiveRebase.cs @@ -15,9 +15,9 @@ namespace SourceGit.Commands Args = $"log --date-order --no-show-signature --decorate=full --format=\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD"; } - public async Task> ResultAsync() + public async Task> GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return _commits; diff --git a/src/Commands/QueryCurrentBranch.cs b/src/Commands/QueryCurrentBranch.cs new file mode 100644 index 00000000..c721d13b --- /dev/null +++ b/src/Commands/QueryCurrentBranch.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; + +namespace SourceGit.Commands +{ + public class QueryCurrentBranch : Command + { + public QueryCurrentBranch(string repo) + { + WorkingDirectory = repo; + Context = repo; + Args = "branch --show-current"; + } + + public async Task GetResultAsync() + { + var rs = await ReadToEndAsync().ConfigureAwait(false); + return rs.StdOut.Trim(); + } + } +} diff --git a/src/Commands/QueryFileContent.cs b/src/Commands/QueryFileContent.cs index 78fe2060..38ee6e4a 100644 --- a/src/Commands/QueryFileContent.cs +++ b/src/Commands/QueryFileContent.cs @@ -7,70 +7,6 @@ namespace SourceGit.Commands { public static class QueryFileContent { - public static Stream Run(string repo, string revision, string file) - { - var starter = new ProcessStartInfo(); - starter.WorkingDirectory = repo; - starter.FileName = Native.OS.GitExecutable; - starter.Arguments = $"show {revision}:\"{file}\""; - starter.UseShellExecute = false; - starter.CreateNoWindow = true; - starter.WindowStyle = ProcessWindowStyle.Hidden; - starter.RedirectStandardOutput = true; - - var stream = new MemoryStream(); - try - { - var proc = new Process() { StartInfo = starter }; - proc.Start(); - proc.StandardOutput.BaseStream.CopyTo(stream); - proc.WaitForExit(); - proc.Close(); - - stream.Position = 0; - } - catch (Exception e) - { - App.RaiseException(repo, $"Failed to query file content: {e}"); - } - - return stream; - } - - public static Stream FromLFS(string repo, string oid, long size) - { - var starter = new ProcessStartInfo(); - starter.WorkingDirectory = repo; - starter.FileName = Native.OS.GitExecutable; - starter.Arguments = "lfs smudge"; - starter.UseShellExecute = false; - starter.CreateNoWindow = true; - starter.WindowStyle = ProcessWindowStyle.Hidden; - starter.RedirectStandardInput = true; - starter.RedirectStandardOutput = true; - - var stream = new MemoryStream(); - try - { - var proc = new Process() { StartInfo = starter }; - proc.Start(); - proc.StandardInput.WriteLine("version https://git-lfs.github.com/spec/v1"); - proc.StandardInput.WriteLine($"oid sha256:{oid}"); - proc.StandardInput.WriteLine($"size {size}"); - proc.StandardOutput.BaseStream.CopyTo(stream); - proc.WaitForExit(); - proc.Close(); - - stream.Position = 0; - } - catch (Exception e) - { - App.RaiseException(repo, $"Failed to query file content: {e}"); - } - - return stream; - } - public static async Task RunAsync(string repo, string revision, string file) { var starter = new ProcessStartInfo(); @@ -87,8 +23,8 @@ namespace SourceGit.Commands { var proc = new Process() { StartInfo = starter }; proc.Start(); - await proc.StandardOutput.BaseStream.CopyToAsync(stream); - await proc.WaitForExitAsync(); + await proc.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false); + await proc.WaitForExitAsync().ConfigureAwait(false); proc.Close(); stream.Position = 0; @@ -118,11 +54,11 @@ namespace SourceGit.Commands { var proc = new Process() { StartInfo = starter }; proc.Start(); - await proc.StandardInput.WriteLineAsync("version https://git-lfs.github.com/spec/v1"); - await proc.StandardInput.WriteLineAsync($"oid sha256:{oid}"); - await proc.StandardInput.WriteLineAsync($"size {size}"); - await proc.StandardOutput.BaseStream.CopyToAsync(stream); - await proc.WaitForExitAsync(); + await proc.StandardInput.WriteLineAsync("version https://git-lfs.github.com/spec/v1").ConfigureAwait(false); + await proc.StandardInput.WriteLineAsync($"oid sha256:{oid}").ConfigureAwait(false); + await proc.StandardInput.WriteLineAsync($"size {size}").ConfigureAwait(false); + await proc.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false); + await proc.WaitForExitAsync().ConfigureAwait(false); proc.Close(); stream.Position = 0; diff --git a/src/Commands/QueryFileSize.cs b/src/Commands/QueryFileSize.cs index b30b0a24..1371df8b 100644 --- a/src/Commands/QueryFileSize.cs +++ b/src/Commands/QueryFileSize.cs @@ -15,9 +15,9 @@ namespace SourceGit.Commands Args = $"ls-tree {revision} -l -- \"{file}\""; } - public async Task ResultAsync() + public async Task GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (rs.IsSuccess) { var match = REG_FORMAT().Match(rs.StdOut); diff --git a/src/Commands/QueryGitCommonDir.cs b/src/Commands/QueryGitCommonDir.cs index 875a88df..c5b9339d 100644 --- a/src/Commands/QueryGitCommonDir.cs +++ b/src/Commands/QueryGitCommonDir.cs @@ -9,31 +9,19 @@ namespace SourceGit.Commands { WorkingDirectory = workDir; Args = "rev-parse --git-common-dir"; - RaiseError = false; } - public string Result() + public async Task GetResultAsync() { - var rs = ReadToEnd().StdOut; - if (string.IsNullOrEmpty(rs)) + var rs = await ReadToEndAsync().ConfigureAwait(false); + if (!rs.IsSuccess) return null; - rs = rs.Trim(); - if (Path.IsPathRooted(rs)) - return rs; - return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); - } - - public async Task ResultAsync() - { - var rs = (await ReadToEndAsync()).StdOut; - if (string.IsNullOrEmpty(rs)) + var stdout = rs.StdOut.Trim(); + if (string.IsNullOrEmpty(stdout)) return null; - rs = rs.Trim(); - if (Path.IsPathRooted(rs)) - return rs; - return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); + return Path.IsPathRooted(stdout) ? stdout : Path.GetFullPath(Path.Combine(WorkingDirectory, stdout)); } } } diff --git a/src/Commands/QueryGitDir.cs b/src/Commands/QueryGitDir.cs index 3c2831d1..ce8bfee6 100644 --- a/src/Commands/QueryGitDir.cs +++ b/src/Commands/QueryGitDir.cs @@ -9,31 +9,19 @@ namespace SourceGit.Commands { WorkingDirectory = workDir; Args = "rev-parse --git-dir"; - RaiseError = false; } - public string Result() + public async Task GetResultAsync() { - var rs = ReadToEnd().StdOut; - if (string.IsNullOrEmpty(rs)) + var rs = await ReadToEndAsync().ConfigureAwait(false); + if (!rs.IsSuccess) return null; - rs = rs.Trim(); - if (Path.IsPathRooted(rs)) - return rs; - return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); - } - - public async Task ResultAsync() - { - var rs = (await ReadToEndAsync()).StdOut; - if (string.IsNullOrEmpty(rs)) + var stdout = rs.StdOut.Trim(); + if (string.IsNullOrEmpty(stdout)) return null; - rs = rs.Trim(); - if (Path.IsPathRooted(rs)) - return rs; - return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); + return Path.IsPathRooted(stdout) ? stdout : Path.GetFullPath(Path.Combine(WorkingDirectory, stdout)); } } } diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs index e27162a3..9605014d 100644 --- a/src/Commands/QueryLocalChanges.cs +++ b/src/Commands/QueryLocalChanges.cs @@ -18,153 +18,10 @@ namespace SourceGit.Commands Args = $"--no-optional-locks status -u{UNTRACKED[includeUntracked ? 1 : 0]} --ignore-submodules=dirty --porcelain"; } - public List Result() + public async Task> GetResultAsync() { var outs = new List(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - { - App.RaiseException(Context, rs.StdErr); - return outs; - } - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var match = REG_FORMAT().Match(line); - if (!match.Success) - continue; - - var change = new Models.Change() { Path = match.Groups[2].Value }; - var status = match.Groups[1].Value; - - switch (status) - { - case " M": - change.Set(Models.ChangeState.None, Models.ChangeState.Modified); - break; - case " T": - change.Set(Models.ChangeState.None, Models.ChangeState.TypeChanged); - break; - case " A": - change.Set(Models.ChangeState.None, Models.ChangeState.Added); - break; - case " D": - change.Set(Models.ChangeState.None, Models.ChangeState.Deleted); - break; - case " R": - change.Set(Models.ChangeState.None, Models.ChangeState.Renamed); - break; - case " C": - change.Set(Models.ChangeState.None, Models.ChangeState.Copied); - break; - case "M": - change.Set(Models.ChangeState.Modified); - break; - case "MM": - change.Set(Models.ChangeState.Modified, Models.ChangeState.Modified); - break; - case "MT": - change.Set(Models.ChangeState.Modified, Models.ChangeState.TypeChanged); - break; - case "MD": - change.Set(Models.ChangeState.Modified, Models.ChangeState.Deleted); - break; - case "T": - change.Set(Models.ChangeState.TypeChanged); - break; - case "TM": - change.Set(Models.ChangeState.TypeChanged, Models.ChangeState.Modified); - break; - case "TT": - change.Set(Models.ChangeState.TypeChanged, Models.ChangeState.TypeChanged); - break; - case "TD": - change.Set(Models.ChangeState.TypeChanged, Models.ChangeState.Deleted); - break; - case "A": - change.Set(Models.ChangeState.Added); - break; - case "AM": - change.Set(Models.ChangeState.Added, Models.ChangeState.Modified); - break; - case "AT": - change.Set(Models.ChangeState.Added, Models.ChangeState.TypeChanged); - break; - case "AD": - change.Set(Models.ChangeState.Added, Models.ChangeState.Deleted); - break; - case "D": - change.Set(Models.ChangeState.Deleted); - break; - case "R": - change.Set(Models.ChangeState.Renamed); - break; - case "RM": - change.Set(Models.ChangeState.Renamed, Models.ChangeState.Modified); - break; - case "RT": - change.Set(Models.ChangeState.Renamed, Models.ChangeState.TypeChanged); - break; - case "RD": - change.Set(Models.ChangeState.Renamed, Models.ChangeState.Deleted); - break; - case "C": - change.Set(Models.ChangeState.Copied); - break; - case "CM": - change.Set(Models.ChangeState.Copied, Models.ChangeState.Modified); - break; - case "CT": - change.Set(Models.ChangeState.Copied, Models.ChangeState.TypeChanged); - break; - case "CD": - change.Set(Models.ChangeState.Copied, Models.ChangeState.Deleted); - break; - case "DD": - change.ConflictReason = Models.ConflictReason.BothDeleted; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "AU": - change.ConflictReason = Models.ConflictReason.AddedByUs; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "UD": - change.ConflictReason = Models.ConflictReason.DeletedByThem; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "UA": - change.ConflictReason = Models.ConflictReason.AddedByThem; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "DU": - change.ConflictReason = Models.ConflictReason.DeletedByUs; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "AA": - change.ConflictReason = Models.ConflictReason.BothAdded; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "UU": - change.ConflictReason = Models.ConflictReason.BothModified; - change.Set(Models.ChangeState.None, Models.ChangeState.Conflicted); - break; - case "??": - change.Set(Models.ChangeState.None, Models.ChangeState.Untracked); - break; - } - - if (change.Index != Models.ChangeState.None || change.WorkTree != Models.ChangeState.None) - outs.Add(change); - } - - return outs; - } - - public async Task> ResultAsync() - { - var outs = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) { App.RaiseException(Context, rs.StdErr); diff --git a/src/Commands/QueryRefsContainsCommit.cs b/src/Commands/QueryRefsContainsCommit.cs index 8e4cf871..186b6a80 100644 --- a/src/Commands/QueryRefsContainsCommit.cs +++ b/src/Commands/QueryRefsContainsCommit.cs @@ -13,54 +13,28 @@ namespace SourceGit.Commands Args = $"for-each-ref --format=\"%(refname)\" --contains {commit}"; } - public List Result() + public async Task> GetResultAsync() { - var rs = new List(); + var outs = new List(); + var rs = await ReadToEndAsync().ConfigureAwait(false); + if (!rs.IsSuccess) + return outs; - var output = ReadToEnd(); - if (!output.IsSuccess) - return rs; - - var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); + var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { if (line.EndsWith("/HEAD", StringComparison.Ordinal)) continue; if (line.StartsWith("refs/heads/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead }); + outs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead }); else if (line.StartsWith("refs/remotes/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead }); + outs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead }); else if (line.StartsWith("refs/tags/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag }); + outs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag }); } - return rs; - } - - public async Task> ResultAsync() - { - var rs = new List(); - - var output = await ReadToEndAsync(); - if (!output.IsSuccess) - return rs; - - var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - if (line.EndsWith("/HEAD", StringComparison.Ordinal)) - continue; - - if (line.StartsWith("refs/heads/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead }); - else if (line.StartsWith("refs/remotes/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead }); - else if (line.StartsWith("refs/tags/", StringComparison.Ordinal)) - rs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag }); - } - - return rs; + return outs; } } } diff --git a/src/Commands/QueryRemotes.cs b/src/Commands/QueryRemotes.cs index c91b658b..bd42aabf 100644 --- a/src/Commands/QueryRemotes.cs +++ b/src/Commands/QueryRemotes.cs @@ -17,39 +17,10 @@ namespace SourceGit.Commands Args = "remote -v"; } - public List Result() + public async Task> GetResultAsync() { var outs = new List(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return outs; - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var match = REG_REMOTE().Match(line); - if (!match.Success) - continue; - - var remote = new Models.Remote() - { - Name = match.Groups[1].Value, - URL = match.Groups[2].Value, - }; - - if (outs.Find(x => x.Name == remote.Name) != null) - continue; - - outs.Add(remote); - } - - return outs; - } - - public async Task> ResultAsync() - { - var outs = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return outs; diff --git a/src/Commands/QueryRepositoryRootPath.cs b/src/Commands/QueryRepositoryRootPath.cs index 016621c8..f7e1eb63 100644 --- a/src/Commands/QueryRepositoryRootPath.cs +++ b/src/Commands/QueryRepositoryRootPath.cs @@ -1,4 +1,6 @@ -namespace SourceGit.Commands +using System.Threading.Tasks; + +namespace SourceGit.Commands { public class QueryRepositoryRootPath : Command { @@ -7,5 +9,10 @@ WorkingDirectory = path; Args = "rev-parse --show-toplevel"; } + + public async Task GetResultAsync() + { + return await ReadToEndAsync().ConfigureAwait(false); + } } } diff --git a/src/Commands/QueryRevisionByRefName.cs b/src/Commands/QueryRevisionByRefName.cs index ef0240d4..64a03e9d 100644 --- a/src/Commands/QueryRevisionByRefName.cs +++ b/src/Commands/QueryRevisionByRefName.cs @@ -11,18 +11,9 @@ namespace SourceGit.Commands Args = $"rev-parse {refname}"; } - public string Result() + public async Task GetResultAsync() { - var rs = ReadToEnd(); - if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut)) - return rs.StdOut.Trim(); - - return null; - } - - public async Task ResultAsync() - { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut)) return rs.StdOut.Trim(); diff --git a/src/Commands/QueryRevisionFileNames.cs b/src/Commands/QueryRevisionFileNames.cs index e19a73c9..74753412 100644 --- a/src/Commands/QueryRevisionFileNames.cs +++ b/src/Commands/QueryRevisionFileNames.cs @@ -12,9 +12,9 @@ namespace SourceGit.Commands Args = $"ls-tree -r -z --name-only {revision}"; } - public async Task> ResultAsync() + public async Task> GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return []; diff --git a/src/Commands/QueryRevisionObjects.cs b/src/Commands/QueryRevisionObjects.cs index 40fc55b1..e991cd0c 100644 --- a/src/Commands/QueryRevisionObjects.cs +++ b/src/Commands/QueryRevisionObjects.cs @@ -19,9 +19,10 @@ namespace SourceGit.Commands Args += $" -- \"{parentFolder}\""; } - public List Result() + public async Task> GetResultAsync() { - var rs = ReadToEnd(); + var outs = new List(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (rs.IsSuccess) { var start = 0; @@ -29,41 +30,19 @@ namespace SourceGit.Commands while (end > 0) { var line = rs.StdOut.Substring(start, end - start); - Parse(line); + Parse(outs, line); start = end + 1; end = rs.StdOut.IndexOf('\0', start); } if (start < rs.StdOut.Length) - Parse(rs.StdOut.Substring(start)); + Parse(outs, rs.StdOut.Substring(start)); } - return _objects; + return outs; } - public async Task> ResultAsync() - { - var rs = await ReadToEndAsync(); - if (rs.IsSuccess) - { - var start = 0; - var end = rs.StdOut.IndexOf('\0', start); - while (end > 0) - { - var line = rs.StdOut.Substring(start, end - start); - Parse(line); - start = end + 1; - end = rs.StdOut.IndexOf('\0', start); - } - - if (start < rs.StdOut.Length) - Parse(rs.StdOut.Substring(start)); - } - - return _objects; - } - - private void Parse(string line) + private void Parse(List outs, string line) { var match = REG_FORMAT().Match(line); if (!match.Success) @@ -83,9 +62,7 @@ namespace SourceGit.Commands _ => obj.Type, }; - _objects.Add(obj); + outs.Add(obj); } - - private List _objects = new List(); } } diff --git a/src/Commands/QuerySingleCommit.cs b/src/Commands/QuerySingleCommit.cs index e35df36a..897459f0 100644 --- a/src/Commands/QuerySingleCommit.cs +++ b/src/Commands/QuerySingleCommit.cs @@ -12,36 +12,9 @@ namespace SourceGit.Commands Args = $"show --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}"; } - public Models.Commit Result() + public async Task GetResultAsync() { - var rs = ReadToEnd(); - if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut)) - { - var commit = new Models.Commit(); - var lines = rs.StdOut.Split('\n'); - if (lines.Length < 8) - return null; - - commit.SHA = lines[0]; - if (!string.IsNullOrEmpty(lines[1])) - commit.Parents.AddRange(lines[1].Split(' ', StringSplitOptions.RemoveEmptyEntries)); - if (!string.IsNullOrEmpty(lines[2])) - commit.ParseDecorators(lines[2]); - commit.Author = Models.User.FindOrAdd(lines[3]); - commit.AuthorTime = ulong.Parse(lines[4]); - commit.Committer = Models.User.FindOrAdd(lines[5]); - commit.CommitterTime = ulong.Parse(lines[6]); - commit.Subject = lines[7]; - - return commit; - } - - return null; - } - - public async Task ResultAsync() - { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut)) { var commit = new Models.Commit(); diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs index 0c3e0df1..bec033ff 100644 --- a/src/Commands/QueryStagedChangesWithAmend.cs +++ b/src/Commands/QueryStagedChangesWithAmend.cs @@ -20,77 +20,9 @@ namespace SourceGit.Commands _parent = parent; } - public List Result() + public async Task> GetResultAsync() { - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return []; - - var changes = new List(); - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var match = REG_FORMAT2().Match(line); - if (match.Success) - { - var change = new Models.Change() - { - Path = match.Groups[3].Value, - DataForAmend = new Models.ChangeDataForAmend() - { - FileMode = match.Groups[1].Value, - ObjectHash = match.Groups[2].Value, - ParentSHA = _parent, - }, - }; - change.Set(Models.ChangeState.Renamed); - changes.Add(change); - continue; - } - - match = REG_FORMAT1().Match(line); - if (match.Success) - { - var change = new Models.Change() - { - Path = match.Groups[4].Value, - DataForAmend = new Models.ChangeDataForAmend() - { - FileMode = match.Groups[1].Value, - ObjectHash = match.Groups[2].Value, - ParentSHA = _parent, - }, - }; - - var type = match.Groups[3].Value; - switch (type) - { - case "A": - change.Set(Models.ChangeState.Added); - break; - case "C": - change.Set(Models.ChangeState.Copied); - break; - case "D": - change.Set(Models.ChangeState.Deleted); - break; - case "M": - change.Set(Models.ChangeState.Modified); - break; - case "T": - change.Set(Models.ChangeState.TypeChanged); - break; - } - changes.Add(change); - } - } - - return changes; - } - - public async Task> ResultAsync() - { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return []; diff --git a/src/Commands/QueryStagedFileBlobGuid.cs b/src/Commands/QueryStagedFileBlobGuid.cs index 20aad002..b6910034 100644 --- a/src/Commands/QueryStagedFileBlobGuid.cs +++ b/src/Commands/QueryStagedFileBlobGuid.cs @@ -15,16 +15,11 @@ namespace SourceGit.Commands Args = $"ls-files -s -- \"{file}\""; } - public async Task ResultAsync() + public async Task GetResultAsync() { - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var match = REG_FORMAT().Match(rs.StdOut.Trim()); - if (match.Success) - { - return match.Groups[1].Value; - } - - return string.Empty; + return match.Success ? match.Groups[1].Value : string.Empty; } } } diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs index 5b007bda..2b292f71 100644 --- a/src/Commands/QueryStashes.cs +++ b/src/Commands/QueryStashes.cs @@ -13,63 +13,10 @@ namespace SourceGit.Commands Args = "stash list -z --no-show-signature --format=\"%H%n%P%n%ct%n%gd%n%B\""; } - public List Result() + public async Task> GetResultAsync() { var outs = new List(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return outs; - - var items = rs.StdOut.Split('\0', StringSplitOptions.RemoveEmptyEntries); - foreach (var item in items) - { - var current = new Models.Stash(); - - var nextPartIdx = 0; - var start = 0; - var end = item.IndexOf('\n', start); - while (end > 0 && nextPartIdx < 4) - { - var line = item.Substring(start, end - start); - - switch (nextPartIdx) - { - case 0: - current.SHA = line; - break; - case 1: - if (line.Length > 6) - current.Parents.AddRange(line.Split(' ', StringSplitOptions.RemoveEmptyEntries)); - break; - case 2: - current.Time = ulong.Parse(line); - break; - case 3: - current.Name = line; - break; - } - - nextPartIdx++; - - start = end + 1; - if (start >= item.Length - 1) - break; - - end = item.IndexOf('\n', start); - } - - if (start < item.Length) - current.Message = item.Substring(start); - - outs.Add(current); - } - return outs; - } - - public async Task> ResultAsync() - { - var outs = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return outs; diff --git a/src/Commands/QuerySubmodules.cs b/src/Commands/QuerySubmodules.cs index ecb072f7..53030128 100644 --- a/src/Commands/QuerySubmodules.cs +++ b/src/Commands/QuerySubmodules.cs @@ -22,122 +22,10 @@ namespace SourceGit.Commands Args = "submodule status"; } - public List Result() + public async Task> GetResultAsync() { var submodules = new List(); - var rs = ReadToEnd(); - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - var map = new Dictionary(); - var needCheckLocalChanges = false; - foreach (var line in lines) - { - var match = REG_FORMAT_STATUS().Match(line); - if (match.Success) - { - var stat = match.Groups[1].Value; - var sha = match.Groups[2].Value; - var path = match.Groups[3].Value; - - var module = new Models.Submodule() { Path = path, SHA = sha }; - switch (stat[0]) - { - case '-': - module.Status = Models.SubmoduleStatus.NotInited; - break; - case '+': - module.Status = Models.SubmoduleStatus.RevisionChanged; - break; - case 'U': - module.Status = Models.SubmoduleStatus.Unmerged; - break; - default: - module.Status = Models.SubmoduleStatus.Normal; - needCheckLocalChanges = true; - break; - } - - map.Add(path, module); - submodules.Add(module); - } - } - - if (submodules.Count > 0) - { - Args = "config --file .gitmodules --list"; - rs = ReadToEnd(); - if (rs.IsSuccess) - { - var modules = new Dictionary(); - lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var match = REG_FORMAT_MODULE_INFO().Match(line); - if (match.Success) - { - var name = match.Groups[1].Value; - var key = match.Groups[2].Value; - var val = match.Groups[3].Value; - - if (!modules.TryGetValue(name, out var m)) - { - m = new ModuleInfo(); - modules.Add(name, m); - } - - if (key.Equals("path", StringComparison.Ordinal)) - m.Path = val; - else if (key.Equals("url", StringComparison.Ordinal)) - m.URL = val; - } - } - - foreach (var kv in modules) - { - if (map.TryGetValue(kv.Value.Path, out var m)) - m.URL = kv.Value.URL; - } - } - } - - if (needCheckLocalChanges) - { - var builder = new StringBuilder(); - foreach (var kv in map) - { - if (kv.Value.Status == Models.SubmoduleStatus.Normal) - { - builder.Append('"'); - builder.Append(kv.Key); - builder.Append("\" "); - } - } - - Args = $"--no-optional-locks status --porcelain -- {builder}"; - rs = ReadToEnd(); - if (!rs.IsSuccess) - return submodules; - - lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - var match = REG_FORMAT_DIRTY().Match(line); - if (match.Success) - { - var path = match.Groups[1].Value; - if (map.TryGetValue(path, out var m)) - m.Status = Models.SubmoduleStatus.Modified; - } - } - } - - return submodules; - } - - public async Task> ResultAsync() - { - var submodules = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); var map = new Dictionary(); diff --git a/src/Commands/QueryTags.cs b/src/Commands/QueryTags.cs index 32ccca48..ba83cb18 100644 --- a/src/Commands/QueryTags.cs +++ b/src/Commands/QueryTags.cs @@ -15,42 +15,10 @@ namespace SourceGit.Commands Args = $"tag -l --format=\"{_boundary}%(refname)%00%(objecttype)%00%(objectname)%00%(*objectname)%00%(creatordate:unix)%00%(contents:subject)%0a%0a%(contents:body)\""; } - public List Result() + public async Task> GetResultAsync() { var tags = new List(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return tags; - - var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries); - foreach (var record in records) - { - var subs = record.Split('\0'); - if (subs.Length != 6) - continue; - - var name = subs[0].Substring(10); - var message = subs[5].Trim(); - if (!string.IsNullOrEmpty(message) && message.Equals(name, StringComparison.Ordinal)) - message = null; - - tags.Add(new Models.Tag() - { - Name = name, - IsAnnotated = subs[1].Equals("tag", StringComparison.Ordinal), - SHA = string.IsNullOrEmpty(subs[3]) ? subs[2] : subs[3], - CreatorDate = ulong.Parse(subs[4]), - Message = message, - }); - } - - return tags; - } - - public async Task> ResultAsync() - { - var tags = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return tags; diff --git a/src/Commands/QueryTrackStatus.cs b/src/Commands/QueryTrackStatus.cs index c807451e..d687d274 100644 --- a/src/Commands/QueryTrackStatus.cs +++ b/src/Commands/QueryTrackStatus.cs @@ -12,31 +12,11 @@ namespace SourceGit.Commands Args = $"rev-list --left-right {local}...{upstream}"; } - public Models.BranchTrackStatus Result() + public async Task GetResultAsync() { var status = new Models.BranchTrackStatus(); - var rs = ReadToEnd(); - if (!rs.IsSuccess) - return status; - - var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); - foreach (var line in lines) - { - if (line[0] == '>') - status.Behind.Add(line.Substring(1)); - else - status.Ahead.Add(line.Substring(1)); - } - - return status; - } - - public async Task ResultAsync() - { - var status = new Models.BranchTrackStatus(); - - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return status; diff --git a/src/Commands/QueryUpdatableSubmodules.cs b/src/Commands/QueryUpdatableSubmodules.cs index 5d89ea2e..05fcc053 100644 --- a/src/Commands/QueryUpdatableSubmodules.cs +++ b/src/Commands/QueryUpdatableSubmodules.cs @@ -17,10 +17,10 @@ namespace SourceGit.Commands Args = "submodule status"; } - public async Task> ResultAsync() + public async Task> GetResultAsync() { var submodules = new List(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) diff --git a/src/Commands/SaveChangesAsPatch.cs b/src/Commands/SaveChangesAsPatch.cs index 173456fd..659d5329 100644 --- a/src/Commands/SaveChangesAsPatch.cs +++ b/src/Commands/SaveChangesAsPatch.cs @@ -64,8 +64,8 @@ namespace SourceGit.Commands { var proc = new Process() { StartInfo = starter }; proc.Start(); - await proc.StandardOutput.BaseStream.CopyToAsync(writer); - await proc.WaitForExitAsync(); + await proc.StandardOutput.BaseStream.CopyToAsync(writer).ConfigureAwait(false); + await proc.WaitForExitAsync().ConfigureAwait(false); var rs = proc.ExitCode == 0; proc.Close(); diff --git a/src/Commands/SaveRevisionFile.cs b/src/Commands/SaveRevisionFile.cs index 386eccba..24d803df 100644 --- a/src/Commands/SaveRevisionFile.cs +++ b/src/Commands/SaveRevisionFile.cs @@ -13,15 +13,15 @@ namespace SourceGit.Commands if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); - var isLFSFiltered = await new IsLFSFiltered(repo, revision, file).ResultAsync(); + var isLFSFiltered = await new IsLFSFiltered(repo, revision, file).GetResultAsync().ConfigureAwait(false); if (isLFSFiltered) { - var pointerStream = await QueryFileContent.RunAsync(repo, revision, file); - await ExecCmdAsync(repo, "lfs smudge", saveTo, pointerStream); + var pointerStream = await QueryFileContent.RunAsync(repo, revision, file).ConfigureAwait(false); + await ExecCmdAsync(repo, "lfs smudge", saveTo, pointerStream).ConfigureAwait(false); } else { - await ExecCmdAsync(repo, $"show {revision}:\"{file}\"", saveTo); + await ExecCmdAsync(repo, $"show {revision}:\"{file}\"", saveTo).ConfigureAwait(false); } } diff --git a/src/Commands/Stash.cs b/src/Commands/Stash.cs index b2f86b95..9774ed56 100644 --- a/src/Commands/Stash.cs +++ b/src/Commands/Stash.cs @@ -25,7 +25,7 @@ namespace SourceGit.Commands builder.Append("\""); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task PushAsync(string message, List changes, bool keepIndex) @@ -42,7 +42,7 @@ namespace SourceGit.Commands builder.Append($"\"{c.Path}\" "); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task PushAsync(string message, string pathspecFromFile, bool keepIndex) @@ -58,7 +58,7 @@ namespace SourceGit.Commands builder.Append("\""); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task PushOnlyStagedAsync(string message, bool keepIndex) @@ -71,32 +71,32 @@ namespace SourceGit.Commands builder.Append(message); builder.Append("\""); Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task ApplyAsync(string name, bool restoreIndex) { var opts = restoreIndex ? "--index" : string.Empty; Args = $"stash apply -q {opts} \"{name}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task PopAsync(string name) { Args = $"stash pop -q --index \"{name}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task DropAsync(string name) { Args = $"stash drop -q \"{name}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task ClearAsync() { Args = "stash clear"; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/Statistics.cs b/src/Commands/Statistics.cs index 64ebda60..513b9640 100644 --- a/src/Commands/Statistics.cs +++ b/src/Commands/Statistics.cs @@ -12,10 +12,10 @@ namespace SourceGit.Commands Args = $"log --date-order --branches --remotes -{max} --format=%ct$%aN±%aE"; } - public async Task ResultAsync() + public async Task ReadAsync() { var statistics = new Models.Statistics(); - var rs = await ReadToEndAsync(); + var rs = await ReadToEndAsync().ConfigureAwait(false); if (!rs.IsSuccess) return statistics; diff --git a/src/Commands/Submodule.cs b/src/Commands/Submodule.cs index 29fd17e6..37411ab0 100644 --- a/src/Commands/Submodule.cs +++ b/src/Commands/Submodule.cs @@ -15,18 +15,20 @@ namespace SourceGit.Commands public async Task AddAsync(string url, string relativePath, bool recursive) { Args = $"-c protocol.file.allow=always submodule add \"{url}\" \"{relativePath}\""; - if (!await ExecAsync()) + + var succ = await ExecAsync().ConfigureAwait(false); + if (!succ) return false; if (recursive) { Args = $"submodule update --init --recursive -- \"{relativePath}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } else { Args = $"submodule update --init -- \"{relativePath}\""; - return true; + return await ExecAsync().ConfigureAwait(false); } } @@ -49,19 +51,19 @@ namespace SourceGit.Commands } Args = builder.ToString(); - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task DeinitAsync(string module, bool force) { Args = force ? $"submodule deinit -f -- \"{module}\"" : $"submodule deinit -- \"{module}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task DeleteAsync(string module) { Args = $"rm -rf \"{module}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/Tag.cs b/src/Commands/Tag.cs index e7e9f5ee..d372573a 100644 --- a/src/Commands/Tag.cs +++ b/src/Commands/Tag.cs @@ -12,7 +12,7 @@ namespace SourceGit.Commands cmd.Context = repo; cmd.Args = $"tag --no-sign {name} {basedOn}"; cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task AddAsync(string repo, string name, string basedOn, string message, bool sign, Models.ICommandLog log) @@ -30,13 +30,13 @@ namespace SourceGit.Commands await File.WriteAllTextAsync(tmp, message); cmd.Args += $"-F \"{tmp}\""; - var succ = await cmd.ExecAsync(); + var succ = await cmd.ExecAsync().ConfigureAwait(false); File.Delete(tmp); return succ; } cmd.Args += $"-m {name}"; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } public static async Task DeleteAsync(string repo, string name, Models.ICommandLog log) @@ -46,7 +46,7 @@ namespace SourceGit.Commands cmd.Context = repo; cmd.Args = $"tag --delete {name}"; cmd.Log = log; - return await cmd.ExecAsync(); + return await cmd.ExecAsync().ConfigureAwait(false); } } } diff --git a/src/Commands/UnstageChangesForAmend.cs b/src/Commands/UnstageChangesForAmend.cs index 6d2fe2b3..049811e5 100644 --- a/src/Commands/UnstageChangesForAmend.cs +++ b/src/Commands/UnstageChangesForAmend.cs @@ -48,43 +48,6 @@ namespace SourceGit.Commands } } - public bool Exec() - { - var starter = new ProcessStartInfo(); - starter.WorkingDirectory = _repo; - starter.FileName = Native.OS.GitExecutable; - starter.Arguments = "-c core.editor=true update-index --index-info"; - starter.UseShellExecute = false; - starter.CreateNoWindow = true; - starter.WindowStyle = ProcessWindowStyle.Hidden; - starter.RedirectStandardInput = true; - starter.RedirectStandardOutput = false; - starter.RedirectStandardError = true; - - try - { - var proc = new Process() { StartInfo = starter }; - proc.Start(); - proc.StandardInput.Write(_patchBuilder.ToString()); - proc.StandardInput.Close(); - - var err = proc.StandardError.ReadToEnd(); - proc.WaitForExit(); - var rs = proc.ExitCode == 0; - proc.Close(); - - if (!rs) - App.RaiseException(_repo, err); - - return rs; - } - catch (Exception e) - { - App.RaiseException(_repo, "Failed to unstage changes: " + e.Message); - return false; - } - } - public async Task ExecAsync() { var starter = new ProcessStartInfo(); @@ -105,8 +68,8 @@ namespace SourceGit.Commands await proc.StandardInput.WriteAsync(_patchBuilder.ToString()); proc.StandardInput.Close(); - var err = await proc.StandardError.ReadToEndAsync(); - await proc.WaitForExitAsync(); + var err = await proc.StandardError.ReadToEndAsync().ConfigureAwait(false); + await proc.WaitForExitAsync().ConfigureAwait(false); var rs = proc.ExitCode == 0; proc.Close(); diff --git a/src/Commands/Worktree.cs b/src/Commands/Worktree.cs index 33c37b1b..4e6bc4e4 100644 --- a/src/Commands/Worktree.cs +++ b/src/Commands/Worktree.cs @@ -13,11 +13,11 @@ namespace SourceGit.Commands Context = repo; } - public List List() + public async Task> ReadAllAsync() { Args = "worktree list --porcelain"; - var rs = ReadToEnd(); + var rs = await ReadToEndAsync().ConfigureAwait(false); var worktrees = new List(); Models.Worktree last = null; if (rs.IsSuccess) @@ -79,25 +79,25 @@ namespace SourceGit.Commands else if (!string.IsNullOrEmpty(name) && !createNew) Args += name; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task PruneAsync() { Args = "worktree prune -v"; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task LockAsync(string fullpath) { Args = $"worktree lock \"{fullpath}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task UnlockAsync(string fullpath) { Args = $"worktree unlock \"{fullpath}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } public async Task RemoveAsync(string fullpath, bool force) @@ -107,7 +107,7 @@ namespace SourceGit.Commands else Args = $"worktree remove \"{fullpath}\""; - return await ExecAsync(); + return await ExecAsync().ConfigureAwait(false); } } } diff --git a/src/ViewModels/AddRemote.cs b/src/ViewModels/AddRemote.cs index 7520c3f1..f9595557 100644 --- a/src/ViewModels/AddRemote.cs +++ b/src/ViewModels/AddRemote.cs @@ -95,20 +95,29 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Add Remote"); Use(log); - var succ = await new Commands.Remote(_repo.FullPath).Use(log).AddAsync(_name, _url); + var succ = await new Commands.Remote(_repo.FullPath) + .Use(log) + .AddAsync(_name, _url) + .ConfigureAwait(false); + if (succ) { - await new Commands.Config(_repo.FullPath).Use(log).SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null); - await new Commands.Fetch(_repo.FullPath, _name, false, false).Use(log).ExecAsync(); + await new Commands.Config(_repo.FullPath) + .Use(log) + .SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null) + .ConfigureAwait(false); + + await new Commands.Fetch(_repo.FullPath, _name, false, false) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => - { - _repo.MarkFetched(); - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + + _repo.MarkFetched(); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/AddSubmodule.cs b/src/ViewModels/AddSubmodule.cs index 304f6016..bf320d69 100644 --- a/src/ViewModels/AddSubmodule.cs +++ b/src/ViewModels/AddSubmodule.cs @@ -59,10 +59,13 @@ namespace SourceGit.ViewModels relativePath = Path.GetFileName(_url); } - var succ = await new Commands.Submodule(_repo.FullPath).Use(log).AddAsync(_url, relativePath, Recursive); - log.Complete(); + var succ = await new Commands.Submodule(_repo.FullPath) + .Use(log) + .AddAsync(_url, relativePath, Recursive) + .ConfigureAwait(false); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + log.Complete(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/AddToIgnore.cs b/src/ViewModels/AddToIgnore.cs index 11989ae1..d2a194f4 100644 --- a/src/ViewModels/AddToIgnore.cs +++ b/src/ViewModels/AddToIgnore.cs @@ -46,12 +46,8 @@ namespace SourceGit.ViewModels await File.AppendAllLinesAsync(file, [_pattern]); } - await CallUIThreadAsync(() => - { - _repo.MarkWorkingCopyDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - + _repo.MarkWorkingCopyDirtyManually(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/AddWorktree.cs b/src/ViewModels/AddWorktree.cs index b77147cf..a64cc1f4 100644 --- a/src/ViewModels/AddWorktree.cs +++ b/src/ViewModels/AddWorktree.cs @@ -116,10 +116,13 @@ namespace SourceGit.ViewModels Use(log); - var succ = await new Commands.Worktree(_repo.FullPath).Use(log).AddAsync(_path, branchName, _createNewBranch, tracking); - log.Complete(); + var succ = await new Commands.Worktree(_repo.FullPath) + .Use(log) + .AddAsync(_path, branchName, _createNewBranch, tracking) + .ConfigureAwait(false); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + log.Complete(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/Apply.cs b/src/ViewModels/Apply.cs index d6d73e87..80aa5dc5 100644 --- a/src/ViewModels/Apply.cs +++ b/src/ViewModels/Apply.cs @@ -47,10 +47,15 @@ namespace SourceGit.ViewModels ProgressDescription = "Apply patch..."; var log = _repo.CreateLog("Apply Patch"); - var succ = await new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Use(log).ExecAsync(); - log.Complete(); + Use(log); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + var succ = await new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + + log.Complete(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/ApplyStash.cs b/src/ViewModels/ApplyStash.cs index 4343a8bc..8a91ac37 100644 --- a/src/ViewModels/ApplyStash.cs +++ b/src/ViewModels/ApplyStash.cs @@ -30,14 +30,25 @@ namespace SourceGit.ViewModels public override async Task Sure() { + _repo.SetWatcherEnabled(false); ProgressDescription = $"Applying stash: {Stash.Name}"; var log = _repo.CreateLog("Apply Stash"); - var succ = await new Commands.Stash(_repo.FullPath).Use(log).ApplyAsync(Stash.Name, RestoreIndex); + Use(log); + + var succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .ApplyAsync(Stash.Name, RestoreIndex) + .ConfigureAwait(false); + if (succ && DropAfterApply) - await new Commands.Stash(_repo.FullPath).Use(log).DropAsync(Stash.Name); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .DropAsync(Stash.Name) + .ConfigureAwait(false); log.Complete(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Archive.cs b/src/ViewModels/Archive.cs index 30cded3e..f740a140 100644 --- a/src/ViewModels/Archive.cs +++ b/src/ViewModels/Archive.cs @@ -52,16 +52,16 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Archive"); Use(log); - var succ = await new Commands.Archive(_repo.FullPath, _revision, _saveFile).Use(log).ExecAsync(); + var succ = await new Commands.Archive(_repo.FullPath, _revision, _saveFile) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); + _repo.SetWatcherEnabled(true); - await CallUIThreadAsync(() => - { - _repo.SetWatcherEnabled(true); - if (succ) - App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}"); - }); - + if (succ) + App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}"); return succ; } diff --git a/src/ViewModels/AssumeUnchangedManager.cs b/src/ViewModels/AssumeUnchangedManager.cs index d5e523c9..601a2266 100644 --- a/src/ViewModels/AssumeUnchangedManager.cs +++ b/src/ViewModels/AssumeUnchangedManager.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; - using Avalonia.Collections; using Avalonia.Threading; @@ -16,7 +15,10 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var collect = await new Commands.QueryAssumeUnchangedFiles(_repo.FullPath).ResultAsync(); + var collect = await new Commands.QueryAssumeUnchangedFiles(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + await Dispatcher.UIThread.InvokeAsync(() => Files.AddRange(collect)); }); } @@ -26,7 +28,12 @@ namespace SourceGit.ViewModels if (!string.IsNullOrEmpty(file)) { var log = _repo.CreateLog("Remove Assume Unchanged File"); - await new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).ExecAsync(); + + await new Commands.AssumeUnchanged(_repo.FullPath, file, false) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); Files.Remove(file); } diff --git a/src/ViewModels/Blame.cs b/src/ViewModels/Blame.cs index 944fc1c8..96b3fa26 100644 --- a/src/ViewModels/Blame.cs +++ b/src/ViewModels/Blame.cs @@ -2,9 +2,7 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; - using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -65,7 +63,10 @@ namespace SourceGit.ViewModels if (_commitMessages.TryGetValue(sha, out var msg)) return msg; - msg = new Commands.QueryCommitFullMessage(_repo, sha).Result(); + msg = new Commands.QueryCommitFullMessage(_repo, sha) + .GetResultAsync() + .Result; + _commitMessages[sha] = msg; return msg; } @@ -134,7 +135,9 @@ namespace SourceGit.ViewModels { Task.Run(async () => { - var result = await new Commands.QuerySingleCommit(_repo, commitSHA).ResultAsync(); + var result = await new Commands.QuerySingleCommit(_repo, commitSHA) + .GetResultAsync() + .ConfigureAwait(false); await Dispatcher.UIThread.InvokeAsync(() => { @@ -149,7 +152,9 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var result = await new Commands.Blame(_repo, FilePath, commitSHA).ResultAsync(); + var result = await new Commands.Blame(_repo, FilePath, commitSHA) + .ReadAsync() + .ConfigureAwait(false); await Dispatcher.UIThread.InvokeAsync(() => { diff --git a/src/ViewModels/BranchCompare.cs b/src/ViewModels/BranchCompare.cs index 1cef5e22..978fe2bf 100644 --- a/src/ViewModels/BranchCompare.cs +++ b/src/ViewModels/BranchCompare.cs @@ -156,9 +156,9 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(change.Path); + await App.CopyTextAsync(change.Path); ev.Handled = true; }; menu.Items.Add(copyPath); @@ -166,9 +166,9 @@ namespace SourceGit.ViewModels var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(Native.OS.GetAbsPath(_repo, change.Path)); + await App.CopyTextAsync(Native.OS.GetAbsPath(_repo, change.Path)); e.Handled = true; }; menu.Items.Add(copyFullPath); @@ -182,8 +182,14 @@ namespace SourceGit.ViewModels { if (_baseHead == null) { - var baseHead = await new Commands.QuerySingleCommit(_repo, _based.Head).ResultAsync(); - var toHead = await new Commands.QuerySingleCommit(_repo, _to.Head).ResultAsync(); + var baseHead = await new Commands.QuerySingleCommit(_repo, _based.Head) + .GetResultAsync() + .ConfigureAwait(false); + + var toHead = await new Commands.QuerySingleCommit(_repo, _to.Head) + .GetResultAsync() + .ConfigureAwait(false); + await Dispatcher.UIThread.InvokeAsync(() => { BaseHead = baseHead; @@ -191,7 +197,9 @@ namespace SourceGit.ViewModels }); } - _changes = await new Commands.CompareRevisions(_repo, _based.Head, _to.Head).ResultAsync(); + _changes = await new Commands.CompareRevisions(_repo, _based.Head, _to.Head) + .ReadAsync() + .ConfigureAwait(false); var visible = _changes; if (!string.IsNullOrWhiteSpace(_searchFilter)) diff --git a/src/ViewModels/Checkout.cs b/src/ViewModels/Checkout.cs index 83b9592f..9bd5f562 100644 --- a/src/ViewModels/Checkout.cs +++ b/src/ViewModels/Checkout.cs @@ -42,66 +42,84 @@ namespace SourceGit.ViewModels Use(log); var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules; - bool succ; + var succ = false; var needPopStash = false; - if (!_repo.ConfirmCheckoutBranch()) + var confirmed = await _repo.ConfirmCheckoutBranchAsync().ConfigureAwait(false); + if (!confirmed) { - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } if (DiscardLocalChanges) { - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(Branch, true); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(Branch, true) + .ConfigureAwait(false); } else { - var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync(); + var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (changes > 0) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AUTO_STASH"); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("CHECKOUT_AUTO_STASH") + .ConfigureAwait(false); if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } needPopStash = true; } - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(Branch, false); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(Branch, false) + .ConfigureAwait(false); } if (succ) { if (updateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (submodules.Count > 0) - await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(_repo.FullPath) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } if (needPopStash) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => - { - ProgressDescription = "Waiting for branch updated..."; + var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch); + if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included) + _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false); - var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch); - if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included) - _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - - Task.Delay(400).Wait(); + ProgressDescription = "Waiting for branch updated..."; + await Task.Delay(400); return succ; } diff --git a/src/ViewModels/CheckoutAndFastForward.cs b/src/ViewModels/CheckoutAndFastForward.cs index 559acc34..2046df1d 100644 --- a/src/ViewModels/CheckoutAndFastForward.cs +++ b/src/ViewModels/CheckoutAndFastForward.cs @@ -50,62 +50,81 @@ namespace SourceGit.ViewModels var succ = false; var needPopStash = false; - if (!_repo.ConfirmCheckoutBranch()) + var confirmed = await _repo.ConfirmCheckoutBranchAsync().ConfigureAwait(false); + if (!confirmed) { - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } if (DiscardLocalChanges) { - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(LocalBranch.Name, RemoteBranch.Head, true, true); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(LocalBranch.Name, RemoteBranch.Head, true, true) + .ConfigureAwait(false); } else { - var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync(); + var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (changes > 0) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AND_FASTFORWARD_AUTO_STASH"); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("CHECKOUT_AND_FASTFORWARD_AUTO_STASH") + .ConfigureAwait(false); + if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } needPopStash = true; } - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(LocalBranch.Name, RemoteBranch.Head, false, true); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(LocalBranch.Name, RemoteBranch.Head, false, true) + .ConfigureAwait(false); } if (succ) { if (updateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (submodules.Count > 0) - await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(_repo.FullPath) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } if (needPopStash) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => - { - ProgressDescription = "Waiting for branch updated..."; + if (_repo.HistoriesFilterMode == Models.FilterMode.Included) + _repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false); - if (_repo.HistoriesFilterMode == Models.FilterMode.Included) - _repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - - Task.Delay(400).Wait(); + ProgressDescription = "Waiting for branch updated..."; + await Task.Delay(400); return succ; } diff --git a/src/ViewModels/CheckoutCommit.cs b/src/ViewModels/CheckoutCommit.cs index b95829ff..88805c2b 100644 --- a/src/ViewModels/CheckoutCommit.cs +++ b/src/ViewModels/CheckoutCommit.cs @@ -45,50 +45,73 @@ namespace SourceGit.ViewModels bool succ; var needPop = false; - if (!_repo.ConfirmCheckoutBranch()) + var confirmed = await _repo.ConfirmCheckoutBranchAsync().ConfigureAwait(false); + if (!confirmed) { - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } if (DiscardLocalChanges) { - succ = await new Commands.Checkout(_repo.FullPath).Use(log).CommitAsync(Commit.SHA, true); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .CommitAsync(Commit.SHA, true) + .ConfigureAwait(false); } else { - var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync(); + var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (changes > 0) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AUTO_STASH"); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("CHECKOUT_AUTO_STASH") + .ConfigureAwait(false); + if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } needPop = true; } - succ = await new Commands.Checkout(_repo.FullPath).Use(log).CommitAsync(Commit.SHA, false); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .CommitAsync(Commit.SHA, false) + .ConfigureAwait(false); } if (succ) { if (updateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (submodules.Count > 0) - await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(_repo.FullPath) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } if (needPop) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/CherryPick.cs b/src/ViewModels/CherryPick.cs index 66961b20..f2d52b23 100644 --- a/src/ViewModels/CherryPick.cs +++ b/src/ViewModels/CherryPick.cs @@ -79,7 +79,10 @@ namespace SourceGit.ViewModels Targets[0].SHA, !AutoCommit, AppendSourceToMessage, - $"-m {MainlineForMergeCommit + 1}").Use(log).ExecAsync(); + $"-m {MainlineForMergeCommit + 1}") + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } else { @@ -88,11 +91,14 @@ namespace SourceGit.ViewModels string.Join(' ', Targets.ConvertAll(c => c.SHA)), !AutoCommit, AppendSourceToMessage, - string.Empty).Use(log).ExecAsync(); + string.Empty) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Cleanup.cs b/src/ViewModels/Cleanup.cs index 458405e0..e3d06f75 100644 --- a/src/ViewModels/Cleanup.cs +++ b/src/ViewModels/Cleanup.cs @@ -17,9 +17,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Cleanup (GC & prune)"); Use(log); - await new Commands.GC(_repo.FullPath).Use(log).ExecAsync(); + await new Commands.GC(_repo.FullPath) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/ClearStashes.cs b/src/ViewModels/ClearStashes.cs index 02c23f28..f778e392 100644 --- a/src/ViewModels/ClearStashes.cs +++ b/src/ViewModels/ClearStashes.cs @@ -17,9 +17,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Clear Stashes"); Use(log); - await new Commands.Stash(_repo.FullPath).Use(log).ClearAsync(); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .ClearAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Clone.cs b/src/ViewModels/Clone.cs index c23bc4a3..00028650 100644 --- a/src/ViewModels/Clone.cs +++ b/src/ViewModels/Clone.cs @@ -3,8 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; -using Avalonia.Threading; - namespace SourceGit.ViewModels { public class Clone : Popup @@ -68,19 +66,16 @@ namespace SourceGit.ViewModels if (string.IsNullOrEmpty(ParentFolder)) _parentFolder = Preferences.Instance.GitDefaultCloneDir; - Task.Run(async () => + try { - try - { - var text = await App.GetClipboardTextAsync(); - if (Models.Remote.IsValidURL(text)) - await Dispatcher.UIThread.InvokeAsync(() => Remote = text); - } - catch - { - // ignore - } - }); + var text = App.GetClipboardTextAsync().Result; + if (Models.Remote.IsValidURL(text)) + Remote = text; + } + catch + { + // Ignore + } } public static ValidationResult ValidateRemote(string remote, ValidationContext _) @@ -104,8 +99,12 @@ namespace SourceGit.ViewModels var log = new CommandLog("Clone"); Use(log); - var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs).Use(log); - if (!await cmd.ExecAsync()) + var succ = await new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + + if (succ) return false; var path = _parentFolder; @@ -132,37 +131,41 @@ namespace SourceGit.ViewModels if (_useSSH && !string.IsNullOrEmpty(_sshKey)) { - var config = new Commands.Config(path); - await config.SetAsync("remote.origin.sshkey", _sshKey); + await new Commands.Config(path) + .Use(log) + .SetAsync("remote.origin.sshkey", _sshKey) + .ConfigureAwait(false); } if (InitAndUpdateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(path).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(path) + .GetResultAsync() + .ConfigureAwait(false); + if (submodules.Count > 0) - await new Commands.Submodule(path).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(path) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => + var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true); + var launcher = App.GetLauncher(); + LauncherPage page = null; + foreach (var one in launcher.Pages) { - var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, null, true); - var launcher = App.GetLauncher(); - LauncherPage page = null; - foreach (var one in launcher.Pages) + if (one.Node.Id == _pageId) { - if (one.Node.Id == _pageId) - { - page = one; - break; - } + page = one; + break; } + } - Welcome.Instance.Refresh(); - launcher.OpenRepositoryInTab(node, page); - }); - + Welcome.Instance.Refresh(); + launcher.OpenRepositoryInTab(node, page); return true; } diff --git a/src/ViewModels/CommandLog.cs b/src/ViewModels/CommandLog.cs index 896869cf..1accc226 100644 --- a/src/ViewModels/CommandLog.cs +++ b/src/ViewModels/CommandLog.cs @@ -51,36 +51,41 @@ namespace SourceGit.ViewModels public void AppendLine(string line = null) { - var newline = line ?? string.Empty; - - Dispatcher.UIThread.Invoke(() => + if (!Dispatcher.UIThread.CheckAccess()) { + Dispatcher.UIThread.Invoke(() => AppendLine(line)); + } + else + { + var newline = line ?? string.Empty; _builder.AppendLine(newline); _onNewLineReceived?.Invoke(newline); - }); + } } public void Complete() { - IsComplete = true; - - Dispatcher.UIThread.Invoke(() => + if (!Dispatcher.UIThread.CheckAccess()) { - _content = _builder.ToString(); - _builder.Clear(); - _builder = null; + Dispatcher.UIThread.Invoke(Complete); + return; + } - EndTime = DateTime.Now; + IsComplete = true; + EndTime = DateTime.Now; - OnPropertyChanged(nameof(IsComplete)); + _content = _builder.ToString(); + _builder.Clear(); + _builder = null; - if (_onNewLineReceived != null) - { - var dumpHandlers = _onNewLineReceived.GetInvocationList(); - foreach (var d in dumpHandlers) - _onNewLineReceived -= (Action)d; - } - }); + OnPropertyChanged(nameof(IsComplete)); + + if (_onNewLineReceived != null) + { + var dumpHandlers = _onNewLineReceived.GetInvocationList(); + foreach (var d in dumpHandlers) + _onNewLineReceived -= (Action)d; + } } private string _content = string.Empty; diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index d6ffdf79..e561b715 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -169,9 +169,11 @@ namespace SourceGit.ViewModels _repo?.NavigateToCommit(commitSHA); } - public List GetRefsContainsThisCommit() + public async Task> GetRefsContainsThisCommitAsync() { - return new Commands.QueryRefsContainsCommit(_repo.FullPath, _commit.SHA).Result(); + return await new Commands.QueryRefsContainsCommit(_repo.FullPath, _commit.SHA) + .GetResultAsync() + .ConfigureAwait(false); } public void ClearSearchChangeFilter() @@ -189,93 +191,34 @@ namespace SourceGit.ViewModels RevisionFileSearchSuggestion = null; } - public Models.Commit GetParent(string sha) + public async Task GetCommitAsync(string sha) { - return new Commands.QuerySingleCommit(_repo.FullPath, sha).Result(); + return await new Commands.QuerySingleCommit(_repo.FullPath, sha) + .GetResultAsync() + .ConfigureAwait(false); } - public List GetRevisionFilesUnderFolder(string parentFolder) + public async Task> GetRevisionFilesUnderFolderAsync(string parentFolder) { - return new Commands.QueryRevisionObjects(_repo.FullPath, _commit.SHA, parentFolder).Result(); + return await new Commands.QueryRevisionObjects(_repo.FullPath, _commit.SHA, parentFolder) + .GetResultAsync() + .ConfigureAwait(false); } - public void ViewRevisionFile(Models.Object file) + public async Task ViewRevisionFileAsync(Models.Object file) { - if (file == null) - { - ViewRevisionFilePath = string.Empty; - ViewRevisionFileContent = null; - CanOpenRevisionFileWithDefaultEditor = false; - return; - } + var obj = file ?? new Models.Object() { Path = string.Empty, Type = Models.ObjectType.None }; + ViewRevisionFilePath = obj.Path; - ViewRevisionFilePath = file.Path; - - switch (file.Type) + switch (obj.Type) { case Models.ObjectType.Blob: CanOpenRevisionFileWithDefaultEditor = true; - Task.Run(async () => - { - var isBinary = await new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).ResultAsync(); - if (isBinary) - { - var imgDecoder = ImageSource.GetDecoder(file.Path); - if (imgDecoder != Models.ImageDecoder.None) - { - var source = ImageSource.FromRevision(_repo.FullPath, _commit.SHA, file.Path, imgDecoder); - var image = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size); - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = image); - } - else - { - var size = await new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).ResultAsync(); - var binary = new Models.RevisionBinaryFile() { Size = size }; - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = binary); - } - - return; - } - - var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _commit.SHA, file.Path); - var content = await new StreamReader(contentStream).ReadToEndAsync(); - var lfs = Models.LFSObject.Parse(content); - if (lfs != null) - { - var imgDecoder = ImageSource.GetDecoder(file.Path); - if (imgDecoder != Models.ImageDecoder.None) - { - var combined = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder); - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = combined); - } - else - { - var rlfs = new Models.RevisionLFSObject() { Object = lfs }; - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = rlfs); - } - } - else - { - var txt = new Models.RevisionTextFile() { FileName = file.Path, Content = content }; - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = txt); - } - }); + await SetViewingBlobAsync(obj); break; case Models.ObjectType.Commit: CanOpenRevisionFileWithDefaultEditor = false; - Task.Run(async () => - { - var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/'); - var commit = await new Commands.QuerySingleCommit(submoduleRoot, file.SHA).ResultAsync(); - var message = commit != null ? await new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).ResultAsync() : null; - var module = new Models.RevisionSubmodule() - { - Commit = commit ?? new Models.Commit() { SHA = _commit.SHA }, - FullMessage = new Models.CommitFullMessage { Message = message } - }; - - await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = module); - }); + await SetViewingCommitAsync(obj); break; default: CanOpenRevisionFileWithDefaultEditor = false; @@ -284,17 +227,18 @@ namespace SourceGit.ViewModels } } - public async Task OpenRevisionFileWithDefaultEditor(string file) + public async Task OpenRevisionFileWithDefaultEditorAsync(string file) { - { - var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file); - var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? ""; - var fileExt = Path.GetExtension(fullPath) ?? ""; - var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}"); + var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file); + var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? ""; + var fileExt = Path.GetExtension(fullPath) ?? ""; + var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}"); - await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _commit.SHA, file, tmpFile); - Native.OS.OpenWithDefaultEditor(tmpFile); - } + await Commands.SaveRevisionFile + .RunAsync(_repo.FullPath, _commit.SHA, file, tmpFile) + .ConfigureAwait(false); + + Native.OS.OpenWithDefaultEditor(tmpFile); } public ContextMenu CreateChangeContextMenuByFolder(ChangeTreeNode node, List changes) @@ -338,7 +282,10 @@ namespace SourceGit.ViewModels if (storageFile != null) { var saveTo = storageFile.Path.LocalPath; - var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo); + var succ = await Commands.SaveChangesAsPatch + .ProcessRevisionCompareChangesAsync(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo) + .ConfigureAwait(false); + if (succ) App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess")); } @@ -349,18 +296,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(node.FullPath); + await App.CopyTextAsync(node.FullPath); ev.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(fullPath); + await App.CopyTextAsync(fullPath); e.Handled = true; }; @@ -464,7 +411,7 @@ namespace SourceGit.ViewModels resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToThisRevision.Click += async (_, ev) => { - await ResetToThisRevision(change.Path); + await ResetToThisRevisionAsync(change.Path); ev.Handled = true; }; @@ -474,7 +421,7 @@ namespace SourceGit.ViewModels resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; resetToFirstParent.Click += async (_, ev) => { - await ResetToParentRevision(change); + await ResetToParentRevisionAsync(change); ev.Handled = true; }; @@ -488,18 +435,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(change.Path); + await App.CopyTextAsync(change.Path); ev.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(fullPath); + await App.CopyTextAsync(fullPath); e.Handled = true; }; @@ -533,18 +480,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(path); + await App.CopyTextAsync(path); ev.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(fullPath); + await App.CopyTextAsync(fullPath); e.Handled = true; }; @@ -581,7 +528,7 @@ namespace SourceGit.ViewModels openWith.IsEnabled = file.Type == Models.ObjectType.Blob; openWith.Click += async (_, ev) => { - await OpenRevisionFileWithDefaultEditor(file.Path); + await OpenRevisionFileWithDefaultEditorAsync(file.Path); ev.Handled = true; }; @@ -604,7 +551,10 @@ namespace SourceGit.ViewModels 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)!); - await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _commit.SHA, file.Path, saveTo); + + await Commands.SaveRevisionFile + .RunAsync(_repo.FullPath, _commit.SHA, file.Path, saveTo) + .ConfigureAwait(false); } } catch (Exception e) @@ -650,7 +600,7 @@ namespace SourceGit.ViewModels resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToThisRevision.Click += async (_, ev) => { - await ResetToThisRevision(file.Path); + await ResetToThisRevisionAsync(file.Path); ev.Handled = true; }; @@ -661,7 +611,7 @@ namespace SourceGit.ViewModels resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; resetToFirstParent.Click += async (_, ev) => { - await ResetToParentRevision(change); + await ResetToParentRevisionAsync(change); ev.Handled = true; }; @@ -675,18 +625,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(file.Path); + await App.CopyTextAsync(file.Path); ev.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(fullPath); + await App.CopyTextAsync(fullPath); e.Handled = true; }; @@ -720,18 +670,30 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var message = await new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).ResultAsync(); + var message = await new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA) + .GetResultAsync() + .ConfigureAwait(false); var inlines = await ParseInlinesInMessageAsync(message); if (!token.IsCancellationRequested) - await Dispatcher.UIThread.InvokeAsync(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines }); + Dispatcher.UIThread.Post(() => + { + FullMessage = new Models.CommitFullMessage + { + Message = message, + Inlines = inlines + }; + }); }, token); Task.Run(async () => { - var signInfo = await new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).ResultAsync(); + var signInfo = await new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile) + .GetResultAsync() + .ConfigureAwait(false); + if (!token.IsCancellationRequested) - await Dispatcher.UIThread.InvokeAsync(() => SignInfo = signInfo); + Dispatcher.UIThread.Post(() => SignInfo = signInfo); }, token); if (Preferences.Instance.ShowChildren) @@ -740,7 +702,7 @@ namespace SourceGit.ViewModels { var max = Preferences.Instance.MaxHistoryCommits; var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token }; - var children = await cmd.ResultAsync(); + var children = await cmd.GetResultAsync().ConfigureAwait(false); if (!token.IsCancellationRequested) Dispatcher.UIThread.Post(() => Children = children); }, token); @@ -750,7 +712,7 @@ namespace SourceGit.ViewModels { var parent = _commit.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : _commit.Parents[0]; var cmd = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { CancellationToken = token }; - var changes = await cmd.ResultAsync(); + var changes = await cmd.ReadAsync().ConfigureAwait(false); var visible = changes; if (!string.IsNullOrWhiteSpace(_searchChangeFilter)) { @@ -815,7 +777,7 @@ namespace SourceGit.ViewModels continue; var sha = match.Groups[1].Value; - var isCommitSHA = await new Commands.IsCommitSHA(_repo.FullPath, sha).ResultAsync(); + var isCommitSHA = await new Commands.IsCommitSHA(_repo.FullPath, sha).GetResultAsync().ConfigureAwait(false); if (isCommitSHA) inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha)); } @@ -867,7 +829,10 @@ namespace SourceGit.ViewModels lfsLock.Click += async (_, e) => { var log = _repo.CreateLog("Lock LFS file"); - var succ = await new Commands.LFS(_repo.FullPath).LockAsync(_repo.Remotes[0].Name, path, log); + var succ = await new Commands.LFS(_repo.FullPath) + .LockAsync(_repo.Remotes[0].Name, path, log) + .ConfigureAwait(false); + if (succ) App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!"); @@ -885,7 +850,10 @@ namespace SourceGit.ViewModels lockRemote.Click += async (_, e) => { var log = _repo.CreateLog("Lock LFS file"); - var succ = await new Commands.LFS(_repo.FullPath).LockAsync(remoteName, path, log); + var succ = await new Commands.LFS(_repo.FullPath) + .LockAsync(remoteName, path, log) + .ConfigureAwait(false); + if (succ) App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!"); @@ -905,7 +873,10 @@ namespace SourceGit.ViewModels lfsUnlock.Click += async (_, e) => { var log = _repo.CreateLog("Unlock LFS file"); - var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(_repo.Remotes[0].Name, path, false, log); + var succ = await new Commands.LFS(_repo.FullPath) + .UnlockAsync(_repo.Remotes[0].Name, path, false, log) + .ConfigureAwait(false); + if (succ) App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!"); @@ -923,7 +894,10 @@ namespace SourceGit.ViewModels unlockRemote.Click += async (_, e) => { var log = _repo.CreateLog("Unlock LFS file"); - var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(remoteName, path, false, log); + var succ = await new Commands.LFS(_repo.FullPath) + .UnlockAsync(remoteName, path, false, log) + .ConfigureAwait(false); + if (succ) App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!"); @@ -953,8 +927,11 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var files = await new Commands.QueryRevisionFileNames(_repo.FullPath, sha).ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => + var files = await new Commands.QueryRevisionFileNames(_repo.FullPath, sha) + .GetResultAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => { if (sha == Commit.SHA && _requestingRevisionFiles) { @@ -995,7 +972,83 @@ namespace SourceGit.ViewModels RevisionFileSearchSuggestion = suggestion; } - private async Task ResetToThisRevision(string path) + private async Task SetViewingBlobAsync(Models.Object file) + { + var isBinary = await new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path) + .GetResultAsync() + .ConfigureAwait(false); + + if (isBinary) + { + var imgDecoder = ImageSource.GetDecoder(file.Path); + if (imgDecoder != Models.ImageDecoder.None) + { + var source = await ImageSource.FromRevisionAsync(_repo.FullPath, _commit.SHA, file.Path, imgDecoder).ConfigureAwait(false); + ViewRevisionFileContent = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size); + } + else + { + var size = await new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA) + .GetResultAsync() + .ConfigureAwait(false); + ViewRevisionFileContent = new Models.RevisionBinaryFile() { Size = size }; + } + + return; + } + + var contentStream = await Commands.QueryFileContent + .RunAsync(_repo.FullPath, _commit.SHA, file.Path) + .ConfigureAwait(false); + var content = await new StreamReader(contentStream) + .ReadToEndAsync() + .ConfigureAwait(false); + + var lfs = Models.LFSObject.Parse(content); + if (lfs != null) + { + var imgDecoder = ImageSource.GetDecoder(file.Path); + if (imgDecoder != Models.ImageDecoder.None) + ViewRevisionFileContent = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder); + else + ViewRevisionFileContent = new Models.RevisionLFSObject() { Object = lfs }; + } + else + { + ViewRevisionFileContent = new Models.RevisionTextFile() { FileName = file.Path, Content = content }; + } + } + + private async Task SetViewingCommitAsync(Models.Object file) + { + var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/'); + var commit = await new Commands.QuerySingleCommit(submoduleRoot, file.SHA) + .GetResultAsync() + .ConfigureAwait(false); + + if (commit == null) + { + ViewRevisionFileContent = new Models.RevisionSubmodule() + { + Commit = new Models.Commit() { SHA = file.SHA }, + FullMessage = new Models.CommitFullMessage() + }; + } + else + { + var message = await new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA) + .GetResultAsync() + .ConfigureAwait(false); + + ViewRevisionFileContent = new Models.RevisionSubmodule() + { + Commit = commit, + FullMessage = new Models.CommitFullMessage { Message = message } + }; + } + } + + private async Task ResetToThisRevisionAsync(string path) { var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'"); @@ -1003,7 +1056,7 @@ namespace SourceGit.ViewModels log.Complete(); } - private async Task ResetToParentRevision(Models.Change change) + private async Task ResetToParentRevisionAsync(Models.Change change) { var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'"); diff --git a/src/ViewModels/Confirm.cs b/src/ViewModels/Confirm.cs deleted file mode 100644 index ecbda72c..00000000 --- a/src/ViewModels/Confirm.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; - -namespace SourceGit.ViewModels -{ - public class Confirm - { - public string Message - { - get; - private set; - } - - public Confirm(string message, Action onSure, Action onCancel = null) - { - Message = message; - _onSure = onSure; - _onCancel = onCancel; - } - - public void Done(bool isSure) - { - if (isSure) - _onSure?.Invoke(); - else - _onCancel?.Invoke(); - } - - private Action _onSure; - private Action _onCancel; - } -} diff --git a/src/ViewModels/Conflict.cs b/src/ViewModels/Conflict.cs index bf93b5bc..a9ddfb7a 100644 --- a/src/ViewModels/Conflict.cs +++ b/src/ViewModels/Conflict.cs @@ -17,9 +17,13 @@ namespace SourceGit.ViewModels public ConflictSourceBranch(Repository repo, Models.Branch branch) { + var revision = new Commands.QuerySingleCommit(repo.FullPath, branch.Head).GetResultAsync().Result; + if (revision == null) + revision = new Models.Commit() { SHA = branch.Head }; + Name = branch.Name; Head = branch.Head; - Revision = new Commands.QuerySingleCommit(repo.FullPath, branch.Head).Result() ?? new Models.Commit() { SHA = branch.Head }; + Revision = revision; } } @@ -65,10 +69,10 @@ namespace SourceGit.ViewModels _change = change; var isSubmodule = repo.Submodules.Find(x => x.Path.Equals(change.Path, StringComparison.Ordinal)) != null; - if (!isSubmodule && (_change.ConflictReason == Models.ConflictReason.BothAdded || _change.ConflictReason == Models.ConflictReason.BothModified)) + if (!isSubmodule && (_change.ConflictReason is Models.ConflictReason.BothAdded or Models.ConflictReason.BothModified)) { CanUseExternalMergeTool = true; - IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).Result(); + IsResolved = new Commands.IsConflictResolved(repo.FullPath, change).GetResultAsync().Result; } var context = wc.InProgressContext; diff --git a/src/ViewModels/CreateBranch.cs b/src/ViewModels/CreateBranch.cs index 116d4976..e8c5bbff 100644 --- a/src/ViewModels/CreateBranch.cs +++ b/src/ViewModels/CreateBranch.cs @@ -125,10 +125,14 @@ namespace SourceGit.ViewModels var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules; bool succ; - if (CheckoutAfterCreated && !_repo.ConfirmCheckoutBranch()) + if (CheckoutAfterCreated) { - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); - return true; + var confirmed = await _repo.ConfirmCheckoutBranchAsync(); + if (!confirmed) + { + _repo.SetWatcherEnabled(true); + return true; + } } if (CheckoutAfterCreated && !_repo.IsBare) @@ -136,71 +140,94 @@ namespace SourceGit.ViewModels var needPopStash = false; if (DiscardLocalChanges) { - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(fixedName, _baseOnRevision, true, _allowOverwrite); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(fixedName, _baseOnRevision, true, _allowOverwrite) + .ConfigureAwait(false); } else { - var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync(); + var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (changes > 0) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CREATE_BRANCH_AUTO_STASH"); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("CREATE_BRANCH_AUTO_STASH") + .ConfigureAwait(false); + if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } needPopStash = true; } - succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(fixedName, _baseOnRevision, false, _allowOverwrite); + succ = await new Commands.Checkout(_repo.FullPath) + .Use(log) + .BranchAsync(fixedName, _baseOnRevision, false, _allowOverwrite) + .ConfigureAwait(false); } if (succ) { if (updateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + if (submodules.Count > 0) - await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(_repo.FullPath) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } if (needPopStash) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); } } else { - succ = await Commands.Branch.CreateAsync(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log); + succ = await Commands.Branch + .CreateAsync(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log) + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => + if (succ && CheckoutAfterCreated) { - if (succ && CheckoutAfterCreated) - { - var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" }; - if (BasedOn is Models.Branch { IsLocal: false } based) - fake.Upstream = based.FullName; + var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" }; + if (BasedOn is Models.Branch { IsLocal: false } based) + fake.Upstream = based.FullName; - var folderEndIdx = fake.FullName.LastIndexOf('/'); - if (folderEndIdx > 10) - _repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx)); + var folderEndIdx = fake.FullName.LastIndexOf('/'); + if (folderEndIdx > 10) + _repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx)); - if (_repo.HistoriesFilterMode == Models.FilterMode.Included) - _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false); + if (_repo.HistoriesFilterMode == Models.FilterMode.Included) + _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false); - ProgressDescription = "Waiting for branch updated..."; - } + } - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); if (CheckoutAfterCreated) - Task.Delay(400).Wait(); + { + ProgressDescription = "Waiting for branch updated..."; + await Task.Delay(400); + } return true; } diff --git a/src/ViewModels/CreateGroup.cs b/src/ViewModels/CreateGroup.cs index fb0218f0..eb8ef2b5 100644 --- a/src/ViewModels/CreateGroup.cs +++ b/src/ViewModels/CreateGroup.cs @@ -29,7 +29,7 @@ namespace SourceGit.ViewModels }, _parent, true); Welcome.Instance.Refresh(); - return null; + return Task.FromResult(true); } private readonly RepositoryNode _parent = null; diff --git a/src/ViewModels/CreateTag.cs b/src/ViewModels/CreateTag.cs index b6683a8f..51bc0d09 100644 --- a/src/ViewModels/CreateTag.cs +++ b/src/ViewModels/CreateTag.cs @@ -51,7 +51,7 @@ namespace SourceGit.ViewModels _basedOn = branch.Head; BasedOn = branch; - SignTag = new Commands.Config(repo.FullPath).Get("tag.gpgsign").Equals("true", StringComparison.OrdinalIgnoreCase); + SignTag = new Commands.Config(repo.FullPath).GetAsync("tag.gpgsign").Result.Equals("true", StringComparison.OrdinalIgnoreCase); } public CreateTag(Repository repo, Models.Commit commit) @@ -60,7 +60,7 @@ namespace SourceGit.ViewModels _basedOn = commit.SHA; BasedOn = commit; - SignTag = new Commands.Config(repo.FullPath).Get("tag.gpgsign").Equals("true", StringComparison.OrdinalIgnoreCase); + SignTag = new Commands.Config(repo.FullPath).GetAsync("tag.gpgsign").Result.Equals("true", StringComparison.OrdinalIgnoreCase); } public static ValidationResult ValidateTagName(string name, ValidationContext ctx) @@ -85,18 +85,21 @@ namespace SourceGit.ViewModels bool succ; if (_annotated) - succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log); + succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log).ConfigureAwait(false); else - succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, log); + succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, log).ConfigureAwait(false); if (succ && remotes != null) { foreach (var remote in remotes) - await new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Use(log).ExecAsync(); + await new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/DeinitSubmodule.cs b/src/ViewModels/DeinitSubmodule.cs index 0fa26acb..dfceba04 100644 --- a/src/ViewModels/DeinitSubmodule.cs +++ b/src/ViewModels/DeinitSubmodule.cs @@ -31,9 +31,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("De-initialize Submodule"); Use(log); - var succ = await new Commands.Submodule(_repo.FullPath).Use(log).DeinitAsync(Submodule, false); + var succ = await new Commands.Submodule(_repo.FullPath) + .Use(log) + .DeinitAsync(Submodule, false) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/DeleteBranch.cs b/src/ViewModels/DeleteBranch.cs index 48109eab..2b18fbe9 100644 --- a/src/ViewModels/DeleteBranch.cs +++ b/src/ViewModels/DeleteBranch.cs @@ -49,23 +49,26 @@ namespace SourceGit.ViewModels if (Target.IsLocal) { - await Commands.Branch.DeleteLocalAsync(_repo.FullPath, Target.Name, log); + await Commands.Branch + .DeleteLocalAsync(_repo.FullPath, Target.Name, log) + .ConfigureAwait(false); if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null) - await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log); + await Commands.Branch + .DeleteRemoteAsync(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log) + .ConfigureAwait(false); } else { - await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, Target.Remote, Target.Name, log); + await Commands.Branch + .DeleteRemoteAsync(_repo.FullPath, Target.Remote, Target.Name, log) + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => - { - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/DeleteMultipleBranches.cs b/src/ViewModels/DeleteMultipleBranches.cs index 57ac06dc..40400d42 100644 --- a/src/ViewModels/DeleteMultipleBranches.cs +++ b/src/ViewModels/DeleteMultipleBranches.cs @@ -28,22 +28,21 @@ namespace SourceGit.ViewModels if (_isLocal) { foreach (var target in Targets) - await Commands.Branch.DeleteLocalAsync(_repo.FullPath, target.Name, log); + await Commands.Branch + .DeleteLocalAsync(_repo.FullPath, target.Name, log) + .ConfigureAwait(false); } else { foreach (var target in Targets) - await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, target.Remote, target.Name, log); + await Commands.Branch + .DeleteRemoteAsync(_repo.FullPath, target.Remote, target.Name, log) + .ConfigureAwait(false); } log.Complete(); - - await CallUIThreadAsync(() => - { - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/DeleteRemote.cs b/src/ViewModels/DeleteRemote.cs index 90d7e205..4e849d8c 100644 --- a/src/ViewModels/DeleteRemote.cs +++ b/src/ViewModels/DeleteRemote.cs @@ -24,14 +24,14 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Delete Remote"); Use(log); - var succ = await new Commands.Remote(_repo.FullPath).Use(log).DeleteAsync(Remote.Name); - log.Complete(); + var succ = await new Commands.Remote(_repo.FullPath) + .Use(log) + .DeleteAsync(Remote.Name) + .ConfigureAwait(false); - await CallUIThreadAsync(() => - { - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + log.Complete(); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/DeleteRepositoryNode.cs b/src/ViewModels/DeleteRepositoryNode.cs index 38e03d9f..59ef60ea 100644 --- a/src/ViewModels/DeleteRepositoryNode.cs +++ b/src/ViewModels/DeleteRepositoryNode.cs @@ -18,7 +18,7 @@ namespace SourceGit.ViewModels { Preferences.Instance.RemoveNode(Node, true); Welcome.Instance.Refresh(); - return null; + return Task.FromResult(true); } } } diff --git a/src/ViewModels/DeleteSubmodule.cs b/src/ViewModels/DeleteSubmodule.cs index 930009de..24153dcb 100644 --- a/src/ViewModels/DeleteSubmodule.cs +++ b/src/ViewModels/DeleteSubmodule.cs @@ -24,9 +24,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Delete Submodule"); Use(log); - var succ = await new Commands.Submodule(_repo.FullPath).Use(log).DeleteAsync(Submodule); + var succ = await new Commands.Submodule(_repo.FullPath) + .Use(log) + .DeleteAsync(Submodule) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/DeleteTag.cs b/src/ViewModels/DeleteTag.cs index bcc37ee7..98db0505 100644 --- a/src/ViewModels/DeleteTag.cs +++ b/src/ViewModels/DeleteTag.cs @@ -31,20 +31,22 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Delete Tag"); Use(log); - var succ = await Commands.Tag.DeleteAsync(_repo.FullPath, Target.Name, log); + var succ = await Commands.Tag + .DeleteAsync(_repo.FullPath, Target.Name, log) + .ConfigureAwait(false); + if (succ) { foreach (var r in remotes) - await new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true).Use(log).ExecAsync(); + await new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); - - await CallUIThreadAsync(() => - { - _repo.MarkTagsDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + _repo.MarkTagsDirtyManually(); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 6514f0db..5b772fc8 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -113,7 +113,11 @@ namespace SourceGit.ViewModels { var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines; var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff; - var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).ResultAsync(); + + var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace) + .ReadAsync() + .ConfigureAwait(false); + var info = new Info(_option, numLines, ignoreWhitespace, latest); if (_info != null && info.IsSame(_info)) return; @@ -141,9 +145,9 @@ namespace SourceGit.ViewModels var sha = line.Content.Substring(18); if (line.Type == Models.TextDiffLineType.Added) - submoduleDiff.New = QuerySubmoduleRevision(submoduleRoot, sha); + submoduleDiff.New = await QuerySubmoduleRevisionAsync(submoduleRoot, sha).ConfigureAwait(false); else if (line.Type == Models.TextDiffLineType.Deleted) - submoduleDiff.Old = QuerySubmoduleRevision(submoduleRoot, sha); + submoduleDiff.Old = await QuerySubmoduleRevisionAsync(submoduleRoot, sha).ConfigureAwait(false); } if (isSubmodule) @@ -167,8 +171,8 @@ namespace SourceGit.ViewModels if (_option.Revisions.Count == 2) { - var oldImage = ImageSource.FromRevision(_repo, _option.Revisions[0], oldPath, imgDecoder); - var newImage = ImageSource.FromRevision(_repo, _option.Revisions[1], _option.Path, imgDecoder); + var oldImage = await ImageSource.FromRevisionAsync(_repo, _option.Revisions[0], oldPath, imgDecoder).ConfigureAwait(false); + var newImage = await ImageSource.FromRevisionAsync(_repo, _option.Revisions[1], _option.Path, imgDecoder).ConfigureAwait(false); imgDiff.Old = oldImage.Bitmap; imgDiff.OldFileSize = oldImage.Size; imgDiff.New = newImage.Bitmap; @@ -178,7 +182,7 @@ namespace SourceGit.ViewModels { if (!oldPath.Equals("/dev/null", StringComparison.Ordinal)) { - var oldImage = ImageSource.FromRevision(_repo, "HEAD", oldPath, imgDecoder); + var oldImage = await ImageSource.FromRevisionAsync(_repo, "HEAD", oldPath, imgDecoder).ConfigureAwait(false); imgDiff.Old = oldImage.Bitmap; imgDiff.OldFileSize = oldImage.Size; } @@ -186,7 +190,7 @@ namespace SourceGit.ViewModels var fullPath = Path.Combine(_repo, _option.Path); if (File.Exists(fullPath)) { - var newImage = ImageSource.FromFile(fullPath, imgDecoder); + var newImage = await ImageSource.FromFileAsync(fullPath, imgDecoder).ConfigureAwait(false); imgDiff.New = newImage.Bitmap; imgDiff.NewFileSize = newImage.Size; } @@ -199,13 +203,13 @@ namespace SourceGit.ViewModels var binaryDiff = new Models.BinaryDiff(); if (_option.Revisions.Count == 2) { - binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).ResultAsync(); - binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).ResultAsync(); + binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).GetResultAsync().ConfigureAwait(false); + binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).GetResultAsync().ConfigureAwait(false); } else { var fullPath = Path.Combine(_repo, _option.Path); - binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").ResultAsync(); + binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").GetResultAsync().ConfigureAwait(false); binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0; } rs = binaryDiff; @@ -236,13 +240,13 @@ namespace SourceGit.ViewModels }); } - private Models.RevisionSubmodule QuerySubmoduleRevision(string repo, string sha) + private async Task QuerySubmoduleRevisionAsync(string repo, string sha) { - var commit = new Commands.QuerySingleCommit(repo, sha).Result(); + var commit = await new Commands.QuerySingleCommit(repo, sha).GetResultAsync().ConfigureAwait(false); if (commit == null) return new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = sha } }; - var body = new Commands.QueryCommitFullMessage(repo, sha).Result(); + var body = await new Commands.QueryCommitFullMessage(repo, sha).GetResultAsync().ConfigureAwait(false); return new Models.RevisionSubmodule() { Commit = commit, diff --git a/src/ViewModels/DirHistories.cs b/src/ViewModels/DirHistories.cs index 0fbecb25..6b4aa039 100644 --- a/src/ViewModels/DirHistories.cs +++ b/src/ViewModels/DirHistories.cs @@ -53,8 +53,11 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision ?? string.Empty} -- \"{dir}\"", false).ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => + var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision ?? string.Empty} -- \"{dir}\"", false) + .GetResultAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => { Commits = commits; IsLoading = false; @@ -76,7 +79,7 @@ namespace SourceGit.ViewModels if (_cachedCommitFullMessage.TryGetValue(sha, out var msg)) return msg; - msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).Result(); + msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).GetResultAsync().Result; _cachedCommitFullMessage[sha] = msg; return msg; } diff --git a/src/ViewModels/Discard.cs b/src/ViewModels/Discard.cs index 6433ca9d..e0a87641 100644 --- a/src/ViewModels/Discard.cs +++ b/src/ViewModels/Discard.cs @@ -65,18 +65,13 @@ namespace SourceGit.ViewModels Use(log); if (Mode is DiscardAllMode all) - await Commands.Discard.AllAsync(_repo.FullPath, all.IncludeIgnored, log); + await Commands.Discard.AllAsync(_repo.FullPath, all.IncludeIgnored, log).ConfigureAwait(false); else - await Commands.Discard.ChangesAsync(_repo.FullPath, _changes, log); + await Commands.Discard.ChangesAsync(_repo.FullPath, _changes, log).ConfigureAwait(false); log.Complete(); - - await CallUIThreadAsync(() => - { - _repo.MarkWorkingCopyDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - + _repo.MarkWorkingCopyDirtyManually(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/DropStash.cs b/src/ViewModels/DropStash.cs index 1c2ca6ea..3ae5090c 100644 --- a/src/ViewModels/DropStash.cs +++ b/src/ViewModels/DropStash.cs @@ -19,7 +19,11 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Drop Stash"); Use(log); - await new Commands.Stash(_repo.FullPath).Use(log).DropAsync(Stash.Name); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .DropAsync(Stash.Name) + .ConfigureAwait(false); + log.Complete(); return true; } diff --git a/src/ViewModels/EditRemote.cs b/src/ViewModels/EditRemote.cs index 09833205..378c092b 100644 --- a/src/ViewModels/EditRemote.cs +++ b/src/ViewModels/EditRemote.cs @@ -54,7 +54,7 @@ namespace SourceGit.ViewModels if (_useSSH) { - SSHKey = new Commands.Config(repo.FullPath).Get($"remote.{remote.Name}.sshkey"); + SSHKey = new Commands.Config(repo.FullPath).GetAsync($"remote.{remote.Name}.sshkey").Result; } } @@ -107,25 +107,36 @@ namespace SourceGit.ViewModels if (_remote.Name != _name) { - var succ = await new Commands.Remote(_repo.FullPath).RenameAsync(_remote.Name, _name); + var succ = await new Commands.Remote(_repo.FullPath) + .RenameAsync(_remote.Name, _name) + .ConfigureAwait(false); if (succ) _remote.Name = _name; } if (_remote.URL != _url) { - var succ = await new Commands.Remote(_repo.FullPath).SetURLAsync(_name, _url, false); + var succ = await new Commands.Remote(_repo.FullPath) + .SetURLAsync(_name, _url, false) + .ConfigureAwait(false); if (succ) _remote.URL = _url; } - var pushURL = await new Commands.Remote(_repo.FullPath).GetURLAsync(_name, true); + var pushURL = await new Commands.Remote(_repo.FullPath) + .GetURLAsync(_name, true) + .ConfigureAwait(false); + if (pushURL != _url) - await new Commands.Remote(_repo.FullPath).SetURLAsync(_name, _url, true); + await new Commands.Remote(_repo.FullPath) + .SetURLAsync(_name, _url, true) + .ConfigureAwait(false); - await new Commands.Config(_repo.FullPath).SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null); + await new Commands.Config(_repo.FullPath) + .SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null) + .ConfigureAwait(false); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/EditRepositoryNode.cs b/src/ViewModels/EditRepositoryNode.cs index 599b7f63..38d072a1 100644 --- a/src/ViewModels/EditRepositoryNode.cs +++ b/src/ViewModels/EditRepositoryNode.cs @@ -51,7 +51,7 @@ namespace SourceGit.ViewModels Welcome.Instance.Refresh(); } - return null; + return Task.FromResult(true); } private RepositoryNode _node = null; diff --git a/src/ViewModels/ExecuteCustomAction.cs b/src/ViewModels/ExecuteCustomAction.cs index c4449640..daffdc52 100644 --- a/src/ViewModels/ExecuteCustomAction.cs +++ b/src/ViewModels/ExecuteCustomAction.cs @@ -169,12 +169,12 @@ namespace SourceGit.ViewModels log.AppendLine($"$ {CustomAction.Executable} {cmdline}\n"); if (CustomAction.WaitForExit) - RunAndWait(cmdline, log); + await RunAsync(cmdline, log); else - Run(cmdline); + _ = Task.Run(() => Run(cmdline)); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } @@ -237,7 +237,7 @@ namespace SourceGit.ViewModels } } - private void RunAndWait(string args, Models.ICommandLog log) + private async Task RunAsync(string args, Models.ICommandLog log) { var start = new ProcessStartInfo(); start.FileName = CustomAction.Executable; @@ -273,7 +273,7 @@ namespace SourceGit.ViewModels proc.Start(); proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); - proc.WaitForExit(); + await proc.WaitForExitAsync().ConfigureAwait(false); var exitCode = proc.ExitCode; if (exitCode != 0) diff --git a/src/ViewModels/Fetch.cs b/src/ViewModels/Fetch.cs index 00b3de5e..4b875bfd 100644 --- a/src/ViewModels/Fetch.cs +++ b/src/ViewModels/Fetch.cs @@ -66,29 +66,32 @@ namespace SourceGit.ViewModels if (FetchAllRemotes) { foreach (var remote in _repo.Remotes) - await new Commands.Fetch(_repo.FullPath, remote.Name, notags, force).Use(log).ExecAsync(); + await new Commands.Fetch(_repo.FullPath, remote.Name, notags, force) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } else { - await new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force).Use(log).ExecAsync(); + await new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); var upstream = _repo.CurrentBranch?.Upstream; - var upstreamHead = string.Empty; if (!string.IsNullOrEmpty(upstream)) - upstreamHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, upstream.Substring(13)).ResultAsync(); - - await CallUIThreadAsync(() => { - if (!string.IsNullOrEmpty(upstreamHead)) - _repo.NavigateToCommit(upstreamHead, true); - - _repo.MarkFetched(); - _repo.SetWatcherEnabled(true); - }); + var upstreamHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, upstream.Substring(13)) + .GetResultAsync() + .ConfigureAwait(false); + _repo.NavigateToCommit(upstreamHead, true); + } + _repo.MarkFetched(); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/FetchInto.cs b/src/ViewModels/FetchInto.cs index 89fad2a1..b6723c51 100644 --- a/src/ViewModels/FetchInto.cs +++ b/src/ViewModels/FetchInto.cs @@ -29,16 +29,19 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Fetch Into '{Local.FriendlyName}'"); Use(log); - await new Commands.Fetch(_repo.FullPath, Local, Upstream).Use(log).ExecAsync(); + await new Commands.Fetch(_repo.FullPath, Local, Upstream) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - var changedLocalBranchHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).ResultAsync(); - await CallUIThreadAsync(() => - { - _repo.NavigateToCommit(changedLocalBranchHead, true); - _repo.SetWatcherEnabled(true); - }); + var newHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name) + .GetResultAsync() + .ConfigureAwait(false); + _repo.NavigateToCommit(newHead, true); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 051414dc..ad4ce461 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -45,12 +45,14 @@ namespace SourceGit.ViewModels RefreshViewContent(); } - public async Task ResetToSelectedRevision() + public async Task ResetToSelectedRevisionAsync() { - return await new Commands.Checkout(_repo.FullPath).FileWithRevisionAsync(_file, $"{_revision.SHA}"); + return await new Commands.Checkout(_repo.FullPath) + .FileWithRevisionAsync(_file, $"{_revision.SHA}") + .ConfigureAwait(false); } - public async Task OpenWithDefaultEditor() + public async Task OpenWithDefaultEditorAsync() { if (_viewContent is not FileHistoriesRevisionFile { CanOpenWithDefaultEditor: true }) return; @@ -60,7 +62,10 @@ namespace SourceGit.ViewModels var fileExt = Path.GetExtension(fullPath) ?? ""; var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_revision.SHA.Substring(0, 10)}{fileExt}"); - await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _revision.SHA, _file, tmpFile); + await Commands.SaveRevisionFile + .RunAsync(_repo.FullPath, _revision.SHA, _file, tmpFile) + .ConfigureAwait(false); + Native.OS.OpenWithDefaultEditor(tmpFile); } @@ -74,7 +79,7 @@ namespace SourceGit.ViewModels private void SetViewContentAsRevisionFile() { - var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _revision.SHA, _file).Result(); + var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _revision.SHA, _file).GetResultAsync().Result; if (objs.Count == 0) { ViewContent = new FileHistoriesRevisionFile(_file); @@ -87,27 +92,27 @@ namespace SourceGit.ViewModels case Models.ObjectType.Blob: Task.Run(async () => { - var isBinary = await new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).ResultAsync(); + var isBinary = await new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).GetResultAsync().ConfigureAwait(false); if (isBinary) { var imgDecoder = ImageSource.GetDecoder(_file); if (imgDecoder != Models.ImageDecoder.None) { - var source = ImageSource.FromRevision(_repo.FullPath, _revision.SHA, _file, imgDecoder); + var source = await ImageSource.FromRevisionAsync(_repo.FullPath, _revision.SHA, _file, imgDecoder).ConfigureAwait(false); var image = new Models.RevisionImageFile(_file, source.Bitmap, source.Size); - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, image, true)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, image, true)); } else { - var size = await new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).ResultAsync(); + var size = await new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).GetResultAsync().ConfigureAwait(false); var binaryFile = new Models.RevisionBinaryFile() { Size = size }; - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile, true)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile, true)); } return; } - var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _revision.SHA, _file); + var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _revision.SHA, _file).ConfigureAwait(false); var content = await new StreamReader(contentStream).ReadToEndAsync(); var lfs = Models.LFSObject.Parse(content); if (lfs != null) @@ -116,18 +121,18 @@ namespace SourceGit.ViewModels if (imgDecoder != Models.ImageDecoder.None) { var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder); - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, combined, true)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, combined, true)); } else { var rlfs = new Models.RevisionLFSObject() { Object = lfs }; - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs, true)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs, true)); } } else { var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content }; - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, txt, true)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, txt, true)); } }); break; @@ -135,15 +140,15 @@ namespace SourceGit.ViewModels Task.Run(async () => { var submoduleRoot = Path.Combine(_repo.FullPath, _file); - var commit = await new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).ResultAsync(); - var message = commit != null ? await new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).ResultAsync() : null; + var commit = await new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).GetResultAsync().ConfigureAwait(false); + var message = commit != null ? await new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).GetResultAsync().ConfigureAwait(false) : null; var module = new Models.RevisionSubmodule() { Commit = commit ?? new Models.Commit() { SHA = obj.SHA }, FullMessage = new Models.CommitFullMessage { Message = message } }; - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); + Dispatcher.UIThread.Post(() => ViewContent = new FileHistoriesRevisionFile(_file, module)); }); break; default: @@ -202,25 +207,25 @@ namespace SourceGit.ViewModels public async Task SaveAsPatch(string saveTo) { - { - await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, _changes, _startPoint.SHA, _endPoint.SHA, saveTo); - return true; - } + return await Commands.SaveChangesAsPatch + .ProcessRevisionCompareChangesAsync(_repo.FullPath, _changes, _startPoint.SHA, _endPoint.SHA, saveTo) + .ConfigureAwait(false); } private void RefreshViewContent() { Task.Run(async () => { - _changes = await new Commands.CompareRevisions(_repo.FullPath, _startPoint.SHA, _endPoint.SHA, _file).ResultAsync(); + _changes = await new Commands.CompareRevisions(_repo.FullPath, _startPoint.SHA, _endPoint.SHA, _file).ReadAsync().ConfigureAwait(false); if (_changes.Count == 0) { - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = null); - return; + Dispatcher.UIThread.Post(() => ViewContent = null); + } + else + { + var option = new Models.DiffOption(_startPoint.SHA, _endPoint.SHA, _changes[0]); + Dispatcher.UIThread.Post(() => ViewContent = new DiffContext(_repo.FullPath, option, _viewContent)); } - - var option = new Models.DiffOption(_startPoint.SHA, _endPoint.SHA, _changes[0]); - await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new DiffContext(_repo.FullPath, option, _viewContent)); }); } @@ -274,9 +279,11 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var based = commit ?? string.Empty; - var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {based} -- \"{file}\"", false).ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => + var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {commit ?? string.Empty} -- \"{file}\"", false) + .GetResultAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => { IsLoading = false; Commits = commits; @@ -310,7 +317,7 @@ namespace SourceGit.ViewModels if (_fullCommitMessages.TryGetValue(sha, out var msg)) return msg; - msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).Result(); + msg = new Commands.QueryCommitFullMessage(_repo.FullPath, sha).GetResultAsync().Result; _fullCommitMessages[sha] = msg; return msg; } diff --git a/src/ViewModels/GitFlowFinish.cs b/src/ViewModels/GitFlowFinish.cs index 7ae3deaa..63e5aac3 100644 --- a/src/ViewModels/GitFlowFinish.cs +++ b/src/ViewModels/GitFlowFinish.cs @@ -51,9 +51,12 @@ namespace SourceGit.ViewModels var prefix = _repo.GitFlow.GetPrefix(Type); var name = Branch.Name.StartsWith(prefix) ? Branch.Name.Substring(prefix.Length) : Branch.Name; - var succ = await Commands.GitFlow.FinishAsync(_repo.FullPath, Type, name, Squash, AutoPush, KeepBranch, log); + var succ = await Commands.GitFlow + .FinishAsync(_repo.FullPath, Type, name, Squash, AutoPush, KeepBranch, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/GitFlowStart.cs b/src/ViewModels/GitFlowStart.cs index 29110c8c..58d03087 100644 --- a/src/ViewModels/GitFlowStart.cs +++ b/src/ViewModels/GitFlowStart.cs @@ -57,9 +57,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("GitFlow - Start"); Use(log); - var succ = await Commands.GitFlow.StartAsync(_repo.FullPath, Type, _name, log); + var succ = await Commands.GitFlow + .StartAsync(_repo.FullPath, Type, _name, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index b0642b49..243758b9 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -139,7 +139,7 @@ namespace SourceGit.ViewModels if (commit == null) { AutoSelectedCommit = null; - commit = new Commands.QuerySingleCommit(_repo.FullPath, commitSHA).Result(); + commit = new Commands.QuerySingleCommit(_repo.FullPath, commitSHA).GetResultAsync().Result; } else { @@ -415,26 +415,26 @@ namespace SourceGit.ViewModels var copyMultipleSHAs = new MenuItem(); copyMultipleSHAs.Header = App.Text("CommitCM.CopySHA"); copyMultipleSHAs.Icon = App.CreateMenuIcon("Icons.Fingerprint"); - copyMultipleSHAs.Click += (_, e) => + copyMultipleSHAs.Click += async (_, e) => { var builder = new StringBuilder(); foreach (var c in selected) builder.AppendLine(c.SHA); - App.CopyText(builder.ToString()); + await App.CopyTextAsync(builder.ToString()); e.Handled = true; }; var copyMultipleInfo = new MenuItem(); copyMultipleInfo.Header = App.Text("CommitCM.CopyInfo"); copyMultipleInfo.Icon = App.CreateMenuIcon("Icons.Info"); - copyMultipleInfo.Click += (_, e) => + copyMultipleInfo.Click += async (_, e) => { var builder = new StringBuilder(); foreach (var c in selected) builder.AppendLine($"{c.SHA.AsSpan(0, 10)} - {c.Subject}"); - App.CopyText(builder.ToString()); + await App.CopyTextAsync(builder.ToString()); e.Handled = true; }; @@ -600,7 +600,9 @@ namespace SourceGit.ViewModels var parents = new List(); foreach (var sha in commit.Parents) { - var parent = _commits.Find(x => x.SHA == sha) ?? await new Commands.QuerySingleCommit(_repo.FullPath, sha).ResultAsync(); + var parent = _commits.Find(x => x.SHA == sha); + if (parent == null) + parent = await new Commands.QuerySingleCommit(_repo.FullPath, sha).GetResultAsync().ConfigureAwait(false); if (parent != null) parents.Add(parent); @@ -690,7 +692,7 @@ namespace SourceGit.ViewModels if (head == null) { _repo.SelectedSearchedCommit = null; - head = await new Commands.QuerySingleCommit(_repo.FullPath, current.Head).ResultAsync(); + head = await new Commands.QuerySingleCommit(_repo.FullPath, current.Head).GetResultAsync().ConfigureAwait(false); if (head != null) DetailContext = new RevisionCompare(_repo.FullPath, commit, head); } @@ -819,45 +821,45 @@ namespace SourceGit.ViewModels var copySHA = new MenuItem(); copySHA.Header = App.Text("CommitCM.CopySHA"); copySHA.Icon = App.CreateMenuIcon("Icons.Fingerprint"); - copySHA.Click += (_, e) => + copySHA.Click += async (_, e) => { - App.CopyText(commit.SHA); + await App.CopyTextAsync(commit.SHA); e.Handled = true; }; var copySubject = new MenuItem(); copySubject.Header = App.Text("CommitCM.CopySubject"); copySubject.Icon = App.CreateMenuIcon("Icons.Subject"); - copySubject.Click += (_, e) => + copySubject.Click += async (_, e) => { - App.CopyText(commit.Subject); + await App.CopyTextAsync(commit.Subject); e.Handled = true; }; var copyInfo = new MenuItem(); copyInfo.Header = App.Text("CommitCM.CopyInfo"); copyInfo.Icon = App.CreateMenuIcon("Icons.Info"); - copyInfo.Click += (_, e) => + copyInfo.Click += async (_, e) => { - App.CopyText($"{commit.SHA.AsSpan(0, 10)} - {commit.Subject}"); + await App.CopyTextAsync($"{commit.SHA.AsSpan(0, 10)} - {commit.Subject}"); e.Handled = true; }; var copyAuthor = new MenuItem(); copyAuthor.Header = App.Text("CommitCM.CopyAuthor"); copyAuthor.Icon = App.CreateMenuIcon("Icons.User"); - copyAuthor.Click += (_, e) => + copyAuthor.Click += async (_, e) => { - App.CopyText(commit.Author.ToString()); + await App.CopyTextAsync(commit.Author.ToString()); e.Handled = true; }; var copyCommitter = new MenuItem(); copyCommitter.Header = App.Text("CommitCM.CopyCommitter"); copyCommitter.Icon = App.CreateMenuIcon("Icons.User"); - copyCommitter.Click += (_, e) => + copyCommitter.Click += async (_, e) => { - App.CopyText(commit.Committer.ToString()); + await App.CopyTextAsync(commit.Committer.ToString()); e.Handled = true; }; @@ -965,9 +967,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(current.Name); + await App.CopyTextAsync(current.Name); e.Handled = true; }; submenu.Items.Add(copy); @@ -1057,9 +1059,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(branch.Name); + await App.CopyTextAsync(branch.Name); e.Handled = true; }; submenu.Items.Add(copy); @@ -1119,9 +1121,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(name); + await App.CopyTextAsync(name); e.Handled = true; }; submenu.Items.Add(copy); @@ -1183,9 +1185,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("TagCM.Copy"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(tag.Name); + await App.CopyTextAsync(tag.Name); e.Handled = true; }; submenu.Items.Add(copy); diff --git a/src/ViewModels/ImageSource.cs b/src/ViewModels/ImageSource.cs index 039403f4..348a2369 100644 --- a/src/ViewModels/ImageSource.cs +++ b/src/ViewModels/ImageSource.cs @@ -2,11 +2,10 @@ using System.Globalization; using System.IO; using System.Runtime.InteropServices; - +using System.Threading.Tasks; using Avalonia; using Avalonia.Media.Imaging; using Avalonia.Platform; - using BitMiracle.LibTiff.Classic; using Pfim; @@ -36,25 +35,25 @@ namespace SourceGit.ViewModels }; } - public static ImageSource FromFile(string fullpath, Models.ImageDecoder decoder) + public static async Task FromFileAsync(string fullpath, Models.ImageDecoder decoder) { - using (var stream = File.OpenRead(fullpath)) - return LoadFromStream(stream, decoder); + await using (var stream = File.OpenRead(fullpath)) + return await Task.Run(() => LoadFromStream(stream, decoder)); } - public static ImageSource FromRevision(string repo, string revision, string file, Models.ImageDecoder decoder) + public static async Task FromRevisionAsync(string repo, string revision, string file, Models.ImageDecoder decoder) { - var stream = Commands.QueryFileContent.Run(repo, revision, file); - return LoadFromStream(stream, decoder); + var stream = await Commands.QueryFileContent.RunAsync(repo, revision, file).ConfigureAwait(false); + return await Task.Run(() => LoadFromStream(stream, decoder)); } - public static ImageSource FromLFSObject(string repo, Models.LFSObject lfs, Models.ImageDecoder decoder) + public static async Task FromLFSObjectAsync(string repo, Models.LFSObject lfs, Models.ImageDecoder decoder) { if (string.IsNullOrEmpty(lfs.Oid) || lfs.Size == 0) return new ImageSource(null, 0); - var stream = Commands.QueryFileContent.FromLFS(repo, lfs.Oid, lfs.Size); - return LoadFromStream(stream, decoder); + var stream = await Commands.QueryFileContent.FromLFSAsync(repo, lfs.Oid, lfs.Size).ConfigureAwait(false); + return await Task.Run(() => LoadFromStream(stream, decoder)); } private static ImageSource LoadFromStream(Stream stream, Models.ImageDecoder decoder) diff --git a/src/ViewModels/InProgressContexts.cs b/src/ViewModels/InProgressContexts.cs index 922ad997..a1e7448c 100644 --- a/src/ViewModels/InProgressContexts.cs +++ b/src/ViewModels/InProgressContexts.cs @@ -75,7 +75,7 @@ namespace SourceGit.ViewModels public CherryPickInProgress(Repository repo) : base(repo.FullPath, "cherry-pick") { var headSHA = File.ReadAllText(Path.Combine(repo.GitDir, "CHERRY_PICK_HEAD")).Trim(); - Head = new Commands.QuerySingleCommit(repo.FullPath, headSHA).Result() ?? new Models.Commit() { SHA = headSHA }; + Head = new Commands.QuerySingleCommit(repo.FullPath, headSHA).GetResultAsync().Result ?? new Models.Commit() { SHA = headSHA }; } } @@ -115,13 +115,13 @@ namespace SourceGit.ViewModels var stoppedSHAPath = Path.Combine(repo.GitDir, "rebase-merge", "stopped-sha"); var stoppedSHA = File.Exists(stoppedSHAPath) ? File.ReadAllText(stoppedSHAPath).Trim() - : new Commands.QueryRevisionByRefName(repo.FullPath, HeadName).Result(); + : new Commands.QueryRevisionByRefName(repo.FullPath, HeadName).GetResultAsync().Result; if (!string.IsNullOrEmpty(stoppedSHA)) - StoppedAt = new Commands.QuerySingleCommit(repo.FullPath, stoppedSHA).Result() ?? new Models.Commit() { SHA = stoppedSHA }; + StoppedAt = new Commands.QuerySingleCommit(repo.FullPath, stoppedSHA).GetResultAsync().Result ?? new Models.Commit() { SHA = stoppedSHA }; var ontoSHA = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "onto")).Trim(); - Onto = new Commands.QuerySingleCommit(repo.FullPath, ontoSHA).Result() ?? new Models.Commit() { SHA = ontoSHA }; + Onto = new Commands.QuerySingleCommit(repo.FullPath, ontoSHA).GetResultAsync().Result ?? new Models.Commit() { SHA = ontoSHA }; } public override Task ContinueAsync() @@ -147,7 +147,7 @@ namespace SourceGit.ViewModels public RevertInProgress(Repository repo) : base(repo.FullPath, "revert") { var headSHA = File.ReadAllText(Path.Combine(repo.GitDir, "REVERT_HEAD")).Trim(); - Head = new Commands.QuerySingleCommit(repo.FullPath, headSHA).Result() ?? new Models.Commit() { SHA = headSHA }; + Head = new Commands.QuerySingleCommit(repo.FullPath, headSHA).GetResultAsync().Result ?? new Models.Commit() { SHA = headSHA }; } } @@ -172,10 +172,10 @@ namespace SourceGit.ViewModels public MergeInProgress(Repository repo) : base(repo.FullPath, "merge") { - Current = Commands.Branch.ShowCurrent(repo.FullPath); + Current = new Commands.QueryCurrentBranch(repo.FullPath).GetResultAsync().Result; var sourceSHA = File.ReadAllText(Path.Combine(repo.GitDir, "MERGE_HEAD")).Trim(); - Source = new Commands.QuerySingleCommit(repo.FullPath, sourceSHA).Result() ?? new Models.Commit() { SHA = sourceSHA }; + Source = new Commands.QuerySingleCommit(repo.FullPath, sourceSHA).GetResultAsync().Result ?? new Models.Commit() { SHA = sourceSHA }; } public override Task SkipAsync() diff --git a/src/ViewModels/Init.cs b/src/ViewModels/Init.cs index 7a5ebbbd..344ce4e4 100644 --- a/src/ViewModels/Init.cs +++ b/src/ViewModels/Init.cs @@ -31,18 +31,18 @@ namespace SourceGit.ViewModels var log = new CommandLog("Initialize"); Use(log); - var succ = await new Commands.Init(_pageId, _targetPath).Use(log).ExecAsync(); + var succ = await new Commands.Init(_pageId, _targetPath) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); if (succ) { - await CallUIThreadAsync(() => - { - Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true); - Welcome.Instance.Refresh(); - }); + Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true); + Welcome.Instance.Refresh(); } - return succ; } diff --git a/src/ViewModels/InitGitFlow.cs b/src/ViewModels/InitGitFlow.cs index 95084e61..31130ea1 100644 --- a/src/ViewModels/InitGitFlow.cs +++ b/src/ViewModels/InitGitFlow.cs @@ -114,11 +114,11 @@ namespace SourceGit.ViewModels var masterBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_master, StringComparison.Ordinal)); if (masterBranch == null) { - succ = await Commands.Branch.CreateAsync(_repo.FullPath, _master, current.Head, true, log); + succ = await Commands.Branch.CreateAsync(_repo.FullPath, _master, current.Head, true, log).ConfigureAwait(false); if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } } @@ -126,11 +126,11 @@ namespace SourceGit.ViewModels var developBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_develop, StringComparison.Ordinal)); if (developBranch == null) { - succ = await Commands.Branch.CreateAsync(_repo.FullPath, _develop, current.Head, true, log); + succ = await Commands.Branch.CreateAsync(_repo.FullPath, _develop, current.Head, true, log).ConfigureAwait(false); if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } } @@ -143,26 +143,22 @@ namespace SourceGit.ViewModels _releasePrefix, _hotfixPrefix, _tagPrefix, - log); + log).ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => + if (succ) { - if (succ) - { - var gitflow = new Models.GitFlow(); - gitflow.Master = _master; - gitflow.Develop = _develop; - gitflow.FeaturePrefix = _featurePrefix; - gitflow.ReleasePrefix = _releasePrefix; - gitflow.HotfixPrefix = _hotfixPrefix; - _repo.GitFlow = gitflow; - } - - _repo.SetWatcherEnabled(true); - }); + var gitflow = new Models.GitFlow(); + gitflow.Master = _master; + gitflow.Develop = _develop; + gitflow.FeaturePrefix = _featurePrefix; + gitflow.ReleasePrefix = _releasePrefix; + gitflow.HotfixPrefix = _hotfixPrefix; + _repo.GitFlow = gitflow; + } + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index b59e2c3a..fda6f847 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -133,7 +133,7 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var commits = await new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).ResultAsync(); + var commits = await new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).GetResultAsync().ConfigureAwait(false); var list = new List(); for (var i = 0; i < commits.Count; i++) @@ -142,7 +142,7 @@ namespace SourceGit.ViewModels list.Add(new InteractiveRebaseItem(c.Commit, c.Message, i < commits.Count - 1)); } - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Post(() => { Items.AddRange(list); IsLoading = false; @@ -212,9 +212,13 @@ namespace SourceGit.ViewModels } var log = _repo.CreateLog("Interactive Rebase"); - var succ = await new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).ExecAsync(); + var succ = await new Commands.InteractiveRebase(_repo.FullPath, On.SHA) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - await Dispatcher.UIThread.InvokeAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/LFSFetch.cs b/src/ViewModels/LFSFetch.cs index 4456070b..fb09b5e3 100644 --- a/src/ViewModels/LFSFetch.cs +++ b/src/ViewModels/LFSFetch.cs @@ -27,9 +27,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("LFS Fetch"); Use(log); - await new Commands.LFS(_repo.FullPath).FetchAsync(SelectedRemote.Name, log); + await new Commands.LFS(_repo.FullPath) + .FetchAsync(SelectedRemote.Name, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/LFSImageDiff.cs b/src/ViewModels/LFSImageDiff.cs index bb69fd65..c554f178 100644 --- a/src/ViewModels/LFSImageDiff.cs +++ b/src/ViewModels/LFSImageDiff.cs @@ -21,10 +21,10 @@ namespace SourceGit.ViewModels { LFS = lfs; - Task.Run(() => + Task.Run(async () => { - var oldImage = ImageSource.FromLFSObject(repo, lfs.Old, decoder); - var newImage = ImageSource.FromLFSObject(repo, lfs.New, decoder); + var oldImage = await ImageSource.FromLFSObjectAsync(repo, lfs.Old, decoder).ConfigureAwait(false); + var newImage = await ImageSource.FromLFSObjectAsync(repo, lfs.New, decoder).ConfigureAwait(false); var img = new Models.ImageDiff() { @@ -34,7 +34,7 @@ namespace SourceGit.ViewModels NewFileSize = newImage.Size }; - Dispatcher.UIThread.Invoke(() => Image = img); + Dispatcher.UIThread.Post(() => Image = img); }); } diff --git a/src/ViewModels/LFSLocks.cs b/src/ViewModels/LFSLocks.cs index 5c44ff20..cc9b7edf 100644 --- a/src/ViewModels/LFSLocks.cs +++ b/src/ViewModels/LFSLocks.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; - using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -42,22 +40,22 @@ namespace SourceGit.ViewModels { _repo = repo; _remote = remote; - _userName = new Commands.Config(repo.FullPath).Get("user.name"); - - HasValidUserName = !string.IsNullOrEmpty(_userName); Task.Run(async () => { - _cachedLocks = await new Commands.LFS(_repo.FullPath).LocksAsync(_remote); - await Dispatcher.UIThread.InvokeAsync(() => + _userName = await new Commands.Config(repo.FullPath).GetAsync("user.name").ConfigureAwait(false); + _cachedLocks = await new Commands.LFS(_repo.FullPath).GetLocksAsync(_remote).ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => { UpdateVisibleLocks(); IsLoading = false; + HasValidUserName = !string.IsNullOrEmpty(_userName); }); }); } - public void Unlock(Models.LFSLock lfsLock, bool force) + public async Task UnlockAsync(Models.LFSLock lfsLock, bool force) { if (_isLoading) return; @@ -65,22 +63,19 @@ namespace SourceGit.ViewModels IsLoading = true; var log = _repo.CreateLog("Unlock LFS File"); - Task.Run(async () => + var succ = await new Commands.LFS(_repo.FullPath) + .UnlockAsync(_remote, lfsLock.ID, force, log) + .ConfigureAwait(false); + + log.Complete(); + + if (succ) { - var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(_remote, lfsLock.ID, force, log); - log.Complete(); + _cachedLocks.Remove(lfsLock); + UpdateVisibleLocks(); + } - await Dispatcher.UIThread.InvokeAsync(() => - { - if (succ) - { - _cachedLocks.Remove(lfsLock); - UpdateVisibleLocks(); - } - - IsLoading = false; - }); - }); + IsLoading = false; } private void UpdateVisibleLocks() diff --git a/src/ViewModels/LFSPrune.cs b/src/ViewModels/LFSPrune.cs index 780a7f85..f1847876 100644 --- a/src/ViewModels/LFSPrune.cs +++ b/src/ViewModels/LFSPrune.cs @@ -17,9 +17,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("LFS Prune"); Use(log); - await new Commands.LFS(_repo.FullPath).PruneAsync(log); + await new Commands.LFS(_repo.FullPath) + .PruneAsync(log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/LFSPull.cs b/src/ViewModels/LFSPull.cs index c4dde9f7..7c14a826 100644 --- a/src/ViewModels/LFSPull.cs +++ b/src/ViewModels/LFSPull.cs @@ -27,9 +27,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("LFS Pull"); Use(log); - await new Commands.LFS(_repo.FullPath).PullAsync(SelectedRemote.Name, log); + await new Commands.LFS(_repo.FullPath) + .PullAsync(SelectedRemote.Name, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/LFSPush.cs b/src/ViewModels/LFSPush.cs index 33de0a9e..9862c60e 100644 --- a/src/ViewModels/LFSPush.cs +++ b/src/ViewModels/LFSPush.cs @@ -27,9 +27,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("LFS Push"); Use(log); - await new Commands.LFS(_repo.FullPath).PushAsync(SelectedRemote.Name, log); + await new Commands.LFS(_repo.FullPath) + .PushAsync(SelectedRemote.Name, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/LFSTrackCustomPattern.cs b/src/ViewModels/LFSTrackCustomPattern.cs index f43af2ec..c492bea9 100644 --- a/src/ViewModels/LFSTrackCustomPattern.cs +++ b/src/ViewModels/LFSTrackCustomPattern.cs @@ -31,9 +31,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("LFS Add Custom Pattern"); Use(log); - var succ = await new Commands.LFS(_repo.FullPath).TrackAsync(_pattern, IsFilename, log); + var succ = await new Commands.LFS(_repo.FullPath) + .TrackAsync(_pattern, IsFilename, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 05afbf3f..b27ae0ac 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -96,7 +96,7 @@ namespace SourceGit.ViewModels foreach (var w in pref.Workspaces) w.IsActive = false; - var test = new Commands.QueryRepositoryRootPath(startupRepo).ReadToEnd(); + var test = new Commands.QueryRepositoryRootPath(startupRepo).GetResultAsync().Result; if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut)) { Pages[0].Notifications.Add(new Models.Notification @@ -346,7 +346,7 @@ namespace SourceGit.ViewModels return; } - var isBare = new Commands.IsBareRepository(node.Id).Result(); + var isBare = new Commands.IsBareRepository(node.Id).GetResultAsync().Result; var gitDir = isBare ? node.Id : GetRepositoryGitDir(node.Id); if (string.IsNullOrEmpty(gitDir)) { @@ -523,9 +523,9 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("PageTabBar.Tab.CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, e) => + copyPath.Click += async (_, e) => { - page.CopyPath(); + await page.CopyPathAsync(); e.Handled = true; }; menu.Items.Add(new MenuItem() { Header = "-" }); @@ -563,7 +563,7 @@ namespace SourceGit.ViewModels return null; } - return new Commands.QueryGitDir(repo).Result(); + return new Commands.QueryGitDir(repo).GetResultAsync().Result; } private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace = true) diff --git a/src/ViewModels/LauncherPage.cs b/src/ViewModels/LauncherPage.cs index 191a8163..9b6c2b0f 100644 --- a/src/ViewModels/LauncherPage.cs +++ b/src/ViewModels/LauncherPage.cs @@ -1,8 +1,7 @@ using System; - +using System.Threading.Tasks; using Avalonia.Collections; using Avalonia.Media; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -59,10 +58,10 @@ namespace SourceGit.ViewModels Notifications.Clear(); } - public void CopyPath() + public async Task CopyPathAsync() { if (_node.IsRepository) - App.CopyText(_node.Id); + await App.CopyTextAsync(_node.Id); } public void ChangeDirtyState(Models.DirtyState flag, bool remove) diff --git a/src/ViewModels/Merge.cs b/src/ViewModels/Merge.cs index ade122bc..9a13093e 100644 --- a/src/ViewModels/Merge.cs +++ b/src/ViewModels/Merge.cs @@ -65,15 +65,19 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Merging '{_sourceName}' into '{Into}'"); Use(log); - await new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, Edit).Use(log).ExecAsync(); + await new Commands.Merge(_repo.FullPath, _sourceName, Mode.Arg, Edit) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - var head = await new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").ResultAsync(); - await CallUIThreadAsync(() => - { - _repo.NavigateToCommit(head, true); - _repo.SetWatcherEnabled(true); - }); + var head = await new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD") + .GetResultAsync() + .ConfigureAwait(false); + + _repo.NavigateToCommit(head, true); + _repo.SetWatcherEnabled(true); return true; } @@ -87,7 +91,7 @@ namespace SourceGit.ViewModels private Models.MergeMode GetGitConfigBranchMergeOptions() { - var config = new Commands.Config(_repo.FullPath).Get($"branch.{Into}.mergeoptions"); + var config = new Commands.Config(_repo.FullPath).GetAsync($"branch.{Into}.mergeoptions").Result; return config switch { null or "" => null, @@ -110,7 +114,7 @@ namespace SourceGit.ViewModels private Models.MergeMode GetGitConfigMergeFF() { - var config = new Commands.Config(_repo.FullPath).Get("merge.ff"); + var config = new Commands.Config(_repo.FullPath).GetAsync("merge.ff").Result; return config switch { "false" => Models.MergeMode.NoFastForward, diff --git a/src/ViewModels/MergeMultiple.cs b/src/ViewModels/MergeMultiple.cs index c54afffe..c924b722 100644 --- a/src/ViewModels/MergeMultiple.cs +++ b/src/ViewModels/MergeMultiple.cs @@ -51,10 +51,13 @@ namespace SourceGit.ViewModels _repo.FullPath, ConvertTargetToMergeSources(), AutoCommit, - Strategy.Arg).Use(log).ExecAsync(); + Strategy.Arg) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Popup.cs b/src/ViewModels/Popup.cs index f9399668..942d33f9 100644 --- a/src/ViewModels/Popup.cs +++ b/src/ViewModels/Popup.cs @@ -1,9 +1,5 @@ -using System; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; - -using Avalonia.Threading; - using CommunityToolkit.Mvvm.ComponentModel; namespace SourceGit.ViewModels @@ -41,16 +37,6 @@ namespace SourceGit.ViewModels return null; } - protected void CallUIThread(Action action) - { - Dispatcher.UIThread.Invoke(action); - } - - protected async Task CallUIThreadAsync(Action action) - { - await Dispatcher.UIThread.InvokeAsync(action); - } - protected void Use(CommandLog log) { log.Register(SetDescription); diff --git a/src/ViewModels/PruneRemote.cs b/src/ViewModels/PruneRemote.cs index d9e57a71..246b2d3c 100644 --- a/src/ViewModels/PruneRemote.cs +++ b/src/ViewModels/PruneRemote.cs @@ -23,9 +23,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Prune Remote '{Remote.Name}'"); Use(log); - var succ = await new Commands.Remote(_repo.FullPath).Use(log).PruneAsync(Remote.Name); + var succ = await new Commands.Remote(_repo.FullPath) + .Use(log) + .PruneAsync(Remote.Name) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/PruneWorktrees.cs b/src/ViewModels/PruneWorktrees.cs index 53096e95..e5e3c63e 100644 --- a/src/ViewModels/PruneWorktrees.cs +++ b/src/ViewModels/PruneWorktrees.cs @@ -17,9 +17,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Prune Worktrees"); Use(log); - await new Commands.Worktree(_repo.FullPath).Use(log).PruneAsync(); + await new Commands.Worktree(_repo.FullPath) + .Use(log) + .PruneAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Pull.cs b/src/ViewModels/Pull.cs index eebc7345..b0f74a7a 100644 --- a/src/ViewModels/Pull.cs +++ b/src/ViewModels/Pull.cs @@ -119,21 +119,29 @@ namespace SourceGit.ViewModels Use(log); var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules; - var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync(); + var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); + var needPopStash = false; if (changes > 0) { if (DiscardLocalChanges) { - await Commands.Discard.AllAsync(_repo.FullPath, false, log); + await Commands.Discard + .AllAsync(_repo.FullPath, false, log) + .ConfigureAwait(false); } else { - var succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("PULL_AUTO_STASH"); + var succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("PULL_AUTO_STASH") + .ConfigureAwait(false); if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } @@ -145,30 +153,40 @@ namespace SourceGit.ViewModels _repo.FullPath, _selectedRemote.Name, !string.IsNullOrEmpty(Current.Upstream) && Current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name, - UseRebase).Use(log).ExecAsync(); + UseRebase) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); if (rs) { if (updateSubmodules) { - var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync(); + var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath) + .GetResultAsync() + .ConfigureAwait(false); if (submodules.Count > 0) - await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true); + await new Commands.Submodule(_repo.FullPath) + .Use(log) + .UpdateAsync(submodules, true, true) + .ConfigureAwait(false); } if (needPopStash) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); } log.Complete(); - var head = await new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").ResultAsync(); - await CallUIThreadAsync(() => - { - _repo.NavigateToCommit(head, true); - _repo.SetWatcherEnabled(true); - }); + var head = await new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD") + .GetResultAsync() + .ConfigureAwait(false); + _repo.NavigateToCommit(head, true); + _repo.SetWatcherEnabled(true); return rs; } diff --git a/src/ViewModels/Push.cs b/src/ViewModels/Push.cs index b8217c7b..048cce9a 100644 --- a/src/ViewModels/Push.cs +++ b/src/ViewModels/Push.cs @@ -176,10 +176,13 @@ namespace SourceGit.ViewModels PushAllTags, _repo.Submodules.Count > 0 && CheckSubmodules, _isSetTrackOptionVisible && Tracking, - ForcePush).Use(log).ExecAsync(); + ForcePush) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/PushRevision.cs b/src/ViewModels/PushRevision.cs index 5d361b1e..86e2a989 100644 --- a/src/ViewModels/PushRevision.cs +++ b/src/ViewModels/PushRevision.cs @@ -44,10 +44,10 @@ namespace SourceGit.ViewModels false, false, false, - Force).Use(log).ExecAsync(); + Force).Use(log).ExecAsync().ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/PushTag.cs b/src/ViewModels/PushTag.cs index 7ce621e6..9f37757f 100644 --- a/src/ViewModels/PushTag.cs +++ b/src/ViewModels/PushTag.cs @@ -48,18 +48,24 @@ namespace SourceGit.ViewModels { foreach (var remote in _repo.Remotes) { - succ = await new Commands.Push(_repo.FullPath, remote.Name, tag, false).Use(log).ExecAsync(); + succ = await new Commands.Push(_repo.FullPath, remote.Name, tag, false) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); if (!succ) break; } } else { - succ = await new Commands.Push(_repo.FullPath, SelectedRemote.Name, tag, false).Use(log).ExecAsync(); + succ = await new Commands.Push(_repo.FullPath, SelectedRemote.Name, tag, false) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); } log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/Rebase.cs b/src/ViewModels/Rebase.cs index 8616c745..14ba97c8 100644 --- a/src/ViewModels/Rebase.cs +++ b/src/ViewModels/Rebase.cs @@ -49,9 +49,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Rebase"); Use(log); - await new Commands.Rebase(_repo.FullPath, _revision, AutoStash).Use(log).ExecAsync(); + await new Commands.Rebase(_repo.FullPath, _revision, AutoStash) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/RemoveWorktree.cs b/src/ViewModels/RemoveWorktree.cs index aace0b64..249bdb00 100644 --- a/src/ViewModels/RemoveWorktree.cs +++ b/src/ViewModels/RemoveWorktree.cs @@ -29,9 +29,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Remove worktree"); Use(log); - var succ = await new Commands.Worktree(_repo.FullPath).Use(log).RemoveAsync(Target.FullPath, Force); + var succ = await new Commands.Worktree(_repo.FullPath) + .Use(log) + .RemoveAsync(Target.FullPath, Force) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/RenameBranch.cs b/src/ViewModels/RenameBranch.cs index 9b2f239c..b5222cb6 100644 --- a/src/ViewModels/RenameBranch.cs +++ b/src/ViewModels/RenameBranch.cs @@ -58,32 +58,32 @@ namespace SourceGit.ViewModels var isCurrent = Target.IsCurrent; var oldName = Target.FullName; - var succ = await Commands.Branch.RenameAsync(_repo.FullPath, Target.Name, fixedName, log); - log.Complete(); + var succ = await Commands.Branch + .RenameAsync(_repo.FullPath, Target.Name, fixedName, log) + .ConfigureAwait(false); - await CallUIThreadAsync(() => + if (succ) { - ProgressDescription = "Waiting for branch updated..."; - - if (succ) + foreach (var filter in _repo.Settings.HistoriesFilters) { - foreach (var filter in _repo.Settings.HistoriesFilters) + if (filter.Type == Models.FilterType.LocalBranch && + filter.Pattern.Equals(oldName, StringComparison.Ordinal)) { - if (filter.Type == Models.FilterType.LocalBranch && - filter.Pattern.Equals(oldName, StringComparison.Ordinal)) - { - filter.Pattern = $"refs/heads/{fixedName}"; - break; - } + filter.Pattern = $"refs/heads/{fixedName}"; + break; } } + } - _repo.MarkBranchesDirtyManually(); - _repo.SetWatcherEnabled(true); - }); + log.Complete(); + _repo.MarkBranchesDirtyManually(); + _repo.SetWatcherEnabled(true); if (isCurrent) - Task.Delay(400).Wait(); + { + ProgressDescription = "Waiting for branch updated..."; + await Task.Delay(400); + } return succ; } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 86b542ab..3e0613df 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -510,7 +510,7 @@ namespace SourceGit.ViewModels var gitDirForWatcher = _gitDir; if (_gitDir.Replace('\\', '/').IndexOf("/worktrees/", StringComparison.Ordinal) > 0) { - var commonDir = new Commands.QueryGitCommonDir(_fullpath).Result(); + var commonDir = new Commands.QueryGitCommonDir(_fullpath).GetResultAsync().Result; if (!string.IsNullOrEmpty(commonDir)) gitDirForWatcher = commonDir; } @@ -651,7 +651,7 @@ namespace SourceGit.ViewModels Task.Run(async () => { - var config = await new Commands.Config(_fullpath).ListAllAsync(); + var config = await new Commands.Config(_fullpath).ReadAllAsync().ConfigureAwait(false); _hasAllowedSignersFile = config.TryGetValue("gpg.ssh.allowedSignersFile", out var allowedSignersFile) && !string.IsNullOrEmpty(allowedSignersFile); if (config.TryGetValue("gitflow.branch.master", out var masterName)) @@ -876,19 +876,26 @@ namespace SourceGit.ViewModels if (method == Models.CommitSearchMethod.BySHA) { - var isCommitSHA = await new Commands.IsCommitSHA(_fullpath, _searchCommitFilter).ResultAsync(); + var isCommitSHA = await new Commands.IsCommitSHA(_fullpath, _searchCommitFilter) + .GetResultAsync() + .ConfigureAwait(false); + if (isCommitSHA) { - var commit = await new Commands.QuerySingleCommit(_fullpath, _searchCommitFilter).ResultAsync(); + var commit = await new Commands.QuerySingleCommit(_fullpath, _searchCommitFilter) + .GetResultAsync() + .ConfigureAwait(false); visible.Add(commit); } } else { - visible = await new Commands.QueryCommits(_fullpath, _searchCommitFilter, method, _onlySearchCommitsInCurrentBranch).ResultAsync(); + visible = await new Commands.QueryCommits(_fullpath, _searchCommitFilter, method, _onlySearchCommitsInCurrentBranch) + .GetResultAsync() + .ConfigureAwait(false); } - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Post(() => { SearchedCommits = visible; IsSearchLoadingVisible = false; @@ -1096,31 +1103,29 @@ namespace SourceGit.ViewModels return actions; } - public void Bisect(string subcmd) + public async Task ExecBisectCommandAsync(string subcmd) { IsBisectCommandRunning = true; SetWatcherEnabled(false); var log = CreateLog($"Bisect({subcmd})"); - Task.Run(async () => - { - var succ = await new Commands.Bisect(_fullpath, subcmd).Use(log).ExecAsync(); - log.Complete(); - var head = await new Commands.QueryRevisionByRefName(_fullpath, "HEAD").ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => - { - if (!succ) - App.RaiseException(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim()); - else if (log.Content.Contains("is the first bad commit")) - App.SendNotification(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim()); + var succ = await new Commands.Bisect(_fullpath, subcmd).Use(log).ExecAsync(); + log.Complete(); - MarkBranchesDirtyManually(); - NavigateToCommit(head, true); - SetWatcherEnabled(true); - IsBisectCommandRunning = false; - }); - }); + var head = await new Commands.QueryRevisionByRefName(_fullpath, "HEAD") + .GetResultAsync() + .ConfigureAwait(false); + + if (!succ) + App.RaiseException(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim()); + else if (log.Content.Contains("is the first bad commit")) + App.SendNotification(_fullpath, log.Content.Substring(log.Content.IndexOf('\n')).Trim()); + + MarkBranchesDirtyManually(); + NavigateToCommit(head, true); + SetWatcherEnabled(true); + IsBisectCommandRunning = false; } public bool MayHaveSubmodules() @@ -1132,8 +1137,8 @@ namespace SourceGit.ViewModels public void RefreshBranches() { - var branches = new Commands.QueryBranches(_fullpath).Result(out var localBranchesCount); - var remotes = new Commands.QueryRemotes(_fullpath).Result(); + var branches = new Commands.QueryBranches(_fullpath).GetResultAsync().Result; + var remotes = new Commands.QueryRemotes(_fullpath).GetResultAsync().Result; var builder = BuildBranchTree(branches, remotes); Dispatcher.UIThread.Invoke(() => @@ -1145,6 +1150,13 @@ namespace SourceGit.ViewModels CurrentBranch = branches.Find(x => x.IsCurrent); LocalBranchTrees = builder.Locals; RemoteBranchTrees = builder.Remotes; + + var localBranchesCount = 0; + foreach (var b in branches) + { + if (b.IsLocal && !b.IsDetachedHead) + localBranchesCount++; + } LocalBranchesCount = localBranchesCount; if (_workingCopy != null) @@ -1157,7 +1169,7 @@ namespace SourceGit.ViewModels public void RefreshWorktrees() { - var worktrees = new Commands.Worktree(_fullpath).List(); + var worktrees = new Commands.Worktree(_fullpath).ReadAllAsync().Result; var cleaned = new List(); foreach (var worktree in worktrees) @@ -1176,7 +1188,7 @@ namespace SourceGit.ViewModels public void RefreshTags() { - var tags = new Commands.QueryTags(_fullpath).Result(); + var tags = new Commands.QueryTags(_fullpath).GetResultAsync().Result; Dispatcher.UIThread.Invoke(() => { Tags = tags; @@ -1207,7 +1219,7 @@ namespace SourceGit.ViewModels else builder.Append(filters); - var commits = new Commands.QueryCommits(_fullpath, builder.ToString()).Result(); + var commits = new Commands.QueryCommits(_fullpath, builder.ToString()).GetResultAsync().Result; var graph = Models.CommitGraph.Parse(commits, _settings.EnableFirstParentInHistories); Dispatcher.UIThread.Invoke(() => @@ -1244,7 +1256,7 @@ namespace SourceGit.ViewModels return; } - var submodules = new Commands.QuerySubmodules(_fullpath).Result(); + var submodules = new Commands.QuerySubmodules(_fullpath).GetResultAsync().Result; _watcher?.SetSubmodules(submodules); Dispatcher.UIThread.Invoke(() => @@ -1286,7 +1298,7 @@ namespace SourceGit.ViewModels if (IsBare) return; - var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result(); + var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).GetResultAsync().Result; if (_workingCopy == null) return; @@ -1306,7 +1318,7 @@ namespace SourceGit.ViewModels if (IsBare) return; - var stashes = new Commands.QueryStashes(_fullpath).Result(); + var stashes = new Commands.QueryStashes(_fullpath).GetResultAsync().Result; Dispatcher.UIThread.Invoke(() => { if (_stashesPage != null) @@ -1328,36 +1340,16 @@ namespace SourceGit.ViewModels ShowPopup(new CreateBranch(this, _currentBranch)); } - public bool ConfirmCheckoutBranch() + public async Task ConfirmCheckoutBranchAsync() { - if (Dispatcher.UIThread.CheckAccess()) - return true; - if (_currentBranch is not { IsDetachedHead: true }) return true; - var refs = new Commands.QueryRefsContainsCommit(_fullpath, _currentBranch.Head).Result(); + var refs = await new Commands.QueryRefsContainsCommit(_fullpath, _currentBranch.Head).GetResultAsync().ConfigureAwait(false); if (refs.Count == 0) { - var confirmCheckout = false; - var resetEvent = new AutoResetEvent(false); - - Dispatcher.UIThread.Invoke(() => - { - var msg = App.Text("Checkout.WarnLostCommits"); - App.ShowWindow(new Confirm(msg, () => - { - confirmCheckout = true; - resetEvent.Set(); - }, () => - { - confirmCheckout = false; - resetEvent.Set(); - }), true); - }); - - resetEvent.WaitOne(); - return confirmCheckout; + var msg = App.Text("Checkout.WarnLostCommits"); + return await App.AskConfirmAsync(msg, null); } return true; @@ -2026,7 +2018,7 @@ namespace SourceGit.ViewModels if (_histories != null) { - var target = await new Commands.QuerySingleCommit(_fullpath, branch.Head).ResultAsync(); + var target = await new Commands.QuerySingleCommit(_fullpath, branch.Head).GetResultAsync().ConfigureAwait(false); _histories.AutoSelectedCommit = null; _histories.DetailContext = new RevisionCompare(_fullpath, target, null); } @@ -2143,9 +2135,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(branch.Name); + await App.CopyTextAsync(branch.Name); e.Handled = true; }; menu.Items.Add(copy); @@ -2215,9 +2207,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("RemoteCM.CopyURL"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(remote.URL); + await App.CopyTextAsync(remote.URL); e.Handled = true; }; @@ -2305,7 +2297,7 @@ namespace SourceGit.ViewModels if (_histories != null) { - var target = await new Commands.QuerySingleCommit(_fullpath, branch.Head).ResultAsync(); + var target = await new Commands.QuerySingleCommit(_fullpath, branch.Head).GetResultAsync().ConfigureAwait(false); _histories.AutoSelectedCommit = null; _histories.DetailContext = new RevisionCompare(_fullpath, target, null); } @@ -2357,9 +2349,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(name); + await App.CopyTextAsync(name); e.Handled = true; }; @@ -2457,9 +2449,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("TagCM.Copy"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(tag.Name); + await App.CopyTextAsync(tag.Name); ev.Handled = true; }; @@ -2467,9 +2459,9 @@ namespace SourceGit.ViewModels copyMessage.Header = App.Text("TagCM.CopyMessage"); copyMessage.Icon = App.CreateMenuIcon("Icons.Copy"); copyMessage.IsEnabled = !string.IsNullOrEmpty(tag.Message); - copyMessage.Click += (_, ev) => + copyMessage.Click += async (_, ev) => { - App.CopyText(tag.Message); + await App.CopyTextAsync(tag.Message); ev.Handled = true; }; @@ -2606,9 +2598,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("Submodule.CopyPath"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(submodule.Path); + await App.CopyTextAsync(submodule.Path); ev.Handled = true; }; @@ -2677,9 +2669,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("Worktree.CopyPath"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(worktree.FullPath); + await App.CopyTextAsync(worktree.FullPath); e.Handled = true; }; menu.Items.Add(new MenuItem() { Header = "-" }); @@ -2912,8 +2904,11 @@ namespace SourceGit.ViewModels Task.Run(async () => { - _worktreeFiles = await new Commands.QueryRevisionFileNames(_fullpath, "HEAD").ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => + _worktreeFiles = await new Commands.QueryRevisionFileNames(_fullpath, "HEAD") + .GetResultAsync() + .ConfigureAwait(false); + + Dispatcher.UIThread.Post(() => { if (IsSearchingCommitsByFilePath() && _requestingWorktreeFiles) CalcMatchedFilesForSearching(); diff --git a/src/ViewModels/RepositoryConfigure.cs b/src/ViewModels/RepositoryConfigure.cs index 1a6a21d8..ba079819 100644 --- a/src/ViewModels/RepositoryConfigure.cs +++ b/src/ViewModels/RepositoryConfigure.cs @@ -161,7 +161,7 @@ namespace SourceGit.ViewModels if (!AvailableOpenAIServices.Contains(PreferredOpenAIService)) PreferredOpenAIService = "---"; - _cached = new Commands.Config(repo.FullPath).ListAll(); + _cached = new Commands.Config(repo.FullPath).ReadAllAsync().Result; if (_cached.TryGetValue("user.name", out var name)) UserName = name; if (_cached.TryGetValue("user.email", out var email)) diff --git a/src/ViewModels/Reset.cs b/src/ViewModels/Reset.cs index 784fd060..84399fc7 100644 --- a/src/ViewModels/Reset.cs +++ b/src/ViewModels/Reset.cs @@ -36,9 +36,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Reset HEAD to '{To.SHA}'"); Use(log); - var succ = await new Commands.Reset(_repo.FullPath, To.SHA, SelectedMode.Arg).Use(log).ExecAsync(); + var succ = await new Commands.Reset(_repo.FullPath, To.SHA, SelectedMode.Arg) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/ResetWithoutCheckout.cs b/src/ViewModels/ResetWithoutCheckout.cs index 0c9a5fd6..1c8073a3 100644 --- a/src/ViewModels/ResetWithoutCheckout.cs +++ b/src/ViewModels/ResetWithoutCheckout.cs @@ -38,9 +38,12 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Reset '{Target.Name}' to '{_revision}'"); Use(log); - var succ = await Commands.Branch.CreateAsync(_repo.FullPath, Target.Name, _revision, true, log); + var succ = await Commands.Branch + .CreateAsync(_repo.FullPath, Target.Name, _revision, true, log) + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/Revert.cs b/src/ViewModels/Revert.cs index 7665eef1..485a15d7 100644 --- a/src/ViewModels/Revert.cs +++ b/src/ViewModels/Revert.cs @@ -31,9 +31,13 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog($"Revert '{Target.SHA}'"); Use(log); - await new Commands.Revert(_repo.FullPath, Target.SHA, AutoCommit).Use(log).ExecAsync(); + await new Commands.Revert(_repo.FullPath, Target.SHA, AutoCommit) + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/RevisionCompare.cs b/src/ViewModels/RevisionCompare.cs index 34f2da62..09fe76b2 100644 --- a/src/ViewModels/RevisionCompare.cs +++ b/src/ViewModels/RevisionCompare.cs @@ -170,9 +170,9 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(change.Path); + await App.CopyTextAsync(change.Path); ev.Handled = true; }; menu.Items.Add(copyPath); @@ -180,9 +180,9 @@ namespace SourceGit.ViewModels var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(Native.OS.GetAbsPath(_repo, change.Path)); + await App.CopyTextAsync(Native.OS.GetAbsPath(_repo, change.Path)); e.Handled = true; }; menu.Items.Add(copyFullPath); @@ -214,7 +214,7 @@ namespace SourceGit.ViewModels private void Refresh() { - _changes = new Commands.CompareRevisions(_repo, GetSHA(_startPoint), GetSHA(_endPoint)).Result(); + _changes = new Commands.CompareRevisions(_repo, GetSHA(_startPoint), GetSHA(_endPoint)).ReadAsync().Result; var visible = _changes; if (!string.IsNullOrWhiteSpace(_searchFilter)) diff --git a/src/ViewModels/RevisionLFSImage.cs b/src/ViewModels/RevisionLFSImage.cs index e0b9a348..2cdd8e66 100644 --- a/src/ViewModels/RevisionLFSImage.cs +++ b/src/ViewModels/RevisionLFSImage.cs @@ -21,9 +21,9 @@ namespace SourceGit.ViewModels { LFS = new Models.RevisionLFSObject() { Object = lfs }; - Task.Run(() => + Task.Run(async () => { - var source = ImageSource.FromLFSObject(repo, lfs, decoder); + var source = await ImageSource.FromLFSObjectAsync(repo, lfs, decoder).ConfigureAwait(false); var img = new Models.RevisionImageFile(file, source.Bitmap, source.Size); Dispatcher.UIThread.Invoke(() => Image = img); }); diff --git a/src/ViewModels/Reword.cs b/src/ViewModels/Reword.cs index 6a9d3688..f1a5b2bb 100644 --- a/src/ViewModels/Reword.cs +++ b/src/ViewModels/Reword.cs @@ -21,7 +21,7 @@ namespace SourceGit.ViewModels public Reword(Repository repo, Models.Commit head) { _repo = repo; - _oldMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, head.SHA).Result(); + _oldMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, head.SHA).GetResultAsync().Result; _message = _oldMessage; Head = head; } @@ -38,10 +38,12 @@ namespace SourceGit.ViewModels Use(log); var signOff = _repo.Settings.EnableSignOffForCommit; - // For reword (only changes the commit message), disable `--reset-author` - var succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false).Use(log).RunAsync(); + var succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false) + .Use(log) + .RunAsync(); + log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/ScanRepositories.cs b/src/ViewModels/ScanRepositories.cs index 2f561482..e29665e8 100644 --- a/src/ViewModels/ScanRepositories.cs +++ b/src/ViewModels/ScanRepositories.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Diagnostics; using System.IO; using System.Threading.Tasks; -using Avalonia.Threading; - namespace SourceGit.ViewModels { public class ScanRepositories : Popup @@ -44,48 +41,37 @@ namespace SourceGit.ViewModels { ProgressDescription = $"Scan repositories under '{_selected.Path}' ..."; - var watch = new Stopwatch(); - watch.Start(); - + var minDelay = Task.Delay(500); var rootDir = new DirectoryInfo(_selected.Path); var found = new List(); - GetUnmanagedRepositories(rootDir, found, new EnumerationOptions() + await GetUnmanagedRepositoriesAsync(rootDir, found, new EnumerationOptions() { AttributesToSkip = FileAttributes.Hidden | FileAttributes.System, IgnoreInaccessible = true, }); // Make sure this task takes at least 0.5s to avoid that the popup panel do not disappear very quickly. - var remain = 500 - (int)watch.Elapsed.TotalMilliseconds; - watch.Stop(); - if (remain > 0) - Task.Delay(remain).Wait(); + await minDelay; - await Dispatcher.UIThread.InvokeAsync(() => + var normalizedRoot = rootDir.FullName.Replace('\\', '/').TrimEnd('/'); + foreach (var f in found) { - var normalizedRoot = rootDir.FullName.Replace('\\', '/').TrimEnd('/'); - - foreach (var f in found) + var parent = new DirectoryInfo(f).Parent!.FullName.Replace('\\', '/').TrimEnd('/'); + if (parent.Equals(normalizedRoot, StringComparison.Ordinal)) { - var parent = new DirectoryInfo(f).Parent!.FullName.Replace('\\', '/').TrimEnd('/'); - if (parent.Equals(normalizedRoot, StringComparison.Ordinal)) - { - Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false, false); - } - else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal)) - { - var relative = parent.Substring(normalizedRoot.Length).TrimStart('/'); - var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative); - Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false, false); - } + Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false, false); } + else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal)) + { + var relative = parent.Substring(normalizedRoot.Length).TrimStart('/'); + var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative); + Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false, false); + } + } - Preferences.Instance.AutoRemoveInvalidNode(); - Preferences.Instance.Save(); - - Welcome.Instance.Refresh(); - }); - + Preferences.Instance.AutoRemoveInvalidNode(); + Preferences.Instance.Save(); + Welcome.Instance.Refresh(); return true; } @@ -100,7 +86,7 @@ namespace SourceGit.ViewModels } } - private void GetUnmanagedRepositories(DirectoryInfo dir, List outs, EnumerationOptions opts, int depth = 0) + private async Task GetUnmanagedRepositoriesAsync(DirectoryInfo dir, List outs, EnumerationOptions opts, int depth = 0) { var subdirs = dir.GetDirectories("*", opts); foreach (var subdir in subdirs) @@ -109,7 +95,7 @@ namespace SourceGit.ViewModels subdir.Name.Equals("node_modules", StringComparison.Ordinal)) continue; - CallUIThread(() => ProgressDescription = $"Scanning {subdir.FullName}..."); + ProgressDescription = $"Scanning {subdir.FullName}..."; var normalizedSelf = subdir.FullName.Replace('\\', '/').TrimEnd('/'); if (_managed.Contains(normalizedSelf)) @@ -118,7 +104,7 @@ namespace SourceGit.ViewModels var gitDir = Path.Combine(subdir.FullName, ".git"); if (Directory.Exists(gitDir) || File.Exists(gitDir)) { - var test = new Commands.QueryRepositoryRootPath(subdir.FullName).ReadToEnd(); + var test = await new Commands.QueryRepositoryRootPath(subdir.FullName).GetResultAsync().ConfigureAwait(false); if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut)) { var normalized = test.StdOut.Trim().Replace('\\', '/').TrimEnd('/'); @@ -129,7 +115,7 @@ namespace SourceGit.ViewModels continue; } - var isBare = new Commands.IsBareRepository(subdir.FullName).Result(); + var isBare = await new Commands.IsBareRepository(subdir.FullName).GetResultAsync().ConfigureAwait(false); if (isBare) { outs.Add(normalizedSelf); @@ -137,7 +123,7 @@ namespace SourceGit.ViewModels } if (depth < 5) - GetUnmanagedRepositories(subdir, outs, opts, depth + 1); + await GetUnmanagedRepositoriesAsync(subdir, outs, opts, depth + 1); } } diff --git a/src/ViewModels/SetUpstream.cs b/src/ViewModels/SetUpstream.cs index 44812d8f..d3373426 100644 --- a/src/ViewModels/SetUpstream.cs +++ b/src/ViewModels/SetUpstream.cs @@ -61,11 +61,14 @@ namespace SourceGit.ViewModels var log = _repo.CreateLog("Set Upstream"); Use(log); - var succ = await Commands.Branch.SetUpstreamAsync(_repo.FullPath, Local.Name, upstream.Replace("refs/remotes/", ""), log); - if (succ) - _repo.RefreshBranches(); + var succ = await Commands.Branch + .SetUpstreamAsync(_repo.FullPath, Local.Name, upstream.Replace("refs/remotes/", ""), log) + .ConfigureAwait(false); log.Complete(); + + if (succ) + _repo.MarkBranchesDirtyManually(); return true; } diff --git a/src/ViewModels/Squash.cs b/src/ViewModels/Squash.cs index e9736405..6afc1e06 100644 --- a/src/ViewModels/Squash.cs +++ b/src/ViewModels/Squash.cs @@ -20,7 +20,7 @@ namespace SourceGit.ViewModels public Squash(Repository repo, Models.Commit target, string shaToGetPreferMessage) { _repo = repo; - _message = new Commands.QueryCommitFullMessage(_repo.FullPath, shaToGetPreferMessage).Result(); + _message = new Commands.QueryCommitFullMessage(_repo.FullPath, shaToGetPreferMessage).GetResultAsync().Result; Target = target; } @@ -38,26 +38,40 @@ namespace SourceGit.ViewModels if (_repo.LocalChangesCount > 0) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("SQUASH_AUTO_STASH"); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync("SQUASH_AUTO_STASH") + .ConfigureAwait(false); + if (!succ) { log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return false; } autoStashed = true; } - succ = await new Commands.Reset(_repo.FullPath, Target.SHA, "--soft").Use(log).ExecAsync(); + succ = await new Commands.Reset(_repo.FullPath, Target.SHA, "--soft") + .Use(log) + .ExecAsync() + .ConfigureAwait(false); + if (succ) - succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false).Use(log).RunAsync(); + succ = await new Commands.Commit(_repo.FullPath, _message, signOff, true, false) + .Use(log) + .RunAsync() + .ConfigureAwait(false); if (succ && autoStashed) - await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); + await new Commands.Stash(_repo.FullPath) + .Use(log) + .PopAsync("stash@{0}") + .ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return succ; } diff --git a/src/ViewModels/StashChanges.cs b/src/ViewModels/StashChanges.cs index ceede29c..93c8718d 100644 --- a/src/ViewModels/StashChanges.cs +++ b/src/ViewModels/StashChanges.cs @@ -68,7 +68,10 @@ namespace SourceGit.ViewModels { if (Native.OS.GitVersion >= Models.GitVersions.STASH_PUSH_ONLY_STAGED) { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushOnlyStagedAsync(Message, keepIndex); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushOnlyStagedAsync(Message, keepIndex) + .ConfigureAwait(false); } else { @@ -84,7 +87,10 @@ namespace SourceGit.ViewModels } else { - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync(Message, IncludeUntracked, keepIndex); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync(Message, IncludeUntracked, keepIndex) + .ConfigureAwait(false); } } else @@ -93,15 +99,14 @@ namespace SourceGit.ViewModels } if (mode == DealWithChangesAfterStashing.KeepAll && succ) - succ = await new Commands.Stash(_repo.FullPath).Use(log).ApplyAsync("stash@{0}", true); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .ApplyAsync("stash@{0}", true) + .ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => - { - _repo.MarkWorkingCopyDirtyManually(); - _repo.SetWatcherEnabled(true); - }); - + _repo.MarkWorkingCopyDirtyManually(); + _repo.SetWatcherEnabled(true); return succ; } @@ -119,7 +124,10 @@ namespace SourceGit.ViewModels var pathSpecFile = Path.GetTempFileName(); await File.WriteAllLinesAsync(pathSpecFile, paths); - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync(Message, pathSpecFile, keepIndex); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync(Message, pathSpecFile, keepIndex) + .ConfigureAwait(false); File.Delete(pathSpecFile); } else @@ -128,7 +136,10 @@ namespace SourceGit.ViewModels { var count = Math.Min(32, changes.Count - i); var step = changes.GetRange(i, count); - succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync(Message, step, keepIndex); + succ = await new Commands.Stash(_repo.FullPath) + .Use(log) + .PushAsync(Message, step, keepIndex) + .ConfigureAwait(false); if (!succ) break; } diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs index 60b2d190..78859626 100644 --- a/src/ViewModels/StashesPage.cs +++ b/src/ViewModels/StashesPage.cs @@ -59,21 +59,24 @@ namespace SourceGit.ViewModels { Task.Run(async () => { - var changes = await new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA).ResultAsync(); - var untracked = new List(); + var changes = await new Commands.CompareRevisions(_repo.FullPath, $"{value.SHA}^", value.SHA) + .ReadAsync() + .ConfigureAwait(false); + var untracked = new List(); if (value.Parents.Count == 3) { - untracked = await new Commands.CompareRevisions(_repo.FullPath, Models.Commit.EmptyTreeSHA1, value.Parents[2]).ResultAsync(); + untracked = await new Commands.CompareRevisions(_repo.FullPath, Models.Commit.EmptyTreeSHA1, value.Parents[2]) + .ReadAsync() + .ConfigureAwait(false); + var needSort = changes.Count > 0 && untracked.Count > 0; - changes.AddRange(untracked); - if (needSort) changes.Sort((l, r) => Models.NumericSort.Compare(l.Path, r.Path)); } - await Dispatcher.UIThread.InvokeAsync(() => + Dispatcher.UIThread.Post(() => { _untracked = untracked; Changes = changes; @@ -198,9 +201,9 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("StashCM.CopyMessage"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(stash.Message); + await App.CopyTextAsync(stash.Message); ev.Handled = true; }; @@ -272,18 +275,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, ev) => + copyPath.Click += async (_, ev) => { - App.CopyText(change.Path); + await App.CopyTextAsync(change.Path); ev.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); + await App.CopyTextAsync(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); e.Handled = true; }; diff --git a/src/ViewModels/Statistics.cs b/src/ViewModels/Statistics.cs index e630a763..a16c94ec 100644 --- a/src/ViewModels/Statistics.cs +++ b/src/ViewModels/Statistics.cs @@ -58,8 +58,8 @@ namespace SourceGit.ViewModels { Task.Run(async () => { - var result = await new Commands.Statistics(repo, Preferences.Instance.MaxHistoryCommits).ResultAsync(); - await Dispatcher.UIThread.InvokeAsync(() => + var result = await new Commands.Statistics(repo, Preferences.Instance.MaxHistoryCommits).ReadAsync().ConfigureAwait(false); + Dispatcher.UIThread.Post(() => { _data = result; RefreshReport(); diff --git a/src/ViewModels/UpdateSubmodules.cs b/src/ViewModels/UpdateSubmodules.cs index 7b08f111..5dbd5388 100644 --- a/src/ViewModels/UpdateSubmodules.cs +++ b/src/ViewModels/UpdateSubmodules.cs @@ -65,10 +65,11 @@ namespace SourceGit.ViewModels await new Commands.Submodule(_repo.FullPath) .Use(log) - .UpdateAsync(targets, EnableInit, EnableRecursive, EnableRemote); + .UpdateAsync(targets, EnableInit, EnableRecursive, EnableRemote) + .ConfigureAwait(false); log.Complete(); - await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true)); + _repo.SetWatcherEnabled(true); return true; } diff --git a/src/ViewModels/Welcome.cs b/src/ViewModels/Welcome.cs index 4b6dc7d4..3a8653d5 100644 --- a/src/ViewModels/Welcome.cs +++ b/src/ViewModels/Welcome.cs @@ -93,11 +93,11 @@ namespace SourceGit.ViewModels return; } - var isBare = new Commands.IsBareRepository(path).Result(); + var isBare = new Commands.IsBareRepository(path).GetResultAsync().Result; var repoRoot = path; if (!isBare) { - var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd(); + var test = new Commands.QueryRepositoryRootPath(path).GetResultAsync().Result; if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut)) { InitRepository(path, parent, test.StdErr); diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 7a89d5a3..e520dd34 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -91,7 +91,9 @@ namespace SourceGit.ViewModels return; } - CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, currentBranch.Head).Result(); + CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, currentBranch.Head) + .GetResultAsync() + .Result; } else { @@ -841,7 +843,7 @@ namespace SourceGit.ViewModels lfs.Header = App.Text("GitLFS"); lfs.Icon = App.CreateMenuIcon("Icons.LFS"); - var isLFSFiltered = new Commands.IsLFSFiltered(_repo.FullPath, change.Path).Result(); + var isLFSFiltered = new Commands.IsLFSFiltered(_repo.FullPath, change.Path).GetResultAsync().Result; if (!isLFSFiltered) { var filename = Path.GetFileName(change.Path); @@ -981,18 +983,18 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("CopyPath"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(hasSelectedFolder ? selectedSingleFolder : change.Path); + await App.CopyTextAsync(hasSelectedFolder ? selectedSingleFolder : change.Path); e.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(hasSelectedFolder ? Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder) : path); + await App.CopyTextAsync(hasSelectedFolder ? Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder) : path); e.Handled = true; }; @@ -1173,18 +1175,18 @@ namespace SourceGit.ViewModels var copy = new MenuItem(); copy.Header = App.Text("CopyPath"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, e) => + copy.Click += async (_, e) => { - App.CopyText(selectedSingleFolder); + await App.CopyTextAsync(selectedSingleFolder); e.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder)); + await App.CopyTextAsync(Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder)); e.Handled = true; }; menu.Items.Add(new MenuItem() { Header = "-" }); @@ -1428,19 +1430,19 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, e) => + copyPath.Click += async (_, e) => { - App.CopyText(hasSelectedFolder ? selectedSingleFolder : change.Path); + await App.CopyTextAsync(hasSelectedFolder ? selectedSingleFolder : change.Path); e.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { var target = hasSelectedFolder ? Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder) : path; - App.CopyText(target); + await App.CopyTextAsync(target); e.Handled = true; }; @@ -1537,18 +1539,18 @@ namespace SourceGit.ViewModels var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); copyPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyPath.Click += (_, e) => + copyPath.Click += async (_, e) => { - App.CopyText(selectedSingleFolder); + await App.CopyTextAsync(selectedSingleFolder); e.Handled = true; }; var copyFullPath = new MenuItem(); copyFullPath.Header = App.Text("CopyFullPath"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); - copyFullPath.Click += (_, e) => + copyFullPath.Click += async (_, e) => { - App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder)); + await App.CopyTextAsync(Native.OS.GetAbsPath(_repo.FullPath, selectedSingleFolder)); e.Handled = true; }; @@ -1567,7 +1569,7 @@ namespace SourceGit.ViewModels { var menu = new ContextMenu(); - var gitTemplate = new Commands.Config(_repo.FullPath).Get("commit.template"); + var gitTemplate = new Commands.Config(_repo.FullPath).GetAsync("commit.template").Result; var templateCount = _repo.Settings.CommitTemplates.Count; if (templateCount == 0 && string.IsNullOrEmpty(gitTemplate)) { @@ -1712,8 +1714,13 @@ namespace SourceGit.ViewModels { if (_useAmend) { - var head = new Commands.QuerySingleCommit(_repo.FullPath, "HEAD").Result(); - return new Commands.QueryStagedChangesWithAmend(_repo.FullPath, head.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : $"{head.SHA}^").Result(); + var head = new Commands.QuerySingleCommit(_repo.FullPath, "HEAD") + .GetResultAsync() + .Result; + + return new Commands.QueryStagedChangesWithAmend(_repo.FullPath, head.Parents.Count == 0 ? Models.Commit.EmptyTreeSHA1 : $"{head.SHA}^") + .GetResultAsync() + .Result; } var rs = new List(); @@ -1759,7 +1766,7 @@ namespace SourceGit.ViewModels if (File.Exists(rebaseMsgFile)) CommitMessage = File.ReadAllText(rebaseMsgFile); else if (rebasing.StoppedAt != null) - CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, rebasing.StoppedAt.SHA).Result(); + CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, rebasing.StoppedAt.SHA).GetResultAsync().Result; } } else if (File.Exists(Path.Combine(_repo.GitDir, "REVERT_HEAD"))) @@ -1880,14 +1887,14 @@ namespace SourceGit.ViewModels if (_repo.CurrentBranch is { IsDetachedHead: true } && checkPassed < CommitCheckPassed.DetachedHead) { var msg = App.Text("WorkingCopy.ConfirmCommitWithDetachedHead"); - App.ShowWindow(new Confirm(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.DetachedHead)), true); + _ = App.AskConfirmAsync(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.DetachedHead)); return; } if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && checkPassed < CommitCheckPassed.Filter) { var msg = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count); - App.ShowWindow(new Confirm(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.Filter)), true); + _ = App.AskConfirmAsync(msg, () => DoCommit(autoStage, autoPush, CommitCheckPassed.Filter)); return; } @@ -1910,14 +1917,14 @@ namespace SourceGit.ViewModels { var succ = true; if (autoStage && _unstaged.Count > 0) - succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).ExecAsync(); + succ = await new Commands.Add(_repo.FullPath, _repo.IncludeUntracked).Use(log).ExecAsync().ConfigureAwait(false); if (succ) - succ = await new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).RunAsync(); + succ = await new Commands.Commit(_repo.FullPath, _commitMessage, signOff, _useAmend, _resetAuthor).Use(log).RunAsync().ConfigureAwait(false); log.Complete(); - Dispatcher.UIThread.Post(() => + await Dispatcher.UIThread.InvokeAsync(async () => { if (succ) { @@ -1928,7 +1935,7 @@ namespace SourceGit.ViewModels { if (_repo.CurrentBranch == null) { - var currentBranchName = Commands.Branch.ShowCurrent(_repo.FullPath); + var currentBranchName = await new Commands.QueryCurrentBranch(_repo.FullPath).GetResultAsync().ConfigureAwait(false); var tmp = new Models.Branch() { Name = currentBranchName }; _repo.ShowAndStartPopup(new Push(_repo, tmp)); } diff --git a/src/Views/AIAssistant.axaml.cs b/src/Views/AIAssistant.axaml.cs index f865cabe..31475d81 100644 --- a/src/Views/AIAssistant.axaml.cs +++ b/src/Views/AIAssistant.axaml.cs @@ -84,9 +84,9 @@ namespace SourceGit.Views return; var copy = new MenuItem() { Header = App.Text("Copy") }; - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(selected); + await App.CopyTextAsync(selected); ev.Handled = true; }; diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index d760f797..362dc024 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -394,9 +394,9 @@ namespace SourceGit.Views var copy = new MenuItem(); copy.Header = App.Text("Copy"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(selected); + await App.CopyTextAsync(selected); ev.Handled = true; }; diff --git a/src/Views/CommitBaseInfo.axaml.cs b/src/Views/CommitBaseInfo.axaml.cs index ac9b53cc..ae76b081 100644 --- a/src/Views/CommitBaseInfo.axaml.cs +++ b/src/Views/CommitBaseInfo.axaml.cs @@ -1,11 +1,10 @@ +using System; using System.Collections.Generic; -using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Threading; namespace SourceGit.Views { @@ -61,10 +60,10 @@ namespace SourceGit.Views InitializeComponent(); } - private void OnCopyCommitSHA(object sender, RoutedEventArgs e) + private async void OnCopyCommitSHA(object sender, RoutedEventArgs e) { if (sender is Button { DataContext: Models.Commit commit }) - App.CopyText(commit.SHA); + await App.CopyTextAsync(commit.SHA); e.Handled = true; } @@ -103,39 +102,32 @@ namespace SourceGit.Views e.Handled = true; } - private void OnOpenContainsIn(object sender, RoutedEventArgs e) + private async void OnOpenContainsIn(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.CommitDetail detail && sender is Button button) { - var tracking = new CommitRelationTracking(detail); + var tracking = new CommitRelationTracking(); var flyout = new Flyout(); flyout.Content = tracking; flyout.ShowAt(button); + + await tracking.SetDataAsync(detail); } e.Handled = true; } - private void OnSHAPointerEntered(object sender, PointerEventArgs e) + private async void OnSHAPointerEntered(object sender, PointerEventArgs e) { if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha } ctl) { var tooltip = ToolTip.GetTip(ctl); - if (tooltip is Models.Commit commit && commit.SHA == sha) + if (tooltip is Models.Commit commit && commit.SHA.Equals(sha, StringComparison.Ordinal)) return; - Task.Run(() => - { - var c = detail.GetParent(sha); - if (c == null) - return; - - Dispatcher.UIThread.Invoke(() => - { - if (ctl.IsEffectivelyVisible && ctl.DataContext is string newSHA && newSHA == sha) - ToolTip.SetTip(ctl, c); - }); - }); + var c = await detail.GetCommitAsync(sha).ConfigureAwait(false); + if (c is not null && ctl is { IsEffectivelyVisible: true, DataContext: string newSHA } && sha.Equals(newSHA, StringComparison.Ordinal)) + ToolTip.SetTip(ctl, c); } e.Handled = true; @@ -144,11 +136,10 @@ namespace SourceGit.Views private void OnSHAPressed(object sender, PointerPressedEventArgs e) { var point = e.GetCurrentPoint(this); - - if (point.Properties.IsLeftButtonPressed && DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha }) - { + if (point.Properties.IsLeftButtonPressed && + DataContext is ViewModels.CommitDetail detail && + sender is Control { DataContext: string sha }) detail.NavigateTo(sha); - } e.Handled = true; } diff --git a/src/Views/CommitMessagePresenter.cs b/src/Views/CommitMessagePresenter.cs index 61119991..ea1b98f2 100644 --- a/src/Views/CommitMessagePresenter.cs +++ b/src/Views/CommitMessagePresenter.cs @@ -135,9 +135,9 @@ namespace SourceGit.Views var copy = new MenuItem(); copy.Header = App.Text("SHALinkCM.CopySHA"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(link); + await App.CopyTextAsync(link); ev.Handled = true; }; @@ -168,9 +168,9 @@ namespace SourceGit.Views var copy = new MenuItem(); copy.Header = App.Text("IssueLinkCM.CopyLink"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(link); + await App.CopyTextAsync(link); ev.Handled = true; }; @@ -256,7 +256,7 @@ namespace SourceGit.Views var lastDetailCommit = detail.Commit.SHA; Task.Run(() => { - var c = detail.GetParent(sha); + var c = detail.GetCommitAsync(sha).Result; Dispatcher.UIThread.Invoke(() => { // Make sure the DataContext of CommitBaseInfo is not changed. diff --git a/src/Views/CommitMessageTextBox.axaml.cs b/src/Views/CommitMessageTextBox.axaml.cs index 5330852c..0fbf3ab4 100644 --- a/src/Views/CommitMessageTextBox.axaml.cs +++ b/src/Views/CommitMessageTextBox.axaml.cs @@ -212,9 +212,9 @@ namespace SourceGit.Views e.Handled = true; } - private void CopyAllText(object sender, RoutedEventArgs e) + private async void CopyAllText(object sender, RoutedEventArgs e) { - App.CopyText(Text); + await App.CopyTextAsync(Text); e.Handled = true; } diff --git a/src/Views/CommitRelationTracking.axaml.cs b/src/Views/CommitRelationTracking.axaml.cs index 1e436552..01627d03 100644 --- a/src/Views/CommitRelationTracking.axaml.cs +++ b/src/Views/CommitRelationTracking.axaml.cs @@ -1,7 +1,5 @@ using System.Threading.Tasks; - using Avalonia.Controls; -using Avalonia.Threading; namespace SourceGit.Views { @@ -12,21 +10,12 @@ namespace SourceGit.Views InitializeComponent(); } - public CommitRelationTracking(ViewModels.CommitDetail detail) + public async Task SetDataAsync(ViewModels.CommitDetail detail) { - InitializeComponent(); - LoadingIcon.IsVisible = true; - - Task.Run(() => - { - var containsIn = detail.GetRefsContainsThisCommit(); - Dispatcher.UIThread.Invoke(() => - { - Container.ItemsSource = containsIn; - LoadingIcon.IsVisible = false; - }); - }); + var containsIn = await detail.GetRefsContainsThisCommitAsync().ConfigureAwait(false); + Container.ItemsSource = containsIn; + LoadingIcon.IsVisible = false; } } } diff --git a/src/Views/Confirm.axaml b/src/Views/Confirm.axaml index 93361533..6f2dbd6d 100644 --- a/src/Views/Confirm.axaml +++ b/src/Views/Confirm.axaml @@ -3,10 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:v="using:SourceGit.Views" - xmlns:vm="using:SourceGit.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="SourceGit.Views.Confirm" - x:DataType="vm:Confirm" x:Name="ThisControl" Icon="/App.ico" Title="{DynamicResource Text.Warn}" @@ -38,7 +36,7 @@ - + diff --git a/src/Views/Confirm.axaml.cs b/src/Views/Confirm.axaml.cs index 13e488ee..f214da23 100644 --- a/src/Views/Confirm.axaml.cs +++ b/src/Views/Confirm.axaml.cs @@ -5,28 +5,26 @@ namespace SourceGit.Views { public partial class Confirm : ChromelessWindow { + public Action OnSure + { + get; + set; + } + public Confirm() { InitializeComponent(); } - protected override void OnClosed(EventArgs e) - { - (DataContext as ViewModels.Confirm)?.Done(_isOkPressed); - base.OnClosed(e); - } - private void Sure(object _1, RoutedEventArgs _2) { - _isOkPressed = true; - Close(); + OnSure?.Invoke(); + Close(true); } private void CloseWindow(object _1, RoutedEventArgs _2) { - Close(); + Close(false); } - - private bool _isOkPressed = false; } } diff --git a/src/Views/FileHistories.axaml.cs b/src/Views/FileHistories.axaml.cs index 6a67d120..164e8514 100644 --- a/src/Views/FileHistories.axaml.cs +++ b/src/Views/FileHistories.axaml.cs @@ -29,7 +29,7 @@ namespace SourceGit.Views { if (sender is Button { DataContext: ViewModels.FileHistoriesSingleRevision single }) { - await single.ResetToSelectedRevision(); + await single.ResetToSelectedRevisionAsync().ConfigureAwait(false); NotifyDonePanel.IsVisible = true; } @@ -80,7 +80,7 @@ namespace SourceGit.Views private async void OnOpenFileWithDefaultEditor(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.FileHistories { ViewContent: ViewModels.FileHistoriesSingleRevision revision }) - await revision.OpenWithDefaultEditor(); + await revision.OpenWithDefaultEditorAsync(); e.Handled = true; } diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 1856e763..f32b930d 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -208,7 +208,7 @@ namespace SourceGit.Views e.Handled = true; } - private void OnCommitListKeyDown(object sender, KeyEventArgs e) + private async void OnCommitListKeyDown(object sender, KeyEventArgs e) { if (!e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control)) return; @@ -226,7 +226,7 @@ namespace SourceGit.Views builder.AppendLine($"{commit.SHA.AsSpan(0, 10)} - {commit.Subject}"); } - App.CopyText(builder.ToString()); + await App.CopyTextAsync(builder.ToString()); e.Handled = true; return; } diff --git a/src/Views/LFSLocks.axaml.cs b/src/Views/LFSLocks.axaml.cs index 695341f4..cb5b6427 100644 --- a/src/Views/LFSLocks.axaml.cs +++ b/src/Views/LFSLocks.axaml.cs @@ -10,18 +10,18 @@ namespace SourceGit.Views InitializeComponent(); } - private void OnUnlockButtonClicked(object sender, RoutedEventArgs e) + private async void OnUnlockButtonClicked(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.LFSLocks vm && sender is Button button) - vm.Unlock(button.DataContext as Models.LFSLock, false); + await vm.UnlockAsync(button.DataContext as Models.LFSLock, false); e.Handled = true; } - private void OnForceUnlockButtonClicked(object sender, RoutedEventArgs e) + private async void OnForceUnlockButtonClicked(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.LFSLocks vm && sender is Button button) - vm.Unlock(button.DataContext as Models.LFSLock, true); + await vm.UnlockAsync(button.DataContext as Models.LFSLock, true); e.Handled = true; } diff --git a/src/Views/LauncherPage.axaml.cs b/src/Views/LauncherPage.axaml.cs index 5941ceae..95bddcad 100644 --- a/src/Views/LauncherPage.axaml.cs +++ b/src/Views/LauncherPage.axaml.cs @@ -34,10 +34,10 @@ namespace SourceGit.Views OnPopupCancel(sender, e); } - private void OnCopyNotification(object sender, RoutedEventArgs e) + private async void OnCopyNotification(object sender, RoutedEventArgs e) { if (sender is Button { DataContext: Models.Notification notice }) - App.CopyText(notice.Message); + await App.CopyTextAsync(notice.Message); e.Handled = true; } diff --git a/src/Views/Preferences.axaml.cs b/src/Views/Preferences.axaml.cs index f9f7404a..50da4228 100644 --- a/src/Views/Preferences.axaml.cs +++ b/src/Views/Preferences.axaml.cs @@ -120,7 +120,7 @@ namespace SourceGit.Views if (pref.IsGitConfigured()) { - var config = new Commands.Config(null).ListAll(); + var config = new Commands.Config(null).ReadAllAsync().Result; if (config.TryGetValue("user.name", out var name)) DefaultUser = name; @@ -160,7 +160,7 @@ namespace SourceGit.Views if (change.Property == GPGFormatProperty) { - var config = await new Commands.Config(null).ListAllAsync(); + var config = await new Commands.Config(null).ReadAllAsync(); if (GPGFormat.Value == "openpgp" && config.TryGetValue("gpg.program", out var openpgp)) GPGExecutableFile = openpgp; else if (config.TryGetValue($"gpg.{GPGFormat.Value}.program", out var gpgProgram)) @@ -175,7 +175,7 @@ namespace SourceGit.Views if (Design.IsDesignMode) return; - var config = await new Commands.Config(null).ListAllAsync(); + var config = await new Commands.Config(null).ReadAllAsync(); await SetIfChangedAsync(config, "user.name", DefaultUser, ""); await SetIfChangedAsync(config, "user.email", DefaultEmail, ""); await SetIfChangedAsync(config, "user.signingkey", GPGUserKey, ""); diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index 472f552a..ac243e55 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -437,12 +437,12 @@ namespace SourceGit.Views e.Handled = true; } - private void OnBisectCommand(object sender, RoutedEventArgs e) + private async void OnBisectCommand(object sender, RoutedEventArgs e) { if (sender is Button button && DataContext is ViewModels.Repository { IsBisectCommandRunning: false } repo && repo.CanCreatePopup()) - repo.Bisect(button.Tag as string); + await repo.ExecBisectCommandAsync(button.Tag as string); e.Handled = true; } diff --git a/src/Views/RepositoryToolbar.axaml.cs b/src/Views/RepositoryToolbar.axaml.cs index aad6fef3..d32aab20 100644 --- a/src/Views/RepositoryToolbar.axaml.cs +++ b/src/Views/RepositoryToolbar.axaml.cs @@ -116,7 +116,7 @@ namespace SourceGit.Views e.Handled = true; } - private void StartBisect(object sender, RoutedEventArgs e) + private async void StartBisect(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.Repository { IsBisectCommandRunning: false, InProgressContext: null } repo && repo.CanCreatePopup()) @@ -126,7 +126,7 @@ namespace SourceGit.Views else if (repo.IsBisectCommandRunning || repo.BisectState != Models.BisectState.None) App.RaiseException(repo.FullPath, "Bisect is running! Please abort it before starting a new one."); else - repo.Bisect("start"); + await repo.ExecBisectCommandAsync("start"); } e.Handled = true; diff --git a/src/Views/RevisionFileContentViewer.axaml.cs b/src/Views/RevisionFileContentViewer.axaml.cs index cfbb6e3d..acb2017f 100644 --- a/src/Views/RevisionFileContentViewer.axaml.cs +++ b/src/Views/RevisionFileContentViewer.axaml.cs @@ -108,9 +108,9 @@ namespace SourceGit.Views return; var copy = new MenuItem() { Header = App.Text("Copy") }; - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(selected); + await App.CopyTextAsync(selected); ev.Handled = true; }; diff --git a/src/Views/RevisionFileTreeView.axaml.cs b/src/Views/RevisionFileTreeView.axaml.cs index 2c6a61c2..95847bdb 100644 --- a/src/Views/RevisionFileTreeView.axaml.cs +++ b/src/Views/RevisionFileTreeView.axaml.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; - +using System.Threading.Tasks; using Avalonia; using Avalonia.Collections; using Avalonia.Controls; @@ -16,13 +16,13 @@ namespace SourceGit.Views { protected override Type StyleKeyOverride => typeof(ToggleButton); - protected override void OnPointerPressed(PointerPressedEventArgs e) + protected override async void OnPointerPressed(PointerPressedEventArgs e) { if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && DataContext is ViewModels.RevisionFileTreeNode { IsFolder: true } node) { var tree = this.FindAncestorOfType(); - tree?.ToggleNodeIsExpanded(node); + await tree?.ToggleNodeIsExpandedAsync(node); } e.Handled = true; @@ -107,13 +107,14 @@ namespace SourceGit.Views { protected override Type StyleKeyOverride => typeof(ListBox); - protected override void OnKeyDown(KeyEventArgs e) + protected override async void OnKeyDown(KeyEventArgs e) { if (SelectedItem is ViewModels.RevisionFileTreeNode { IsFolder: true } node && e.KeyModifiers == KeyModifiers.None) { if ((node.IsExpanded && e.Key == Key.Left) || (!node.IsExpanded && e.Key == Key.Right)) { - this.FindAncestorOfType()?.ToggleNodeIsExpanded(node); + var tree = this.FindAncestorOfType(); + await tree?.ToggleNodeIsExpandedAsync(node); e.Handled = true; } } @@ -141,7 +142,7 @@ namespace SourceGit.Views InitializeComponent(); } - public void SetSearchResult(string file) + public async Task SetSearchResultAsync(string file) { Rows.Clear(); _searchResult.Clear(); @@ -157,7 +158,7 @@ namespace SourceGit.Views if (vm?.Commit == null) return; - var objects = vm.GetRevisionFilesUnderFolder(file); + var objects = await vm.GetRevisionFilesUnderFolderAsync(file).ConfigureAwait(false); if (objects is not { Count: 1 }) return; @@ -203,7 +204,7 @@ namespace SourceGit.Views GC.Collect(); } - public void ToggleNodeIsExpanded(ViewModels.RevisionFileTreeNode node) + public async Task ToggleNodeIsExpandedAsync(ViewModels.RevisionFileTreeNode node) { _disableSelectionChangingEvent = true; node.IsExpanded = !node.IsExpanded; @@ -215,7 +216,7 @@ namespace SourceGit.Views if (node.IsExpanded) { - var subtree = GetChildrenOfTreeNode(node); + var subtree = await GetChildrenOfTreeNodeAsync(node); if (subtree is { Count: > 0 }) { var subrows = new List(); @@ -240,7 +241,7 @@ namespace SourceGit.Views _disableSelectionChangingEvent = false; } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override async void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -257,7 +258,7 @@ namespace SourceGit.Views return; } - var objects = vm.GetRevisionFilesUnderFolder(null); + var objects = await vm.GetRevisionFilesUnderFolderAsync(null).ConfigureAwait(false); if (objects == null || objects.Count == 0) { GC.Collect(); @@ -288,7 +289,7 @@ namespace SourceGit.Views e.Handled = true; } - private void OnTreeNodeDoubleTapped(object sender, TappedEventArgs e) + private async void OnTreeNodeDoubleTapped(object sender, TappedEventArgs e) { if (sender is Grid { DataContext: ViewModels.RevisionFileTreeNode { IsFolder: true } node }) { @@ -296,22 +297,22 @@ namespace SourceGit.Views if (posX < node.Depth * 16 + 16) return; - ToggleNodeIsExpanded(node); + await ToggleNodeIsExpandedAsync(node); } } - private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _) + private async void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _) { if (_disableSelectionChangingEvent || DataContext is not ViewModels.CommitDetail vm) return; if (sender is ListBox { SelectedItem: ViewModels.RevisionFileTreeNode { IsFolder: false } node }) - vm.ViewRevisionFile(node.Backend); + await vm.ViewRevisionFileAsync(node.Backend); else - vm.ViewRevisionFile(null); + await vm.ViewRevisionFileAsync(null); } - private List GetChildrenOfTreeNode(ViewModels.RevisionFileTreeNode node) + private async Task> GetChildrenOfTreeNodeAsync(ViewModels.RevisionFileTreeNode node) { if (!node.IsFolder) return null; @@ -320,8 +321,10 @@ namespace SourceGit.Views return node.Children; var vm = DataContext as ViewModels.CommitDetail; + if (vm == null) + return null; - var objects = vm?.GetRevisionFilesUnderFolder(node.Backend.Path + "/"); + var objects = await vm.GetRevisionFilesUnderFolderAsync(node.Backend.Path + "/").ConfigureAwait(false); if (objects == null || objects.Count == 0) return null; diff --git a/src/Views/RevisionFiles.axaml.cs b/src/Views/RevisionFiles.axaml.cs index 4894d1d4..3ebfc4e1 100644 --- a/src/Views/RevisionFiles.axaml.cs +++ b/src/Views/RevisionFiles.axaml.cs @@ -11,7 +11,7 @@ namespace SourceGit.Views InitializeComponent(); } - private void OnSearchBoxKeyDown(object _, KeyEventArgs e) + private async void OnSearchBoxKeyDown(object _, KeyEventArgs e) { var vm = DataContext as ViewModels.CommitDetail; if (vm == null) @@ -19,7 +19,7 @@ namespace SourceGit.Views if (e.Key == Key.Enter) { - FileTree.SetSearchResult(vm.RevisionFileSearchFilter); + await FileTree.SetSearchResultAsync(vm.RevisionFileSearchFilter); e.Handled = true; } else if (e.Key == Key.Down || e.Key == Key.Up) @@ -39,13 +39,13 @@ namespace SourceGit.Views } } - private void OnSearchBoxTextChanged(object _, TextChangedEventArgs e) + private async void OnSearchBoxTextChanged(object _, TextChangedEventArgs e) { if (string.IsNullOrEmpty(TxtSearchRevisionFiles.Text)) - FileTree.SetSearchResult(null); + await FileTree.SetSearchResultAsync(null); } - private void OnSearchSuggestionBoxKeyDown(object _, KeyEventArgs e) + private async void OnSearchSuggestionBoxKeyDown(object _, KeyEventArgs e) { var vm = DataContext as ViewModels.CommitDetail; if (vm == null) @@ -60,12 +60,12 @@ namespace SourceGit.Views { vm.RevisionFileSearchFilter = content; TxtSearchRevisionFiles.CaretIndex = content.Length; - FileTree.SetSearchResult(vm.RevisionFileSearchFilter); + await FileTree.SetSearchResultAsync(vm.RevisionFileSearchFilter); e.Handled = true; } } - private void OnSearchSuggestionDoubleTapped(object sender, TappedEventArgs e) + private async void OnSearchSuggestionDoubleTapped(object sender, TappedEventArgs e) { var vm = DataContext as ViewModels.CommitDetail; if (vm == null) @@ -76,7 +76,7 @@ namespace SourceGit.Views { vm.RevisionFileSearchFilter = content; TxtSearchRevisionFiles.CaretIndex = content.Length; - FileTree.SetSearchResult(vm.RevisionFileSearchFilter); + await FileTree.SetSearchResultAsync(vm.RevisionFileSearchFilter); } e.Handled = true; @@ -85,7 +85,7 @@ namespace SourceGit.Views private async void OnOpenFileWithDefaultEditor(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.CommitDetail { CanOpenRevisionFileWithDefaultEditor: true } vm) - await vm.OpenRevisionFileWithDefaultEditor(vm.ViewRevisionFilePath); + await vm.OpenRevisionFileWithDefaultEditorAsync(vm.ViewRevisionFilePath); e.Handled = true; } diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index 3a9de5b8..75e690a1 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -4,7 +4,7 @@ using System.ComponentModel; using System.Globalization; using System.IO; using System.Text; - +using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; using Avalonia.Data; @@ -758,13 +758,13 @@ namespace SourceGit.Views } } - private void OnTextAreaKeyDown(object sender, KeyEventArgs e) + private async void OnTextAreaKeyDown(object sender, KeyEventArgs e) { if (e.KeyModifiers.Equals(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control)) { if (e.Key == Key.C) { - CopyWithoutIndicators(); + await CopyWithoutIndicatorsAsync(); e.Handled = true; } } @@ -788,9 +788,9 @@ namespace SourceGit.Views var copy = new MenuItem(); copy.Header = App.Text("Copy"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - CopyWithoutIndicators(); + await CopyWithoutIndicatorsAsync(); ev.Handled = true; }; @@ -983,12 +983,12 @@ namespace SourceGit.Views } } - private void CopyWithoutIndicators() + private async Task CopyWithoutIndicatorsAsync() { var selection = TextArea.Selection; if (selection.IsEmpty) { - App.CopyText(string.Empty); + await App.CopyTextAsync(string.Empty); return; } @@ -1009,11 +1009,11 @@ namespace SourceGit.Views if (line.Type == Models.TextDiffLineType.Indicator || line.Type == Models.TextDiffLineType.None) { - App.CopyText(string.Empty); + await App.CopyTextAsync(string.Empty); return; } - App.CopyText(SelectedText); + await App.CopyTextAsync(SelectedText); return; } @@ -1058,7 +1058,7 @@ namespace SourceGit.Views builder.AppendLine(line.Content); } - App.CopyText(builder.ToString()); + await App.CopyTextAsync(builder.ToString()); } private TextMate.Installation _textMate = null; @@ -1843,7 +1843,7 @@ namespace SourceGit.Views if (!selection.HasLeftChanges) { - await new Commands.Add(repo.FullPath, change).ExecAsync(); + await new Commands.Add(repo.FullPath, change).ExecAsync().ConfigureAwait(false); } else { @@ -1854,16 +1854,16 @@ namespace SourceGit.Views } else if (chunk.Combined) { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).ResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync().ConfigureAwait(false); diff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile); } else { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).ResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync().ConfigureAwait(false); diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, chunk.IsOldSide, tmpFile); } - await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index").ExecAsync(); + await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index").ExecAsync().ConfigureAwait(false); File.Delete(tmpFile); } @@ -1898,13 +1898,13 @@ namespace SourceGit.Views if (!selection.HasLeftChanges) { if (change.DataForAmend != null) - await new Commands.UnstageChangesForAmend(repo.FullPath, [change]).ExecAsync(); + await new Commands.UnstageChangesForAmend(repo.FullPath, [change]).ExecAsync().ConfigureAwait(false); else - await new Commands.Restore(repo.FullPath, change).ExecAsync(); + await new Commands.Restore(repo.FullPath, change).ExecAsync().ConfigureAwait(false); } else { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).ResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync().ConfigureAwait(false); var tmpFile = Path.GetTempFileName(); if (change.Index == Models.ChangeState.Added) diff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile); @@ -1913,7 +1913,7 @@ namespace SourceGit.Views else diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile); - await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index --reverse").ExecAsync(); + await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index --reverse").ExecAsync().ConfigureAwait(false); File.Delete(tmpFile); } @@ -1947,7 +1947,7 @@ namespace SourceGit.Views if (!selection.HasLeftChanges) { - await Commands.Discard.ChangesAsync(repo.FullPath, [change], null); + await Commands.Discard.ChangesAsync(repo.FullPath, [change], null).ConfigureAwait(false); } else { @@ -1958,16 +1958,16 @@ namespace SourceGit.Views } else if (chunk.Combined) { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).ResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync().ConfigureAwait(false); diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile); } else { - var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).ResultAsync(); + var treeGuid = await new Commands.QueryStagedFileBlobGuid(diff.Repo, change.Path).GetResultAsync().ConfigureAwait(false); diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile); } - await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--reverse").ExecAsync(); + await new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--reverse").ExecAsync().ConfigureAwait(false); File.Delete(tmpFile); } diff --git a/src/Views/ViewLogs.axaml.cs b/src/Views/ViewLogs.axaml.cs index b9c71882..40a53235 100644 --- a/src/Views/ViewLogs.axaml.cs +++ b/src/Views/ViewLogs.axaml.cs @@ -18,9 +18,9 @@ namespace SourceGit.Views var copy = new MenuItem(); copy.Header = App.Text("ViewLogs.CopyLog"); copy.Icon = App.CreateMenuIcon("Icons.Copy"); - copy.Click += (_, ev) => + copy.Click += async (_, ev) => { - App.CopyText(log.Content); + await App.CopyTextAsync(log.Content); ev.Handled = true; };