enhance: use ArgumentList instead of manual escaping

This commit is contained in:
Aikawa Yataro 2024-09-14 06:10:42 +00:00
parent 7f87ce3431
commit 77fa7169df
No known key found for this signature in database
GPG key ID: 1C5D95FB10179404
77 changed files with 325 additions and 326 deletions

View file

@ -12,19 +12,14 @@ namespace SourceGit.Commands
if (changes == null || changes.Count == 0)
{
Args = "add .";
Args = ["add", "."];
}
else
{
var builder = new StringBuilder();
builder.Append("add --");
Args.AddRange(["add", "--"]);
foreach (var c in changes)
{
builder.Append(" \"");
builder.Append(c.Path);
builder.Append("\"");
}
Args = builder.ToString();
Args.Add(c.Path);
}
}
}

View file

@ -1,19 +1,20 @@
namespace SourceGit.Commands
using System.Collections.Generic;
namespace SourceGit.Commands
{
public class Apply : Command
{
public Apply(string repo, string file, bool ignoreWhitespace, string whitespaceMode, string extra)
public Apply(string repo, string file, bool ignoreWhitespace, string whitespaceMode, IEnumerable<string> extra)
{
WorkingDirectory = repo;
Context = repo;
Args = "apply ";
Args = ["apply"];
if (ignoreWhitespace)
Args += "--ignore-whitespace ";
Args.Add("--ignore-whitespace");
else
Args += $"--whitespace={whitespaceMode} ";
if (!string.IsNullOrEmpty(extra))
Args += $"{extra} ";
Args += $"\"{file}\"";
Args.Add($"--whitespace={whitespaceMode}");
Args.AddRange(extra);
Args.Add(file);
}
}
}

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"archive --format=zip --verbose --output=\"{saveTo}\" {revision}";
Args = ["archive", "--format=zip", "--verbose", "-o", saveTo, revision];
TraitErrorAsOutput = true;
_outputHandler = outputHandler;
}

View file

@ -13,7 +13,7 @@ namespace SourceGit.Commands
public ViewCommand(string repo)
{
WorkingDirectory = repo;
Args = "ls-files -v";
Args = ["ls-files", "-v"];
RaiseError = false;
}
@ -46,7 +46,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
Args = $"update-index {mode} -- \"{file}\"";
Args = ["update-index", mode, "--", file];
}
}

View file

@ -13,7 +13,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"blame -t {revision} -- \"{file}\"";
Args = ["blame", "-t", revision, "--", file];
RaiseError = false;
_result.File = file;

View file

@ -7,7 +7,7 @@
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch {name} {basedOn}";
cmd.Args = ["branch", name, basedOn];
return cmd.Exec();
}
@ -16,7 +16,7 @@
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -M {name} {to}";
cmd.Args = ["branch", "-M", name, to];
return cmd.Exec();
}
@ -27,9 +27,9 @@
cmd.Context = repo;
if (string.IsNullOrEmpty(upstream))
cmd.Args = $"branch {name} --unset-upstream";
cmd.Args = ["branch", name, "--unset-upstream"];
else
cmd.Args = $"branch {name} -u {upstream}";
cmd.Args = ["branch", name, "-u", upstream];
return cmd.Exec();
}
@ -39,7 +39,7 @@
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"branch -D {name}";
cmd.Args = ["branch", "-D", name];
return cmd.Exec();
}
@ -49,7 +49,7 @@
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
cmd.Args = $"push {remote} --delete {name}";
cmd.Args = ["push", remote, "--delete", name];
return cmd.Exec();
}
}

View file

@ -14,7 +14,7 @@ namespace SourceGit.Commands
public bool Branch(string branch, Action<string> onProgress)
{
Args = $"checkout --progress {branch}";
Args = ["checkout", "--progress", branch];
TraitErrorAsOutput = true;
_outputHandler = onProgress;
return Exec();
@ -22,7 +22,7 @@ namespace SourceGit.Commands
public bool Branch(string branch, string basedOn, Action<string> onProgress)
{
Args = $"checkout --progress -b {branch} {basedOn}";
Args = ["checkout", "--progress", "-b", branch, basedOn];
TraitErrorAsOutput = true;
_outputHandler = onProgress;
return Exec();
@ -30,41 +30,25 @@ namespace SourceGit.Commands
public bool UseTheirs(List<string> files)
{
StringBuilder builder = new StringBuilder();
builder.Append("checkout --theirs --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
Args = builder.ToString();
Args = ["checkout", "--theirs", "--", ..files];
return Exec();
}
public bool UseMine(List<string> files)
{
StringBuilder builder = new StringBuilder();
builder.Append("checkout --ours --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
Args = builder.ToString();
Args = ["checkout", "--ours", "--", ..files];
return Exec();
}
public bool FileWithRevision(string file, string revision)
{
Args = $"checkout --no-overlay {revision} -- \"{file}\"";
Args = ["checkout", "--no-overlay", revision, "--", file];
return Exec();
}
public bool Commit(string commitId, Action<string> onProgress)
{
Args = $"checkout --detach --progress {commitId}";
Args = ["checkout", "--detach", "--progress", commitId];
TraitErrorAsOutput = true;
_outputHandler = onProgress;
return Exec();
@ -72,15 +56,7 @@ namespace SourceGit.Commands
public bool Files(List<string> files)
{
StringBuilder builder = new StringBuilder();
builder.Append("checkout -f -q --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
Args = builder.ToString();
Args = ["checkout", "-f", "-q", "--", ..files];
return Exec();
}

View file

@ -7,7 +7,7 @@
var mode = noCommit ? "-n" : "--ff";
WorkingDirectory = repo;
Context = repo;
Args = $"cherry-pick {mode} {commits}";
Args = ["cherry-pick", mode, commits];
}
}
}

View file

@ -9,23 +9,15 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "clean -qfd";
Args = ["clean", "-qfd"];
}
public Clean(string repo, List<string> files)
{
StringBuilder builder = new StringBuilder();
builder.Append("clean -qfd --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
Args = ["clean", "-qfd", "--", ..files];
WorkingDirectory = repo;
Context = repo;
Args = builder.ToString();
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace SourceGit.Commands
{
@ -6,21 +7,20 @@ namespace SourceGit.Commands
{
private readonly Action<string> _notifyProgress;
public Clone(string ctx, string path, string url, string localName, string sshKey, string extraArgs, Action<string> ouputHandler)
public Clone(string ctx, string path, string url, string localName, string sshKey, IEnumerable<string> extraArgs, Action<string> ouputHandler)
{
Context = ctx;
WorkingDirectory = path;
TraitErrorAsOutput = true;
SSHKey = sshKey;
Args = "clone --progress --verbose --recurse-submodules ";
Args = ["clone", "--progress", "--verbose", "--recurse-submodules"];
if (!string.IsNullOrEmpty(extraArgs))
Args += $"{extraArgs} ";
Args.AddRange(extraArgs);
Args += $"{url} ";
Args.Add(url);
if (!string.IsNullOrEmpty(localName))
Args += localName;
Args.Add(localName);
_notifyProgress = ouputHandler;
}

View file

@ -34,15 +34,15 @@ namespace SourceGit.Commands
public string WorkingDirectory { get; set; } = null;
public EditorType Editor { get; set; } = EditorType.CoreEditor; // Only used in Exec() mode
public string SSHKey { get; set; } = string.Empty;
public string Args { get; set; } = string.Empty;
public List<string> Args { get; set; } = [];
public bool RaiseError { get; set; } = true;
public bool TraitErrorAsOutput { get; set; } = false;
public bool Exec()
{
var start = new ProcessStartInfo();
start.FileName = Native.OS.GitExecutable;
start.Arguments = "--no-pager -c core.quotepath=off ";
List<string> gitArgs = ["--no-pager", "-c", "core.quotepath=off"];
var start = new ProcessStartInfo(Native.OS.GitExecutable);
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
@ -61,7 +61,7 @@ namespace SourceGit.Commands
if (!string.IsNullOrEmpty(SSHKey))
start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o StrictHostKeyChecking=accept-new -i '{SSHKey}'");
else
start.Arguments += "-c credential.helper=manager ";
gitArgs.AddRange(["-c", "credential.helper=manager"]);
// Force using en_US.UTF-8 locale to avoid GCM crash
if (OperatingSystem.IsLinux())
@ -71,18 +71,28 @@ namespace SourceGit.Commands
switch (Editor)
{
case EditorType.CoreEditor:
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --core-editor\" ";
gitArgs.AddRange(["-c", $"core.editor=\"{selfExecFile}\" --core-editor"]);
break;
case EditorType.RebaseEditor:
start.Arguments += $"-c core.editor=\"\\\"{selfExecFile}\\\" --rebase-message-editor\" -c sequence.editor=\"\\\"{selfExecFile}\\\" --rebase-todo-editor\" -c rebase.abbreviateCommands=true ";
gitArgs.AddRange([
"-c", $"core.editor=\"{selfExecFile}\" --rebase-message-editor",
"-c", $"sequence.editor=\"{selfExecFile}\" --rebase-todo-editor",
"-c", "rebase.abbreviateCommands=true"
]);
break;
default:
start.Arguments += "-c core.editor=true ";
gitArgs.AddRange(["-c", "core.editor=true"]);
break;
}
// Append command args
start.Arguments += Args;
gitArgs.AddRange(Args);
// Append git args
foreach (var arg in gitArgs)
{
start.ArgumentList.Add(arg);
}
// Working directory
if (!string.IsNullOrEmpty(WorkingDirectory))
@ -181,9 +191,8 @@ namespace SourceGit.Commands
public ReadToEndResult ReadToEnd()
{
var start = new ProcessStartInfo();
start.FileName = Native.OS.GitExecutable;
start.Arguments = "--no-pager -c core.quotepath=off " + Args;
List<string> gitArgs = ["--no-pager", "-c", "core.quotepath=off", ..Args];
var start = new ProcessStartInfo(Native.OS.GitExecutable, gitArgs);
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;

View file

@ -12,11 +12,11 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
TraitErrorAsOutput = true;
Args = $"commit --file=\"{file}\"";
Args = ["commit", $"--file={file}"];
if (amend)
Args += " --amend --no-edit";
Args.AddRange(["--amend", "--no-edit"]);
if (allowEmpty)
Args += " --allow-empty";
Args.Add("--allow-empty");
}
}
}

View file

@ -15,7 +15,7 @@ namespace SourceGit.Commands
Context = repo;
var based = string.IsNullOrEmpty(start) ? "-R" : start;
Args = $"diff --name-status {based} {end}";
Args = ["diff", "--name-status", based, end];
}
public List<Models.Change> Result()

View file

@ -15,9 +15,9 @@ namespace SourceGit.Commands
public Dictionary<string, string> ListAll()
{
if (string.IsNullOrEmpty(WorkingDirectory))
Args = "config --global -l";
Args = ["config", "--global", "-l"];
else
Args = "config -l";
Args = ["config", "-l"];
var output = ReadToEnd();
var rs = new Dictionary<string, string>();
@ -41,7 +41,7 @@ namespace SourceGit.Commands
public string Get(string key)
{
Args = $"config {key}";
Args = ["config", key];
return ReadToEnd().StdOut.Trim();
}
@ -50,16 +50,16 @@ namespace SourceGit.Commands
if (!allowEmpty && string.IsNullOrWhiteSpace(value))
{
if (string.IsNullOrEmpty(WorkingDirectory))
Args = $"config --global --unset {key}";
Args = ["config", "--global", "--unset", key];
else
Args = $"config --unset {key}";
Args = ["config", "--unset", key];
}
else
{
if (string.IsNullOrWhiteSpace(WorkingDirectory))
Args = $"config --global {key} \"{value}\"";
Args = ["config", "--global", key, value];
else
Args = $"config {key} \"{value}\"";
Args = ["config", key, value];
}
return Exec();

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "status -uno --ignore-submodules=dirty --porcelain";
Args = ["status", "-uno", "--ignore-submodules=dirty", "--porcelain"];
}
public int Result()

View file

@ -22,7 +22,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
Args = $"diff --ignore-cr-at-eol --unified={unified} {opt}";
Args = ["diff", "--ignore-cr-at-eol", $"--unified={unified}", ..opt.ToArgs()];
}
public Models.DiffResult Result()

View file

@ -33,7 +33,7 @@ namespace SourceGit.Commands
for (int i = 0; i < needCheckout.Count; i += 10)
{
var count = Math.Min(10, needCheckout.Count - i);
new Restore(repo, needCheckout.GetRange(i, count), "--worktree --recurse-submodules").Exec();
new Restore(repo, needCheckout.GetRange(i, count), ["--worktree", "--recurse-submodules"]).Exec();
}
}
}

View file

@ -11,17 +11,17 @@ namespace SourceGit.Commands
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "fetch --progress --verbose ";
Args = ["fetch", "--progress", "--verbose"];
if (prune)
Args += "--prune ";
Args.Add("--prune");
if (noTags)
Args += "--no-tags ";
Args.Add("--no-tags");
else
Args += "--force ";
Args.Add("--force");
Args += remote;
Args.Add(remote);
Models.AutoFetchManager.Instance.MarkFetched(repo);
}
@ -33,7 +33,7 @@ namespace SourceGit.Commands
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = $"fetch --progress --verbose {remote} {remoteBranch}:{localBranch}";
Args = ["fetch", "--progress", "--verbose", remote, $"{remoteBranch}:{localBranch}"];
}
protected override void OnReadline(string line)

View file

@ -6,7 +6,7 @@
{
WorkingDirectory = repo;
Context = repo;
Args = $"format-patch {commit} -1 -o \"{saveTo}\"";
Args = ["format-patch", commit, "-1", "-o", saveTo];
}
}
}

View file

@ -10,7 +10,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
TraitErrorAsOutput = true;
Args = "gc --prune";
Args = ["gc", "--prune"];
}
protected override void OnReadline(string line)

View file

@ -16,7 +16,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"diff --diff-algorithm=minimal {opt}";
Args = ["diff", "--diff-algorithm=minimal", ..opt.ToArgs()];
}
}

View file

@ -60,7 +60,7 @@ namespace SourceGit.Commands
var init = new Command();
init.WorkingDirectory = repo;
init.Context = repo;
init.Args = "flow init -d";
init.Args = ["flow", "init", "-d"];
return init.Exec();
}
@ -128,7 +128,7 @@ namespace SourceGit.Commands
var start = new Command();
start.WorkingDirectory = repo;
start.Context = repo;
start.Args = $"flow {type} start {name}";
start.Args = ["flow", type, "start", name];
return start.Exec();
}
@ -148,7 +148,7 @@ namespace SourceGit.Commands
var finish = new Command();
finish.WorkingDirectory = repo;
finish.Context = repo;
finish.Args = $"flow {type} finish {option} {name}";
finish.Args = ["flow", type, "finish", option, name];
return finish.Exec();
}

View file

@ -6,7 +6,7 @@
{
Context = ctx;
WorkingDirectory = dir;
Args = "init -q";
Args = ["init", "-q"];
}
}
}

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 {commit} --numstat -- \"{path}\"";
Args = ["diff", "4b825dc642cb6eb9a060e54bf8d69288fbee4904", commit, "--numstat", "--", path];
RaiseError = false;
}

View file

@ -8,7 +8,7 @@
WorkingDirectory = repo;
Context = repo;
Args = $"diff -a --ignore-cr-at-eol --check {opt}";
Args = ["diff", "-a", "--ignore-cr-at-eol", "--check", ..opt.ToArgs()];
}
}
}

View file

@ -6,7 +6,7 @@
{
WorkingDirectory = repo;
Context = repo;
Args = $"check-attr -z filter \"{path}\"";
Args = ["check-attr", "-z", "filter", path];
RaiseError = false;
}
@ -14,7 +14,7 @@
{
WorkingDirectory = repo;
Context = repo;
Args = $"check-attr --source {sha} -z filter \"{path}\"";
Args = ["check-attr", "--source", sha, "-z", "filter", path];
RaiseError = false;
}

View file

@ -12,11 +12,11 @@ namespace SourceGit.Commands
class SubCmd : Command
{
public SubCmd(string repo, string args, Action<string> onProgress)
public SubCmd(string repo, IEnumerable<string> args, Action<string> onProgress)
{
WorkingDirectory = repo;
Context = repo;
Args = args;
Args = new List<string>(args);
TraitErrorAsOutput = true;
_outputHandler = onProgress;
}
@ -46,39 +46,43 @@ namespace SourceGit.Commands
public bool Install()
{
return new SubCmd(_repo, "lfs install --local", null).Exec();
return new SubCmd(_repo, ["lfs", "install", "--local"], null).Exec();
}
public bool Track(string pattern, bool isFilenameMode = false)
{
var opt = isFilenameMode ? "--filename" : "";
return new SubCmd(_repo, $"lfs track {opt} \"{pattern}\"", null).Exec();
List<string> args = ["lfs", "track"];
if (isFilenameMode)
args.Add("--filename");
args.Add(pattern);
return new SubCmd(_repo, args, null).Exec();
}
public void Fetch(string remote, Action<string> outputHandler)
{
new SubCmd(_repo, $"lfs fetch {remote}", outputHandler).Exec();
new SubCmd(_repo, ["lfs", "fetch", remote], outputHandler).Exec();
}
public void Pull(string remote, Action<string> outputHandler)
{
new SubCmd(_repo, $"lfs pull {remote}", outputHandler).Exec();
new SubCmd(_repo, ["lfs", "pull", remote], outputHandler).Exec();
}
public void Push(string remote, Action<string> outputHandler)
{
new SubCmd(_repo, $"lfs push {remote}", outputHandler).Exec();
new SubCmd(_repo, ["lfs", "push", remote], outputHandler).Exec();
}
public void Prune(Action<string> outputHandler)
{
new SubCmd(_repo, "lfs prune", outputHandler).Exec();
new SubCmd(_repo, ["lfs", "prune"], outputHandler).Exec();
}
public List<Models.LFSLock> Locks(string remote)
{
var locks = new List<Models.LFSLock>();
var cmd = new SubCmd(_repo, $"lfs locks --remote={remote}", null);
var cmd = new SubCmd(_repo, ["lfs", "locks", $"--remote={remote}"], null);
var rs = cmd.ReadToEnd();
if (rs.IsSuccess)
{
@ -103,19 +107,25 @@ namespace SourceGit.Commands
public bool Lock(string remote, string file)
{
return new SubCmd(_repo, $"lfs lock --remote={remote} \"{file}\"", null).Exec();
return new SubCmd(_repo, ["lfs", "lock", $"--remote={remote}", file], null).Exec();
}
public bool Unlock(string remote, string file, bool force)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} \"{file}\"", null).Exec();
List<string> args = ["lfs", "unlock", $"--remote={remote}"];
if (force)
args.Add("-f");
args.Add(file);
return new SubCmd(_repo, args, null).Exec();
}
public bool Unlock(string remote, long id, bool force)
{
var opt = force ? "-f" : "";
return new SubCmd(_repo, $"lfs unlock --remote={remote} {opt} --id={id}", null).Exec();
List<string> args = ["lfs", "unlock", $"--remote={remote}"];
if (force)
args.Add("-f");
args.Add($"--id={id}");
return new SubCmd(_repo, args, null).Exec();
}
private readonly string _repo;

View file

@ -10,7 +10,7 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
TraitErrorAsOutput = true;
Args = $"merge --progress {source} {mode}";
Args = ["merge", "--progress", source, mode];
}
protected override void OnReadline(string line)

View file

@ -15,7 +15,7 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"mergetool \"{file}\"";
cmd.Args = ["mergetool", file];
return cmd.Exec();
}
@ -32,7 +32,13 @@ namespace SourceGit.Commands
return false;
}
cmd.Args = $"-c mergetool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.Cmd}\" -c mergetool.writeToTemp=true -c mergetool.keepBackup=false -c mergetool.trustExitCode=true mergetool --tool=sourcegit \"{file}\"";
cmd.Args = [
"-c", $"mergetool.sourcegit.cmd=\"{toolPath}\" {supported.Cmd}",
"-c", "mergetool.writeToTemp=true",
"-c", "mergetool.keepBackup=false",
"-c", "mergetool.trustExitCode=true",
"mergetool", "--tool=sourcegit", file
];
return cmd.Exec();
}
@ -45,7 +51,7 @@ namespace SourceGit.Commands
if (toolType == 0)
{
cmd.Args = $"difftool -g --no-prompt {option}";
cmd.Args = ["difftool", "-g", "--no-prompt", ..option.ToArgs()];
return cmd.Exec();
}
@ -62,7 +68,11 @@ namespace SourceGit.Commands
return false;
}
cmd.Args = $"-c difftool.sourcegit.cmd=\"\\\"{toolPath}\\\" {supported.DiffCmd}\" difftool --tool=sourcegit --no-prompt {option}";
cmd.Args = [
"-c", $"difftool.sourcegit.cmd=\"{toolPath}\" {supported.DiffCmd}",
"difftool", "--tool=sourcegit", "--no-prompt"
];
cmd.Args.AddRange(option.ToArgs());
return cmd.Exec();
}
}

View file

@ -11,14 +11,14 @@ namespace SourceGit.Commands
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "pull --verbose --progress --tags ";
Args = ["pull", "--verbose", "--progress", "--tags"];
if (useRebase)
Args += "--rebase ";
Args.Add("--rebase");
if (noTags)
Args += "--no-tags ";
Args.Add("--no-tags");
Args += $"{remote} {branch}";
Args.AddRange([remote, branch]);
}
protected override void OnReadline(string line)

View file

@ -12,18 +12,18 @@ namespace SourceGit.Commands
Context = repo;
TraitErrorAsOutput = true;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "push --progress --verbose ";
Args = ["push", "--progress", "--verbose"];
if (withTags)
Args += "--tags ";
Args.Add("--tags");
if (checkSubmodules)
Args += "--recurse-submodules=check ";
Args.Add("--recurse-submodules=check");
if (track)
Args += "-u ";
Args.Add("-u");
if (force)
Args += "--force-with-lease ";
Args.Add("--force-with-lease");
Args += $"{remote} {local}:{remoteBranch}";
Args.AddRange([remote, $"{local}:{remoteBranch}"]);
}
public Push(string repo, string remote, string tag, bool isDelete)
@ -31,12 +31,12 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
Args = "push ";
Args = ["push"];
if (isDelete)
Args += "--delete ";
Args.Add("--delete");
Args += $"{remote} refs/tags/{tag}";
Args.AddRange([remote, $"refs/tags/{tag}"]);
}
protected override void OnReadline(string line)

View file

@ -14,7 +14,10 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "branch -l --all -v --format=\"%(refname)$%(objectname)$%(HEAD)$%(upstream)$%(upstream:trackshort)\"";
Args = [
"branch", "-l", "--all", "-v",
"--format=%(refname)$%(objectname)$%(HEAD)$%(upstream)$%(upstream:trackshort)"
];
}
public List<Models.Branch> Result()

View file

@ -6,7 +6,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"show --no-show-signature --pretty=format:%B -s {sha}";
Args = ["show", "--no-show-signature", "--pretty=format:%B", "-s", sha];
}
public string Result()

View file

@ -1,47 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands
{
public class QueryCommits : Command
{
public QueryCommits(string repo, string limits, bool needFindHead = true)
public QueryCommits(string repo, IEnumerable<string> limits, bool needFindHead = true)
{
WorkingDirectory = repo;
Context = repo;
Args = "log --date-order --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s " + limits;
Args = [
"log", "--date-order", "--no-show-signature", "--decorate=full",
"--pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s",
..limits
];
_findFirstMerged = needFindHead;
}
public QueryCommits(string repo, string filter, Models.CommitSearchMethod method)
{
string search;
var search = new List<string>();
if (method == Models.CommitSearchMethod.ByUser)
{
search = $"-i --author=\"{filter}\" --committer=\"{filter}\"";
search = ["-i", $"--author={filter}", $"--commiter={filter}"];
}
else if (method == Models.CommitSearchMethod.ByFile)
{
search = $"-- \"{filter}\"";
search = ["--", filter];
}
else
{
var argsBuilder = new StringBuilder();
var words = filter.Split(new[] { ' ', '\t', '\r' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var word in words)
{
var escaped = word.Trim().Replace("\"", "\\\"", StringComparison.Ordinal);
argsBuilder.Append($"--grep=\"{escaped}\" ");
search.Add($"--grep={word.Trim()}");
}
argsBuilder.Append("--all-match -i");
search = argsBuilder.ToString();
search.AddRange(["--all-match", "-i"]);
}
WorkingDirectory = repo;
Context = repo;
Args = $"log -1000 --date-order --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s --branches --remotes " + search;
Args = [
"log", "-1000", "--date-order", "--no-show-signature", "--decorate=full",
"--pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s",
"--branches", "--remotes", ..search
];
_findFirstMerged = false;
}
@ -122,7 +126,7 @@ namespace SourceGit.Commands
private void MarkFirstMerged()
{
Args = $"log --since=\"{_commits[^1].CommitterTimeStr}\" --format=\"%H\"";
Args = ["log", $"--since={_commits[^1].CommitterTimeStr}", "--format=%H"];
var rs = ReadToEnd();
var shas = rs.StdOut.Split('\n', StringSplitOptions.RemoveEmptyEntries);

View file

@ -5,13 +5,17 @@ namespace SourceGit.Commands
{
public class QueryCommitsWithFullMessage : Command
{
public QueryCommitsWithFullMessage(string repo, string args)
public QueryCommitsWithFullMessage(string repo, IEnumerable<string> args)
{
_boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----";
WorkingDirectory = repo;
Context = repo;
Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}";
Args = [
"log", "--date-order", "--no-show-signature", "--decorate=full",
$"--pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}",
..args
];
}
public List<Models.CommitWithMessage> Result()

View file

@ -6,7 +6,7 @@
{
WorkingDirectory = repo;
Context = repo;
Args = "ls-tree -r --name-only HEAD";
Args = ["ls-tree", "-r", "--name-only", "HEAD"];
}
public string[] Result()

View file

@ -8,10 +8,8 @@ namespace SourceGit.Commands
{
public static Stream Run(string repo, string revision, string file)
{
var starter = new ProcessStartInfo();
var starter = new ProcessStartInfo(Native.OS.GitExecutable, ["show", $"{revision}:{file}"]);
starter.WorkingDirectory = repo;
starter.FileName = Native.OS.GitExecutable;
starter.Arguments = $"show {revision}:\"{file}\"";
starter.UseShellExecute = false;
starter.CreateNoWindow = true;
starter.WindowStyle = ProcessWindowStyle.Hidden;

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"ls-tree {revision} -l -- {file}";
Args = ["ls-tree", revision, "-l", "--", file];
}
public long Result()

View file

@ -7,7 +7,7 @@ namespace SourceGit.Commands
public QueryGitDir(string workDir)
{
WorkingDirectory = workDir;
Args = "rev-parse --git-dir";
Args = ["rev-parse", "--git-dir"];
RaiseError = false;
}

View file

@ -14,7 +14,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"status -u{UNTRACKED[includeUntracked ? 1 : 0]} --ignore-submodules=dirty --porcelain";
Args = ["status", $"-u{UNTRACKED[includeUntracked ? 1 : 0]}", "--ignore-submodules=dirty", "--porcelain"];
}
public List<Models.Change> Result()

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
RaiseError = false;
Args = $"for-each-ref --format=\"%(refname)\" --contains {commit}";
Args = ["for-each-ref", "--format=%(refname)", "--contains", commit];
}
public List<Models.Decorator> Result()

View file

@ -12,7 +12,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "remote -v";
Args = ["remote", "-v"];
}
public List<Models.Remote> Result()

View file

@ -5,7 +5,7 @@
public QueryRepositoryRootPath(string path)
{
WorkingDirectory = path;
Args = "rev-parse --show-toplevel";
Args = ["rev-parse", "--show-toplevel"];
}
}
}

View file

@ -12,10 +12,10 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"ls-tree {sha}";
Args = ["ls-tree", sha];
if (!string.IsNullOrEmpty(parentFolder))
Args += $" -- \"{parentFolder}\"";
Args.AddRange(["--", parentFolder]);
}
public List<Models.Object> Result()

View file

@ -8,7 +8,11 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"show --no-show-signature --decorate=full --pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s -s {sha}";
Args = [
"show", "--no-show-signature", "--decorate=full",
"--pretty=format:%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s",
"-s", sha
];
}
public Models.Commit Result()

View file

@ -15,7 +15,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "diff-index --cached -M HEAD^";
Args = ["diff-index", "--cached", "-M", "HEAD^"];
}
public List<Models.Change> Result()

View file

@ -11,7 +11,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"ls-files -s -- \"{file}\"";
Args = ["ls-files", "-s", "--", file];
}
public string Result()

View file

@ -12,7 +12,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"diff --name-status --pretty=format: {sha}^ {sha}";
Args = ["diff", "--name-status", "--pretty=format:", $"{sha}^", sha];
}
public List<Models.Change> Result()

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "stash list --pretty=format:%H%n%ct%n%gd%n%s";
Args = ["stash", "list", "--pretty=format:%H%n%ct%n%gd%n%s"];
}
public List<Models.Stash> Result()

View file

@ -17,7 +17,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "submodule status";
Args = ["submodule", "status"];
}
public List<Models.Submodule> Result()
@ -27,7 +27,7 @@ namespace SourceGit.Commands
if (!rs.IsSuccess)
return submodules;
var builder = new StringBuilder();
var extra = new List<string>();
var lines = rs.StdOut.Split('\n', System.StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
@ -35,7 +35,7 @@ namespace SourceGit.Commands
if (match.Success)
{
var path = match.Groups[1].Value;
builder.Append($"\"{path}\" ");
extra.Add(path);
submodules.Add(new Models.Submodule() { Path = path });
continue;
}
@ -44,14 +44,14 @@ namespace SourceGit.Commands
if (match.Success)
{
var path = match.Groups[1].Value;
builder.Append($"\"{path}\" ");
extra.Add(path);
submodules.Add(new Models.Submodule() { Path = path });
}
}
if (submodules.Count > 0)
{
Args = $"status -uno --porcelain -- {builder}";
Args = ["status", "-uno", "--porcelain", "--", ..extra];
rs = ReadToEnd();
if (!rs.IsSuccess)
return submodules;

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{
Context = repo;
WorkingDirectory = repo;
Args = "tag -l --sort=-creatordate --format=\"$%(refname)$%(objectname)$%(*objectname)\"";
Args = ["tag", "-l", "--sort=-creatordate", "--format=$%(refname)$%(objectname)$%(*objectname)"];
}
public List<Models.Tag> Result()

View file

@ -8,7 +8,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = $"rev-list --left-right {local}...{upstream}";
Args = ["rev-list", "--left-right", $"{local}...{upstream}"];
}
public Models.BranchTrackStatus Result()

View file

@ -6,10 +6,10 @@
{
WorkingDirectory = repo;
Context = repo;
Args = "rebase ";
Args = ["rebase"];
if (autoStash)
Args += "--autostash ";
Args += basedOn;
Args.Add("--autostash");
Args.Add(basedOn);
}
}
@ -20,7 +20,7 @@
WorkingDirectory = repo;
Context = repo;
Editor = EditorType.RebaseEditor;
Args = $"rebase -i --autosquash {basedOn}";
Args = ["rebase", "-i", "--autosquash", basedOn];
}
}
}

View file

@ -10,31 +10,31 @@
public bool Add(string name, string url)
{
Args = $"remote add {name} {url}";
Args = ["remote", "add", name, url];
return Exec();
}
public bool Delete(string name)
{
Args = $"remote remove {name}";
Args = ["remote", "remove", name];
return Exec();
}
public bool Rename(string name, string to)
{
Args = $"remote rename {name} {to}";
Args = ["remote", "rename", name, to];
return Exec();
}
public bool Prune(string name)
{
Args = $"remote prune {name}";
Args = ["remote", "prune", name];
return Exec();
}
public bool SetURL(string name, string url)
{
Args = $"remote set-url {name} {url}";
Args = ["remote", "set-url", name, url];
return Exec();
}
}

View file

@ -9,7 +9,7 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "reset";
Args = ["reset"];
}
public Reset(string repo, List<Models.Change> changes)
@ -17,22 +17,18 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
var builder = new StringBuilder();
builder.Append("reset --");
Args = ["reset", "--"];
foreach (var c in changes)
{
builder.Append(" \"");
builder.Append(c.Path);
builder.Append("\"");
Args.Add(c.Path);
}
Args = builder.ToString();
}
public Reset(string repo, string revision, string mode)
{
WorkingDirectory = repo;
Context = repo;
Args = $"reset {mode} {revision}";
Args = ["reset", mode, revision];
}
}
}

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands
{
@ -9,22 +8,15 @@ namespace SourceGit.Commands
{
WorkingDirectory = repo;
Context = repo;
Args = "restore . --source=HEAD --staged --worktree --recurse-submodules";
Args = ["restore", ".", "--source=HEAD", "--staged", "--worktree", "--recurse-submodules"];
}
public Restore(string repo, List<string> files, string extra)
public Restore(string repo, IEnumerable<string> files, IEnumerable<string> extra)
{
WorkingDirectory = repo;
Context = repo;
StringBuilder builder = new StringBuilder();
builder.Append("restore ");
if (!string.IsNullOrEmpty(extra))
builder.Append(extra).Append(" ");
builder.Append("--");
foreach (var f in files)
builder.Append(' ').Append('"').Append(f).Append('"');
Args = builder.ToString();
Args = ["restore", ..extra, "--", ..files];
}
}
}

View file

@ -6,9 +6,9 @@
{
WorkingDirectory = repo;
Context = repo;
Args = $"revert -m 1 {commit} --no-edit";
Args = ["revert", "-m", "1", commit, "--no-edit"];
if (!autoCommit)
Args += " --no-commit";
Args.Add("--no-commit");
}
}
}

View file

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Avalonia.Threading;
namespace SourceGit.Commands
@ -25,10 +24,11 @@ namespace SourceGit.Commands
private static bool ProcessSingleChange(string repo, Models.DiffOption opt, FileStream writer)
{
var starter = new ProcessStartInfo();
var starter = new ProcessStartInfo(
Native.OS.GitExecutable,
["diff", "--ignore-cr-at-eol", "--unified=4", ..opt.ToArgs()]
);
starter.WorkingDirectory = repo;
starter.FileName = Native.OS.GitExecutable;
starter.Arguments = $"diff --ignore-cr-at-eol --unified=4 {opt}";
starter.UseShellExecute = false;
starter.CreateNoWindow = true;
starter.WindowStyle = ProcessWindowStyle.Hidden;

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -14,24 +15,22 @@ namespace SourceGit.Commands
if (isLFSFiltered)
{
var tmpFile = saveTo + ".tmp";
if (ExecCmd(repo, $"show {revision}:\"{file}\"", tmpFile))
if (ExecCmd(repo, ["show", $"{revision}:{file}"], tmpFile))
{
ExecCmd(repo, $"lfs smudge", saveTo, tmpFile);
ExecCmd(repo, ["lfs", "smudge"], saveTo, tmpFile);
}
File.Delete(tmpFile);
}
else
{
ExecCmd(repo, $"show {revision}:\"{file}\"", saveTo);
ExecCmd(repo, ["show", $"{revision}:{file}"], saveTo);
}
}
private static bool ExecCmd(string repo, string args, string outputFile, string inputFile = null)
private static bool ExecCmd(string repo, IEnumerable<string> args, string outputFile, string inputFile = null)
{
var starter = new ProcessStartInfo();
var starter = new ProcessStartInfo(Native.OS.GitExecutable, args);
starter.WorkingDirectory = repo;
starter.FileName = Native.OS.GitExecutable;
starter.Arguments = args;
starter.UseShellExecute = false;
starter.CreateNoWindow = true;
starter.WindowStyle = ProcessWindowStyle.Hidden;

View file

@ -13,17 +13,17 @@ namespace SourceGit.Commands
public bool Push(string message)
{
Args = $"stash push -m \"{message}\"";
Args = ["stash", "push", "-m", message];
return Exec();
}
public bool Push(List<Models.Change> changes, string message)
{
var pathsBuilder = new StringBuilder();
Args = ["stash", "push", "-m", message, "--"];
var needAdd = new List<Models.Change>();
foreach (var c in changes)
{
pathsBuilder.Append($"\"{c.Path}\" ");
Args.Add(c.Path);
if (c.WorkTree == Models.ChangeState.Added || c.WorkTree == Models.ChangeState.Untracked)
{
@ -41,32 +41,30 @@ namespace SourceGit.Commands
needAdd.Clear();
}
var paths = pathsBuilder.ToString();
Args = $"stash push -m \"{message}\" -- {paths}";
return Exec();
}
public bool Apply(string name)
{
Args = $"stash apply -q {name}";
Args = ["stash", "apply", "-q", name];
return Exec();
}
public bool Pop(string name)
{
Args = $"stash pop -q {name}";
Args = ["stash", "pop", "-q", name];
return Exec();
}
public bool Drop(string name)
{
Args = $"stash drop -q {name}";
Args = ["stash", "drop", "-q", name];
return Exec();
}
public bool Clear()
{
Args = "stash clear";
Args = ["stash", "clear"];
return Exec();
}
}

View file

@ -10,7 +10,10 @@ namespace SourceGit.Commands
WorkingDirectory = repo;
Context = repo;
Args = $"log --date-order --branches --remotes --since=\"{_statistics.Since()}\" --pretty=format:\"%ct$%an\"";
Args = [
"log", "--date-order", "--branches", "--remotes",
$"--since={_statistics.Since()}", "--pretty=format:%ct$%an"
];
}
public Models.Statistics Result()

View file

@ -13,34 +13,34 @@ namespace SourceGit.Commands
public bool Add(string url, string relativePath, bool recursive, Action<string> outputHandler)
{
_outputHandler = outputHandler;
Args = $"submodule add {url} \"{relativePath}\"";
Args = ["submodule", "add", url, relativePath];
if (!Exec())
return false;
if (recursive)
{
Args = $"submodule update --init --recursive -- \"{relativePath}\"";
Args = ["submodule", "update", "--init", "--recursive", "--", relativePath];
return Exec();
}
else
{
Args = $"submodule update --init -- \"{relativePath}\"";
Args = ["submodule", "update", "--init", "--", relativePath];
return true;
}
}
public bool Update(string module, bool init, bool recursive, bool useRemote, Action<string> outputHandler)
{
Args = "submodule update";
Args = ["submodule", "update"];
if (init)
Args += " --init";
Args.Add("--init");
if (recursive)
Args += " --recursive";
Args.Add("--recursive");
if (useRemote)
Args += " --remote";
Args.Add("--remote");
if (!string.IsNullOrEmpty(module))
Args += $" -- \"{module}\"";
Args.AddRange(["--", module]);
_outputHandler = outputHandler;
return Exec();
@ -48,11 +48,11 @@ namespace SourceGit.Commands
public bool Delete(string relativePath)
{
Args = $"submodule deinit -f \"{relativePath}\"";
Args = ["submodule", "deinit", "-f", relativePath];
if (!Exec())
return false;
Args = $"rm -rf \"{relativePath}\"";
Args = ["rm", "-rf", relativePath];
return Exec();
}

View file

@ -10,27 +10,27 @@ namespace SourceGit.Commands
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag {name} {basedOn}";
cmd.Args = ["tag", name, basedOn];
return cmd.Exec();
}
public static bool Add(string repo, string name, string basedOn, string message, bool sign)
{
var param = sign ? "-s -a" : "-a";
IEnumerable<string> param = sign ? ["-s", "-a"] : ["-a"];
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag {param} {name} {basedOn} ";
cmd.Args = ["tag", ..param, name, basedOn];
if (!string.IsNullOrEmpty(message))
{
string tmp = Path.GetTempFileName();
File.WriteAllText(tmp, message);
cmd.Args += $"-F \"{tmp}\"";
cmd.Args.AddRange(["-F", tmp]);
}
else
{
cmd.Args += $"-m {name}";
cmd.Args.AddRange(["-m", name]);
}
return cmd.Exec();
@ -41,7 +41,7 @@ namespace SourceGit.Commands
var cmd = new Command();
cmd.WorkingDirectory = repo;
cmd.Context = repo;
cmd.Args = $"tag --delete {name}";
cmd.Args = ["tag", "--delete", name];
if (!cmd.Exec())
return false;

View file

@ -53,10 +53,11 @@ namespace SourceGit.Commands
public bool Exec()
{
var starter = new ProcessStartInfo();
var starter = new ProcessStartInfo(
Native.OS.GitExecutable,
["-c", "core.editor=true", "update-index", "--index-info"]
);
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;

View file

@ -4,7 +4,7 @@
{
public Version()
{
Args = "--version";
Args = ["--version"];
RaiseError = false;
}

View file

@ -13,7 +13,7 @@ namespace SourceGit.Commands
public List<Models.Worktree> List()
{
Args = "worktree list --porcelain";
Args = ["worktree", "list", "--porcelain"];
var rs = ReadToEnd();
var worktrees = new List<Models.Worktree>();
@ -56,23 +56,23 @@ namespace SourceGit.Commands
public bool Add(string fullpath, string name, bool createNew, string tracking, Action<string> outputHandler)
{
Args = "worktree add ";
Args = ["worktree", "add"];
if (!string.IsNullOrEmpty(tracking))
Args += "--track ";
Args.Add("--track");
if (!string.IsNullOrEmpty(name))
{
if (createNew)
Args += $"-b {name} ";
Args.AddRange(["-b", name]);
else
Args += $"-B {name} ";
Args.AddRange(["-B", name]);
}
Args += $"\"{fullpath}\" ";
Args.Add(fullpath);
if (!string.IsNullOrEmpty(tracking))
Args += tracking;
Args.Add(tracking);
_outputHandler = outputHandler;
return Exec();
@ -80,29 +80,29 @@ namespace SourceGit.Commands
public bool Prune(Action<string> outputHandler)
{
Args = "worktree prune -v";
Args = ["worktree", "prune", "-v"];
_outputHandler = outputHandler;
return Exec();
}
public bool Lock(string fullpath)
{
Args = $"worktree lock \"{fullpath}\"";
Args = ["worktree", "lock", fullpath];
return Exec();
}
public bool Unlock(string fullpath)
{
Args = $"worktree unlock \"{fullpath}\"";
Args = ["worktree", "unlock", fullpath];
return Exec();
}
public bool Remove(string fullpath, bool force, Action<string> outputHandler)
{
if (force)
Args = $"worktree remove -f \"{fullpath}\"";
Args = ["worktree", "remove", "-f", fullpath];
else
Args = $"worktree remove \"{fullpath}\"";
Args = ["worktree", "remove", fullpath];
_outputHandler = outputHandler;
return Exec();

View file

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Text;
namespace SourceGit.Models
{
@ -27,7 +26,7 @@ namespace SourceGit.Models
{
case ChangeState.Added:
case ChangeState.Untracked:
_extra = "--no-index";
_extra = ["--no-index"];
_path = change.Path;
_orgPath = "/dev/null";
break;
@ -40,9 +39,9 @@ namespace SourceGit.Models
else
{
if (change.DataForAmend != null)
_extra = "--cached HEAD^";
_extra = ["--cached", "HEAD^"];
else
_extra = "--cached";
_extra = ["--cached"];
_path = change.Path;
_orgPath = change.OriginalPath;
@ -94,27 +93,25 @@ namespace SourceGit.Models
/// Converts to diff command arguments.
/// </summary>
/// <returns></returns>
public override string ToString()
public List<string> ToArgs()
{
var builder = new StringBuilder();
if (!string.IsNullOrEmpty(_extra))
builder.Append($"{_extra} ");
foreach (var r in _revisions)
builder.Append($"{r} ");
var args = new List<string>();
args.AddRange(_extra);
args.AddRange(_revisions);
builder.Append("-- ");
args.Add("--");
if (!string.IsNullOrEmpty(_orgPath))
builder.Append($"\"{_orgPath}\" ");
builder.Append($"\"{_path}\"");
args.Add(_orgPath);
args.Add(_path);
return builder.ToString();
return args;
}
private readonly Change _workingCopyChange = null;
private readonly bool _isUnstaged = false;
private readonly string _path;
private readonly string _orgPath = string.Empty;
private readonly string _extra = string.Empty;
private readonly IEnumerable<string> _extra = [];
private readonly List<string> _revisions = new List<string>();
}
}

View file

@ -12,12 +12,14 @@ namespace SourceGit.Models
{
public class ExternalTool
{
public const string ARG_PLACEHOLDER = "$ARG";
public string Name { get; private set; }
public string Executable { get; private set; }
public string OpenCmdArgs { get; private set; }
public IEnumerable<string> OpenCmdArgs { get; private set; }
public Bitmap IconImage { get; private set; } = null;
public ExternalTool(string name, string icon, string executable, string openCmdArgs)
public ExternalTool(string name, string icon, string executable, IEnumerable<string> openCmdArgs)
{
Name = name;
Executable = executable;
@ -37,11 +39,15 @@ namespace SourceGit.Models
public void Open(string repo)
{
Process.Start(new ProcessStartInfo()
var args = new List<string>(OpenCmdArgs);
int i = args.IndexOf(ARG_PLACEHOLDER);
if (i != -1) {
args[i] = repo;
}
Process.Start(new ProcessStartInfo(Executable, args)
{
WorkingDirectory = repo,
FileName = Executable,
Arguments = string.Format(OpenCmdArgs, repo),
UseShellExecute = false,
});
}
@ -110,7 +116,7 @@ namespace SourceGit.Models
_customPaths = new ExternalToolPaths();
}
public void TryAdd(string name, string icon, string args, string key, Func<string> finder)
public void TryAdd(string name, string icon, IEnumerable<string> args, string key, Func<string> finder)
{
if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath))
{
@ -126,27 +132,27 @@ namespace SourceGit.Models
public void VSCode(Func<string> platformFinder)
{
TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder);
TryAdd("Visual Studio Code", "vscode", [ExternalTool.ARG_PLACEHOLDER], "VSCODE", platformFinder);
}
public void VSCodeInsiders(Func<string> platformFinder)
{
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", "\"{0}\"", "VSCODE_INSIDERS", platformFinder);
TryAdd("Visual Studio Code - Insiders", "vscode_insiders", [ExternalTool.ARG_PLACEHOLDER], "VSCODE_INSIDERS", platformFinder);
}
public void VSCodium(Func<string> platformFinder)
{
TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder);
TryAdd("VSCodium", "codium", [ExternalTool.ARG_PLACEHOLDER], "VSCODIUM", platformFinder);
}
public void Fleet(Func<string> platformFinder)
{
TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder);
TryAdd("Fleet", "fleet", [ExternalTool.ARG_PLACEHOLDER], "FLEET", platformFinder);
}
public void SublimeText(Func<string> platformFinder)
{
TryAdd("Sublime Text", "sublime_text", "\"{0}\"", "SUBLIME_TEXT", platformFinder);
TryAdd("Sublime Text", "sublime_text", [ExternalTool.ARG_PLACEHOLDER], "SUBLIME_TEXT", platformFinder);
}
public void FindJetBrainsFromToolbox(Func<string> platformFinder)
@ -166,7 +172,7 @@ namespace SourceGit.Models
$"{tool.DisplayName} {tool.DisplayVersion}",
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
Path.Combine(tool.InstallLocation, tool.LaunchCommand),
"\"{0}\""));
[ExternalTool.ARG_PLACEHOLDER]));
}
}
}

View file

@ -52,20 +52,20 @@ namespace SourceGit.Native
public void OpenBrowser(string url)
{
Process.Start("xdg-open", $"\"{url}\"");
Process.Start("xdg-open", [url]);
}
public void OpenInFileManager(string path, bool select)
{
if (Directory.Exists(path))
{
Process.Start("xdg-open", $"\"{path}\"");
Process.Start("xdg-open", [path]);
}
else
{
var dir = Path.GetDirectoryName(path);
if (Directory.Exists(dir))
Process.Start("xdg-open", $"\"{dir}\"");
Process.Start("xdg-open", [dir]);
}
}
@ -85,7 +85,7 @@ namespace SourceGit.Native
public void OpenWithDefaultEditor(string file)
{
var proc = Process.Start("xdg-open", $"\"{file}\"");
var proc = Process.Start("xdg-open", [file]);
if (proc != null)
{
proc.WaitForExit();

View file

@ -51,27 +51,27 @@ namespace SourceGit.Native
public void OpenBrowser(string url)
{
Process.Start("open", url);
Process.Start("open", [url]);
}
public void OpenInFileManager(string path, bool select)
{
if (Directory.Exists(path))
Process.Start("open", $"\"{path}\"");
Process.Start("open", [path]);
else if (File.Exists(path))
Process.Start("open", $"\"{path}\" -R");
Process.Start("open", [path]);
}
public void OpenTerminal(string workdir)
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var dir = string.IsNullOrEmpty(workdir) ? home : workdir;
Process.Start("open", $"-a {OS.ShellOrTerminal} \"{dir}\"");
Process.Start("open", ["-a", OS.ShellOrTerminal, dir]);
}
public void OpenWithDefaultEditor(string file)
{
Process.Start("open", $"\"{file}\"");
Process.Start("open", [file]);
}
}
}

View file

@ -151,7 +151,7 @@ namespace SourceGit.Native
public void OpenBrowser(string url)
{
var info = new ProcessStartInfo("cmd", $"/c start {url}");
var info = new ProcessStartInfo("cmd", ["/c", "start", url]);
info.CreateNoWindow = true;
Process.Start(info);
}
@ -201,7 +201,7 @@ namespace SourceGit.Native
public void OpenWithDefaultEditor(string file)
{
var info = new FileInfo(file);
var start = new ProcessStartInfo("cmd", $"/c start \"\" \"{info.FullName}\"");
var start = new ProcessStartInfo("cmd", ["/c", "start", "", info.FullName]);
start.CreateNoWindow = true;
Process.Start(start);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading.Tasks;
@ -47,7 +48,7 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _local, value);
}
public string ExtraArgs
public IEnumerable<string> ExtraArgs
{
get => _extraArgs;
set => SetProperty(ref _extraArgs, value);
@ -154,6 +155,6 @@ namespace SourceGit.ViewModels
private string _sshKey = string.Empty;
private string _parentFolder = Preference.Instance.GitDefaultCloneDir;
private string _local = string.Empty;
private string _extraArgs = string.Empty;
private IEnumerable<string> _extraArgs = [];
}
}

View file

@ -63,7 +63,7 @@ namespace SourceGit.ViewModels
Task.Run(() =>
{
var commits = new Commands.QueryCommits(_repo.FullPath, $"-n 10000 -- \"{file}\"", false).Result();
var commits = new Commands.QueryCommits(_repo.FullPath, ["-n", "10000", "--", file], false).Result();
Dispatcher.UIThread.Invoke(() =>
{
IsLoading = false;

View file

@ -28,7 +28,7 @@ namespace SourceGit.ViewModels
{
WorkingDirectory = Repository,
Context = Repository,
Args = $"{Cmd} --abort",
Args = [Cmd, "--abort"],
}.Exec();
}
@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
WorkingDirectory = Repository,
Context = Repository,
Editor = Commands.Command.EditorType.None,
Args = $"{Cmd} --continue",
Args = [Cmd, "--continue"],
}.Exec();
}
}
@ -63,7 +63,7 @@ namespace SourceGit.ViewModels
WorkingDirectory = Repository,
Context = Repository,
Editor = Commands.Command.EditorType.RebaseEditor,
Args = $"rebase --continue",
Args = ["rebase", "--continue"],
}.Exec();
if (succ)

View file

@ -118,7 +118,7 @@ namespace SourceGit.ViewModels
Task.Run(() =>
{
var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}...HEAD").Result();
var commits = new Commands.QueryCommitsWithFullMessage(repoPath, [$"{on.SHA}...HEAD"]).Result();
var list = new List<InteractiveRebaseItem>();
foreach (var c in commits)

View file

@ -765,9 +765,9 @@ namespace SourceGit.ViewModels
{
Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true);
var limits = $"-{Preference.Instance.MaxHistoryCommits} ";
List<string> limits = [$"-{Preference.Instance.MaxHistoryCommits}"];
if (_enableFirstParentInHistories)
limits += "--first-parent ";
limits.Add("--first-parent");
var validFilters = new List<string>();
foreach (var filter in _settings.Filters)
@ -786,7 +786,7 @@ namespace SourceGit.ViewModels
if (validFilters.Count > 0)
{
limits += string.Join(" ", validFilters);
limits.AddRange(validFilters);
if (_settings.Filters.Count != validFilters.Count)
{
@ -799,7 +799,7 @@ namespace SourceGit.ViewModels
}
else
{
limits += "--exclude=refs/stash --all";
limits.AddRange(["--exclude=refs/stash", "-all"]);
}
var commits = new Commands.QueryCommits(_fullpath, limits).Result();

View file

@ -1211,7 +1211,7 @@ namespace SourceGit.Views
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, chunk.IsOldSide, tmpFile);
}
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index").Exec();
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", ["--cache", "--index"]).Exec();
File.Delete(tmpFile);
}
@ -1265,7 +1265,7 @@ namespace SourceGit.Views
else
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--cache --index --reverse").Exec();
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", ["--cache", "--index", "--reverse"]).Exec();
File.Delete(tmpFile);
}
@ -1323,7 +1323,7 @@ namespace SourceGit.Views
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, chunk.IsOldSide, tmpFile);
}
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", "--reverse").Exec();
new Commands.Apply(diff.Repo, tmpFile, true, "nowarn", ["--reverse"]).Exec();
File.Delete(tmpFile);
}