feature: async (#1492)

* Async command methods
* Async `Task.Run` where possible
* Remove redundant `Task.Run` in `Sure` methods
* Remove leftover braces and reformat
* Async event handlers as needed
This commit is contained in:
Nathan Baulch
2025-07-02 23:16:06 +10:00
committed by leo
parent 3b8dcd72ee
commit 463e304491
134 changed files with 2333 additions and 1549 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -19,9 +20,9 @@ namespace SourceGit.Commands
_result.File = file;
}
public Models.BlameData Result()
public async Task<Models.BlameData> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return _result;

View File

@@ -1,4 +1,5 @@
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -13,7 +14,16 @@ namespace SourceGit.Commands
return cmd.ReadToEnd().StdOut.Trim();
}
public static bool Create(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
public static async Task<string> 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<bool> CreateAsync(string repo, string name, string basedOn, bool force, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("branch ");
@@ -28,20 +38,20 @@ namespace SourceGit.Commands
cmd.Context = repo;
cmd.Args = builder.ToString();
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool Rename(string repo, string name, string to, Models.ICommandLog log)
public static async Task<bool> RenameAsync(string repo, string name, string to, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -M {name} {to}";
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool SetUpstream(string repo, string name, string upstream, Models.ICommandLog log)
public static async Task<bool> SetUpstreamAsync(string repo, string name, string upstream, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -53,31 +63,31 @@ namespace SourceGit.Commands
else
cmd.Args = $"branch {name} -u {upstream}";
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool DeleteLocal(string repo, string name, Models.ICommandLog log)
public static async Task<bool> DeleteLocalAsync(string repo, string name, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D {name}";
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool DeleteRemote(string repo, string remote, string name, Models.ICommandLog log)
public static async Task<bool> DeleteRemoteAsync(string repo, string remote, string name, Models.ICommandLog log)
{
bool exists = new Remote(repo).HasBranch(remote, name);
bool exists = await new Remote(repo).HasBranchAsync(remote, name);
if (exists)
return new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.Exec();
return await new Push(repo, remote, $"refs/heads/{name}", true) { Log = log }.ExecAsync();
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D -r {remote}/{name}";
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
}
}

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,7 +12,7 @@ namespace SourceGit.Commands
Context = repo;
}
public bool Branch(string branch, bool force)
public async Task<bool> BranchAsync(string branch, bool force)
{
var builder = new StringBuilder();
builder.Append("checkout --progress ");
@@ -20,10 +21,10 @@ namespace SourceGit.Commands
builder.Append(branch);
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Branch(string branch, string basedOn, bool force, bool allowOverwrite)
public async Task<bool> BranchAsync(string branch, string basedOn, bool force, bool allowOverwrite)
{
var builder = new StringBuilder();
builder.Append("checkout --progress ");
@@ -35,17 +36,17 @@ namespace SourceGit.Commands
builder.Append(basedOn);
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Commit(string commitId, bool force)
public async Task<bool> CommitAsync(string commitId, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --detach --progress {commitId}";
return Exec();
return await ExecAsync();
}
public bool UseTheirs(List<string> files)
public async Task<bool> UseTheirsAsync(List<string> files)
{
var builder = new StringBuilder();
builder.Append("checkout --theirs --");
@@ -56,10 +57,10 @@ namespace SourceGit.Commands
builder.Append("\"");
}
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool UseMine(List<string> files)
public async Task<bool> UseMineAsync(List<string> files)
{
var builder = new StringBuilder();
builder.Append("checkout --ours --");
@@ -69,14 +70,15 @@ namespace SourceGit.Commands
builder.Append(f);
builder.Append("\"");
}
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool FileWithRevision(string file, string revision)
public async Task<bool> FileWithRevisionAsync(string file, string revision)
{
Args = $"checkout --no-overlay {revision} -- \"{file}\"";
return Exec();
return await ExecAsync();
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -32,7 +33,39 @@ namespace SourceGit.Commands
public bool RaiseError { get; set; } = true;
public Models.ICommandLog Log { get; set; } = null;
public bool Exec()
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<bool> ExecAsync()
{
Log?.AppendLine($"$ git {Args}\n");
@@ -74,7 +107,7 @@ namespace SourceGit.Commands
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
await proc.WaitForExitAsync(CancellationToken);
if (dummy != null)
{
@@ -103,7 +136,7 @@ namespace SourceGit.Commands
return true;
}
public ReadToEndResult ReadToEnd()
public async Task<ReadToEndResult> ReadToEndAsync()
{
var start = CreateGitStartInfo();
var proc = new Process() { StartInfo = start };
@@ -124,11 +157,11 @@ namespace SourceGit.Commands
var rs = new ReadToEndResult()
{
StdOut = proc.StandardOutput.ReadToEnd(),
StdErr = proc.StandardError.ReadToEnd(),
StdOut = await proc.StandardOutput.ReadToEndAsync(CancellationToken),
StdErr = await proc.StandardError.ReadToEndAsync(CancellationToken),
};
proc.WaitForExit();
await proc.WaitForExitAsync(CancellationToken);
rs.IsSuccess = proc.ExitCode == 0;
proc.Close();

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -18,9 +19,9 @@ namespace SourceGit.Commands
Args += resetAuthor ? " --amend --reset-author --no-edit" : " --amend --no-edit";
}
public bool Run()
public async Task<bool> RunAsync()
{
var succ = Exec();
var succ = await ExecAsync();
try
{

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -43,6 +44,20 @@ namespace SourceGit.Commands
return _changes;
}
public async Task<List<Models.Change>> 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)
{
var match = REG_FORMAT().Match(line);

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -51,7 +52,37 @@ namespace SourceGit.Commands
return ReadToEnd().StdOut.Trim();
}
public bool Set(string key, string value, bool allowEmpty = false)
public async Task<Dictionary<string, string>> ListAllAsync()
{
Args = "config -l";
var output = await ReadToEndAsync();
var rs = new Dictionary<string, string>();
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 async Task<string> GetAsync(string key)
{
Args = $"config {key}";
return (await ReadToEndAsync()).StdOut.Trim();
}
public async Task<bool> SetAsync(string key, string value, bool allowEmpty = false)
{
var scope = _isLocal ? "--local" : "--global";
@@ -60,7 +91,7 @@ namespace SourceGit.Commands
else
Args = $"config {scope} {key} \"{value}\"";
return Exec();
return await ExecAsync();
}
private bool _isLocal = false;

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,9 +12,9 @@ namespace SourceGit.Commands
Args = "--no-optional-locks status -uno --ignore-submodules=all --porcelain";
}
public int Result()
public async Task<int> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -35,9 +36,9 @@ namespace SourceGit.Commands
Args = $"diff --no-ext-diff --patch --unified={unified} {opt}";
}
public Models.DiffResult Result()
public async Task<Models.DiffResult> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
var start = 0;
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -12,9 +13,9 @@ namespace SourceGit.Commands
/// <param name="repo"></param>
/// <param name="includeIgnored"></param>
/// <param name="log"></param>
public static void All(string repo, bool includeIgnored, Models.ICommandLog log)
public static async Task AllAsync(string repo, bool includeIgnored, Models.ICommandLog log)
{
var changes = new QueryLocalChanges(repo).Result();
var changes = await new QueryLocalChanges(repo).ResultAsync();
try
{
foreach (var c in changes)
@@ -37,10 +38,10 @@ namespace SourceGit.Commands
App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
}
new Reset(repo, "HEAD", "--hard") { Log = log }.Exec();
await new Reset(repo, "HEAD", "--hard") { Log = log }.ExecAsync();
if (includeIgnored)
new Clean(repo) { Log = log }.Exec();
await new Clean(repo) { Log = log }.ExecAsync();
}
/// <summary>
@@ -49,7 +50,7 @@ namespace SourceGit.Commands
/// <param name="repo"></param>
/// <param name="changes"></param>
/// <param name="log"></param>
public static void Changes(string repo, List<Models.Change> changes, Models.ICommandLog log)
public static async Task ChangesAsync(string repo, List<Models.Change> changes, Models.ICommandLog log)
{
var restores = new List<string>();
@@ -79,8 +80,8 @@ namespace SourceGit.Commands
if (restores.Count > 0)
{
var pathSpecFile = Path.GetTempFileName();
File.WriteAllLines(pathSpecFile, restores);
new Restore(repo, pathSpecFile, false) { Log = log }.Exec();
await File.WriteAllLinesAsync(pathSpecFile, restores);
await new Restore(repo, pathSpecFile, false) { Log = log }.ExecAsync();
File.Delete(pathSpecFile);
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -29,7 +30,7 @@ namespace SourceGit.Commands
_onResponse = onResponse;
}
public void Exec()
public async Task ExecAsync()
{
try
{
@@ -45,10 +46,10 @@ namespace SourceGit.Commands
responseBuilder.Append("- ");
summaryBuilder.Append("- ");
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
var rs = await new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEndAsync();
if (rs.IsSuccess)
{
_service.Chat(
await _service.ChatAsync(
_service.AnalyzeDiffPrompt,
$"Here is the `git diff` output: {rs.StdOut}",
_cancelToken,
@@ -72,7 +73,7 @@ namespace SourceGit.Commands
var responseBody = responseBuilder.ToString();
var subjectBuilder = new StringBuilder();
_service.Chat(
await _service.ChatAsync(
_service.GenerateSubjectPrompt,
$"Here are the summaries changes:\n{summaryBuilder}",
_cancelToken,

View File

@@ -1,30 +1,31 @@
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class GitFlow
{
public static bool Init(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
public static async Task<bool> InitAsync(string repo, string master, string develop, string feature, string release, string hotfix, string version, Models.ICommandLog log)
{
var config = new Config(repo);
config.Set("gitflow.branch.master", master);
config.Set("gitflow.branch.develop", develop);
config.Set("gitflow.prefix.feature", feature);
config.Set("gitflow.prefix.bugfix", "bugfix/");
config.Set("gitflow.prefix.release", release);
config.Set("gitflow.prefix.hotfix", hotfix);
config.Set("gitflow.prefix.support", "support/");
config.Set("gitflow.prefix.versiontag", version, true);
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);
var init = new Command();
init.WorkingDirectory = repo;
init.Context = repo;
init.Args = "flow init -d";
init.Log = log;
return init.Exec();
return await init.ExecAsync();
}
public static bool Start(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log)
public static async Task<bool> StartAsync(string repo, Models.GitFlowBranchType type, string name, Models.ICommandLog log)
{
var start = new Command();
start.WorkingDirectory = repo;
@@ -47,10 +48,10 @@ namespace SourceGit.Commands
}
start.Log = log;
return start.Exec();
return await start.ExecAsync();
}
public static bool Finish(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
public static async Task<bool> FinishAsync(string repo, Models.GitFlowBranchType type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
{
var builder = new StringBuilder();
builder.Append("flow ");
@@ -85,7 +86,7 @@ namespace SourceGit.Commands
finish.Context = repo;
finish.Args = builder.ToString();
finish.Log = log;
return finish.Exec();
return await finish.ExecAsync();
}
}
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -20,5 +21,16 @@ namespace SourceGit.Commands
var rs = ReadToEnd();
return rs.IsSuccess && rs.StdOut.Trim() == "true";
}
public async Task<bool> 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();
return rs.IsSuccess && rs.StdOut.Trim() == "true";
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -15,9 +16,9 @@ namespace SourceGit.Commands
RaiseError = false;
}
public bool Result()
public async Task<bool> ResultAsync()
{
return REG_TEST().IsMatch(ReadToEnd().StdOut);
return REG_TEST().IsMatch((await ReadToEndAsync()).StdOut);
}
}
}

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class IsCommitSHA : Command
{
@@ -8,9 +10,9 @@
Args = $"cat-file -t {hash}";
}
public bool Result()
public async Task<bool> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
return rs.IsSuccess && rs.StdOut.Trim().Equals("commit");
}
}

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class IsConflictResolved : Command
{
@@ -15,5 +17,10 @@
{
return ReadToEnd().IsSuccess;
}
public async Task<bool> ResultAsync()
{
return (await ReadToEndAsync()).IsSuccess;
}
}
}

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class IsLFSFiltered : Command
{
@@ -23,5 +25,11 @@
var rs = ReadToEnd();
return rs.IsSuccess && rs.StdOut.Contains("filter\0lfs");
}
public async Task<bool> ResultAsync()
{
var rs = await ReadToEndAsync();
return rs.IsSuccess && rs.StdOut.Contains("filter\0lfs");
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -36,42 +37,42 @@ namespace SourceGit.Commands
return content.Contains("git lfs pre-push");
}
public bool Install(Models.ICommandLog log)
public async Task<bool> InstallAsync(Models.ICommandLog log)
{
return new SubCmd(_repo, "lfs install --local", log).Exec();
return await new SubCmd(_repo, "lfs install --local", log).ExecAsync();
}
public bool Track(string pattern, bool isFilenameMode, Models.ICommandLog log)
public async Task<bool> TrackAsync(string pattern, bool isFilenameMode, Models.ICommandLog log)
{
var opt = isFilenameMode ? "--filename" : "";
return new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).Exec();
return await new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", log).ExecAsync();
}
public void Fetch(string remote, Models.ICommandLog log)
public async Task FetchAsync(string remote, Models.ICommandLog log)
{
new SubCmd(_repo, $"lfs fetch {remote}", log).Exec();
await new SubCmd(_repo, $"lfs fetch {remote}", log).ExecAsync();
}
public void Pull(string remote, Models.ICommandLog log)
public async Task PullAsync(string remote, Models.ICommandLog log)
{
new SubCmd(_repo, $"lfs pull {remote}", log).Exec();
await new SubCmd(_repo, $"lfs pull {remote}", log).ExecAsync();
}
public void Push(string remote, Models.ICommandLog log)
public async Task PushAsync(string remote, Models.ICommandLog log)
{
new SubCmd(_repo, $"lfs push {remote}", log).Exec();
await new SubCmd(_repo, $"lfs push {remote}", log).ExecAsync();
}
public void Prune(Models.ICommandLog log)
public async Task PruneAsync(Models.ICommandLog log)
{
new SubCmd(_repo, "lfs prune", log).Exec();
await new SubCmd(_repo, "lfs prune", log).ExecAsync();
}
public List<Models.LFSLock> Locks(string remote)
public async Task<List<Models.LFSLock>> LocksAsync(string remote)
{
var locks = new List<Models.LFSLock>();
var cmd = new SubCmd(_repo, $"lfs locks --remote={remote}", null);
var rs = cmd.ReadToEnd();
var rs = await cmd.ReadToEndAsync();
if (rs.IsSuccess)
{
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
@@ -93,21 +94,21 @@ namespace SourceGit.Commands
return locks;
}
public bool Lock(string remote, string file, Models.ICommandLog log)
public async Task<bool> LockAsync(string remote, string file, Models.ICommandLog log)
{
return new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).Exec();
return await new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", log).ExecAsync();
}
public bool Unlock(string remote, string file, bool force, Models.ICommandLog log)
public async Task<bool> UnlockAsync(string remote, string file, bool force, Models.ICommandLog log)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).Exec();
return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", log).ExecAsync();
}
public bool Unlock(string remote, long id, bool force, Models.ICommandLog log)
public async Task<bool> UnlockAsync(string remote, long id, bool force, Models.ICommandLog log)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).Exec();
return await new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", log).ExecAsync();
}
private readonly string _repo;

View File

@@ -1,10 +1,11 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class MergeTool
{
public static bool OpenForMerge(string repo, int toolType, string toolPath, string file)
public static async Task<bool> OpenForMergeAsync(string repo, int toolType, string toolPath, string file)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -17,7 +18,7 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"mergetool {fileArg}";
return cmd.Exec();
return await cmd.ExecAsync();
}
if (!File.Exists(toolPath))
@@ -34,10 +35,10 @@ 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 cmd.Exec();
return await cmd.ExecAsync();
}
public static bool OpenForDiff(string repo, int toolType, string toolPath, Models.DiffOption option)
public static async Task<bool> OpenForDiffAsync(string repo, int toolType, string toolPath, Models.DiffOption option)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
@@ -47,7 +48,7 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"difftool -g --no-prompt {option}";
return cmd.Exec();
return await cmd.ExecAsync();
}
if (!File.Exists(toolPath))
@@ -64,7 +65,7 @@ namespace SourceGit.Commands
}
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}";
return cmd.Exec();
return await cmd.ExecAsync();
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -16,10 +17,10 @@ namespace SourceGit.Commands
RaiseError = false;
}
public List<string> Result()
public async Task<List<string>> ResultAsync()
{
var outs = new List<string>();
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -61,6 +62,46 @@ namespace SourceGit.Commands
return branches;
}
public async Task<List<Models.Branch>> ResultAsync()
{
var branches = new List<Models.Branch>();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return branches;
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var remoteHeads = new Dictionary<string, string>();
foreach (var line in lines)
{
var b = ParseLine(line);
if (b != null)
{
branches.Add(b);
if (!b.IsLocal)
remoteHeads.Add(b.FullName, b.Head);
}
}
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 ??= await new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).ResultAsync();
}
else
{
b.IsUpstreamGone = true;
b.TrackStatus ??= new Models.BranchTrackStatus();
}
}
}
return branches;
}
private Models.Branch ParseLine(string line)
{
var parts = line.Split('\0');

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -13,9 +14,9 @@ namespace SourceGit.Commands
Args = $"rev-list -{max} --parents --branches --remotes --ancestry-path ^{commit}";
}
public List<string> Result()
public async Task<List<string>> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
var outs = new List<string>();
if (rs.IsSuccess)
{

View File

@@ -1,3 +1,5 @@
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class QueryCommitFullMessage : Command
@@ -16,5 +18,13 @@ namespace SourceGit.Commands
return rs.StdOut.TrimEnd();
return string.Empty;
}
public async Task<string> ResultAsync()
{
var rs = await ReadToEndAsync();
if (rs.IsSuccess)
return rs.StdOut.TrimEnd();
return string.Empty;
}
}
}

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class QueryCommitSignInfo : Command
{
@@ -12,9 +14,9 @@
Args = $"{(useFakeSignersFile ? fakeSignersFileArg : string.Empty)} {baseArgs} {sha}";
}
public Models.CommitSignInfo Result()
public async Task<Models.CommitSignInfo> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return null;

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -143,6 +144,88 @@ namespace SourceGit.Commands
}
}
public async Task<List<Models.Commit>> 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 shas = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
if (shas.Length == 0)
return;
var set = new HashSet<string>();
foreach (var sha in shas)
set.Add(sha);
foreach (var c in _commits)
{
if (set.Contains(c.SHA))
{
c.IsMerged = true;
break;
}
}
}
private List<Models.Commit> _commits = new List<Models.Commit>();
private Models.Commit _current = null;
private bool _findFirstMerged = false;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,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 List<Models.InteractiveCommit> Result()
public async Task<List<Models.InteractiveCommit>> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return _commits;

View File

@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -69,5 +70,69 @@ namespace SourceGit.Commands
return stream;
}
public static async Task<Stream> RunAsync(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();
await proc.StandardOutput.BaseStream.CopyToAsync(stream);
await proc.WaitForExitAsync();
proc.Close();
stream.Position = 0;
}
catch (Exception e)
{
App.RaiseException(repo, $"Failed to query file content: {e}");
}
return stream;
}
public static async Task<Stream> FromLFSAsync(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();
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();
proc.Close();
stream.Position = 0;
}
catch (Exception e)
{
App.RaiseException(repo, $"Failed to query file content: {e}");
}
return stream;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,9 +15,9 @@ namespace SourceGit.Commands
Args = $"ls-tree {revision} -l -- \"{file}\"";
}
public long Result()
public async Task<long> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (rs.IsSuccess)
{
var match = REG_FORMAT().Match(rs.StdOut);

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -22,5 +23,17 @@ namespace SourceGit.Commands
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
}
public async Task<string> ResultAsync()
{
var rs = (await ReadToEndAsync()).StdOut;
if (string.IsNullOrEmpty(rs))
return null;
rs = rs.Trim();
if (Path.IsPathRooted(rs))
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
}
}
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -22,5 +23,17 @@ namespace SourceGit.Commands
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
}
public async Task<string> ResultAsync()
{
var rs = (await ReadToEndAsync()).StdOut;
if (string.IsNullOrEmpty(rs))
return null;
rs = rs.Trim();
if (Path.IsPathRooted(rs))
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -159,5 +160,148 @@ namespace SourceGit.Commands
return outs;
}
public async Task<List<Models.Change>> ResultAsync()
{
var outs = new List<Models.Change>();
var rs = await ReadToEndAsync();
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;
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -36,5 +37,30 @@ namespace SourceGit.Commands
return rs;
}
public async Task<List<Models.Decorator>> ResultAsync()
{
var rs = new List<Models.Decorator>();
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;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -44,5 +45,34 @@ namespace SourceGit.Commands
return outs;
}
public async Task<List<Models.Remote>> ResultAsync()
{
var outs = new List<Models.Remote>();
var rs = await ReadToEndAsync();
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;
}
}
}

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class QueryRevisionByRefName : Command
{
@@ -17,5 +19,14 @@
return null;
}
public async Task<string> ResultAsync()
{
var rs = await ReadToEndAsync();
if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut))
return rs.StdOut.Trim();
return null;
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,9 +12,9 @@ namespace SourceGit.Commands
Args = $"ls-tree -r -z --name-only {revision}";
}
public List<string> Result()
public async Task<List<string>> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return [];

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -40,6 +41,28 @@ namespace SourceGit.Commands
return _objects;
}
public async Task<List<Models.Object>> 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)
{
var match = REG_FORMAT().Match(line);

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -37,5 +38,32 @@ namespace SourceGit.Commands
return null;
}
public async Task<Models.Commit> ResultAsync()
{
var rs = await ReadToEndAsync();
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;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -87,6 +88,74 @@ namespace SourceGit.Commands
return changes;
}
public async Task<List<Models.Change>> ResultAsync()
{
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return [];
var changes = new List<Models.Change>();
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;
}
private readonly string _parent;
}
}

View File

@@ -1,4 +1,5 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -14,9 +15,9 @@ namespace SourceGit.Commands
Args = $"ls-files -s -- \"{file}\"";
}
public string Result()
public async Task<string> ResultAsync()
{
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
var match = REG_FORMAT().Match(rs.StdOut.Trim());
if (match.Success)
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -64,5 +65,58 @@ namespace SourceGit.Commands
}
return outs;
}
public async Task<List<Models.Stash>> ResultAsync()
{
var outs = new List<Models.Stash>();
var rs = await ReadToEndAsync();
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;
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -133,6 +134,118 @@ namespace SourceGit.Commands
return submodules;
}
public async Task<List<Models.Submodule>> ResultAsync()
{
var submodules = new List<Models.Submodule>();
var rs = await ReadToEndAsync();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
var map = new Dictionary<string, Models.Submodule>();
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 = await ReadToEndAsync();
if (rs.IsSuccess)
{
var modules = new Dictionary<string, ModuleInfo>();
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 = await ReadToEndAsync();
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;
}
private class ModuleInfo
{
public string Path { get; set; } = string.Empty;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -46,6 +47,38 @@ namespace SourceGit.Commands
return tags;
}
public async Task<List<Models.Tag>> ResultAsync()
{
var tags = new List<Models.Tag>();
var rs = await ReadToEndAsync();
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;
}
private string _boundary = string.Empty;
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -30,5 +31,25 @@ namespace SourceGit.Commands
return status;
}
public async Task<Models.BranchTrackStatus> ResultAsync()
{
var status = new Models.BranchTrackStatus();
var rs = await ReadToEndAsync();
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;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -16,10 +17,10 @@ namespace SourceGit.Commands
Args = "submodule status";
}
public List<string> Result()
public async Task<List<string>> ResultAsync()
{
var submodules = new List<string>();
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)

View File

@@ -1,4 +1,6 @@
namespace SourceGit.Commands
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public class Remote : Command
{
@@ -8,50 +10,50 @@
Context = repo;
}
public bool Add(string name, string url)
public async Task<bool> AddAsync(string name, string url)
{
Args = $"remote add {name} {url}";
return Exec();
return await ExecAsync();
}
public bool Delete(string name)
public async Task<bool> DeleteAsync(string name)
{
Args = $"remote remove {name}";
return Exec();
return await ExecAsync();
}
public bool Rename(string name, string to)
public async Task<bool> RenameAsync(string name, string to)
{
Args = $"remote rename {name} {to}";
return Exec();
return await ExecAsync();
}
public bool Prune(string name)
public async Task<bool> PruneAsync(string name)
{
Args = $"remote prune {name}";
return Exec();
return await ExecAsync();
}
public string GetURL(string name, bool isPush)
public async Task<string> GetURLAsync(string name, bool isPush)
{
Args = "remote get-url" + (isPush ? " --push " : " ") + name;
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
return rs.IsSuccess ? rs.StdOut.Trim() : string.Empty;
}
public bool SetURL(string name, string url, bool isPush)
public async Task<bool> SetURLAsync(string name, string url, bool isPush)
{
Args = "remote set-url" + (isPush ? " --push " : " ") + $"{name} {url}";
return Exec();
return await ExecAsync();
}
public bool HasBranch(string remote, string branch)
public async Task<bool> HasBranchAsync(string remote, string branch)
{
SSHKey = new Config(WorkingDirectory).Get($"remote.{remote}.sshkey");
SSHKey = await new Config(WorkingDirectory).GetAsync($"remote.{remote}.sshkey");
Args = $"ls-remote {remote} {branch}";
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
return rs.IsSuccess && rs.StdOut.Trim().Length > 0;
}
}

View File

@@ -2,18 +2,19 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class SaveChangesAsPatch
{
public static bool ProcessLocalChanges(string repo, List<Models.Change> changes, bool isUnstaged, string saveTo)
public static async Task<bool> ProcessLocalChangesAsync(string repo, List<Models.Change> changes, bool isUnstaged, string saveTo)
{
using (var sw = File.Create(saveTo))
await using (var sw = File.Create(saveTo))
{
foreach (var change in changes)
{
if (!ProcessSingleChange(repo, new Models.DiffOption(change, isUnstaged), sw))
if (!await ProcessSingleChangeAsync(repo, new Models.DiffOption(change, isUnstaged), sw))
return false;
}
}
@@ -21,13 +22,13 @@ namespace SourceGit.Commands
return true;
}
public static bool ProcessRevisionCompareChanges(string repo, List<Models.Change> changes, string baseRevision, string targetRevision, string saveTo)
public static async Task<bool> ProcessRevisionCompareChangesAsync(string repo, List<Models.Change> changes, string baseRevision, string targetRevision, string saveTo)
{
using (var sw = File.Create(saveTo))
await using (var sw = File.Create(saveTo))
{
foreach (var change in changes)
{
if (!ProcessSingleChange(repo, new Models.DiffOption(baseRevision, targetRevision, change), sw))
if (!await ProcessSingleChangeAsync(repo, new Models.DiffOption(baseRevision, targetRevision, change), sw))
return false;
}
}
@@ -35,20 +36,20 @@ namespace SourceGit.Commands
return true;
}
public static bool ProcessStashChanges(string repo, List<Models.DiffOption> opts, string saveTo)
public static async Task<bool> ProcessStashChangesAsync(string repo, List<Models.DiffOption> opts, string saveTo)
{
using (var sw = File.Create(saveTo))
await using (var sw = File.Create(saveTo))
{
foreach (var opt in opts)
{
if (!ProcessSingleChange(repo, opt, sw))
if (!await ProcessSingleChangeAsync(repo, opt, sw))
return false;
}
}
return true;
}
private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer)
private static async Task<bool> ProcessSingleChangeAsync(string repo, Models.DiffOption opt, FileStream writer)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -63,8 +64,8 @@ namespace SourceGit.Commands
{
var proc = new Process() { StartInfo = starter };
proc.Start();
proc.StandardOutput.BaseStream.CopyTo(writer);
proc.WaitForExit();
await proc.StandardOutput.BaseStream.CopyToAsync(writer);
await proc.WaitForExitAsync();
var rs = proc.ExitCode == 0;
proc.Close();

View File

@@ -1,30 +1,31 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class SaveRevisionFile
{
public static void Run(string repo, string revision, string file, string saveTo)
public static async Task RunAsync(string repo, string revision, string file, string saveTo)
{
var dir = Path.GetDirectoryName(saveTo);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var isLFSFiltered = new IsLFSFiltered(repo, revision, file).Result();
var isLFSFiltered = await new IsLFSFiltered(repo, revision, file).ResultAsync();
if (isLFSFiltered)
{
var pointerStream = QueryFileContent.Run(repo, revision, file);
ExecCmd(repo, "lfs smudge", saveTo, pointerStream);
var pointerStream = await QueryFileContent.RunAsync(repo, revision, file);
await ExecCmdAsync(repo, "lfs smudge", saveTo, pointerStream);
}
else
{
ExecCmd(repo, $"show {revision}:\"{file}\"", saveTo);
await ExecCmdAsync(repo, $"show {revision}:\"{file}\"", saveTo);
}
}
private static void ExecCmd(string repo, string args, string outputFile, Stream input = null)
private static async Task ExecCmdAsync(string repo, string args, string outputFile, Stream input = null)
{
var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo;
@@ -37,16 +38,16 @@ namespace SourceGit.Commands
starter.RedirectStandardOutput = true;
starter.RedirectStandardError = true;
using (var sw = File.OpenWrite(outputFile))
await using (var sw = File.OpenWrite(outputFile))
{
try
{
var proc = new Process() { StartInfo = starter };
proc.Start();
if (input != null)
proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
proc.StandardOutput.BaseStream.CopyTo(sw);
proc.WaitForExit();
await proc.StandardInput.WriteAsync(await new StreamReader(input).ReadToEndAsync());
await proc.StandardOutput.BaseStream.CopyToAsync(sw);
await proc.WaitForExitAsync();
proc.Close();
}
catch (Exception e)

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,7 +12,7 @@ namespace SourceGit.Commands
Context = repo;
}
public bool Push(string message, bool includeUntracked = true, bool keepIndex = false)
public async Task<bool> PushAsync(string message, bool includeUntracked = true, bool keepIndex = false)
{
var builder = new StringBuilder();
builder.Append("stash push ");
@@ -24,10 +25,10 @@ namespace SourceGit.Commands
builder.Append("\"");
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Push(string message, List<Models.Change> changes, bool keepIndex)
public async Task<bool> PushAsync(string message, List<Models.Change> changes, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --include-untracked ");
@@ -41,10 +42,10 @@ namespace SourceGit.Commands
builder.Append($"\"{c.Path}\" ");
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Push(string message, string pathspecFromFile, bool keepIndex)
public async Task<bool> PushAsync(string message, string pathspecFromFile, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --include-untracked --pathspec-from-file=\"");
@@ -57,10 +58,10 @@ namespace SourceGit.Commands
builder.Append("\"");
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool PushOnlyStaged(string message, bool keepIndex)
public async Task<bool> PushOnlyStagedAsync(string message, bool keepIndex)
{
var builder = new StringBuilder();
builder.Append("stash push --staged ");
@@ -70,32 +71,32 @@ namespace SourceGit.Commands
builder.Append(message);
builder.Append("\"");
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Apply(string name, bool restoreIndex)
public async Task<bool> ApplyAsync(string name, bool restoreIndex)
{
var opts = restoreIndex ? "--index" : string.Empty;
Args = $"stash apply -q {opts} \"{name}\"";
return Exec();
return await ExecAsync();
}
public bool Pop(string name)
public async Task<bool> PopAsync(string name)
{
Args = $"stash pop -q --index \"{name}\"";
return Exec();
return await ExecAsync();
}
public bool Drop(string name)
public async Task<bool> DropAsync(string name)
{
Args = $"stash drop -q \"{name}\"";
return Exec();
return await ExecAsync();
}
public bool Clear()
public async Task<bool> ClearAsync()
{
Args = "stash clear";
return Exec();
return await ExecAsync();
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,10 +12,10 @@ namespace SourceGit.Commands
Args = $"log --date-order --branches --remotes -{max} --format=%ct$%aN±%aE";
}
public Models.Statistics Result()
public async Task<Models.Statistics> ResultAsync()
{
var statistics = new Models.Statistics();
var rs = ReadToEnd();
var rs = await ReadToEndAsync();
if (!rs.IsSuccess)
return statistics;

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -11,16 +12,16 @@ namespace SourceGit.Commands
Context = repo;
}
public bool Add(string url, string relativePath, bool recursive)
public async Task<bool> AddAsync(string url, string relativePath, bool recursive)
{
Args = $"-c protocol.file.allow=always submodule add \"{url}\" \"{relativePath}\"";
if (!Exec())
if (!await ExecAsync())
return false;
if (recursive)
{
Args = $"submodule update --init --recursive -- \"{relativePath}\"";
return Exec();
return await ExecAsync();
}
else
{
@@ -29,7 +30,7 @@ namespace SourceGit.Commands
}
}
public bool Update(List<string> modules, bool init, bool recursive, bool useRemote = false)
public async Task<bool> UpdateAsync(List<string> modules, bool init, bool recursive, bool useRemote = false)
{
var builder = new StringBuilder();
builder.Append("submodule update");
@@ -48,19 +49,19 @@ namespace SourceGit.Commands
}
Args = builder.ToString();
return Exec();
return await ExecAsync();
}
public bool Deinit(string module, bool force)
public async Task<bool> DeinitAsync(string module, bool force)
{
Args = force ? $"submodule deinit -f -- \"{module}\"" : $"submodule deinit -- \"{module}\"";
return Exec();
return await ExecAsync();
}
public bool Delete(string module)
public async Task<bool> DeleteAsync(string module)
{
Args = $"rm -rf \"{module}\"";
return Exec();
return await ExecAsync();
}
}
}

View File

@@ -1,20 +1,21 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
public static class Tag
{
public static bool Add(string repo, string name, string basedOn, Models.ICommandLog log)
public static async Task<bool> AddAsync(string repo, string name, string basedOn, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag --no-sign {name} {basedOn}";
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool Add(string repo, string name, string basedOn, string message, bool sign, Models.ICommandLog log)
public static async Task<bool> AddAsync(string repo, string name, string basedOn, string message, bool sign, Models.ICommandLog log)
{
var param = sign ? "--sign -a" : "--no-sign -a";
var cmd = new Command();
@@ -26,26 +27,26 @@ namespace SourceGit.Commands
if (!string.IsNullOrEmpty(message))
{
string tmp = Path.GetTempFileName();
File.WriteAllText(tmp, message);
await File.WriteAllTextAsync(tmp, message);
cmd.Args += $"-F \"{tmp}\"";
var succ = cmd.Exec();
var succ = await cmd.ExecAsync();
File.Delete(tmp);
return succ;
}
cmd.Args += $"-m {name}";
return cmd.Exec();
return await cmd.ExecAsync();
}
public static bool Delete(string repo, string name, Models.ICommandLog log)
public static async Task<bool> DeleteAsync(string repo, string name, Models.ICommandLog log)
{
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag --delete {name}";
cmd.Log = log;
return cmd.Exec();
return await cmd.ExecAsync();
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -84,6 +85,43 @@ namespace SourceGit.Commands
}
}
public async Task<bool> ExecAsync()
{
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();
await proc.StandardInput.WriteAsync(_patchBuilder.ToString());
proc.StandardInput.Close();
var err = await proc.StandardError.ReadToEndAsync();
await proc.WaitForExitAsync();
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;
}
}
private string _repo = "";
private StringBuilder _patchBuilder = new StringBuilder();
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
{
@@ -56,7 +57,7 @@ namespace SourceGit.Commands
return worktrees;
}
public bool Add(string fullpath, string name, bool createNew, string tracking)
public async Task<bool> AddAsync(string fullpath, string name, bool createNew, string tracking)
{
Args = "worktree add ";
@@ -78,35 +79,35 @@ namespace SourceGit.Commands
else if (!string.IsNullOrEmpty(name) && !createNew)
Args += name;
return Exec();
return await ExecAsync();
}
public bool Prune()
public async Task<bool> PruneAsync()
{
Args = "worktree prune -v";
return Exec();
return await ExecAsync();
}
public bool Lock(string fullpath)
public async Task<bool> LockAsync(string fullpath)
{
Args = $"worktree lock \"{fullpath}\"";
return Exec();
return await ExecAsync();
}
public bool Unlock(string fullpath)
public async Task<bool> UnlockAsync(string fullpath)
{
Args = $"worktree unlock \"{fullpath}\"";
return Exec();
return await ExecAsync();
}
public bool Remove(string fullpath, bool force)
public async Task<bool> RemoveAsync(string fullpath, bool force)
{
if (force)
Args = $"worktree remove -f \"{fullpath}\"";
else
Args = $"worktree remove \"{fullpath}\"";
return Exec();
return await ExecAsync();
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Azure.AI.OpenAI;
using CommunityToolkit.Mvvm.ComponentModel;
using OpenAI;
@@ -173,7 +174,7 @@ namespace SourceGit.Models
""";
}
public void Chat(string prompt, string question, CancellationToken cancellation, Action<string> onUpdate)
public async Task ChatAsync(string prompt, string question, CancellationToken cancellation, Action<string> onUpdate)
{
var server = new Uri(_server);
var key = new ApiKeyCredential(_apiKey);
@@ -191,9 +192,9 @@ namespace SourceGit.Models
if (_streaming)
{
var updates = client.CompleteChatStreaming(messages, null, cancellation);
var updates = client.CompleteChatStreamingAsync(messages, null, cancellation);
foreach (var update in updates)
await foreach (var update in updates)
{
if (update.ContentUpdate.Count > 0)
rsp.Append(update.ContentUpdate[0].Text);
@@ -201,7 +202,7 @@ namespace SourceGit.Models
}
else
{
var completion = client.CompleteChat(messages, null, cancellation);
var completion = await client.CompleteChatAsync(messages, null, cancellation);
if (completion.Value.Content.Count > 0)
rsp.Append(completion.Value.Content[0].Text);

View File

@@ -58,14 +58,14 @@ namespace SourceGit.ViewModels
IsGenerating = true;
_cancel = new CancellationTokenSource();
Task.Run(() =>
Task.Run(async () =>
{
new Commands.GenerateCommitMessage(_service, _repo.FullPath, _changes, _cancel.Token, message =>
await new Commands.GenerateCommitMessage(_service, _repo.FullPath, _changes, _cancel.Token, message =>
{
Dispatcher.UIThread.Invoke(() => Text = message);
}).Exec();
}).ExecAsync();
Dispatcher.UIThread.Invoke(() => IsGenerating = false);
await Dispatcher.UIThread.InvokeAsync(() => IsGenerating = false);
}, _cancel.Token);
}

View File

@@ -87,7 +87,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding remote ...";
@@ -95,24 +95,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Add Remote");
Use(log);
return Task.Run(() =>
var succ = await new Commands.Remote(_repo.FullPath).Use(log).AddAsync(_name, _url);
if (succ)
{
var succ = new Commands.Remote(_repo.FullPath).Use(log).Add(_name, _url);
if (succ)
{
new Commands.Config(_repo.FullPath).Use(log).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
new Commands.Fetch(_repo.FullPath, _name, false, false).Use(log).Exec();
}
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();
}
log.Complete();
CallUIThread(() =>
{
_repo.MarkFetched();
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
log.Complete();
await CallUIThreadAsync(() =>
{
_repo.MarkFetched();
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
}
private readonly Repository _repo = null;

View File

@@ -40,7 +40,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding submodule...";
@@ -59,14 +59,11 @@ namespace SourceGit.ViewModels
relativePath = Path.GetFileName(_url);
}
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Add(_url, relativePath, Recursive);
log.Complete();
var succ = await new Commands.Submodule(_repo.FullPath).Use(log).AddAsync(_url, relativePath, Recursive);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo = null;

View File

@@ -27,35 +27,32 @@ namespace SourceGit.ViewModels
StorageFile = Models.GitIgnoreFile.Supported[0];
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding Ignored File(s) ...";
return Task.Run(() =>
var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir);
if (!File.Exists(file))
{
var file = StorageFile.GetFullPath(_repo.FullPath, _repo.GitDir);
if (!File.Exists(file))
{
File.WriteAllLines(file, [_pattern]);
}
await File.WriteAllLinesAsync(file, [_pattern]);
}
else
{
var org = await File.ReadAllTextAsync(file);
if (!org.EndsWith('\n'))
await File.AppendAllLinesAsync(file, ["", _pattern]);
else
{
var org = File.ReadAllText(file);
if (!org.EndsWith('\n'))
File.AppendAllLines(file, ["", _pattern]);
else
File.AppendAllLines(file, [_pattern]);
}
await File.AppendAllLinesAsync(file, [_pattern]);
}
CallUIThread(() =>
{
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
await CallUIThreadAsync(() =>
{
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
}
private readonly Repository _repo;

View File

@@ -105,7 +105,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Adding worktree ...";
@@ -116,14 +116,11 @@ namespace SourceGit.ViewModels
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Worktree(_repo.FullPath).Use(log).Add(_path, branchName, _createNewBranch, tracking);
log.Complete();
var succ = await new Commands.Worktree(_repo.FullPath).Use(log).AddAsync(_path, branchName, _createNewBranch, tracking);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private Repository _repo = null;

View File

@@ -41,20 +41,17 @@ namespace SourceGit.ViewModels
return new ValidationResult($"File '{file}' can NOT be found!!!");
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Apply patch...";
var log = _repo.CreateLog("Apply Patch");
return Task.Run(() =>
{
var succ = new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Use(log).Exec();
log.Complete();
var succ = await new Commands.Apply(_repo.FullPath, _patchFile, _ignoreWhiteSpace, SelectedWhiteSpaceMode.Arg, null).Use(log).ExecAsync();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo = null;

View File

@@ -28,20 +28,17 @@ namespace SourceGit.ViewModels
Stash = stash;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
ProgressDescription = $"Applying stash: {Stash.Name}";
var log = _repo.CreateLog("Apply Stash");
return Task.Run(() =>
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Apply(Stash.Name, RestoreIndex);
if (succ && DropAfterApply)
new Commands.Stash(_repo.FullPath).Use(log).Drop(Stash.Name);
var succ = await new Commands.Stash(_repo.FullPath).Use(log).ApplyAsync(Stash.Name, RestoreIndex);
if (succ && DropAfterApply)
await new Commands.Stash(_repo.FullPath).Use(log).DropAsync(Stash.Name);
log.Complete();
return true;
});
log.Complete();
return true;
}
private readonly Repository _repo;

View File

@@ -44,7 +44,7 @@ namespace SourceGit.ViewModels
BasedOn = tag;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Archiving ...";
@@ -52,20 +52,17 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Archive");
Use(log);
return Task.Run(() =>
var succ = await new Commands.Archive(_repo.FullPath, _revision, _saveFile).Use(log).ExecAsync();
log.Complete();
await CallUIThreadAsync(() =>
{
var succ = new Commands.Archive(_repo.FullPath, _revision, _saveFile).Use(log).Exec();
log.Complete();
CallUIThread(() =>
{
_repo.SetWatcherEnabled(true);
if (succ)
App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}");
});
return succ;
_repo.SetWatcherEnabled(true);
if (succ)
App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}");
});
return succ;
}
private readonly Repository _repo = null;

View File

@@ -14,19 +14,19 @@ namespace SourceGit.ViewModels
_repo = repo;
Files = new AvaloniaList<string>();
Task.Run(() =>
Task.Run(async () =>
{
var collect = new Commands.QueryAssumeUnchangedFiles(_repo.FullPath).Result();
Dispatcher.UIThread.Invoke(() => Files.AddRange(collect));
var collect = await new Commands.QueryAssumeUnchangedFiles(_repo.FullPath).ResultAsync();
await Dispatcher.UIThread.InvokeAsync(() => Files.AddRange(collect));
});
}
public void Remove(string file)
public async Task RemoveAsync(string file)
{
if (!string.IsNullOrEmpty(file))
{
var log = _repo.CreateLog("Remove Assume Unchanged File");
new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).Exec();
await new Commands.AssumeUnchanged(_repo.FullPath, file, false).Use(log).ExecAsync();
log.Complete();
Files.Remove(file);
}

View File

@@ -132,11 +132,11 @@ namespace SourceGit.ViewModels
}
else
{
Task.Run(() =>
Task.Run(async () =>
{
var result = new Commands.QuerySingleCommit(_repo, commitSHA).Result();
var result = await new Commands.QuerySingleCommit(_repo, commitSHA).ResultAsync();
Dispatcher.UIThread.Invoke(() =>
await Dispatcher.UIThread.InvokeAsync(() =>
{
if (!token.IsCancellationRequested)
{
@@ -147,11 +147,11 @@ namespace SourceGit.ViewModels
}, token);
}
Task.Run(() =>
Task.Run(async () =>
{
var result = new Commands.Blame(_repo, FilePath, commitSHA).Result();
var result = await new Commands.Blame(_repo, FilePath, commitSHA).ResultAsync();
Dispatcher.UIThread.Invoke(() =>
await Dispatcher.UIThread.InvokeAsync(() =>
{
if (!token.IsCancellationRequested)
Data = result;

View File

@@ -133,7 +133,7 @@ namespace SourceGit.ViewModels
var toolPath = Preferences.Instance.ExternalMergeToolPath;
var opt = new Models.DiffOption(_based.Head, _to.Head, change);
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, opt));
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, opt));
ev.Handled = true;
};
menu.Items.Add(diffWithMerger);
@@ -178,20 +178,20 @@ namespace SourceGit.ViewModels
private void Refresh()
{
Task.Run(() =>
Task.Run(async () =>
{
if (_baseHead == null)
{
var baseHead = new Commands.QuerySingleCommit(_repo, _based.Head).Result();
var toHead = new Commands.QuerySingleCommit(_repo, _to.Head).Result();
Dispatcher.UIThread.Invoke(() =>
var baseHead = await new Commands.QuerySingleCommit(_repo, _based.Head).ResultAsync();
var toHead = await new Commands.QuerySingleCommit(_repo, _to.Head).ResultAsync();
await Dispatcher.UIThread.InvokeAsync(() =>
{
BaseHead = baseHead;
ToHead = toHead;
});
}
_changes = new Commands.CompareRevisions(_repo, _based.Head, _to.Head).Result();
_changes = await new Commands.CompareRevisions(_repo, _based.Head, _to.Head).ResultAsync();
var visible = _changes;
if (!string.IsNullOrWhiteSpace(_searchFilter))
@@ -204,7 +204,7 @@ namespace SourceGit.ViewModels
}
}
Dispatcher.UIThread.Invoke(() => VisibleChanges = visible);
await Dispatcher.UIThread.InvokeAsync(() => VisibleChanges = visible);
});
}

View File

@@ -33,7 +33,7 @@ namespace SourceGit.ViewModels
DiscardLocalChanges = false;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout '{Branch}' ...";
@@ -42,70 +42,67 @@ namespace SourceGit.ViewModels
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
bool succ;
var needPopStash = false;
if (!_repo.ConfirmCheckoutBranch())
{
bool succ;
var needPopStash = false;
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
if (!_repo.ConfirmCheckoutBranch())
if (DiscardLocalChanges)
{
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(Branch, true);
}
else
{
var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync();
if (changes > 0)
{
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
}
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AUTO_STASH");
if (!succ)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
needPopStash = true;
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, false);
needPopStash = true;
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(Branch, false);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
if (succ)
{
if (updateSubmodules)
{
var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync();
if (submodules.Count > 0)
await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true);
}
log.Complete();
if (needPopStash)
await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}");
}
CallUIThread(() =>
{
ProgressDescription = "Waiting for branch updated...";
log.Complete();
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);
await CallUIThreadAsync(() =>
{
ProgressDescription = "Waiting for branch updated...";
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
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);
Task.Delay(400).Wait();
return succ;
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
Task.Delay(400).Wait();
return succ;
}
private readonly Repository _repo = null;

View File

@@ -38,7 +38,7 @@ namespace SourceGit.ViewModels
RemoteBranch = remoteBranch;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout and Fast-Forward '{LocalBranch.Name}' ...";
@@ -47,69 +47,66 @@ namespace SourceGit.ViewModels
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
var succ = false;
var needPopStash = false;
if (!_repo.ConfirmCheckoutBranch())
{
var succ = false;
var needPopStash = false;
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
if (!_repo.ConfirmCheckoutBranch())
if (DiscardLocalChanges)
{
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(LocalBranch.Name, RemoteBranch.Head, true, true);
}
else
{
var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync();
if (changes > 0)
{
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
}
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, true, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
if (!succ)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AND_FASTFORWARD_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
needPopStash = true;
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(LocalBranch.Name, RemoteBranch.Head, false, true);
needPopStash = true;
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(LocalBranch.Name, RemoteBranch.Head, false, true);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
if (succ)
{
if (updateSubmodules)
{
var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync();
if (submodules.Count > 0)
await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true);
}
log.Complete();
if (needPopStash)
await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}");
}
CallUIThread(() =>
{
ProgressDescription = "Waiting for branch updated...";
log.Complete();
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
await CallUIThreadAsync(() =>
{
ProgressDescription = "Waiting for branch updated...";
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, true, false);
Task.Delay(400).Wait();
return succ;
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
Task.Delay(400).Wait();
return succ;
}
private Repository _repo;

View File

@@ -33,7 +33,7 @@ namespace SourceGit.ViewModels
DiscardLocalChanges = false;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Checkout Commit '{Commit.SHA}' ...";
@@ -42,57 +42,54 @@ namespace SourceGit.ViewModels
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
bool succ;
var needPop = false;
if (!_repo.ConfirmCheckoutBranch())
{
bool succ;
var needPop = false;
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
if (!_repo.ConfirmCheckoutBranch())
if (DiscardLocalChanges)
{
succ = await new Commands.Checkout(_repo.FullPath).Use(log).CommitAsync(Commit.SHA, true);
}
else
{
var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync();
if (changes > 0)
{
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
}
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CHECKOUT_AUTO_STASH");
if (!succ)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
needPop = true;
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, false);
needPop = true;
}
if (succ)
succ = await new Commands.Checkout(_repo.FullPath).Use(log).CommitAsync(Commit.SHA, false);
}
if (succ)
{
if (updateSubmodules)
{
if (updateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPop)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync();
if (submodules.Count > 0)
await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true);
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
if (needPop)
await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}");
}
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo = null;

View File

@@ -63,7 +63,7 @@ namespace SourceGit.ViewModels
AutoCommit = true;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
_repo.ClearCommitMessage();
@@ -72,31 +72,28 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Cherry-Pick");
Use(log);
return Task.Run(() =>
if (IsMergeCommit)
{
if (IsMergeCommit)
{
new Commands.CherryPick(
_repo.FullPath,
Targets[0].SHA,
!AutoCommit,
AppendSourceToMessage,
$"-m {MainlineForMergeCommit + 1}").Use(log).Exec();
}
else
{
new Commands.CherryPick(
_repo.FullPath,
string.Join(' ', Targets.ConvertAll(c => c.SHA)),
!AutoCommit,
AppendSourceToMessage,
string.Empty).Use(log).Exec();
}
await new Commands.CherryPick(
_repo.FullPath,
Targets[0].SHA,
!AutoCommit,
AppendSourceToMessage,
$"-m {MainlineForMergeCommit + 1}").Use(log).ExecAsync();
}
else
{
await new Commands.CherryPick(
_repo.FullPath,
string.Join(' ', Targets.ConvertAll(c => c.SHA)),
!AutoCommit,
AppendSourceToMessage,
string.Empty).Use(log).ExecAsync();
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

View File

@@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Cleanup (GC & prune) ...";
@@ -17,13 +17,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Cleanup (GC & prune)");
Use(log);
return Task.Run(() =>
{
new Commands.GC(_repo.FullPath).Use(log).Exec();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
await new Commands.GC(_repo.FullPath).Use(log).ExecAsync();
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

View File

@@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Clear all stashes...";
@@ -17,13 +17,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Clear Stashes");
Use(log);
return Task.Run(() =>
{
new Commands.Stash(_repo.FullPath).Use(log).Clear();
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
await new Commands.Stash(_repo.FullPath).Use(log).ClearAsync();
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

View File

@@ -74,7 +74,7 @@ namespace SourceGit.ViewModels
{
var text = await App.GetClipboardTextAsync();
if (Models.Remote.IsValidURL(text))
Dispatcher.UIThread.Invoke(() => Remote = text);
await Dispatcher.UIThread.InvokeAsync(() => Remote = text);
}
catch
{
@@ -97,76 +97,73 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
ProgressDescription = "Clone ...";
var log = new CommandLog("Clone");
Use(log);
return Task.Run(() =>
var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs).Use(log);
if (!await cmd.ExecAsync())
return false;
var path = _parentFolder;
if (!string.IsNullOrEmpty(_local))
{
var cmd = new Commands.Clone(_pageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs).Use(log);
if (!cmd.Exec())
return false;
path = Path.GetFullPath(Path.Combine(path, _local));
}
else
{
var name = Path.GetFileName(_remote)!;
if (name.EndsWith(".git", StringComparison.Ordinal))
name = name.Substring(0, name.Length - 4);
else if (name.EndsWith(".bundle", StringComparison.Ordinal))
name = name.Substring(0, name.Length - 7);
var path = _parentFolder;
if (!string.IsNullOrEmpty(_local))
path = Path.GetFullPath(Path.Combine(path, name));
}
if (!Directory.Exists(path))
{
App.RaiseException(_pageId, $"Folder '{path}' can NOT be found");
return false;
}
if (_useSSH && !string.IsNullOrEmpty(_sshKey))
{
var config = new Commands.Config(path);
await config.SetAsync("remote.origin.sshkey", _sshKey);
}
if (InitAndUpdateSubmodules)
{
var submodules = await new Commands.QueryUpdatableSubmodules(path).ResultAsync();
if (submodules.Count > 0)
await new Commands.Submodule(path).Use(log).UpdateAsync(submodules, true, true);
}
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)
{
path = Path.GetFullPath(Path.Combine(path, _local));
}
else
{
var name = Path.GetFileName(_remote)!;
if (name.EndsWith(".git", StringComparison.Ordinal))
name = name.Substring(0, name.Length - 4);
else if (name.EndsWith(".bundle", StringComparison.Ordinal))
name = name.Substring(0, name.Length - 7);
path = Path.GetFullPath(Path.Combine(path, name));
}
if (!Directory.Exists(path))
{
App.RaiseException(_pageId, $"Folder '{path}' can NOT be found");
return false;
}
if (_useSSH && !string.IsNullOrEmpty(_sshKey))
{
var config = new Commands.Config(path);
config.Set("remote.origin.sshkey", _sshKey);
}
if (InitAndUpdateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(path).Result();
if (submodules.Count > 0)
new Commands.Submodule(path).Use(log).Update(submodules, true, true);
}
log.Complete();
CallUIThread(() =>
{
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);
});
return true;
Welcome.Instance.Refresh();
launcher.OpenRepositoryInTab(node, page);
});
return true;
}
private string _pageId = string.Empty;

View File

@@ -215,9 +215,9 @@ namespace SourceGit.ViewModels
{
case Models.ObjectType.Blob:
CanOpenRevisionFileWithDefaultEditor = true;
Task.Run(() =>
Task.Run(async () =>
{
var isBinary = new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).Result();
var isBinary = await new Commands.IsBinary(_repo.FullPath, _commit.SHA, file.Path).ResultAsync();
if (isBinary)
{
var imgDecoder = ImageSource.GetDecoder(file.Path);
@@ -225,20 +225,20 @@ namespace SourceGit.ViewModels
{
var source = ImageSource.FromRevision(_repo.FullPath, _commit.SHA, file.Path, imgDecoder);
var image = new Models.RevisionImageFile(file.Path, source.Bitmap, source.Size);
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = image);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = image);
}
else
{
var size = new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).Result();
var size = await new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).ResultAsync();
var binary = new Models.RevisionBinaryFile() { Size = size };
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = binary);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = binary);
}
return;
}
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _commit.SHA, file.Path);
var content = new StreamReader(contentStream).ReadToEnd();
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)
{
@@ -246,35 +246,35 @@ namespace SourceGit.ViewModels
if (imgDecoder != Models.ImageDecoder.None)
{
var combined = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = combined);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = combined);
}
else
{
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = rlfs);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = rlfs);
}
}
else
{
var txt = new Models.RevisionTextFile() { FileName = file.Path, Content = content };
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = txt);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = txt);
}
});
break;
case Models.ObjectType.Commit:
CanOpenRevisionFileWithDefaultEditor = false;
Task.Run(() =>
Task.Run(async () =>
{
var submoduleRoot = Path.Combine(_repo.FullPath, file.Path).Replace('\\', '/').Trim('/');
var commit = new Commands.QuerySingleCommit(submoduleRoot, file.SHA).Result();
var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result() : null;
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 }
};
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = module);
await Dispatcher.UIThread.InvokeAsync(() => ViewRevisionFileContent = module);
});
break;
default:
@@ -284,18 +284,17 @@ namespace SourceGit.ViewModels
}
}
public Task OpenRevisionFileWithDefaultEditor(string file)
public async Task OpenRevisionFileWithDefaultEditor(string file)
{
return Task.Run(() =>
{
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}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file, tmpFile);
await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _commit.SHA, file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
});
}
}
public ContextMenu CreateChangeContextMenuByFolder(ChangeTreeNode node, List<Models.Change> changes)
@@ -339,7 +338,7 @@ namespace SourceGit.ViewModels
if (storageFile != null)
{
var saveTo = storageFile.Path.LocalPath;
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo));
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, changes, baseRevision, _commit.SHA, saveTo);
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@@ -388,7 +387,7 @@ namespace SourceGit.ViewModels
var toolPath = Preferences.Instance.ExternalMergeToolPath;
var opt = new Models.DiffOption(_commit, change);
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo.FullPath, toolType, toolPath, opt));
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo.FullPath, toolType, toolPath, opt));
ev.Handled = true;
};
@@ -441,7 +440,7 @@ namespace SourceGit.ViewModels
if (storageFile != null)
{
var saveTo = storageFile.Path.LocalPath;
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo.FullPath, [change], baseRevision, _commit.SHA, saveTo));
var succ = await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, [change], baseRevision, _commit.SHA, saveTo);
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}
@@ -605,7 +604,7 @@ 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 Task.Run(() => Commands.SaveRevisionFile.Run(_repo.FullPath, _commit.SHA, file.Path, saveTo));
await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _commit.SHA, file.Path, saveTo);
}
}
catch (Exception e)
@@ -719,39 +718,39 @@ namespace SourceGit.ViewModels
_cancellationSource = new CancellationTokenSource();
var token = _cancellationSource.Token;
Task.Run(() =>
Task.Run(async () =>
{
var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
var inlines = ParseInlinesInMessage(message);
var message = await new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).ResultAsync();
var inlines = await ParseInlinesInMessageAsync(message);
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines });
await Dispatcher.UIThread.InvokeAsync(() => FullMessage = new Models.CommitFullMessage { Message = message, Inlines = inlines });
}, token);
Task.Run(() =>
Task.Run(async () =>
{
var signInfo = new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).Result();
var signInfo = await new Commands.QueryCommitSignInfo(_repo.FullPath, _commit.SHA, !_repo.HasAllowedSignersFile).ResultAsync();
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Invoke(() => SignInfo = signInfo);
await Dispatcher.UIThread.InvokeAsync(() => SignInfo = signInfo);
}, token);
if (Preferences.Instance.ShowChildren)
{
Task.Run(() =>
Task.Run(async () =>
{
var max = Preferences.Instance.MaxHistoryCommits;
var cmd = new Commands.QueryCommitChildren(_repo.FullPath, _commit.SHA, max) { CancellationToken = token };
var children = cmd.Result();
var children = await cmd.ResultAsync();
if (!token.IsCancellationRequested)
Dispatcher.UIThread.Post(() => Children = children);
}, token);
}
Task.Run(() =>
Task.Run(async () =>
{
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 = cmd.Result();
var changes = await cmd.ResultAsync();
var visible = changes;
if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
{
@@ -777,7 +776,7 @@ namespace SourceGit.ViewModels
}, token);
}
private Models.InlineElementCollector ParseInlinesInMessage(string message)
private async Task<Models.InlineElementCollector> ParseInlinesInMessageAsync(string message)
{
var inlines = new Models.InlineElementCollector();
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
@@ -816,7 +815,7 @@ namespace SourceGit.ViewModels
continue;
var sha = match.Groups[1].Value;
var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, sha).Result();
var isCommitSHA = await new Commands.IsCommitSHA(_repo.FullPath, sha).ResultAsync();
if (isCommitSHA)
inlines.Add(new Models.InlineElement(Models.InlineElementType.CommitSHA, start, len, sha));
}
@@ -868,7 +867,7 @@ namespace SourceGit.ViewModels
lfsLock.Click += async (_, e) =>
{
var log = _repo.CreateLog("Lock LFS file");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(_repo.Remotes[0].Name, path, log));
var succ = await new Commands.LFS(_repo.FullPath).LockAsync(_repo.Remotes[0].Name, path, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
@@ -886,7 +885,7 @@ namespace SourceGit.ViewModels
lockRemote.Click += async (_, e) =>
{
var log = _repo.CreateLog("Lock LFS file");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Lock(remoteName, path, log));
var succ = await new Commands.LFS(_repo.FullPath).LockAsync(remoteName, path, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Lock file \"{path}\" successfully!");
@@ -906,7 +905,7 @@ namespace SourceGit.ViewModels
lfsUnlock.Click += async (_, e) =>
{
var log = _repo.CreateLog("Unlock LFS file");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(_repo.Remotes[0].Name, path, false, log));
var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(_repo.Remotes[0].Name, path, false, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
@@ -924,7 +923,7 @@ namespace SourceGit.ViewModels
unlockRemote.Click += async (_, e) =>
{
var log = _repo.CreateLog("Unlock LFS file");
var succ = await Task.Run(() => new Commands.LFS(_repo.FullPath).Unlock(remoteName, path, false, log));
var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(remoteName, path, false, log);
if (succ)
App.SendNotification(_repo.FullPath, $"Unlock file \"{path}\" successfully!");
@@ -952,10 +951,10 @@ namespace SourceGit.ViewModels
var sha = Commit.SHA;
_requestingRevisionFiles = true;
Task.Run(() =>
Task.Run(async () =>
{
var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result();
Dispatcher.UIThread.Invoke(() =>
var files = await new Commands.QueryRevisionFileNames(_repo.FullPath, sha).ResultAsync();
await Dispatcher.UIThread.InvokeAsync(() =>
{
if (sha == Commit.SHA && _requestingRevisionFiles)
{
@@ -996,29 +995,23 @@ namespace SourceGit.ViewModels
RevisionFileSearchSuggestion = suggestion;
}
private Task ResetToThisRevision(string path)
private async Task ResetToThisRevision(string path)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
return Task.Run(() =>
{
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(path, $"{_commit.SHA}");
log.Complete();
});
await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(path, $"{_commit.SHA}");
log.Complete();
}
private Task ResetToParentRevision(Models.Change change)
private async Task ResetToParentRevision(Models.Change change)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
return Task.Run(() =>
{
if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
if (change.Index == Models.ChangeState.Renamed)
await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
log.Complete();
});
await new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevisionAsync(change.Path, $"{_commit.SHA}~1");
log.Complete();
}
[GeneratedRegex(@"\b(https?://|ftp://)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]")]

View File

@@ -114,7 +114,7 @@ namespace SourceGit.ViewModels
return new ValidationResult("Missing runtime context to create branch!");
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
@@ -123,89 +123,86 @@ namespace SourceGit.ViewModels
Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() =>
bool succ;
if (CheckoutAfterCreated && !_repo.ConfirmCheckoutBranch())
{
bool succ;
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
if (CheckoutAfterCreated && !_repo.ConfirmCheckoutBranch())
if (CheckoutAfterCreated && !_repo.IsBare)
{
var needPopStash = false;
if (DiscardLocalChanges)
{
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
}
if (CheckoutAfterCreated && !_repo.IsBare)
{
var needPopStash = false;
if (DiscardLocalChanges)
{
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true, _allowOverwrite);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
needPopStash = true;
}
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false, _allowOverwrite);
}
if (succ)
{
if (updateSubmodules)
{
var submodules = new Commands.QueryUpdatableSubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(fixedName, _baseOnRevision, true, _allowOverwrite);
}
else
{
succ = Commands.Branch.Create(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
}
log.Complete();
CallUIThread(() =>
{
if (succ && CheckoutAfterCreated)
var changes = await new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).ResultAsync();
if (changes > 0)
{
var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{fixedName}" };
if (BasedOn is Models.Branch { IsLocal: false } based)
fake.Upstream = based.FullName;
succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("CREATE_BRANCH_AUTO_STASH");
if (!succ)
{
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
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);
ProgressDescription = "Waiting for branch updated...";
needPopStash = true;
}
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
succ = await new Commands.Checkout(_repo.FullPath).Use(log).BranchAsync(fixedName, _baseOnRevision, false, _allowOverwrite);
}
if (CheckoutAfterCreated)
Task.Delay(400).Wait();
if (succ)
{
if (updateSubmodules)
{
var submodules = await new Commands.QueryUpdatableSubmodules(_repo.FullPath).ResultAsync();
if (submodules.Count > 0)
await new Commands.Submodule(_repo.FullPath).Use(log).UpdateAsync(submodules, true, true);
}
return true;
if (needPopStash)
await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}");
}
}
else
{
succ = await Commands.Branch.CreateAsync(_repo.FullPath, fixedName, _baseOnRevision, _allowOverwrite, log);
}
log.Complete();
await CallUIThreadAsync(() =>
{
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 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);
ProgressDescription = "Waiting for branch updated...";
}
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
if (CheckoutAfterCreated)
Task.Delay(400).Wait();
return true;
}
private string FixName(string name)

View File

@@ -74,7 +74,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Create tag...";
@@ -83,24 +83,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Create Tag");
Use(log);
return Task.Run(() =>
bool succ;
if (_annotated)
succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log);
else
succ = await Commands.Tag.AddAsync(_repo.FullPath, _tagName, _basedOn, log);
if (succ && remotes != null)
{
bool succ;
if (_annotated)
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, Message, SignTag, log);
else
succ = Commands.Tag.Add(_repo.FullPath, _tagName, _basedOn, log);
foreach (var remote in remotes)
await new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Use(log).ExecAsync();
}
if (succ && remotes != null)
{
foreach (var remote in remotes)
new Commands.Push(_repo.FullPath, remote.Name, $"refs/tags/{_tagName}", false).Use(log).Exec();
}
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo = null;

View File

@@ -23,7 +23,7 @@ namespace SourceGit.ViewModels
Force = false;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "De-initialize Submodule";
@@ -31,13 +31,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("De-initialize Submodule");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Deinit(Submodule, false);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
var succ = await new Commands.Submodule(_repo.FullPath).Use(log).DeinitAsync(Submodule, false);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private Repository _repo;

View File

@@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
}
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting branch...";
@@ -47,29 +47,26 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Branch");
Use(log);
return Task.Run(() =>
if (Target.IsLocal)
{
if (Target.IsLocal)
{
Commands.Branch.DeleteLocal(_repo.FullPath, Target.Name, log);
await Commands.Branch.DeleteLocalAsync(_repo.FullPath, Target.Name, log);
if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
Commands.Branch.DeleteRemote(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
}
else
{
Commands.Branch.DeleteRemote(_repo.FullPath, Target.Remote, Target.Name, log);
}
if (_alsoDeleteTrackingRemote && TrackingRemoteBranch != null)
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, TrackingRemoteBranch.Remote, TrackingRemoteBranch.Name, log);
}
else
{
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, Target.Remote, Target.Name, log);
}
log.Complete();
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
await CallUIThreadAsync(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
}
private readonly Repository _repo = null;

View File

@@ -17,7 +17,7 @@ namespace SourceGit.ViewModels
Targets = branches;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting multiple branches...";
@@ -25,29 +25,26 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Multiple Branches");
Use(log);
return Task.Run(() =>
if (_isLocal)
{
if (_isLocal)
{
foreach (var target in Targets)
Commands.Branch.DeleteLocal(_repo.FullPath, target.Name, log);
}
else
{
foreach (var target in Targets)
Commands.Branch.DeleteRemote(_repo.FullPath, target.Remote, target.Name, log);
}
foreach (var target in Targets)
await Commands.Branch.DeleteLocalAsync(_repo.FullPath, target.Name, log);
}
else
{
foreach (var target in Targets)
await Commands.Branch.DeleteRemoteAsync(_repo.FullPath, target.Remote, target.Name, log);
}
log.Complete();
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
await CallUIThreadAsync(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
}
private Repository _repo = null;

View File

@@ -16,7 +16,7 @@ namespace SourceGit.ViewModels
Remote = remote;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting remote ...";
@@ -24,18 +24,15 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Remote");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Remote(_repo.FullPath).Use(log).Delete(Remote.Name);
log.Complete();
var succ = await new Commands.Remote(_repo.FullPath).Use(log).DeleteAsync(Remote.Name);
log.Complete();
CallUIThread(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
await CallUIThreadAsync(() =>
{
_repo.MarkBranchesDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
}
private readonly Repository _repo = null;

View File

@@ -16,7 +16,7 @@ namespace SourceGit.ViewModels
Submodule = submodule;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Deleting submodule ...";
@@ -24,13 +24,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Submodule");
Use(log);
return Task.Run(() =>
{
var succ = new Commands.Submodule(_repo.FullPath).Use(log).Delete(Submodule);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
var succ = await new Commands.Submodule(_repo.FullPath).Use(log).DeleteAsync(Submodule);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo = null;

View File

@@ -22,7 +22,7 @@ namespace SourceGit.ViewModels
Target = tag;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Deleting tag '{Target.Name}' ...";
@@ -31,24 +31,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Delete Tag");
Use(log);
return Task.Run(() =>
var succ = await Commands.Tag.DeleteAsync(_repo.FullPath, Target.Name, log);
if (succ)
{
var succ = Commands.Tag.Delete(_repo.FullPath, Target.Name, log);
if (succ)
{
foreach (var r in remotes)
new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true).Use(log).Exec();
}
foreach (var r in remotes)
await new Commands.Push(_repo.FullPath, r.Name, $"refs/tags/{Target.Name}", true).Use(log).ExecAsync();
}
log.Complete();
log.Complete();
CallUIThread(() =>
{
_repo.MarkTagsDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
await CallUIThreadAsync(() =>
{
_repo.MarkTagsDirtyManually();
_repo.SetWatcherEnabled(true);
});
return succ;
}
private readonly Repository _repo = null;

View File

@@ -97,7 +97,7 @@ namespace SourceGit.ViewModels
{
var toolType = Preferences.Instance.ExternalMergeToolType;
var toolPath = Preferences.Instance.ExternalMergeToolPath;
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, toolType, toolPath, _option));
Task.Run(() => Commands.MergeTool.OpenForDiffAsync(_repo, toolType, toolPath, _option));
}
private void LoadDiffContent()
@@ -109,11 +109,11 @@ namespace SourceGit.ViewModels
return;
}
Task.Run(() =>
Task.Run(async () =>
{
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
var latest = new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).Result();
var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace).ResultAsync();
var info = new Info(_option, numLines, ignoreWhitespace, latest);
if (_info != null && info.IsSame(_info))
return;
@@ -199,13 +199,13 @@ namespace SourceGit.ViewModels
var binaryDiff = new Models.BinaryDiff();
if (_option.Revisions.Count == 2)
{
binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).Result();
binaryDiff.NewSize = new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).Result();
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();
}
else
{
var fullPath = Path.Combine(_repo, _option.Path);
binaryDiff.OldSize = new Commands.QueryFileSize(_repo, oldPath, "HEAD").Result();
binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").ResultAsync();
binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0;
}
rs = binaryDiff;

View File

@@ -51,10 +51,10 @@ namespace SourceGit.ViewModels
_detail = new CommitDetail(repo, false);
_detail.SearchChangeFilter = dir;
Task.Run(() =>
Task.Run(async () =>
{
var commits = new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision ?? string.Empty} -- \"{dir}\"", false).Result();
Dispatcher.UIThread.Invoke(() =>
var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {revision ?? string.Empty} -- \"{dir}\"", false).ResultAsync();
await Dispatcher.UIThread.InvokeAsync(() =>
{
Commits = commits;
IsLoading = false;

View File

@@ -56,7 +56,7 @@ namespace SourceGit.ViewModels
Mode = new DiscardMultipleFiles() { Count = _changes.Count };
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = _changes == null ? "Discard all local changes ..." : $"Discard total {_changes.Count} changes ...";
@@ -64,23 +64,20 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Discard all");
Use(log);
return Task.Run(() =>
if (Mode is DiscardAllMode all)
await Commands.Discard.AllAsync(_repo.FullPath, all.IncludeIgnored, log);
else
await Commands.Discard.ChangesAsync(_repo.FullPath, _changes, log);
log.Complete();
await CallUIThreadAsync(() =>
{
if (Mode is DiscardAllMode all)
Commands.Discard.All(_repo.FullPath, all.IncludeIgnored, log);
else
Commands.Discard.Changes(_repo.FullPath, _changes, log);
log.Complete();
CallUIThread(() =>
{
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
_repo.MarkWorkingCopyDirtyManually();
_repo.SetWatcherEnabled(true);
});
return true;
}
private readonly Repository _repo = null;

View File

@@ -12,19 +12,16 @@ namespace SourceGit.ViewModels
Stash = stash;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
ProgressDescription = $"Dropping stash: {Stash.Name}";
var log = _repo.CreateLog("Drop Stash");
Use(log);
return Task.Run(() =>
{
new Commands.Stash(_repo.FullPath).Use(log).Drop(Stash.Name);
log.Complete();
return true;
});
await new Commands.Stash(_repo.FullPath).Use(log).DropAsync(Stash.Name);
log.Complete();
return true;
}
private readonly Repository _repo;

View File

@@ -100,36 +100,33 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Editing remote '{_remote.Name}' ...";
return Task.Run(() =>
if (_remote.Name != _name)
{
if (_remote.Name != _name)
{
var succ = new Commands.Remote(_repo.FullPath).Rename(_remote.Name, _name);
if (succ)
_remote.Name = _name;
}
var succ = await new Commands.Remote(_repo.FullPath).RenameAsync(_remote.Name, _name);
if (succ)
_remote.Name = _name;
}
if (_remote.URL != _url)
{
var succ = new Commands.Remote(_repo.FullPath).SetURL(_name, _url, false);
if (succ)
_remote.URL = _url;
}
if (_remote.URL != _url)
{
var succ = await new Commands.Remote(_repo.FullPath).SetURLAsync(_name, _url, false);
if (succ)
_remote.URL = _url;
}
var pushURL = new Commands.Remote(_repo.FullPath).GetURL(_name, true);
if (pushURL != _url)
new Commands.Remote(_repo.FullPath).SetURL(_name, _url, true);
var pushURL = await new Commands.Remote(_repo.FullPath).GetURLAsync(_name, true);
if (pushURL != _url)
await new Commands.Remote(_repo.FullPath).SetURLAsync(_name, _url, true);
new Commands.Config(_repo.FullPath).Set($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
await new Commands.Config(_repo.FullPath).SetAsync($"remote.{_name}.sshkey", _useSSH ? SSHKey : null);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

View File

@@ -151,7 +151,7 @@ namespace SourceGit.ViewModels
PrepareControlParameters();
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Run custom action ...";
@@ -166,19 +166,16 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog(CustomAction.Name);
Use(log);
return Task.Run(() =>
{
log.AppendLine($"$ {CustomAction.Executable} {cmdline}\n");
log.AppendLine($"$ {CustomAction.Executable} {cmdline}\n");
if (CustomAction.WaitForExit)
RunAndWait(cmdline, log);
else
Run(cmdline);
if (CustomAction.WaitForExit)
RunAndWait(cmdline, log);
else
Run(cmdline);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private void PrepareControlParameters()

View File

@@ -54,7 +54,7 @@ namespace SourceGit.ViewModels
}
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
@@ -63,36 +63,33 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Fetch");
Use(log);
return Task.Run(() =>
if (FetchAllRemotes)
{
if (FetchAllRemotes)
{
foreach (var remote in _repo.Remotes)
new Commands.Fetch(_repo.FullPath, remote.Name, notags, force).Use(log).Exec();
}
else
{
new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force).Use(log).Exec();
}
foreach (var remote in _repo.Remotes)
await new Commands.Fetch(_repo.FullPath, remote.Name, notags, force).Use(log).ExecAsync();
}
else
{
await new Commands.Fetch(_repo.FullPath, SelectedRemote.Name, notags, force).Use(log).ExecAsync();
}
log.Complete();
log.Complete();
var upstream = _repo.CurrentBranch?.Upstream;
var upstreamHead = string.Empty;
if (!string.IsNullOrEmpty(upstream))
upstreamHead = new Commands.QueryRevisionByRefName(_repo.FullPath, upstream.Substring(13)).Result();
var upstream = _repo.CurrentBranch?.Upstream;
var upstreamHead = string.Empty;
if (!string.IsNullOrEmpty(upstream))
upstreamHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, upstream.Substring(13)).ResultAsync();
CallUIThread(() =>
{
if (!string.IsNullOrEmpty(upstreamHead))
_repo.NavigateToCommit(upstreamHead, true);
await CallUIThreadAsync(() =>
{
if (!string.IsNullOrEmpty(upstreamHead))
_repo.NavigateToCommit(upstreamHead, true);
_repo.MarkFetched();
_repo.SetWatcherEnabled(true);
});
return true;
_repo.MarkFetched();
_repo.SetWatcherEnabled(true);
});
return true;
}
private readonly Repository _repo = null;

View File

@@ -21,7 +21,7 @@ namespace SourceGit.ViewModels
Upstream = upstream;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fast-Forward ...";
@@ -29,20 +29,17 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Fetch Into '{Local.FriendlyName}'");
Use(log);
return Task.Run(() =>
await new Commands.Fetch(_repo.FullPath, Local, Upstream).Use(log).ExecAsync();
log.Complete();
var changedLocalBranchHead = await new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).ResultAsync();
await CallUIThreadAsync(() =>
{
new Commands.Fetch(_repo.FullPath, Local, Upstream).Use(log).Exec();
log.Complete();
var changedLocalBranchHead = new Commands.QueryRevisionByRefName(_repo.FullPath, Local.Name).Result();
CallUIThread(() =>
{
_repo.NavigateToCommit(changedLocalBranchHead, true);
_repo.SetWatcherEnabled(true);
});
return true;
_repo.NavigateToCommit(changedLocalBranchHead, true);
_repo.SetWatcherEnabled(true);
});
return true;
}
private readonly Repository _repo = null;

View File

@@ -45,26 +45,23 @@ namespace SourceGit.ViewModels
RefreshViewContent();
}
public Task<bool> ResetToSelectedRevision()
public async Task<bool> ResetToSelectedRevision()
{
return Task.Run(() => new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_revision.SHA}"));
return await new Commands.Checkout(_repo.FullPath).FileWithRevisionAsync(_file, $"{_revision.SHA}");
}
public Task OpenWithDefaultEditor()
public async Task OpenWithDefaultEditor()
{
if (_viewContent is not FileHistoriesRevisionFile { CanOpenWithDefaultEditor: true })
return null;
return;
return Task.Run(() =>
{
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}~{_revision.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}~{_revision.SHA.Substring(0, 10)}{fileExt}");
Commands.SaveRevisionFile.Run(_repo.FullPath, _revision.SHA, _file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
});
await Commands.SaveRevisionFile.RunAsync(_repo.FullPath, _revision.SHA, _file, tmpFile);
Native.OS.OpenWithDefaultEditor(tmpFile);
}
private void RefreshViewContent()
@@ -88,9 +85,9 @@ namespace SourceGit.ViewModels
switch (obj.Type)
{
case Models.ObjectType.Blob:
Task.Run(() =>
Task.Run(async () =>
{
var isBinary = new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).Result();
var isBinary = await new Commands.IsBinary(_repo.FullPath, _revision.SHA, _file).ResultAsync();
if (isBinary)
{
var imgDecoder = ImageSource.GetDecoder(_file);
@@ -98,20 +95,20 @@ namespace SourceGit.ViewModels
{
var source = ImageSource.FromRevision(_repo.FullPath, _revision.SHA, _file, imgDecoder);
var image = new Models.RevisionImageFile(_file, source.Bitmap, source.Size);
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image, true));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, image, true));
}
else
{
var size = new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).Result();
var size = await new Commands.QueryFileSize(_repo.FullPath, _file, _revision.SHA).ResultAsync();
var binaryFile = new Models.RevisionBinaryFile() { Size = size };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile, true));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile, true));
}
return;
}
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _revision.SHA, _file);
var content = new StreamReader(contentStream).ReadToEnd();
var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _revision.SHA, _file);
var content = await new StreamReader(contentStream).ReadToEndAsync();
var lfs = Models.LFSObject.Parse(content);
if (lfs != null)
{
@@ -119,34 +116,34 @@ namespace SourceGit.ViewModels
if (imgDecoder != Models.ImageDecoder.None)
{
var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder);
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, combined, true));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, combined, true));
}
else
{
var rlfs = new Models.RevisionLFSObject() { Object = lfs };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs, true));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, rlfs, true));
}
}
else
{
var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, txt, true));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, txt, true));
}
});
break;
case Models.ObjectType.Commit:
Task.Run(() =>
Task.Run(async () =>
{
var submoduleRoot = Path.Combine(_repo.FullPath, _file);
var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
var message = commit != null ? new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result() : null;
var commit = await new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).ResultAsync();
var message = commit != null ? await new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).ResultAsync() : null;
var module = new Models.RevisionSubmodule()
{
Commit = commit ?? new Models.Commit() { SHA = obj.SHA },
FullMessage = new Models.CommitFullMessage { Message = message }
};
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
});
break;
default:
@@ -203,28 +200,27 @@ namespace SourceGit.ViewModels
RefreshViewContent();
}
public Task<bool> SaveAsPatch(string saveTo)
public async Task<bool> SaveAsPatch(string saveTo)
{
return Task.Run(() =>
{
Commands.SaveChangesAsPatch.ProcessRevisionCompareChanges(_repo.FullPath, _changes, _startPoint.SHA, _endPoint.SHA, saveTo);
await Commands.SaveChangesAsPatch.ProcessRevisionCompareChangesAsync(_repo.FullPath, _changes, _startPoint.SHA, _endPoint.SHA, saveTo);
return true;
});
}
}
private void RefreshViewContent()
{
Task.Run(() =>
Task.Run(async () =>
{
_changes = new Commands.CompareRevisions(_repo.FullPath, _startPoint.SHA, _endPoint.SHA, _file).Result();
_changes = await new Commands.CompareRevisions(_repo.FullPath, _startPoint.SHA, _endPoint.SHA, _file).ResultAsync();
if (_changes.Count == 0)
{
Dispatcher.UIThread.Invoke(() => ViewContent = null);
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = null);
return;
}
var option = new Models.DiffOption(_startPoint.SHA, _endPoint.SHA, _changes[0]);
Dispatcher.UIThread.Invoke(() => ViewContent = new DiffContext(_repo.FullPath, option, _viewContent));
await Dispatcher.UIThread.InvokeAsync(() => ViewContent = new DiffContext(_repo.FullPath, option, _viewContent));
});
}
@@ -276,11 +272,11 @@ namespace SourceGit.ViewModels
_repo = repo;
Task.Run(() =>
Task.Run(async () =>
{
var based = commit ?? string.Empty;
var commits = new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {based} -- \"{file}\"", false).Result();
Dispatcher.UIThread.Invoke(() =>
var commits = await new Commands.QueryCommits(_repo.FullPath, $"--date-order -n 10000 {based} -- \"{file}\"", false).ResultAsync();
await Dispatcher.UIThread.InvokeAsync(() =>
{
IsLoading = false;
Commits = commits;

View File

@@ -40,7 +40,7 @@ namespace SourceGit.ViewModels
Type = type;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Git Flow - Finish {Branch.Name} ...";
@@ -51,13 +51,10 @@ namespace SourceGit.ViewModels
var prefix = _repo.GitFlow.GetPrefix(Type);
var name = Branch.Name.StartsWith(prefix) ? Branch.Name.Substring(prefix.Length) : Branch.Name;
return Task.Run(() =>
{
var succ = Commands.GitFlow.Finish(_repo.FullPath, Type, name, Squash, AutoPush, KeepBranch, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
var succ = await Commands.GitFlow.FinishAsync(_repo.FullPath, Type, name, Squash, AutoPush, KeepBranch, log);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo;

View File

@@ -49,7 +49,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Git Flow - Start {Prefix}{_name} ...";
@@ -57,13 +57,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("GitFlow - Start");
Use(log);
return Task.Run(() =>
{
var succ = Commands.GitFlow.Start(_repo.FullPath, Type, _name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;
});
var succ = await Commands.GitFlow.StartAsync(_repo.FullPath, Type, _name, log);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private readonly Repository _repo;

View File

@@ -3,7 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
@@ -393,7 +392,7 @@ namespace SourceGit.ViewModels
for (var i = 0; i < selected.Count; i++)
{
var saveTo = GetPatchFileName(folderPath, selected[i], i);
succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, selected[i].SHA, saveTo).Use(log).Exec());
succ = await new Commands.FormatPatch(_repo.FullPath, selected[i].SHA, saveTo).Use(log).ExecAsync();
if (!succ)
break;
}
@@ -588,7 +587,7 @@ namespace SourceGit.ViewModels
var cherryPick = new MenuItem();
cherryPick.Header = App.Text("CommitCM.CherryPick");
cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick");
cherryPick.Click += (_, e) =>
cherryPick.Click += async (_, e) =>
{
if (_repo.CanCreatePopup())
{
@@ -601,7 +600,7 @@ namespace SourceGit.ViewModels
var parents = new List<Models.Commit>();
foreach (var sha in commit.Parents)
{
var parent = _commits.Find(x => x.SHA == sha) ?? new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
var parent = _commits.Find(x => x.SHA == sha) ?? await new Commands.QuerySingleCommit(_repo.FullPath, sha).ResultAsync();
if (parent != null)
parents.Add(parent);
@@ -685,13 +684,13 @@ namespace SourceGit.ViewModels
var compareWithHead = new MenuItem();
compareWithHead.Header = App.Text("CommitCM.CompareWithHead");
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
compareWithHead.Click += (_, e) =>
compareWithHead.Click += async (_, e) =>
{
var head = _commits.Find(x => x.SHA == current.Head);
if (head == null)
{
_repo.SelectedSearchedCommit = null;
head = new Commands.QuerySingleCommit(_repo.FullPath, current.Head).Result();
head = await new Commands.QuerySingleCommit(_repo.FullPath, current.Head).ResultAsync();
if (head != null)
DetailContext = new RevisionCompare(_repo.FullPath, commit, head);
}
@@ -764,7 +763,7 @@ namespace SourceGit.ViewModels
var folder = selected[0];
var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder.Path.ToString();
var saveTo = GetPatchFileName(folderPath, commit);
var succ = await Task.Run(() => new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).Exec());
var succ = await new Commands.FormatPatch(_repo.FullPath, commit.SHA, saveTo).Use(log).ExecAsync();
if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
@@ -10,27 +11,27 @@ namespace SourceGit.ViewModels
_cmd = cmd;
}
public bool Abort()
public Task<bool> AbortAsync()
{
return new Commands.Command()
{
WorkingDirectory = _repo,
Context = _repo,
Args = $"{_cmd} --abort",
}.Exec();
}.ExecAsync();
}
public virtual bool Skip()
public virtual Task<bool> SkipAsync()
{
return new Commands.Command()
{
WorkingDirectory = _repo,
Context = _repo,
Args = $"{_cmd} --skip",
}.Exec();
}.ExecAsync();
}
public virtual bool Continue()
public virtual Task<bool> ContinueAsync()
{
return new Commands.Command()
{
@@ -38,7 +39,7 @@ namespace SourceGit.ViewModels
Context = _repo,
Editor = Commands.Command.EditorType.None,
Args = $"{_cmd} --continue",
}.Exec();
}.ExecAsync();
}
protected string GetFriendlyNameOfCommit(Models.Commit commit)
@@ -123,7 +124,7 @@ namespace SourceGit.ViewModels
Onto = new Commands.QuerySingleCommit(repo.FullPath, ontoSHA).Result() ?? new Models.Commit() { SHA = ontoSHA };
}
public override bool Continue()
public override Task<bool> ContinueAsync()
{
return new Commands.Command()
{
@@ -131,7 +132,7 @@ namespace SourceGit.ViewModels
Context = _repo,
Editor = Commands.Command.EditorType.RebaseEditor,
Args = "rebase --continue",
}.Exec();
}.ExecAsync();
}
}
@@ -177,9 +178,9 @@ namespace SourceGit.ViewModels
Source = new Commands.QuerySingleCommit(repo.FullPath, sourceSHA).Result() ?? new Models.Commit() { SHA = sourceSHA };
}
public override bool Skip()
public override Task<bool> SkipAsync()
{
return true;
return Task.FromResult(true);
}
}
}

View File

@@ -24,29 +24,26 @@ namespace SourceGit.ViewModels
Reason = string.IsNullOrEmpty(reason) ? "Invalid repository detected!" : reason;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
ProgressDescription = $"Initialize git repository at: '{_targetPath}'";
var log = new CommandLog("Initialize");
Use(log);
return Task.Run(() =>
var succ = await new Commands.Init(_pageId, _targetPath).Use(log).ExecAsync();
log.Complete();
if (succ)
{
var succ = new Commands.Init(_pageId, _targetPath).Use(log).Exec();
log.Complete();
if (succ)
await CallUIThreadAsync(() =>
{
CallUIThread(() =>
{
Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true);
Welcome.Instance.Refresh();
});
}
Preferences.Instance.FindOrAddNodeByRepositoryPath(_targetPath, _parentNode, true);
Welcome.Instance.Refresh();
});
}
return succ;
});
return succ;
}
private readonly string _pageId = null;

View File

@@ -100,7 +100,7 @@ namespace SourceGit.ViewModels
return ValidationResult.Success;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Init git-flow ...";
@@ -108,65 +108,62 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Gitflow - Init");
Use(log);
return Task.Run(() =>
bool succ;
var current = _repo.CurrentBranch;
var masterBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_master, StringComparison.Ordinal));
if (masterBranch == null)
{
bool succ;
var current = _repo.CurrentBranch;
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);
if (!succ)
{
succ = Commands.Branch.Create(_repo.FullPath, _master, current.Head, true, log);
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
}
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);
if (!succ)
{
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return false;
}
}
succ = await Commands.GitFlow.InitAsync(
_repo.FullPath,
_master,
_develop,
_featurePrefix,
_releasePrefix,
_hotfixPrefix,
_tagPrefix,
log);
log.Complete();
await CallUIThreadAsync(() =>
{
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;
}
var developBranch = _repo.Branches.Find(x => x.IsLocal && x.Name.Equals(_develop, StringComparison.Ordinal));
if (developBranch == null)
{
succ = Commands.Branch.Create(_repo.FullPath, _develop, current.Head, true, log);
if (!succ)
{
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return false;
}
}
succ = Commands.GitFlow.Init(
_repo.FullPath,
_master,
_develop,
_featurePrefix,
_releasePrefix,
_hotfixPrefix,
_tagPrefix,
log);
log.Complete();
CallUIThread(() =>
{
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);
});
return succ;
_repo.SetWatcherEnabled(true);
});
return succ;
}
private readonly Repository _repo;

View File

@@ -131,9 +131,9 @@ namespace SourceGit.ViewModels
IsLoading = true;
DetailContext = new CommitDetail(repo, false);
Task.Run(() =>
Task.Run(async () =>
{
var commits = new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).Result();
var commits = await new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).ResultAsync();
var list = new List<InteractiveRebaseItem>();
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));
}
Dispatcher.UIThread.Invoke(() =>
await Dispatcher.UIThread.InvokeAsync(() =>
{
Items.AddRange(list);
IsLoading = false;
@@ -188,7 +188,7 @@ namespace SourceGit.ViewModels
UpdateItems();
}
public Task<bool> Start()
public async Task<bool> Start()
{
_repo.SetWatcherEnabled(false);
@@ -206,19 +206,16 @@ namespace SourceGit.ViewModels
Message = item.FullMessage,
});
}
using (var stream = File.Create(saveFile))
await using (var stream = File.Create(saveFile))
{
JsonSerializer.Serialize(stream, collection, JsonCodeGen.Default.InteractiveRebaseJobCollection);
await JsonSerializer.SerializeAsync(stream, collection, JsonCodeGen.Default.InteractiveRebaseJobCollection);
}
var log = _repo.CreateLog("Interactive Rebase");
return Task.Run(() =>
{
var succ = new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).Exec();
log.Complete();
Dispatcher.UIThread.Invoke(() => _repo.SetWatcherEnabled(true));
return succ;
});
var succ = await new Commands.InteractiveRebase(_repo.FullPath, On.SHA).Use(log).ExecAsync();
log.Complete();
await Dispatcher.UIThread.InvokeAsync(() => _repo.SetWatcherEnabled(true));
return succ;
}
private void UpdateItems()

View File

@@ -19,7 +19,7 @@ namespace SourceGit.ViewModels
SelectedRemote = _repo.Remotes[0];
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Fetching LFS objects from remote ...";
@@ -27,13 +27,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("LFS Fetch");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Fetch(SelectedRemote.Name, log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
await new Commands.LFS(_repo.FullPath).FetchAsync(SelectedRemote.Name, log);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

View File

@@ -46,10 +46,10 @@ namespace SourceGit.ViewModels
HasValidUserName = !string.IsNullOrEmpty(_userName);
Task.Run(() =>
Task.Run(async () =>
{
_cachedLocks = new Commands.LFS(_repo.FullPath).Locks(_remote);
Dispatcher.UIThread.Invoke(() =>
_cachedLocks = await new Commands.LFS(_repo.FullPath).LocksAsync(_remote);
await Dispatcher.UIThread.InvokeAsync(() =>
{
UpdateVisibleLocks();
IsLoading = false;
@@ -65,12 +65,12 @@ namespace SourceGit.ViewModels
IsLoading = true;
var log = _repo.CreateLog("Unlock LFS File");
Task.Run(() =>
Task.Run(async () =>
{
var succ = new Commands.LFS(_repo.FullPath).Unlock(_remote, lfsLock.ID, force, log);
var succ = await new Commands.LFS(_repo.FullPath).UnlockAsync(_remote, lfsLock.ID, force, log);
log.Complete();
Dispatcher.UIThread.Invoke(() =>
await Dispatcher.UIThread.InvokeAsync(() =>
{
if (succ)
{

View File

@@ -9,7 +9,7 @@ namespace SourceGit.ViewModels
_repo = repo;
}
public override Task<bool> Sure()
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "LFS prune ...";
@@ -17,13 +17,10 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("LFS Prune");
Use(log);
return Task.Run(() =>
{
new Commands.LFS(_repo.FullPath).Prune(log);
log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
await new Commands.LFS(_repo.FullPath).PruneAsync(log);
log.Complete();
await CallUIThreadAsync(() => _repo.SetWatcherEnabled(true));
return true;
}
private readonly Repository _repo = null;

Some files were not shown because too many files have changed in this diff Show More