-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from xenial-io/topic/feat-confirm-branch
Topic/feat confirm branch
- Loading branch information
Showing
16 changed files
with
605 additions
and
5 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
...ool.Tests/ReleaseApplicationTests.CheckForGitMustNotCallNextWhenNotInGitRepo.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Not in a git repository: /var/www/ |
3 changes: 3 additions & 0 deletions
3
...onTests.ConfirmBranches_currentBranch=develop_mustConfirm=True_confirm=False.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The current branch you are working on is not main or master | ||
actually it is develop | ||
Do you want to continue [y/n] (n): n |
1 change: 1 addition & 0 deletions
1
...ationTests.ConfirmBranches_currentBranch=main_mustConfirm=False_confirm=True.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
emptyString |
1 change: 1 addition & 0 deletions
1
...ionTests.ConfirmBranches_currentBranch=master_mustConfirm=False_confirm=True.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
emptyString |
3 changes: 3 additions & 0 deletions
3
...irmBranches_currentBranch=topic-my-feature-123_mustConfirm=True_confirm=True.verified.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
The current branch you are working on is not main or master | ||
actually it is topic/my-feature-123 | ||
Do you want to continue [y/n] (n): y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO.Abstractions.TestingHelpers; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using FakeItEasy; | ||
|
||
using Spectre.Console.Testing; | ||
|
||
using Xenial.RTool; | ||
|
||
namespace Xenial.Tests.RTool; | ||
|
||
[UsesVerify] | ||
public sealed class ReleaseApplicationTests | ||
{ | ||
private MockFileSystem FileSystem { get; } = new MockFileSystem( | ||
new Dictionary<string, MockFileData>() | ||
); | ||
private TestConsole Console { get; } = new TestConsole(); | ||
private IGitCommandRunner CommandRunner { get; } = A.Fake<IGitCommandRunner>(); | ||
|
||
private ReleaseContext CreateTestContext(string? cd = null) | ||
=> new ReleaseContext( | ||
FileSystem, | ||
Console, | ||
CommandRunner, | ||
cd ?? Environment.CurrentDirectory | ||
); | ||
|
||
private (ReleaseApplication app, ReleaseContext ctx) CreateApplication() | ||
=> (new ReleaseApplication(FileSystem, Console, CommandRunner), CreateTestContext()); | ||
|
||
[Fact] | ||
public async Task CheckForGitMustNotCallNextWhenNotInGitRepo() | ||
{ | ||
var next = A.Fake<ReleaseApplicationDelegate>(); | ||
var detector = A.Fake<IGitRepositoryDetector>(); | ||
A.CallTo(() => detector.DetectGitRepository(A.Dummy<string>())).Returns(false); | ||
var ctx = CreateTestContext("/var/www/"); | ||
|
||
await ReleaseApplication.CheckForGit(next, ctx, detector); | ||
|
||
A.CallTo(next).MustNotHaveHappened(); | ||
|
||
await Verify(Console.Output); | ||
} | ||
|
||
[Fact] | ||
public async Task CheckForGitMustCallNextWhenInGitRepo() | ||
{ | ||
var next = A.Fake<ReleaseApplicationDelegate>(); | ||
var detector = A.Fake<IGitRepositoryDetector>(); | ||
A.CallTo(() => detector.DetectGitRepository(A<string>.Ignored)).Returns(true); | ||
|
||
var ctx = CreateTestContext(); | ||
|
||
await ReleaseApplication.CheckForGit(next, ctx, detector); | ||
|
||
A.CallTo(next).MustHaveHappened(); | ||
} | ||
|
||
[Theory] | ||
[InlineData("main", false, true)] | ||
[InlineData("master", false, true)] | ||
[InlineData("develop", true, false)] | ||
[InlineData("topic/my-feature-123", true, true)] | ||
public async Task ConfirmBranches(string currentBranch, bool mustConfirm, bool confirm) | ||
{ | ||
var next = A.Fake<ReleaseApplicationDelegate>(); | ||
|
||
A.CallTo(() => CommandRunner.ReadCommand("branch --show-current", A<string>.Ignored)) | ||
.Returns(Task.FromResult(currentBranch)); | ||
|
||
if (mustConfirm) | ||
{ | ||
Console.Input.PushTextWithEnter(confirm ? "y" : "n"); | ||
} | ||
|
||
var (app, ctx) = CreateApplication(); | ||
|
||
await app.ConfirmBranch(next, ctx); | ||
|
||
if (confirm) | ||
{ | ||
A.CallTo(next).MustHaveHappened(); | ||
} | ||
else | ||
{ | ||
A.CallTo(next).MustNotHaveHappened(); | ||
} | ||
|
||
await Verify(Console.Output) | ||
.UseParameters(currentBranch, mustConfirm, confirm); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
|
||
namespace Xenial.RTool.Common; | ||
|
||
public record MiddlewareBuilder<TDelegate, TBuilder> | ||
: MiddlewareBuilder<TDelegate, Unit, TBuilder> | ||
where TBuilder : MiddlewareBuilder<TDelegate, TBuilder> | ||
where TDelegate : Delegate | ||
{ | ||
public MiddlewareBuilder(TDelegate initialDelegate) : base(Unit.Value, initialDelegate) | ||
{ | ||
|
||
} | ||
} | ||
|
||
public record MiddlewareBuilder<TDelegate, TContext, TBuilder> | ||
where TBuilder : MiddlewareBuilder<TDelegate, TContext, TBuilder> | ||
where TDelegate : System.Delegate | ||
{ | ||
private static readonly object locker = new(); | ||
|
||
private ImmutableArray<Func<TDelegate, TDelegate>> middlewares | ||
= ImmutableArray.Create<Func<TDelegate, TDelegate>>(); | ||
|
||
public TContext Context { get; init; } | ||
|
||
private TDelegate InitialDelegate { get; } | ||
|
||
public Func<TDelegate, TDelegate, TDelegate>? Delegate { get; init; } | ||
|
||
public MiddlewareBuilder(TContext context, TDelegate initialDelegate) | ||
{ | ||
Context = context ?? throw new ArgumentNullException(nameof(context)); | ||
InitialDelegate = initialDelegate ?? throw new ArgumentNullException(nameof(initialDelegate)); | ||
} | ||
|
||
[DebuggerStepThrough] | ||
public TBuilder Use(Func<TDelegate, TDelegate> middleware) | ||
{ | ||
lock (locker) | ||
{ | ||
middlewares = middlewares.Add(middleware); | ||
} | ||
|
||
return (TBuilder)this; | ||
} | ||
|
||
[DebuggerStepThrough] | ||
public TBuilder UseMiddleware<TMiddleware>(Func<TMiddleware> createMiddleware) | ||
{ | ||
var methodInfo = typeof(TMiddleware).GetMethod("InvokeAsync"); | ||
if (methodInfo is null) | ||
{ | ||
throw new InvalidOperationException($"{typeof(TMiddleware)} must have an method called 'InvokeAsync' that matches the '{typeof(TMiddleware).FullName}' signiture."); | ||
} | ||
|
||
return Use(next => | ||
{ | ||
var target = createMiddleware(); | ||
var info = methodInfo.CreateDelegate<TDelegate>(target); | ||
if (Delegate is null) | ||
{ | ||
_ = info.DynamicInvoke(Context); | ||
return next; | ||
} | ||
return Delegate(info, next); | ||
}); | ||
} | ||
|
||
[DebuggerStepThrough] | ||
public TDelegate Build() | ||
{ | ||
TDelegate app = InitialDelegate; | ||
|
||
foreach (var middleware in middlewares.Reverse()) | ||
{ | ||
app = middleware(app); | ||
} | ||
|
||
return app; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
namespace Xenial.RTool.Common; | ||
|
||
/// <summary> | ||
/// Represents a void type, since <see cref="System.Void"/> is not a valid return type in C#. | ||
/// </summary> | ||
public readonly struct Unit : IEquatable<Unit>, IComparable<Unit>, IComparable | ||
{ | ||
private static readonly Unit _value = new(); | ||
|
||
/// <summary> | ||
/// Default and only value of the <see cref="Unit"/> type. | ||
/// </summary> | ||
public static ref readonly Unit Value => ref _value; | ||
|
||
/// <summary> | ||
/// Task from a <see cref="Unit"/> type. | ||
/// </summary> | ||
public static Task<Unit> Task { get; } = System.Threading.Tasks.Task.FromResult(_value); | ||
|
||
/// <summary> | ||
/// Compares the current object with another object of the same type. | ||
/// </summary> | ||
/// <param name="other">An object to compare with this object.</param> | ||
/// <returns> | ||
/// A value that indicates the relative order of the objects being compared. | ||
/// The return value has the following meanings: | ||
/// - Less than zero: This object is less than the <paramref name="other" /> parameter. | ||
/// - Zero: This object is equal to <paramref name="other" />. | ||
/// - Greater than zero: This object is greater than <paramref name="other" />. | ||
/// </returns> | ||
public int CompareTo(Unit other) => 0; | ||
|
||
/// <summary> | ||
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. | ||
/// </summary> | ||
/// <param name="obj">An object to compare with this instance.</param> | ||
/// <returns> | ||
/// A value that indicates the relative order of the objects being compared. | ||
/// The return value has these meanings: | ||
/// - Less than zero: This instance precedes <paramref name="obj" /> in the sort order. | ||
/// - Zero: This instance occurs in the same position in the sort order as <paramref name="obj" />. | ||
/// - Greater than zero: This instance follows <paramref name="obj" /> in the sort order. | ||
/// </returns> | ||
int IComparable.CompareTo(object? obj) => 0; | ||
|
||
/// <summary> | ||
/// Returns a hash code for this instance. | ||
/// </summary> | ||
/// <returns> | ||
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. | ||
/// </returns> | ||
public override int GetHashCode() => 0; | ||
|
||
/// <summary> | ||
/// Determines whether the current object is equal to another object of the same type. | ||
/// </summary> | ||
/// <param name="other">An object to compare with this object.</param> | ||
/// <returns> | ||
/// <c>true</c> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <c>false</c>. | ||
/// </returns> | ||
public bool Equals(Unit other) => true; | ||
|
||
/// <summary> | ||
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance. | ||
/// </summary> | ||
/// <param name="obj">The object to compare with the current instance.</param> | ||
/// <returns> | ||
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. | ||
/// </returns> | ||
public override bool Equals(object? obj) => obj is Unit; | ||
|
||
/// <summary> | ||
/// Determines whether the <paramref name="first"/> object is equal to the <paramref name="second"/> object. | ||
/// </summary> | ||
/// <param name="first">The first object.</param> | ||
/// <param name="second">The second object.</param> | ||
/// <c>true</c> if the <paramref name="first"/> object is equal to the <paramref name="second" /> object; otherwise, <c>false</c>. | ||
public static bool operator ==(Unit first, Unit second) => true; | ||
|
||
/// <summary> | ||
/// Determines whether the <paramref name="first"/> object is not equal to the <paramref name="second"/> object. | ||
/// </summary> | ||
/// <param name="first">The first object.</param> | ||
/// <param name="second">The second object.</param> | ||
/// <c>true</c> if the <paramref name="first"/> object is not equal to the <paramref name="second" /> object; otherwise, <c>false</c>. | ||
public static bool operator !=(Unit first, Unit second) => false; | ||
|
||
/// <summary> | ||
/// Returns a <see cref="System.String" /> that represents this instance. | ||
/// </summary> | ||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns> | ||
public override string ToString() => "()"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using static SimpleExec.Command; | ||
|
||
namespace Xenial.RTool; public sealed class GitCommandRunner : IGitCommandRunner | ||
{ | ||
public Task RunCommand(string command, string? cd = null) | ||
=> RunAsync("git", command, workingDirectory: cd ?? Environment.CurrentDirectory); | ||
|
||
public async Task<string> ReadCommand(string command, string? cd = null) | ||
{ | ||
var (stdOut, _) = (await ReadAsync("git", command, workingDirectory: cd ?? Environment.CurrentDirectory)); | ||
var result = stdOut.Trim(); | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Xenial.RTool; | ||
|
||
public interface IGitCommandRunner | ||
{ | ||
Task<string> ReadCommand(string command, string? cd = null); | ||
Task RunCommand(string command, string? cd = null); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace Xenial.RTool; | ||
|
||
public interface IGitRepositoryDetector | ||
{ | ||
bool DetectGitRepository(string? cd = null); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,9 @@ | ||
Console.WriteLine(""); | ||
using System.IO.Abstractions; | ||
|
||
using Spectre.Console; | ||
|
||
using Xenial.RTool; | ||
|
||
var app = new ReleaseApplication(new FileSystem(), AnsiConsole.Console, new GitCommandRunner()); | ||
|
||
await app.Release(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"profiles": { | ||
"Xenial.RTool": { | ||
"commandName": "Project" | ||
}, | ||
"Xenial.RTool No Git": { | ||
"commandName": "Project", | ||
"workingDirectory": "C:\\Users\\mgrun\\Downloads" | ||
} | ||
} | ||
} |
Oops, something went wrong.