Skip to content

NextVersion.txt and GitVersionConfig.yaml support for dynamic repositories #352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
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
48 changes: 44 additions & 4 deletions GitVersionCore.Tests/Helpers/GitTestExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Threading;
using GitVersion;
using LibGit2Sharp;

Expand All @@ -13,10 +14,7 @@ public static Commit MakeACommit(this IRepository repository)

public static Commit MakeACommit(this IRepository repository, DateTimeOffset dateTimeOffset)
{
var randomFile = Path.Combine(repository.Info.WorkingDirectory, Guid.NewGuid().ToString());
File.WriteAllText(randomFile, string.Empty);
repository.Index.Stage(randomFile);
return repository.Commit("Test Commit", Constants.Signature(dateTimeOffset), Constants.Signature(dateTimeOffset));
return CreateFileAndCommit(repository, Guid.NewGuid().ToString(), dateTimeOffset);
}

public static void MergeNoFF(this IRepository repository, string branch)
Expand All @@ -39,6 +37,48 @@ public static Commit[] MakeCommits(this IRepository repository, int numCommitsTo
.ToArray();
}

public static Commit CreateFileAndCommit(this IRepository repository, string relativeFileName, DateTimeOffset dateTimeOffset = default(DateTimeOffset))
{
if (dateTimeOffset == default(DateTimeOffset))
{
dateTimeOffset = DateTimeOffset.Now;
}

var randomFile = Path.Combine(repository.Info.WorkingDirectory, relativeFileName);
if (File.Exists(randomFile))
{
File.Delete(randomFile);
}

File.WriteAllText(randomFile, Guid.NewGuid().ToString());

// GHK: 2015-01-18: I know it's very ugly, but somehow we need to retry here otherwise "there is nothing to commit"
var retryCount = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JakeGinnivan @nulltoken thoughts on how to avoid doing this retry?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed config based versioning branch to increment the commit time for each commit - 14487a0#diff-c7ff189f687fa58758611ef26120e6dcR8

Not sure if this would fix the issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SimonCropp @JakeGinnivan EmptyCommitException is raised when the tree about to be committed matches the tree from the parent commit. This means that no modification has been detected. My guess is that is related to a known issue in libgit2 (see libgit2/libgit2sharp#688).

Meanwhile, in order to work around this, just make sure that your files are of random length

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already implemented random content, but we can also add random length as well. Doesn't libgit see a difference when the file contents are different but equal length?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GeertvanHorrik Time is also a variable of the equation. See libgit2/libgit2sharp#688 (comment)

while (retryCount > 0)
{
try
{
repository.Stage(randomFile);

return repository.Commit(string.Format("Test Commit for file '{0}'", relativeFileName),
Constants.Signature(dateTimeOffset), Constants.Signature(dateTimeOffset));
}
catch (EmptyCommitException)
{
if (retryCount <= 0)
{
throw;
}

Thread.Sleep(100);
}

retryCount--;
}

return null;
}

public static Tag MakeATaggedCommit(this IRepository repository, string tag)
{
var commit = repository.MakeACommit();
Expand Down
54 changes: 39 additions & 15 deletions GitVersionExe.Tests/GitPreparerTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
 using System.IO;
using GitVersion;
using LibGit2Sharp;
using NUnit.Framework;
using System.IO;
using GitVersion;
using LibGit2Sharp;
using NUnit.Framework;

[TestFixture]
public class GitPreparerTests
Expand All @@ -17,21 +17,39 @@ public GitPreparerTests()
const string SpecificBranchName = "feature/foo";

[Test]
[TestCase(null, DefaultBranchName)]
[TestCase(SpecificBranchName, SpecificBranchName)]
public void WorksCorrectlyWithRemoteRepository(string branchName, string expectedBranchName)
[TestCase(null, DefaultBranchName, false)]
[TestCase(SpecificBranchName, SpecificBranchName, false)]
[TestCase(null, DefaultBranchName, true)]
[TestCase(SpecificBranchName, SpecificBranchName, true)]
public void WorksCorrectlyWithRemoteRepository(string branchName, string expectedBranchName, bool checkConfig)
{
var tempDir = Path.GetTempPath();

using (var fixture = new EmptyRepositoryFixture(new Config()))
{
fixture.Repository.MakeCommits(5);
fixture.Repository.CreateBranch("feature/foo");

if (checkConfig)
{
fixture.Repository.CreateFileAndCommit("GitVersionConfig.yaml");
}

fixture.Repository.CreateBranch(SpecificBranchName);

if (checkConfig)
{
fixture.Repository.Refs.UpdateTarget(fixture.Repository.Refs.Head, fixture.Repository.Refs["refs/heads/" + SpecificBranchName]);

fixture.Repository.CreateFileAndCommit("GitVersionConfig.yaml");

fixture.Repository.Refs.UpdateTarget(fixture.Repository.Refs.Head, fixture.Repository.Refs["refs/heads/" + DefaultBranchName]);
}

var arguments = new Arguments
{
TargetPath = tempDir,
TargetUrl = fixture.RepositoryPath
};
{
TargetPath = tempDir,
TargetUrl = fixture.RepositoryPath
};

if (!string.IsNullOrWhiteSpace(branchName))
{
Expand All @@ -49,6 +67,12 @@ public void WorksCorrectlyWithRemoteRepository(string branchName, string expecte
var currentBranch = repository.Head.CanonicalName;

Assert.IsTrue(currentBranch.EndsWith(expectedBranchName));

if (checkConfig)
{
var expectedConfigPath = Path.Combine(dynamicRepositoryPath, "..\\GitVersionConfig.yaml");
Assert.IsTrue(File.Exists(expectedConfigPath));
}
}
}
}
Expand All @@ -59,9 +83,9 @@ public void WorksCorrectlyWithLocalRepository()
var tempDir = Path.GetTempPath();

var arguments = new Arguments
{
TargetPath = tempDir
};
{
TargetPath = tempDir
};

var gitPreparer = new GitPreparer(arguments);
var dynamicRepositoryPath = gitPreparer.Prepare();
Expand Down
61 changes: 34 additions & 27 deletions GitVersionExe/GitPreparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,49 +61,56 @@ string GetGitInfoFromUrl()
Repository.Clone(arguments.TargetUrl, gitDirectory,
new CloneOptions
{
IsBare = true,
IsBare = true,
Checkout = false,
CredentialsProvider = (url, usernameFromUrl, types) => credentials
});

if (!string.IsNullOrWhiteSpace(arguments.TargetBranch))
{
// Normalize (download branches) before using the branch
GitHelper.NormalizeGitDirectory(gitDirectory, arguments.Authentication);
// Normalize (download branches) before using the branch
GitHelper.NormalizeGitDirectory(gitDirectory, arguments.Authentication);

using (var repository = new Repository(gitDirectory))
using (var repository = new Repository(gitDirectory))
{
var targetBranch = arguments.TargetBranch;
if (string.IsNullOrWhiteSpace(targetBranch))
{
Reference newHead = null;
targetBranch = repository.Head.Name;
}

var localReference = GetLocalReference(repository, arguments.TargetBranch);
if (localReference != null)
{
newHead = localReference;
}
Reference newHead = null;

var localReference = GetLocalReference(repository, targetBranch);
if (localReference != null)
{
newHead = localReference;
}

if (newHead == null)
if (newHead == null)
{
var remoteReference = GetRemoteReference(repository, targetBranch, arguments.TargetUrl);
if (remoteReference != null)
{
var remoteReference = GetRemoteReference(repository, arguments.TargetBranch, arguments.TargetUrl);
if (remoteReference != null)
{
repository.Network.Fetch(arguments.TargetUrl, new[]
repository.Network.Fetch(arguments.TargetUrl, new[]
{
string.Format("{0}:{1}", remoteReference.CanonicalName, arguments.TargetBranch)
string.Format("{0}:{1}", remoteReference.CanonicalName, targetBranch)
});

newHead = repository.Refs[string.Format("refs/heads/{0}", arguments.TargetBranch)];
}
newHead = repository.Refs[string.Format("refs/heads/{0}", targetBranch)];
}
}

if (newHead != null)
{
Logger.WriteInfo(string.Format("Switching to branch '{0}'", arguments.TargetBranch));

repository.Refs.UpdateTarget(repository.Refs.Head, newHead);
}
if (newHead != null)
{
Logger.WriteInfo(string.Format("Switching to branch '{0}'", targetBranch));

repository.CheckoutFilesIfExist("NextVersion.txt");
repository.Refs.UpdateTarget(repository.Refs.Head, newHead);
}

// < 3.0 method
repository.CheckoutFilesIfExist("NextVersion.txt");

// > 3.0 method
repository.CheckoutFilesIfExist("GitVersionConfig.yaml");
}

DynamicGitRepositoryPath = gitDirectory;
Expand Down