Skip to content

Commit c119237

Browse files
committed
Refactor IVcs interface to allow passing working directory
To make the VCS providers more testable. Add support for changing working directory in the git vcs provider
1 parent 8369266 commit c119237

File tree

3 files changed

+126
-87
lines changed

3 files changed

+126
-87
lines changed

src/Vcs/Git/GitVcs.cs

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Diagnostics;
3+
using System.IO;
34

45
namespace Skarp.Version.Cli.Vcs.Git
56
{
@@ -10,14 +11,15 @@ public class GitVcs : IVcs
1011
/// </summary>
1112
/// <param name="csProjFilePath">Path to the cs project file that was version updated</param>
1213
/// <param name="message">The message to include in the commit</param>
13-
public void Commit(string csProjFilePath, string message)
14+
/// <param name="cwd"></param>
15+
public void Commit(string csProjFilePath, string message, string cwd = null)
1416
{
15-
if(!LaunchGitWithArgs($"add \"{csProjFilePath}\""))
17+
if(!LaunchGitWithArgs($"add \"{csProjFilePath}\"", cwd: cwd))
1618
{
1719
throw new OperationCanceledException($"Unable to add cs proj file {csProjFilePath} to git index");
1820
}
1921

20-
if(!LaunchGitWithArgs($"commit -m \"{message}\""))
22+
if(!LaunchGitWithArgs($"commit -m \"{message}\"", cwd: cwd))
2123
{
2224
throw new OperationCanceledException("Unable to commit");
2325
}
@@ -27,42 +29,54 @@ public void Commit(string csProjFilePath, string message)
2729
/// Determines whether the current repository is clean.
2830
/// </summary>
2931
/// <returns></returns>
30-
public bool IsRepositoryClean()
32+
public bool IsRepositoryClean(string cwd = null)
3133
{
32-
return LaunchGitWithArgs("diff-index --quiet HEAD --");
34+
return LaunchGitWithArgs("diff-index HEAD --", cwd: cwd);
3335
}
3436

3537
/// <summary>
3638
/// Determines whether git is present in PATH on the current computer
3739
/// </summary>
3840
/// <returns></returns>
39-
public bool IsVcsToolPresent()
41+
public bool IsVcsToolPresent(string cwd = null)
4042
{
4143
// launching `git --help` returns exit code 0 where as `git` returns 1 as git wants a cmd line argument
42-
return LaunchGitWithArgs("--help");
44+
return LaunchGitWithArgs("--help", cwd: cwd);
4345
}
4446

4547
/// <summary>
4648
/// Creates a new tag
4749
/// </summary>
4850
/// <param name="tagName">Name of the tag</param>
49-
public void Tag(string tagName)
51+
/// <param name="cwd"></param>
52+
public void Tag(string tagName, string cwd = null)
5053
{
51-
if(!LaunchGitWithArgs($"tag {tagName}"))
54+
if(!LaunchGitWithArgs($"tag {tagName}", cwd: cwd))
5255
{
5356
throw new OperationCanceledException("Unable to create tag");
5457
}
5558
}
5659

57-
private static bool LaunchGitWithArgs(string args, int waitForExitTimeMs = 1000, int exitCode = 0)
60+
/// <summary>
61+
/// Helper method for launching git with different arguments while returning just a boolean of whether the
62+
/// "command" was successful
63+
/// </summary>
64+
/// <param name="args">The args to pass onto git, e.g `diff` to launch `git diff`</param>
65+
/// <param name="waitForExitTimeMs">How long to wait for the git operation to complete</param>
66+
/// <param name="exitCode">The expected exit code</param>
67+
/// <param name="cwd">The working directory to change into, if any. Leave null for "current directory" </param>
68+
/// <returns></returns>
69+
internal static bool LaunchGitWithArgs(
70+
string args,
71+
int waitForExitTimeMs = 1000,
72+
int exitCode = 0,
73+
string cwd = null
74+
)
5875
{
5976
try
6077
{
61-
var startInfo = CreateGitShellStartInfo(args);
62-
var proc = Process.Start(startInfo);
63-
proc.WaitForExit(waitForExitTimeMs);
64-
65-
return proc.ExitCode == exitCode;
78+
var (procExitCode, stdOut, stdErr) = LaunchGitWithArgsInner(args, waitForExitTimeMs, cwd);
79+
return procExitCode == exitCode;
6680
}
6781
catch (Exception ex)
6882
{
@@ -71,15 +85,36 @@ private static bool LaunchGitWithArgs(string args, int waitForExitTimeMs = 1000,
7185
}
7286
}
7387

74-
private static ProcessStartInfo CreateGitShellStartInfo(string args)
88+
internal static (int ExitCode, string stdOut, string stdErr) LaunchGitWithArgsInner(
89+
string args,
90+
int waitForExitTimeMs,
91+
string cwd = null
92+
)
7593
{
76-
return new ProcessStartInfo("git")
94+
var startInfo = CreateGitShellStartInfo(args, cwd);
95+
var proc = Process.Start(startInfo);
96+
proc.WaitForExit(waitForExitTimeMs);
97+
98+
var stdOut = proc.StandardOutput.ReadToEnd();
99+
var stdErr = proc.StandardError.ReadToEnd();
100+
return (proc.ExitCode, stdOut,stdErr);
101+
}
102+
103+
internal static ProcessStartInfo CreateGitShellStartInfo(string args, string cwd = null)
104+
{
105+
var procInfo = new ProcessStartInfo("git")
77106
{
78107
Arguments = args,
79108
RedirectStandardError = true,
80109
RedirectStandardInput = true,
81110
RedirectStandardOutput = true,
82111
};
112+
113+
if (!string.IsNullOrWhiteSpace(cwd))
114+
{
115+
procInfo.WorkingDirectory = cwd;
116+
}
117+
return procInfo;
83118
}
84119

85120
public string ToolName()

src/Vcs/IVcs.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,33 @@ public interface IVcs
1616
/// are available in the current CLI contenxt - i.e check that `git` command can be found
1717
/// and executed
1818
/// </summary>
19+
/// <param name="cwd">Change working directory - leave null for current directory</param>
1920
/// <returns><c>true</c> if the tool exists, <c>false</c> otherwise</returns>
20-
bool IsVcsToolPresent();
21+
bool IsVcsToolPresent(string cwd = null);
2122

2223
/// <summary>
2324
/// When implemented by a concrete class it returns <c>true</c> if the
2425
/// current HEAD of the local repository is clean - i.e no pending changes
2526
/// </summary>
27+
/// <param name="cwd">Change working directory - leave null for current directory</param>
2628
/// <returns></returns>
27-
bool IsRepositoryClean();
29+
bool IsRepositoryClean(string cwd = null);
2830

2931
/// <summary>
3032
/// When implemented by a concrete class it allows to create a commit with the
3133
/// changed version in the project file
3234
/// </summary>
3335
/// <param name="csProjFilePath">Path to the cs project file</param>
3436
/// <param name="message">The message to create the commit message with</param>
35-
void Commit(string csProjFilePath, string message);
37+
/// <param name="cwd">Change working directory - leave null for current directory</param>
38+
void Commit(string csProjFilePath, string message, string cwd = null);
3639

3740
/// <summary>
3841
/// When implemented by a concrete class it will tag the latest commit with the
3942
/// given tag name
4043
/// </summary>
4144
/// <param name="tagName">The name of the tag to create - i.e v1.0.2 </param>
42-
void Tag(string tagName);
45+
/// <param name="cwd">Change working directory - leave null for current directory</param>
46+
void Tag(string tagName, string cwd = null);
4347
}
4448
}

0 commit comments

Comments
 (0)