Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 137 additions & 94 deletions deployment/cake/generic-variables.cake
Original file line number Diff line number Diff line change
Expand Up @@ -78,124 +78,167 @@ public class VersionContext : BuildContextBase
var gitVersionSettings = new GitVersionSettings
{
UpdateAssemblyInfo = false,
Verbosity = GitVersionVerbosity.Verbose
Verbosity = GitVersionVerbosity.Verbose,
NoFetch = true
};

var gitDirectory = ".git";
if (!CakeContext.DirectoryExists(gitDirectory))
var mutexName = $"Global\\Cake_GitVersion_Clone_{generalContext.Solution.Name}";

CakeContext.Information("Trying to acquire mutex to determine version");

using (var mutex = new System.Threading.Mutex(false, mutexName, out var createdNew))
{
CakeContext.Information("No local .git directory found, treating as dynamic repository");
if (!mutex.WaitOne(TimeSpan.FromMinutes(2)))
{
throw new Exception("Could not acquire mutex to determine version");
}

// Make a *BIG* assumption that the solution name == repository name
var repositoryName = generalContext.Solution.Name;
var dynamicRepositoryPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), repositoryName);
CakeContext.Information("Mutex acquired");

// Note: for now (until we fix the dynamic cloning in the code below), clear cache must be true
var clearCache = ClearCache || true;
if (clearCache)
var gitDirectory = ".git";
if (!CakeContext.DirectoryExists(gitDirectory))
{
CakeContext.Warning("Cleaning the cloned temp directory, disable by setting 'GitVersion_ClearCache' to 'false'");

if (CakeContext.DirectoryExists(dynamicRepositoryPath))
CakeContext.Information("No local .git directory found, treating as dynamic repository");

// Make a *BIG* assumption that the solution name == repository name
var repositoryName = generalContext.Solution.Name;
var dynamicRepositoryPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), repositoryName);

// Note: for now we fully clear the cache each time until we found a solid way to pull the latest changes
var clearCache = ClearCache || true;
if (clearCache)
{
CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings
CakeContext.Warning("Cleaning the cloned temp directory, disable by setting 'GitVersion_ClearCache' to 'false'");

if (CakeContext.DirectoryExists(dynamicRepositoryPath))
{
Force = true,
Recursive = true
});
CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings
{
Force = true,
Recursive = true
});
}
}
}

// Validate first
if (string.IsNullOrWhiteSpace(generalContext.Repository.BranchName))
{
throw new Exception("No local .git directory was found, but repository branch was not specified either. Make sure to specify the branch");
}
// Validate first
if (string.IsNullOrWhiteSpace(generalContext.Repository.BranchName))
{
throw new Exception("No local .git directory was found, but repository branch was not specified either. Make sure to specify the branch");
}

if (string.IsNullOrWhiteSpace(generalContext.Repository.Url))
{
throw new Exception("No local .git directory was found, but repository url was not specified either. Make sure to specify the branch");
}
if (string.IsNullOrWhiteSpace(generalContext.Repository.Url))
{
throw new Exception("No local .git directory was found, but repository url was not specified either. Make sure to specify the branch");
}

CakeContext.Information($"Fetching dynamic repository from url '{generalContext.Repository.Url}' => '{dynamicRepositoryPath}'");
CakeContext.Information($"Fetching dynamic repository from url '{generalContext.Repository.Url}' => '{dynamicRepositoryPath}'");

// Note: starting with GitVersion 6.x, we need to handle dynamic repos ourselves,
// and we will be using LibGit2Sharp directly to support cloning a specific commit id
// Note: starting with GitVersion 6.x, we need to handle dynamic repos ourselves,
// and we will be using Cake.Git and LibGit2Sharp directly to support cloning a specific commit id

// var gitCloneSettings = new GitCloneSettings
// {
// //BranchName = generalContext.Repository.BranchName,
// BranchName = generalContext.Repository.CommitId,
// Checkout = true,
// IsBare = false,
// RecurseSubmodules = false,
// };
var existingRepository = false;
if (CakeContext.DirectoryExists(dynamicRepositoryPath))
{
CakeContext.Information("Dynamic repository directory already exists");

var cloneOptions = new LibGit2Sharp.CloneOptions
{
IsBare = false,
Checkout = true,
BranchName = generalContext.Repository.BranchName,
RecurseSubmodules = false
};

if (!string.IsNullOrWhiteSpace(generalContext.Repository.Username) &&
!string.IsNullOrWhiteSpace(generalContext.Repository.Password))
{
CakeContext.Information("Cloning with authentication");
if (CakeContext.GitIsValidRepository(dynamicRepositoryPath))
{
CakeContext.Information("Dynamic repository already exists, reusing existing clone");
existingRepository = true;
}
else
{
CakeContext.Information("Dynamic repository already exists but is not valid, recloning");

CakeContext.DeleteDirectory(dynamicRepositoryPath, new DeleteDirectorySettings
{
Force = true,
Recursive = true
});
}
}

cloneOptions.FetchOptions.CredentialsProvider =
(url, user, cred) => new LibGit2Sharp.UsernamePasswordCredentials
{
Username = generalContext.Repository.Username,
Password = generalContext.Repository.Password
if (existingRepository)
{
// TODO: How to pull?
}
else
{
var gitCloneSettings = new GitCloneSettings
{
BranchName = generalContext.Repository.BranchName,
Checkout = true,
IsBare = false,
RecurseSubmodules = false,
};
}
else
{
CakeContext.Information("Cloning without authentication");
}

LibGit2Sharp.Repository.Clone(generalContext.Repository.Url, dynamicRepositoryPath, cloneOptions);

if (!CakeContext.GitIsValidRepository(dynamicRepositoryPath))
{
throw new Exception($"Cloned repository at '{dynamicRepositoryPath}' is not a valid repository");
}
if (!string.IsNullOrWhiteSpace(generalContext.Repository.Username) &&
!string.IsNullOrWhiteSpace(generalContext.Repository.Password))
{
CakeContext.Information("Cloning with authentication");

CakeContext.GitClone(generalContext.Repository.Url,
dynamicRepositoryPath,
generalContext.Repository.Username,
generalContext.Repository.Password,
gitCloneSettings);
}
else
{
CakeContext.Information("Cloning without authentication");

CakeContext.Information("Switching to correct commit ID");

// According to docs, to not get into a detached head state, we need to:
//
// git checkout -B 'branch' 'commit id'
//
// This seems impossible via Cake.Git (and LibGit2Sharp directly), so we will
// just invoke git.exe directly here
//
//CakeContext.GitCheckout(dynamicRepositoryPath, generalContext.Repository.CommitId);

var gitExe = CakeContext.Tools.Resolve("git.exe").FullPath;

using (var process = CakeContext.StartAndReturnProcess(gitExe,
new ProcessSettings
{
WorkingDirectory = dynamicRepositoryPath,
Arguments = $"checkout -B {generalContext.Repository.BranchName} {generalContext.Repository.CommitId}",
}))
{
process.WaitForExit();
CakeContext.GitClone(generalContext.Repository.Url,
dynamicRepositoryPath,
gitCloneSettings);
}
}

// This should output 0 as valid arguments supplied
CakeContext.Information("Exit code: {0}", process.GetExitCode());
//LibGit2Sharp.Repository.Clone(generalContext.Repository.Url, dynamicRepositoryPath, cloneOptions);

if (!CakeContext.GitIsValidRepository(dynamicRepositoryPath))
{
throw new Exception($"Cloned repository at '{dynamicRepositoryPath}' is not a valid repository");
}

CakeContext.Information("Ensuring correct commit ID");

// According to docs, to not get into a detached head state, we need to:
//
// git checkout -B 'branch' 'commit id'
//
// This seems impossible via Cake.Git (and LibGit2Sharp directly), so we will
// just invoke git.exe directly here
//
//CakeContext.GitCheckout(dynamicRepositoryPath, generalContext.Repository.CommitId);

var gitCommit = CakeContext.GitLogTip(dynamicRepositoryPath);
if (!string.Equals(gitCommit.Sha, generalContext.Repository.CommitId, StringComparison.OrdinalIgnoreCase))
{
var gitExe = CakeContext.Tools.Resolve("git.exe").FullPath;

using (var process = CakeContext.StartAndReturnProcess(gitExe,
new ProcessSettings
{
WorkingDirectory = dynamicRepositoryPath,
Arguments = $"checkout -B {generalContext.Repository.BranchName} {generalContext.Repository.CommitId}",
}))
{
process.WaitForExit();

// This should output 0 as valid arguments supplied
CakeContext.Information("Exit code: {0}", process.GetExitCode());
}
}

CakeContext.Information("Preparing GitVersion settings");

gitVersionSettings.WorkingDirectory = dynamicRepositoryPath;
}

CakeContext.Information("Preparing GitVersion settings");
CakeContext.Information("Running GitVersion");

gitVersionSettings.RepositoryPath = dynamicRepositoryPath;
gitVersionSettings.Verbosity = GitVersionVerbosity.Verbose;
_gitVersionContext = CakeContext.GitVersion(gitVersionSettings);
}

_gitVersionContext = CakeContext.GitVersion(gitVersionSettings);
}

return _gitVersionContext;
Expand Down