From 77fa7169dfefbef923b24945dfdc825db274e584 Mon Sep 17 00:00:00 2001 From: Aikawa Yataro Date: Sat, 14 Sep 2024 06:10:42 +0000 Subject: [PATCH] enhance: use ArgumentList instead of manual escaping --- src/Commands/Add.cs | 13 ++----- src/Commands/Apply.cs | 17 +++++---- src/Commands/Archive.cs | 2 +- src/Commands/AssumeUnchanged.cs | 4 +- src/Commands/Blame.cs | 2 +- src/Commands/Branch.cs | 12 +++--- src/Commands/Checkout.cs | 38 ++++--------------- src/Commands/CherryPick.cs | 2 +- src/Commands/Clean.cs | 12 +----- src/Commands/Clone.cs | 12 +++--- src/Commands/Command.cs | 33 ++++++++++------ src/Commands/Commit.cs | 6 +-- src/Commands/CompareRevisions.cs | 2 +- src/Commands/Config.cs | 14 +++---- .../CountLocalChangesWithoutUntracked.cs | 2 +- src/Commands/Diff.cs | 2 +- src/Commands/Discard.cs | 2 +- src/Commands/Fetch.cs | 12 +++--- src/Commands/FormatPatch.cs | 2 +- src/Commands/GC.cs | 2 +- src/Commands/GenerateCommitMessage.cs | 2 +- src/Commands/GitFlow.cs | 6 +-- src/Commands/Init.cs | 2 +- src/Commands/IsBinary.cs | 2 +- src/Commands/IsConflictResolved.cs | 2 +- src/Commands/IsLFSFiltered.cs | 4 +- src/Commands/LFS.cs | 38 ++++++++++++------- src/Commands/Merge.cs | 2 +- src/Commands/MergeTool.cs | 18 +++++++-- src/Commands/Pull.cs | 8 ++-- src/Commands/Push.cs | 18 ++++----- src/Commands/QueryBranches.cs | 5 ++- src/Commands/QueryCommitFullMessage.cs | 2 +- src/Commands/QueryCommits.cs | 30 ++++++++------- src/Commands/QueryCommitsWithFullMessage.cs | 8 +++- src/Commands/QueryCurrentRevisionFiles.cs | 2 +- src/Commands/QueryFileContent.cs | 4 +- src/Commands/QueryFileSize.cs | 2 +- src/Commands/QueryGitDir.cs | 2 +- src/Commands/QueryLocalChanges.cs | 2 +- src/Commands/QueryRefsContainsCommit.cs | 2 +- src/Commands/QueryRemotes.cs | 2 +- src/Commands/QueryRepositoryRootPath.cs | 2 +- src/Commands/QueryRevisionObjects.cs | 4 +- src/Commands/QuerySingleCommit.cs | 6 ++- src/Commands/QueryStagedChangesWithAmend.cs | 2 +- src/Commands/QueryStagedFileBlobGuid.cs | 2 +- src/Commands/QueryStashChanges.cs | 2 +- src/Commands/QueryStashes.cs | 2 +- src/Commands/QuerySubmodules.cs | 10 ++--- src/Commands/QueryTags.cs | 2 +- src/Commands/QueryTrackStatus.cs | 2 +- src/Commands/Rebase.cs | 8 ++-- src/Commands/Remote.cs | 10 ++--- src/Commands/Reset.cs | 12 ++---- src/Commands/Restore.cs | 14 ++----- src/Commands/Revert.cs | 4 +- src/Commands/SaveChangesAsPatch.cs | 8 ++-- src/Commands/SaveRevisionFile.cs | 13 +++---- src/Commands/Stash.cs | 16 ++++---- src/Commands/Statistics.cs | 5 ++- src/Commands/Submodule.cs | 20 +++++----- src/Commands/Tag.cs | 12 +++--- src/Commands/UnstageChangesForAmend.cs | 7 ++-- src/Commands/Version.cs | 2 +- src/Commands/Worktree.cs | 24 ++++++------ src/Models/DiffOption.cs | 27 ++++++------- src/Models/ExternalTool.cs | 30 +++++++++------ src/Native/Linux.cs | 8 ++-- src/Native/MacOS.cs | 10 ++--- src/Native/Windows.cs | 4 +- src/ViewModels/Clone.cs | 5 ++- src/ViewModels/FileHistories.cs | 2 +- src/ViewModels/InProgressContexts.cs | 6 +-- src/ViewModels/InteractiveRebase.cs | 2 +- src/ViewModels/Repository.cs | 8 ++-- src/Views/TextDiffView.axaml.cs | 6 +-- 77 files changed, 325 insertions(+), 326 deletions(-) diff --git a/src/Commands/Add.cs b/src/Commands/Add.cs index 2251c892..be0d410d 100644 --- a/src/Commands/Add.cs +++ b/src/Commands/Add.cs @@ -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); } } } diff --git a/src/Commands/Apply.cs b/src/Commands/Apply.cs index d1c9ffbc..1a6d7746 100644 --- a/src/Commands/Apply.cs +++ b/src/Commands/Apply.cs @@ -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 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); } } } diff --git a/src/Commands/Archive.cs b/src/Commands/Archive.cs index d4f6241c..a263cf99 100644 --- a/src/Commands/Archive.cs +++ b/src/Commands/Archive.cs @@ -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; } diff --git a/src/Commands/AssumeUnchanged.cs b/src/Commands/AssumeUnchanged.cs index 1898122a..262a48fd 100644 --- a/src/Commands/AssumeUnchanged.cs +++ b/src/Commands/AssumeUnchanged.cs @@ -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]; } } diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs index de221b07..bcc174d6 100644 --- a/src/Commands/Blame.cs +++ b/src/Commands/Blame.cs @@ -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; diff --git a/src/Commands/Branch.cs b/src/Commands/Branch.cs index 890b54ee..e6f2bd3b 100644 --- a/src/Commands/Branch.cs +++ b/src/Commands/Branch.cs @@ -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(); } } diff --git a/src/Commands/Checkout.cs b/src/Commands/Checkout.cs index 25f93e89..1ca28eb3 100644 --- a/src/Commands/Checkout.cs +++ b/src/Commands/Checkout.cs @@ -14,7 +14,7 @@ namespace SourceGit.Commands public bool Branch(string branch, Action 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 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 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 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 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 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(); } diff --git a/src/Commands/CherryPick.cs b/src/Commands/CherryPick.cs index 95b56655..1bd6ce3a 100644 --- a/src/Commands/CherryPick.cs +++ b/src/Commands/CherryPick.cs @@ -7,7 +7,7 @@ var mode = noCommit ? "-n" : "--ff"; WorkingDirectory = repo; Context = repo; - Args = $"cherry-pick {mode} {commits}"; + Args = ["cherry-pick", mode, commits]; } } } diff --git a/src/Commands/Clean.cs b/src/Commands/Clean.cs index 900a7f93..abd8e7e6 100644 --- a/src/Commands/Clean.cs +++ b/src/Commands/Clean.cs @@ -9,23 +9,15 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = "clean -qfd"; + Args = ["clean", "-qfd"]; } public Clean(string repo, List 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(); } } } diff --git a/src/Commands/Clone.cs b/src/Commands/Clone.cs index 683b8846..24ef30ec 100644 --- a/src/Commands/Clone.cs +++ b/src/Commands/Clone.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace SourceGit.Commands { @@ -6,21 +7,20 @@ namespace SourceGit.Commands { private readonly Action _notifyProgress; - public Clone(string ctx, string path, string url, string localName, string sshKey, string extraArgs, Action ouputHandler) + public Clone(string ctx, string path, string url, string localName, string sshKey, IEnumerable extraArgs, Action 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; } diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index b347dc37..3c006af3 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -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 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 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 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; diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs index b629f82d..95183e0c 100644 --- a/src/Commands/Commit.cs +++ b/src/Commands/Commit.cs @@ -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"); } } } diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs index c4674c8e..dcc7e72b 100644 --- a/src/Commands/CompareRevisions.cs +++ b/src/Commands/CompareRevisions.cs @@ -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 Result() diff --git a/src/Commands/Config.cs b/src/Commands/Config.cs index 53416c86..eb1be71f 100644 --- a/src/Commands/Config.cs +++ b/src/Commands/Config.cs @@ -15,9 +15,9 @@ namespace SourceGit.Commands public Dictionary 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(); @@ -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(); diff --git a/src/Commands/CountLocalChangesWithoutUntracked.cs b/src/Commands/CountLocalChangesWithoutUntracked.cs index afb62840..42bf4ca1 100644 --- a/src/Commands/CountLocalChangesWithoutUntracked.cs +++ b/src/Commands/CountLocalChangesWithoutUntracked.cs @@ -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() diff --git a/src/Commands/Diff.cs b/src/Commands/Diff.cs index 0f2ee626..9b438261 100644 --- a/src/Commands/Diff.cs +++ b/src/Commands/Diff.cs @@ -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() diff --git a/src/Commands/Discard.cs b/src/Commands/Discard.cs index 63fcaa8e..854eca0e 100644 --- a/src/Commands/Discard.cs +++ b/src/Commands/Discard.cs @@ -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(); } } } diff --git a/src/Commands/Fetch.cs b/src/Commands/Fetch.cs index 07622821..25b70dc9 100644 --- a/src/Commands/Fetch.cs +++ b/src/Commands/Fetch.cs @@ -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) diff --git a/src/Commands/FormatPatch.cs b/src/Commands/FormatPatch.cs index 2c7359c0..b3bf30e8 100644 --- a/src/Commands/FormatPatch.cs +++ b/src/Commands/FormatPatch.cs @@ -6,7 +6,7 @@ { WorkingDirectory = repo; Context = repo; - Args = $"format-patch {commit} -1 -o \"{saveTo}\""; + Args = ["format-patch", commit, "-1", "-o", saveTo]; } } } diff --git a/src/Commands/GC.cs b/src/Commands/GC.cs index 61735f53..b2fc4e62 100644 --- a/src/Commands/GC.cs +++ b/src/Commands/GC.cs @@ -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) diff --git a/src/Commands/GenerateCommitMessage.cs b/src/Commands/GenerateCommitMessage.cs index e71fb0b9..f094598a 100644 --- a/src/Commands/GenerateCommitMessage.cs +++ b/src/Commands/GenerateCommitMessage.cs @@ -16,7 +16,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"diff --diff-algorithm=minimal {opt}"; + Args = ["diff", "--diff-algorithm=minimal", ..opt.ToArgs()]; } } diff --git a/src/Commands/GitFlow.cs b/src/Commands/GitFlow.cs index 5e05ed83..8d5c91f5 100644 --- a/src/Commands/GitFlow.cs +++ b/src/Commands/GitFlow.cs @@ -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(); } diff --git a/src/Commands/Init.cs b/src/Commands/Init.cs index c44486da..a867f678 100644 --- a/src/Commands/Init.cs +++ b/src/Commands/Init.cs @@ -6,7 +6,7 @@ { Context = ctx; WorkingDirectory = dir; - Args = "init -q"; + Args = ["init", "-q"]; } } } diff --git a/src/Commands/IsBinary.cs b/src/Commands/IsBinary.cs index de59b5a4..2f609a4f 100644 --- a/src/Commands/IsBinary.cs +++ b/src/Commands/IsBinary.cs @@ -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; } diff --git a/src/Commands/IsConflictResolved.cs b/src/Commands/IsConflictResolved.cs index 13bc12ac..f70b09df 100644 --- a/src/Commands/IsConflictResolved.cs +++ b/src/Commands/IsConflictResolved.cs @@ -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()]; } } } diff --git a/src/Commands/IsLFSFiltered.cs b/src/Commands/IsLFSFiltered.cs index 2a7234bb..e338bbf0 100644 --- a/src/Commands/IsLFSFiltered.cs +++ b/src/Commands/IsLFSFiltered.cs @@ -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; } diff --git a/src/Commands/LFS.cs b/src/Commands/LFS.cs index c9ab7b41..764f7a4e 100644 --- a/src/Commands/LFS.cs +++ b/src/Commands/LFS.cs @@ -12,11 +12,11 @@ namespace SourceGit.Commands class SubCmd : Command { - public SubCmd(string repo, string args, Action onProgress) + public SubCmd(string repo, IEnumerable args, Action onProgress) { WorkingDirectory = repo; Context = repo; - Args = args; + Args = new List(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 args = ["lfs", "track"]; + if (isFilenameMode) + args.Add("--filename"); + args.Add(pattern); + return new SubCmd(_repo, args, null).Exec(); } public void Fetch(string remote, Action outputHandler) { - new SubCmd(_repo, $"lfs fetch {remote}", outputHandler).Exec(); + new SubCmd(_repo, ["lfs", "fetch", remote], outputHandler).Exec(); } public void Pull(string remote, Action outputHandler) { - new SubCmd(_repo, $"lfs pull {remote}", outputHandler).Exec(); + new SubCmd(_repo, ["lfs", "pull", remote], outputHandler).Exec(); } public void Push(string remote, Action outputHandler) { - new SubCmd(_repo, $"lfs push {remote}", outputHandler).Exec(); + new SubCmd(_repo, ["lfs", "push", remote], outputHandler).Exec(); } public void Prune(Action outputHandler) { - new SubCmd(_repo, "lfs prune", outputHandler).Exec(); + new SubCmd(_repo, ["lfs", "prune"], outputHandler).Exec(); } public List Locks(string remote) { var locks = new List(); - 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 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 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; diff --git a/src/Commands/Merge.cs b/src/Commands/Merge.cs index cf2e285f..450e25b2 100644 --- a/src/Commands/Merge.cs +++ b/src/Commands/Merge.cs @@ -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) diff --git a/src/Commands/MergeTool.cs b/src/Commands/MergeTool.cs index d3478d59..24e49dcb 100644 --- a/src/Commands/MergeTool.cs +++ b/src/Commands/MergeTool.cs @@ -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(); } } diff --git a/src/Commands/Pull.cs b/src/Commands/Pull.cs index a4efa4b6..06d586a9 100644 --- a/src/Commands/Pull.cs +++ b/src/Commands/Pull.cs @@ -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) diff --git a/src/Commands/Push.cs b/src/Commands/Push.cs index 69b859ab..17e22199 100644 --- a/src/Commands/Push.cs +++ b/src/Commands/Push.cs @@ -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) diff --git a/src/Commands/QueryBranches.cs b/src/Commands/QueryBranches.cs index 5f9d31a8..08f86357 100644 --- a/src/Commands/QueryBranches.cs +++ b/src/Commands/QueryBranches.cs @@ -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 Result() diff --git a/src/Commands/QueryCommitFullMessage.cs b/src/Commands/QueryCommitFullMessage.cs index c8f1867d..43431382 100644 --- a/src/Commands/QueryCommitFullMessage.cs +++ b/src/Commands/QueryCommitFullMessage.cs @@ -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() diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 8a48eff3..700d827f 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -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 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(); 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); diff --git a/src/Commands/QueryCommitsWithFullMessage.cs b/src/Commands/QueryCommitsWithFullMessage.cs index 36e22b42..a0fb8d40 100644 --- a/src/Commands/QueryCommitsWithFullMessage.cs +++ b/src/Commands/QueryCommitsWithFullMessage.cs @@ -5,13 +5,17 @@ namespace SourceGit.Commands { public class QueryCommitsWithFullMessage : Command { - public QueryCommitsWithFullMessage(string repo, string args) + public QueryCommitsWithFullMessage(string repo, IEnumerable 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 Result() diff --git a/src/Commands/QueryCurrentRevisionFiles.cs b/src/Commands/QueryCurrentRevisionFiles.cs index 217ea20e..ee442b4a 100644 --- a/src/Commands/QueryCurrentRevisionFiles.cs +++ b/src/Commands/QueryCurrentRevisionFiles.cs @@ -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() diff --git a/src/Commands/QueryFileContent.cs b/src/Commands/QueryFileContent.cs index f887859c..5c3c209a 100644 --- a/src/Commands/QueryFileContent.cs +++ b/src/Commands/QueryFileContent.cs @@ -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; diff --git a/src/Commands/QueryFileSize.cs b/src/Commands/QueryFileSize.cs index c36984dd..14ace06f 100644 --- a/src/Commands/QueryFileSize.cs +++ b/src/Commands/QueryFileSize.cs @@ -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() diff --git a/src/Commands/QueryGitDir.cs b/src/Commands/QueryGitDir.cs index e3a94baf..f4986dfe 100644 --- a/src/Commands/QueryGitDir.cs +++ b/src/Commands/QueryGitDir.cs @@ -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; } diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs index bdef9bf8..88caf856 100644 --- a/src/Commands/QueryLocalChanges.cs +++ b/src/Commands/QueryLocalChanges.cs @@ -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 Result() diff --git a/src/Commands/QueryRefsContainsCommit.cs b/src/Commands/QueryRefsContainsCommit.cs index e3b73ccc..a54d6eb6 100644 --- a/src/Commands/QueryRefsContainsCommit.cs +++ b/src/Commands/QueryRefsContainsCommit.cs @@ -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 Result() diff --git a/src/Commands/QueryRemotes.cs b/src/Commands/QueryRemotes.cs index b5b41b4a..c2203f12 100644 --- a/src/Commands/QueryRemotes.cs +++ b/src/Commands/QueryRemotes.cs @@ -12,7 +12,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = "remote -v"; + Args = ["remote", "-v"]; } public List Result() diff --git a/src/Commands/QueryRepositoryRootPath.cs b/src/Commands/QueryRepositoryRootPath.cs index 016621c8..29cf2bd3 100644 --- a/src/Commands/QueryRepositoryRootPath.cs +++ b/src/Commands/QueryRepositoryRootPath.cs @@ -5,7 +5,7 @@ public QueryRepositoryRootPath(string path) { WorkingDirectory = path; - Args = "rev-parse --show-toplevel"; + Args = ["rev-parse", "--show-toplevel"]; } } } diff --git a/src/Commands/QueryRevisionObjects.cs b/src/Commands/QueryRevisionObjects.cs index bcad9129..45b40c98 100644 --- a/src/Commands/QueryRevisionObjects.cs +++ b/src/Commands/QueryRevisionObjects.cs @@ -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 Result() diff --git a/src/Commands/QuerySingleCommit.cs b/src/Commands/QuerySingleCommit.cs index 1e1c9ea4..4a87728b 100644 --- a/src/Commands/QuerySingleCommit.cs +++ b/src/Commands/QuerySingleCommit.cs @@ -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() diff --git a/src/Commands/QueryStagedChangesWithAmend.cs b/src/Commands/QueryStagedChangesWithAmend.cs index f5c9659f..5b24eb1e 100644 --- a/src/Commands/QueryStagedChangesWithAmend.cs +++ b/src/Commands/QueryStagedChangesWithAmend.cs @@ -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 Result() diff --git a/src/Commands/QueryStagedFileBlobGuid.cs b/src/Commands/QueryStagedFileBlobGuid.cs index 3f52a5f2..8848ad9a 100644 --- a/src/Commands/QueryStagedFileBlobGuid.cs +++ b/src/Commands/QueryStagedFileBlobGuid.cs @@ -11,7 +11,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = $"ls-files -s -- \"{file}\""; + Args = ["ls-files", "-s", "--", file]; } public string Result() diff --git a/src/Commands/QueryStashChanges.cs b/src/Commands/QueryStashChanges.cs index 3b8d2db6..4ea3cb68 100644 --- a/src/Commands/QueryStashChanges.cs +++ b/src/Commands/QueryStashChanges.cs @@ -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 Result() diff --git a/src/Commands/QueryStashes.cs b/src/Commands/QueryStashes.cs index 6d089f8e..e9818798 100644 --- a/src/Commands/QueryStashes.cs +++ b/src/Commands/QueryStashes.cs @@ -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 Result() diff --git a/src/Commands/QuerySubmodules.cs b/src/Commands/QuerySubmodules.cs index 5fd6e3d5..f7762bc4 100644 --- a/src/Commands/QuerySubmodules.cs +++ b/src/Commands/QuerySubmodules.cs @@ -17,7 +17,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = "submodule status"; + Args = ["submodule", "status"]; } public List Result() @@ -27,7 +27,7 @@ namespace SourceGit.Commands if (!rs.IsSuccess) return submodules; - var builder = new StringBuilder(); + var extra = new List(); 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; diff --git a/src/Commands/QueryTags.cs b/src/Commands/QueryTags.cs index 2abbe277..21350f28 100644 --- a/src/Commands/QueryTags.cs +++ b/src/Commands/QueryTags.cs @@ -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 Result() diff --git a/src/Commands/QueryTrackStatus.cs b/src/Commands/QueryTrackStatus.cs index 0bf9746f..cf80bc95 100644 --- a/src/Commands/QueryTrackStatus.cs +++ b/src/Commands/QueryTrackStatus.cs @@ -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() diff --git a/src/Commands/Rebase.cs b/src/Commands/Rebase.cs index 2ec50f3c..c62bbcc7 100644 --- a/src/Commands/Rebase.cs +++ b/src/Commands/Rebase.cs @@ -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]; } } } diff --git a/src/Commands/Remote.cs b/src/Commands/Remote.cs index 46aa37e3..c78d982c 100644 --- a/src/Commands/Remote.cs +++ b/src/Commands/Remote.cs @@ -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(); } } diff --git a/src/Commands/Reset.cs b/src/Commands/Reset.cs index da272135..aaee31f3 100644 --- a/src/Commands/Reset.cs +++ b/src/Commands/Reset.cs @@ -9,7 +9,7 @@ namespace SourceGit.Commands { WorkingDirectory = repo; Context = repo; - Args = "reset"; + Args = ["reset"]; } public Reset(string repo, List 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]; } } } diff --git a/src/Commands/Restore.cs b/src/Commands/Restore.cs index 7a363543..0acb0691 100644 --- a/src/Commands/Restore.cs +++ b/src/Commands/Restore.cs @@ -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 files, string extra) + public Restore(string repo, IEnumerable files, IEnumerable 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]; } } } diff --git a/src/Commands/Revert.cs b/src/Commands/Revert.cs index 2e7afd11..1b215386 100644 --- a/src/Commands/Revert.cs +++ b/src/Commands/Revert.cs @@ -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"); } } } diff --git a/src/Commands/SaveChangesAsPatch.cs b/src/Commands/SaveChangesAsPatch.cs index 409127ba..acf64f70 100644 --- a/src/Commands/SaveChangesAsPatch.cs +++ b/src/Commands/SaveChangesAsPatch.cs @@ -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; diff --git a/src/Commands/SaveRevisionFile.cs b/src/Commands/SaveRevisionFile.cs index 99e89093..605e2b40 100644 --- a/src/Commands/SaveRevisionFile.cs +++ b/src/Commands/SaveRevisionFile.cs @@ -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 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; diff --git a/src/Commands/Stash.cs b/src/Commands/Stash.cs index cf7d84d1..6b3c9fa3 100644 --- a/src/Commands/Stash.cs +++ b/src/Commands/Stash.cs @@ -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 changes, string message) { - var pathsBuilder = new StringBuilder(); + Args = ["stash", "push", "-m", message, "--"]; var needAdd = new List(); 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(); } } diff --git a/src/Commands/Statistics.cs b/src/Commands/Statistics.cs index 6b2296ca..30247681 100644 --- a/src/Commands/Statistics.cs +++ b/src/Commands/Statistics.cs @@ -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() diff --git a/src/Commands/Submodule.cs b/src/Commands/Submodule.cs index 9a273703..a17d8310 100644 --- a/src/Commands/Submodule.cs +++ b/src/Commands/Submodule.cs @@ -13,34 +13,34 @@ namespace SourceGit.Commands public bool Add(string url, string relativePath, bool recursive, Action 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 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(); } diff --git a/src/Commands/Tag.cs b/src/Commands/Tag.cs index 5fe57f94..d46af190 100644 --- a/src/Commands/Tag.cs +++ b/src/Commands/Tag.cs @@ -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 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; diff --git a/src/Commands/UnstageChangesForAmend.cs b/src/Commands/UnstageChangesForAmend.cs index c930f136..662d6122 100644 --- a/src/Commands/UnstageChangesForAmend.cs +++ b/src/Commands/UnstageChangesForAmend.cs @@ -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; diff --git a/src/Commands/Version.cs b/src/Commands/Version.cs index ed7c6892..5a662868 100644 --- a/src/Commands/Version.cs +++ b/src/Commands/Version.cs @@ -4,7 +4,7 @@ { public Version() { - Args = "--version"; + Args = ["--version"]; RaiseError = false; } diff --git a/src/Commands/Worktree.cs b/src/Commands/Worktree.cs index 7516b1e3..835462bf 100644 --- a/src/Commands/Worktree.cs +++ b/src/Commands/Worktree.cs @@ -13,7 +13,7 @@ namespace SourceGit.Commands public List List() { - Args = "worktree list --porcelain"; + Args = ["worktree", "list", "--porcelain"]; var rs = ReadToEnd(); var worktrees = new List(); @@ -56,23 +56,23 @@ namespace SourceGit.Commands public bool Add(string fullpath, string name, bool createNew, string tracking, Action 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 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 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(); diff --git a/src/Models/DiffOption.cs b/src/Models/DiffOption.cs index 98387e7f..c5457020 100644 --- a/src/Models/DiffOption.cs +++ b/src/Models/DiffOption.cs @@ -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. /// /// - public override string ToString() + public List ToArgs() { - var builder = new StringBuilder(); - if (!string.IsNullOrEmpty(_extra)) - builder.Append($"{_extra} "); - foreach (var r in _revisions) - builder.Append($"{r} "); + var args = new List(); + 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 _extra = []; private readonly List _revisions = new List(); } } diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs index 45682dab..5d53b340 100644 --- a/src/Models/ExternalTool.cs +++ b/src/Models/ExternalTool.cs @@ -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 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 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(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 finder) + public void TryAdd(string name, string icon, IEnumerable args, string key, Func finder) { if (_customPaths.Tools.TryGetValue(key, out var customPath) && File.Exists(customPath)) { @@ -126,27 +132,27 @@ namespace SourceGit.Models public void VSCode(Func platformFinder) { - TryAdd("Visual Studio Code", "vscode", "\"{0}\"", "VSCODE", platformFinder); + TryAdd("Visual Studio Code", "vscode", [ExternalTool.ARG_PLACEHOLDER], "VSCODE", platformFinder); } public void VSCodeInsiders(Func 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 platformFinder) { - TryAdd("VSCodium", "codium", "\"{0}\"", "VSCODIUM", platformFinder); + TryAdd("VSCodium", "codium", [ExternalTool.ARG_PLACEHOLDER], "VSCODIUM", platformFinder); } public void Fleet(Func platformFinder) { - TryAdd("Fleet", "fleet", "\"{0}\"", "FLEET", platformFinder); + TryAdd("Fleet", "fleet", [ExternalTool.ARG_PLACEHOLDER], "FLEET", platformFinder); } public void SublimeText(Func 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 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])); } } } diff --git a/src/Native/Linux.cs b/src/Native/Linux.cs index 9537a39a..fe1e82d1 100644 --- a/src/Native/Linux.cs +++ b/src/Native/Linux.cs @@ -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(); diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 0ad608b2..e9beee9e 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -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]); } } } diff --git a/src/Native/Windows.cs b/src/Native/Windows.cs index 19362d0c..59399198 100644 --- a/src/Native/Windows.cs +++ b/src/Native/Windows.cs @@ -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); } diff --git a/src/ViewModels/Clone.cs b/src/ViewModels/Clone.cs index cc253d3c..32ec50a1 100644 --- a/src/ViewModels/Clone.cs +++ b/src/ViewModels/Clone.cs @@ -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 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 _extraArgs = []; } } diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 398293a3..7a9bf766 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -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; diff --git a/src/ViewModels/InProgressContexts.cs b/src/ViewModels/InProgressContexts.cs index f7b85032..c20087fd 100644 --- a/src/ViewModels/InProgressContexts.cs +++ b/src/ViewModels/InProgressContexts.cs @@ -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) diff --git a/src/ViewModels/InteractiveRebase.cs b/src/ViewModels/InteractiveRebase.cs index 0c8838e0..4e0c2826 100644 --- a/src/ViewModels/InteractiveRebase.cs +++ b/src/ViewModels/InteractiveRebase.cs @@ -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(); foreach (var c in commits) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 42d26f94..74801216 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -765,9 +765,9 @@ namespace SourceGit.ViewModels { Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true); - var limits = $"-{Preference.Instance.MaxHistoryCommits} "; + List limits = [$"-{Preference.Instance.MaxHistoryCommits}"]; if (_enableFirstParentInHistories) - limits += "--first-parent "; + limits.Add("--first-parent"); var validFilters = new List(); 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(); diff --git a/src/Views/TextDiffView.axaml.cs b/src/Views/TextDiffView.axaml.cs index b2459127..9bac84ea 100644 --- a/src/Views/TextDiffView.axaml.cs +++ b/src/Views/TextDiffView.axaml.cs @@ -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); }