diff --git a/src/Cake.Git/Cake.Git.csproj b/src/Cake.Git/Cake.Git.csproj index eb65d6a..2e862d1 100644 --- a/src/Cake.Git/Cake.Git.csproj +++ b/src/Cake.Git/Cake.Git.csproj @@ -60,7 +60,11 @@ + + + + diff --git a/src/Cake.Git/GitAliases.Add.cs b/src/Cake.Git/GitAliases.Add.cs index 534097e..a066cf6 100644 --- a/src/Cake.Git/GitAliases.Add.cs +++ b/src/Cake.Git/GitAliases.Add.cs @@ -8,6 +8,7 @@ // ReSharper disable UnusedMember.Global namespace Cake.Git { + // ReSharper disable once PublicMembersMustHaveComments public static partial class GitAliases { /// diff --git a/src/Cake.Git/GitAliases.Clone.cs b/src/Cake.Git/GitAliases.Clone.cs index fa42569..38e3ef1 100644 --- a/src/Cake.Git/GitAliases.Clone.cs +++ b/src/Cake.Git/GitAliases.Clone.cs @@ -13,7 +13,7 @@ namespace Cake.Git public static partial class GitAliases { /// - /// Clone using default options. + /// Clone unauthenticated using default options. /// /// The context. /// URI for the remote repository. @@ -54,7 +54,7 @@ DirectoryPath workDirectoryPath } /// - /// Clone using specified options. + /// Clone authenticated using default options. /// /// The context. /// URI for the remote repository. diff --git a/src/Cake.Git/GitAliases.Pull.cs b/src/Cake.Git/GitAliases.Pull.cs new file mode 100644 index 0000000..4c9de3a --- /dev/null +++ b/src/Cake.Git/GitAliases.Pull.cs @@ -0,0 +1,147 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.IO; +using Cake.Git.Extensions; +using LibGit2Sharp; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global +namespace Cake.Git +{ + // ReSharper disable once PublicMembersMustHaveComments + public static partial class GitAliases + { + /// + /// Pull unauthenticated using default options. + /// + /// The context. + /// Repository path. + /// The name of the merger. + /// The email of the merger. + /// The path to the created repository. + /// + [CakeMethodAlias] + [CakeAliasCategory("Pull")] + public static GitMergeResult GitPull( + this ICakeContext context, + DirectoryPath repositoryDirectoryPath, + string mergerName, + string mergerEmail + ) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (repositoryDirectoryPath == null) + { + throw new ArgumentNullException(nameof(repositoryDirectoryPath)); + } + + var workFullDirectoryPath = repositoryDirectoryPath.MakeAbsolute(context.Environment); + + if (!context.FileSystem.Exist(workFullDirectoryPath)) + { + throw new DirectoryNotFoundException($"Failed to find workDirectoryPath: {workFullDirectoryPath}"); + } + + return new GitMergeResult( + context.UseRepository( + repositoryDirectoryPath, + repository => + repository.Network.Pull( + new Signature( + mergerName, + mergerEmail, + DateTimeOffset.Now + ), + new PullOptions() + ) + ) + ); + } + + /// + /// Pull authenticating using default options. + /// + /// The context. + /// Repository path. + /// The name of the merger. + /// The email of the merger. + /// Username used for authentication. + /// Password used for authentication. + /// Name of remote to pull from. + /// The path to the created repository. + /// + [CakeMethodAlias] + [CakeAliasCategory("Pull")] + public static GitMergeResult GitPull( + this ICakeContext context, + DirectoryPath repositoryDirectoryPath, + string mergerName, + string mergerEmail, + string username, + string password, + string remoteName + ) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (repositoryDirectoryPath == null) + { + throw new ArgumentNullException(nameof(repositoryDirectoryPath)); + } + + var repositoryFullDirectoryPath = repositoryDirectoryPath.MakeAbsolute(context.Environment); + + if (!context.FileSystem.Exist(repositoryFullDirectoryPath)) + { + throw new DirectoryNotFoundException($"Failed to find repositoryDirectoryPath: {repositoryFullDirectoryPath}"); + } + + return new GitMergeResult( + context.UseRepository( + repositoryDirectoryPath, + repository => + { + var remote = repository.Network.Remotes[remoteName]; + if (remote == null) + { + throw new NotFoundException("Remote named {0} not found", remoteName); + } + + repository.Network.Fetch( + remote, + new FetchOptions + { + CredentialsProvider = + (url, usernameFromUrl, types) => + new UsernamePasswordCredentials + { + Username = username, + Password = password + } + } + ); + + return repository.MergeFetchedRefs( + new Signature( + mergerName, + mergerEmail, + DateTimeOffset.Now + ), + new MergeOptions() + ); + } + ) + ); + } + } +} \ No newline at end of file diff --git a/src/Cake.Git/GitAliases.Push.cs b/src/Cake.Git/GitAliases.Push.cs new file mode 100644 index 0000000..0ad817d --- /dev/null +++ b/src/Cake.Git/GitAliases.Push.cs @@ -0,0 +1,174 @@ +using System; +using System.IO; +using Cake.Core; +using Cake.Core.Annotations; +using Cake.Core.IO; +using Cake.Git.Extensions; +using LibGit2Sharp; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global +namespace Cake.Git +{ + // ReSharper disable once PublicMembersMustHaveComments + public static partial class GitAliases + { + /// + /// Push all branches unauthenticated. + /// + /// The context. + /// Repository path. + /// The path to the created repository. + /// + [CakeMethodAlias] + [CakeAliasCategory("Push")] + public static void GitPush( + this ICakeContext context, + DirectoryPath repositoryDirectoryPath + ) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (repositoryDirectoryPath == null) + { + throw new ArgumentNullException(nameof(repositoryDirectoryPath)); + } + + var workFullDirectoryPath = repositoryDirectoryPath.MakeAbsolute(context.Environment); + + if (!context.FileSystem.Exist(workFullDirectoryPath)) + { + throw new DirectoryNotFoundException($"Failed to find workDirectoryPath: {workFullDirectoryPath}"); + } + + context.UseRepository( + repositoryDirectoryPath, + repository => + repository.Network.Push( + repository.Branches + ) + ); + } + + /// + /// Push all branches authenticated. + /// + /// The context. + /// Repository path. + /// Username used for authentication. + /// Password used for authentication. + /// The path to the created repository. + /// + [CakeMethodAlias] + [CakeAliasCategory("Push")] + public static void GitPush( + this ICakeContext context, + DirectoryPath repositoryDirectoryPath, + string username, + string password + ) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (repositoryDirectoryPath == null) + { + throw new ArgumentNullException(nameof(repositoryDirectoryPath)); + } + + var repositoryFullDirectoryPath = repositoryDirectoryPath.MakeAbsolute(context.Environment); + + if (!context.FileSystem.Exist(repositoryFullDirectoryPath)) + { + throw new DirectoryNotFoundException($"Failed to find repositoryDirectoryPath: {repositoryFullDirectoryPath}"); + } + + context.UseRepository( + repositoryDirectoryPath, + repository => + repository.Network.Push( + repository.Branches, + new PushOptions + { + CredentialsProvider = + (url, usernameFromUrl, types) => + new UsernamePasswordCredentials + { + Username = username, + Password = password + } + } + ) + ); + } + + /// + /// Push specific branch authenticated. + /// + /// The context. + /// Repository path. + /// Username used for authentication. + /// Password used for authentication. + /// Name of branch to push. + /// The path to the created repository. + /// + [CakeMethodAlias] + [CakeAliasCategory("Push")] + public static void GitPush( + this ICakeContext context, + DirectoryPath repositoryDirectoryPath, + string username, + string password, + string branchName + ) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (repositoryDirectoryPath == null) + { + throw new ArgumentNullException(nameof(repositoryDirectoryPath)); + } + + var repositoryFullDirectoryPath = repositoryDirectoryPath.MakeAbsolute(context.Environment); + + if (!context.FileSystem.Exist(repositoryFullDirectoryPath)) + { + throw new DirectoryNotFoundException($"Failed to find repositoryDirectoryPath: {repositoryFullDirectoryPath}"); + } + + context.UseRepository( + repositoryDirectoryPath, + repository => + { + var branch = repository.Branches[branchName]; + if (branch == null) + { + throw new NotFoundException("Failed to find branch {0}", branchName); + } + + repository.Network.Push( + branch, + new PushOptions + { + CredentialsProvider = + (url, usernameFromUrl, types) => + new UsernamePasswordCredentials + { + Username = username, + Password = password + } + } + ); + } + ); + } + } +} \ No newline at end of file diff --git a/src/Cake.Git/GitMergeResult.cs b/src/Cake.Git/GitMergeResult.cs new file mode 100644 index 0000000..951fc74 --- /dev/null +++ b/src/Cake.Git/GitMergeResult.cs @@ -0,0 +1,33 @@ +using System; +using LibGit2Sharp; +// ReSharper disable MemberCanBePrivate.Global + +namespace Cake.Git +{ + /// + /// Git repository merge operation result + /// + public sealed class GitMergeResult + { + /// + /// Merge commit. + /// + public GitCommit Commit { get; } + + /// + /// Merge status + /// + public GitMergeStatus Status { get; } + + internal GitMergeResult(MergeResult mergeResult) + { + if (mergeResult == null) + { + throw new ArgumentNullException(nameof(mergeResult)); + } + + Commit = new GitCommit(mergeResult.Commit); + Status = (GitMergeStatus) mergeResult.Status; + } + } +} \ No newline at end of file diff --git a/src/Cake.Git/GitMergeStatus.cs b/src/Cake.Git/GitMergeStatus.cs new file mode 100644 index 0000000..434d6da --- /dev/null +++ b/src/Cake.Git/GitMergeStatus.cs @@ -0,0 +1,31 @@ +using LibGit2Sharp; +// ReSharper disable UnusedMember.Global + +namespace Cake.Git +{ + /// + /// The status of what happened as a result of a merge. + /// + public enum GitMergeStatus + { + /// + /// Repository was up to date + /// + UpToDate = MergeStatus.UpToDate, + + /// + /// Repository was fast forward merged + /// + FastForward = MergeStatus.FastForward, + + /// + /// Repository was not fast forward merged + /// + NonFastForward = MergeStatus.NonFastForward, + + /// + /// Repository encountered conflicts during merge + /// + Conflicts = MergeStatus.Conflicts + } +} \ No newline at end of file diff --git a/src/Cake.Git/GitSignature.cs b/src/Cake.Git/GitSignature.cs index 8bb501a..95ab424 100644 --- a/src/Cake.Git/GitSignature.cs +++ b/src/Cake.Git/GitSignature.cs @@ -7,7 +7,7 @@ namespace Cake.Git /// /// Git Commit Author / Committer. /// - public class GitSignature + public sealed class GitSignature { /// /// Email address of author / committer.