Skip to content

GitVersion Performance Issues #734

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 1 commit 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
49 changes: 48 additions & 1 deletion src/GitVersionCore/LibGitExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,39 @@ static bool IsSameBranch(Branch branch, Branch b)
{
return (b.IsRemote ? b.Name.Substring(b.Name.IndexOf("/", StringComparison.Ordinal) + 1) : b.Name) != branch.Name;
}
private static IEnumerable<Branch> TryGetBranchesContainingCommitFromGitCmd(Commit commit, IRepository repository)
{
try
{
var output = new StringBuilder();
ProcessHelper.Run(
o => output.AppendLine(o),
e => { },
null,
"git",
"branch -r --contains " + commit.Sha,
repository.Info.WorkingDirectory);

ProcessHelper.Run(
o => output.AppendLine(o),
e => { },
null,
"git",
"branch --contains " + commit.Sha,
repository.Info.WorkingDirectory);
if (output.Length > 0)
{
var branchNames = output.ToString().Replace("\r", "").Replace("*", ""/*current branch*/)
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(r => r.Trim());
return repository.Branches.Where(r => branchNames.Contains(r.Name));
}
return null;
}
catch (FileNotFoundException)
{
return null;
}
}
public static IEnumerable<Branch> GetBranchesContainingCommit([NotNull] this Commit commit, IRepository repository, IList<Branch> branches, bool onlyTrackedBranches)
{
if (commit == null)
Expand All @@ -154,7 +186,22 @@ public static IEnumerable<Branch> GetBranchesContainingCommit([NotNull] this Com
yield break;
}

foreach (var branch in branches.Where(b => (onlyTrackedBranches && !b.IsTracking)))
var branchesFromGitCmd = TryGetBranchesContainingCommitFromGitCmd(commit, repository);
if (branchesFromGitCmd != null)
{
foreach (var b in branchesFromGitCmd.Where(r => !onlyTrackedBranches || !r.IsTracking)
.Intersect(branches.Where(r => !onlyTrackedBranches || !r.IsTracking)))
{
yield return b;
}
}

if (branchesFromGitCmd != null)
{
yield break;
}

foreach (var branch in branches.Where(b => (!onlyTrackedBranches || !b.IsTracking)))
{
var commits = repository.Commits.QueryBy(new CommitFilter { Since = branch }).Where(c => c.Sha == commit.Sha);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,39 @@ public class TaggedCommitVersionStrategy : BaseVersionStrategy
public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
{
var olderThan = context.CurrentCommit.When();
var allTags = context.Repository.Tags
.Where(tag => ((Commit)tag.PeeledTarget()).When() <= olderThan)
.ToList();
var tagsOnBranch = context.CurrentBranch
.Commits
.SelectMany(commit =>
{
return allTags.Where(t => IsValidTag(t, commit));
})
var tags = context.Repository.Tags
.Where(tag => ((Commit)tag.PeeledTarget()).When() <= olderThan);

return GetVersionsFromTags(context, tags);
}

private IEnumerable<BaseVersion> GetVersionsFromTags(GitVersionContext context, IEnumerable<Tag> tags)
{
var currentBranchName = context.CurrentBranch.CanonicalName;
var versionedTags = tags.Where(t => IsTagInBranch(context, t.PeeledTarget() as Commit, currentBranchName))
.Select(t =>
{
SemanticVersion version;
if (SemanticVersion.TryParse(t.Name, context.Configuration.GitTagPrefix, out version))
{
var commit = t.PeeledTarget() as Commit;
if (commit != null)
return new VersionTaggedCommit(commit, version, t.Name);
return new VersionTaggedCommit((Commit)t.PeeledTarget(), version, t);
}
return null;
})
.Where(a => a != null)
.ToList();
}).Where(a => a != null);
return versionedTags.Select(t => CreateBaseVersion(context, t));
}

return tagsOnBranch.Select(t => CreateBaseVersion(context, t));
static bool IsTagInBranch(GitVersionContext context, Commit tagCommit, string currentBranchName)
{
if(tagCommit == null)
{
return false;
}
var branches = tagCommit.GetBranchesContainingCommit(context.Repository, new List<Branch> { context.CurrentBranch }, false).ToList();
return branches.Any(b =>b.CanonicalName == currentBranchName);
}

BaseVersion CreateBaseVersion(GitVersionContext context, VersionTaggedCommit version)
protected BaseVersion CreateBaseVersion(GitVersionContext context, VersionTaggedCommit version)
{
var shouldUpdateVersion = version.Commit.Sha != context.CurrentCommit.Sha;
var baseVersion = new BaseVersion(FormatSource(version), shouldUpdateVersion, version.SemVer, version.Commit, null);
Expand All @@ -47,23 +53,18 @@ protected virtual string FormatSource(VersionTaggedCommit version)
return string.Format("Git tag '{0}'", version.Tag);
}

protected virtual bool IsValidTag(Tag tag, Commit commit)
{
return tag.PeeledTarget() == commit;
}

protected class VersionTaggedCommit
{
public string Tag;
public Tag Tag;
public Commit Commit;
public SemanticVersion SemVer;

public VersionTaggedCommit(Commit commit, SemanticVersion semVer, string tag)
public VersionTaggedCommit(Commit commit, SemanticVersion semVer, Tag tag)
{
Tag = tag;
Commit = commit;
SemVer = semVer;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,36 @@ public override IEnumerable<BaseVersion> GetVersions(GitVersionContext context)
{
yield break;
}
var olderThan = context.CurrentCommit.When();
var allTags = context.Repository.Tags
.Where(tag => ((Commit)tag.PeeledTarget()).When() <= olderThan)
.ToList();
var tagsOnBranch = context.CurrentBranch
.Commits
.SelectMany(commit =>
{
return allTags.Where(t => IsValidTag(context, t, commit));
})
.Select(t =>
{
SemanticVersion version;
if (SemanticVersion.TryParse(t.Name, context.Configuration.GitTagPrefix, out version))
{
var commit = t.PeeledTarget() as Commit;
if (commit != null)
return new VersionTaggedCommit(commit, version, t);
}
return null;
})
.Where(a => a != null);

foreach (var version in base.GetVersions(context))
foreach (var result in tagsOnBranch.Select(t => CreateBaseVersion(context, t)))
{
yield return version;
yield return result;
}
}

protected override bool IsValidTag(Tag tag, Commit commit)
static bool IsValidTag(GitVersionContext context, Tag tag, Commit commit)
{
return IsDirectMergeFromCommit(tag, commit);
}
Expand Down