Skip to content

Commit

Permalink
(cake-contribGH-183) Add option to use Git CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalberger committed Aug 2, 2021
1 parent 92f208b commit e8fd65a
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Cake.Core.IO;
using Cake.Git;
using Cake.Issues;
using System;
using System.Linq;

namespace Cake.Frosting.Issues.Recipe
{
Expand All @@ -19,8 +17,7 @@ public virtual Uri DetermineRepositoryRemoteUrl(
context.NotNull(nameof(context));
repositoryRootDirectory.NotNull(nameof(repositoryRootDirectory));

var currentBranch = context.GitBranchCurrent(repositoryRootDirectory);
return new Uri(currentBranch.Remotes.Single(x => x.Name == "origin").Url);
return context.State.RepositoryInfo.GetRepositoryRemoteUrl(context, repositoryRootDirectory);
}

/// <inheritdoc />
Expand All @@ -31,7 +28,7 @@ public virtual string DetermineCommitId(
context.NotNull(nameof(context));
repositoryRootDirectory.NotNull(nameof(repositoryRootDirectory));

return context.GitLogTip(repositoryRootDirectory).Sha;
return context.State.RepositoryInfo.GetCommitId(context, repositoryRootDirectory);
}

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ namespace Cake.Frosting.Issues.Recipe
/// </summary>
public class IssuesParameters
{
/// <summary>
/// Gets or sets how information about the Git repository should be determined.
/// Default value is <c>RepositoryInfoProviderType.CakeGit</c>.
/// </summary>
public RepositoryInfoProviderType RepositoryInfoProvider { get; set; } = RepositoryInfoProviderType.CakeGit;

/// <summary>
/// Gets or sets the path to the output directory.
/// A relative path will be relative to the current working directory.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Cake.Frosting.Issues.Recipe
{
/// <summary>
/// Supported ways to read repository information.
/// </summary>
public enum RepositoryInfoProviderType
{
/// <summary>
/// Read repository information using Cake.Git addin.
/// Requires system to be compatible with Cake.Git addin.
/// </summary>
CakeGit,

/// <summary>
/// Read repository information using Git CLI.
/// Requires Git CLI to be available in path.
/// </summary>
Cli
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Cake.Common.Diagnostics;
using Cake.Common.IO;
using Cake.Core.IO;
using Cake.Git;
using Cake.Frosting.Issues.Recipe.RepositoryInfo;
using Cake.Issues;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -47,6 +47,11 @@ public class IssuesState
/// </summary>
public FilePath SummaryIssuesReport { get; set; }

/// <summary>
/// Gets the provider to read information about the Git repository.
/// </summary>
public IRepositoryInfoProvider RepositoryInfo { get; }

/// <summary>
/// Gets the build server under which the build is running.
/// Returns <c>null</c> if running locally or on an unsupported build server.
Expand Down Expand Up @@ -78,7 +83,9 @@ public IssuesState(IssuesContext context)
this.BuildRootDirectory = context.MakeAbsolute(context.Directory("./"));
context.Information("Build script root directory: {0}", this.BuildRootDirectory);

this.RepositoryRootDirectory = context.GitFindRootFromPath(this.BuildRootDirectory);
this.RepositoryInfo = DetermineRepositoryInfoProvider(context);

this.RepositoryRootDirectory = this.RepositoryInfo.GetRepositoryRootDirectory(context, this.BuildRootDirectory);
context.Information("Repository root directory: {0}", this.RepositoryRootDirectory);

this.BuildServer = DetermineBuildServer(context);
Expand Down Expand Up @@ -127,6 +134,31 @@ public void AddIssues(IEnumerable<IIssue> issues)
this.issues.AddRange(issues);
}

/// <summary>
/// Determines the repository info provider to use.
/// </summary>
/// <param name="context">The Cake context.</param>
/// <returns>The repository info provider which should be used.</returns>
private static IRepositoryInfoProvider DetermineRepositoryInfoProvider(IssuesContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}

switch (context.Parameters.RepositoryInfoProvider)
{
case RepositoryInfoProviderType.CakeGit:
context.Information("Using Cake.Git for providing repository information");
return new CliRepositoryInfoProvider();
case RepositoryInfoProviderType.Cli:
context.Information("Using Git CLI for providing repository information");
return new CliRepositoryInfoProvider();
default:
throw new NotImplementedException("Unsupported repository info provider");
}
}

/// <summary>
/// Determines the build server on which the build is running.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using Cake.Common;
using Cake.Core;
using Cake.Core.IO;
using Cake.Git;
using Cake.Issues;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Cake.Frosting.Issues.Recipe.RepositoryInfo
{
public interface IRepositoryInfoProvider
{
DirectoryPath GetRepositoryRootDirectory(IssuesContext context, DirectoryPath buildRootDirectory);
Uri GetRepositoryRemoteUrl(IssuesContext context, DirectoryPath repositoryRootDirectory);
string GetCommitId(IssuesContext context, DirectoryPath repositoryRootDirectory);
}

public class CakeGitRepositoryInfoProvider : IRepositoryInfoProvider
{
/// <inheritdoc />
public DirectoryPath GetRepositoryRootDirectory(IssuesContext context, DirectoryPath buildRootDirectory)
{
context.NotNull(nameof(context));
buildRootDirectory.NotNull(nameof(buildRootDirectory));

return context.GitFindRootFromPath(buildRootDirectory);
}

/// <inheritdoc />
public Uri GetRepositoryRemoteUrl(IssuesContext context, DirectoryPath repositoryRootDirectory)
{
context.NotNull(nameof(context));
repositoryRootDirectory.NotNull(nameof(repositoryRootDirectory));

var currentBranch = context.GitBranchCurrent(repositoryRootDirectory);
return new Uri(currentBranch.Remotes.Single(x => x.Name == "origin").Url);
}

/// <inheritdoc />
public string GetCommitId(IssuesContext context, DirectoryPath repositoryRootDirectory)
{
context.NotNull(nameof(context));
repositoryRootDirectory.NotNull(nameof(repositoryRootDirectory));

return context.GitLogTip(repositoryRootDirectory).Sha;
}
}

public class CliRepositoryInfoProvider : IRepositoryInfoProvider
{
/// <inheritdoc />
public DirectoryPath GetRepositoryRootDirectory(IssuesContext context, DirectoryPath buildRootDirectory)
{
var result = this.GitCommand(context, buildRootDirectory, "rev-parse", "--show-toplevel");
return new DirectoryPath(result.Single());
}

/// <inheritdoc />
public Uri GetRepositoryRemoteUrl(IssuesContext context, DirectoryPath repositoryRootDirectory)
{
return null;
}

/// <inheritdoc />
public string GetCommitId(IssuesContext context, DirectoryPath repositoryRootDirectory)
{
return string.Empty;
}

private IEnumerable<string> GitCommand(
ICakeContext context,
DirectoryPath repositoryRootFolder,
params string[] arguments)
{
if (!arguments.Any())
{
throw new ArgumentOutOfRangeException(nameof(arguments));
}

var gitArguments = string.Join(" ", arguments);

var exitCode = context.StartProcess(
"git",
new ProcessSettings
{
Arguments = gitArguments,
WorkingDirectory = repositoryRootFolder.FullPath,
RedirectStandardOutput = true,
RedirectStandardError = true
},
out var redirectedStandardOutput,
out var redirectedErrorOutput
);

if (exitCode != 0)
{
throw new Exception(
$"Git command failed with arguments {gitArguments}. Exit code: {exitCode}. Error output: {string.Join(Environment.NewLine, redirectedErrorOutput)}"
);
}

return redirectedStandardOutput;

}
}
}

0 comments on commit e8fd65a

Please sign in to comment.