public void CreateNotARepoTest() { Assert.Null(GitRepository.Create(null)); Assert.Null(GitRepository.Create("")); Assert.Null(GitRepository.Create("/A/Path/To/A/Directory/Which/Does/Not/Exist")); Assert.Null(GitRepository.Create(this.RepoPath)); }
public void GetObjectByShaAndWrongTypeTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { Assert.Throws <GitException>(() => repository.GetObjectBySha(headObjectId, "tree")); } }
public void GetInvalidCommitTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { Assert.Throws <GitException>(() => repository.GetCommit(GitObjectId.Empty)); } }
public void GetMissingObjectByShaTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { Assert.Throws <GitException>(() => repository.GetObjectBySha(GitObjectId.Parse("7d6b2c56ffb97eedb92f4e28583c093f7ee4b3d9"), "commit")); Assert.Null(repository.GetObjectBySha(GitObjectId.Empty, "commit")); } }
public void CreateTest() { this.InitializeSourceControl(); this.AddCommits(1); using (var repository = GitRepository.Create(this.RepoPath)) { AssertPath(Path.Combine(this.RepoPath, ".git"), repository.CommonDirectory); AssertPath(Path.Combine(this.RepoPath, ".git"), repository.GitDirectory); AssertPath(this.RepoPath, repository.WorkingDirectory); AssertPath(Path.Combine(this.RepoPath, ".git", "objects"), repository.ObjectDirectory); } }
public void GetCommitTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { var commit = repository.GetCommit(headObjectId); Assert.Equal(headObjectId, commit.Sha); } }
public void CreateGitRepository() { string dir = GetTempPath(); string file = Path.Combine(dir, "file"); using (GitRepository repo = GitRepository.Create(dir)) { Assert.That(repo, Is.Not.Null); Assert.That(repo.IsEmpty, Is.True); Assert.That(repo.IsBare, Is.False); Assert.That(repo.RepositoryDirectory, Is.EqualTo(Path.Combine(dir, GitClient.AdministrativeDirectoryName))); Assert.That(repo.WorkingCopyDirectory, Is.EqualTo(dir)); GitConfiguration config = repo.Configuration; Assert.That(config, Is.Not.Null); GitIndex index = repo.Index; Assert.That(index, Is.Not.Null); //repo.SetIndex(index); GitObjectDatabase odb = repo.ObjectDatabase; Assert.That(odb, Is.Not.Null); //repo.SetObjectDatabase(odb); File.WriteAllText(file, "qqq"); repo.Index.Add("file"); Assert.That(repo.Configuration.Set(GitConfigurationLevel.Repository, GitConfigurationKeys.UserName, "Tester")); Assert.That(repo.Configuration.Set(GitConfigurationLevel.Repository, GitConfigurationKeys.UserEmail, "[email protected]")); string v; Assert.That(repo.Configuration.TryGetString(GitConfigurationKeys.UserName, out v)); Assert.That(v, Is.EqualTo("Tester")); Assert.That(repo.Configuration.TryGetString(GitConfigurationKeys.UserEmail, out v)); Assert.That(v, Is.EqualTo("[email protected]")); Assert.That(index.Contains("file")); GitIndexEntry entry = repo.Index["file"]; Assert.That(entry, Is.Not.Null); Assert.That(entry.FileSize, Is.EqualTo(3)); Assert.That(entry.Id, Is.EqualTo(new GitId("E5A49F32170B89EE4425C4AB09E70DFCDB93E174"))); index.Reload(); Assert.That(index.Contains("file"), Is.False); } }
public void StatusTest() { string[] A = new string[] { "A/a", "A/b", "A/c", "A/d" }; string[] B = new string[] { "B/a", "B/b", "B/c", "B/d" }; string[] C = new string[] { "C/a", "C/b", "C/c", "C/d" }; List <string> all = new List <string>(); all.AddRange(A); all.AddRange(B); all.AddRange(C); using (GitRepository repo = GitRepository.Create(GetTempPath())) { foreach (string d in all) { string fp = Path.Combine(repo.WorkingCopyDirectory, d); Directory.CreateDirectory(Path.GetDirectoryName(fp)); File.WriteAllText(fp, string.Format("This is {0}\n", fp)); repo.Index.Add(d); } repo.Index.Write(); using (GitClient git = new GitClient()) { List <string> found = new List <string>(); GitStatusArgs sa = new GitStatusArgs(); git.Status(Path.Combine(repo.WorkingCopyDirectory, "B"), delegate(object sender, GitStatusEventArgs e) { found.Add(e.RelativePath); }); Assert.That(found.Count, Is.EqualTo(4)); Assert.That(found, Is.All.GreaterThan("B")); Assert.That(found, Is.All.LessThan("C")); found.Clear(); git.Status(Path.Combine(repo.WorkingCopyDirectory, "B/c"), delegate(object sender, GitStatusEventArgs e) { found.Add(e.RelativePath); }); Assert.That(found.Count, Is.EqualTo(1)); Assert.That(found, Is.All.Contains("B/c")); } } }
public void GetObjectFromAlternateTest() { // Add 2 alternates for this repository, each with their own commit. // Make sure that commits from the current repository and the alternates // can be found. // // Alternate1 Alternate2 // | | // +-----+ +-----+ // | // Repo this.InitializeSourceControl(); var localCommit = this.LibGit2Repository.Commit("Local", this.Signer, this.Signer, new CommitOptions() { AllowEmptyCommit = true }); var alternate1Path = this.CreateDirectoryForNewRepo(); this.InitializeSourceControl(alternate1Path).Dispose(); var alternate1 = new Repository(alternate1Path); var alternate1Commit = alternate1.Commit("Alternate 1", this.Signer, this.Signer, new CommitOptions() { AllowEmptyCommit = true }); var alternate2Path = this.CreateDirectoryForNewRepo(); this.InitializeSourceControl(alternate2Path).Dispose(); var alternate2 = new Repository(alternate2Path); var alternate2Commit = alternate2.Commit("Alternate 2", this.Signer, this.Signer, new CommitOptions() { AllowEmptyCommit = true }); var objectDatabasePath = Path.Combine(this.RepoPath, ".git", "objects"); Directory.CreateDirectory(Path.Combine(this.RepoPath, ".git", "objects", "info")); File.WriteAllText( Path.Combine(this.RepoPath, ".git", "objects", "info", "alternates"), $"{Path.GetRelativePath(objectDatabasePath, Path.Combine(alternate1Path, ".git", "objects"))}:{Path.GetRelativePath(objectDatabasePath, Path.Combine(alternate2Path, ".git", "objects"))}:"); using (GitRepository repository = GitRepository.Create(this.RepoPath)) { Assert.Equal(localCommit.Sha, repository.GetCommit(GitObjectId.Parse(localCommit.Sha)).Sha.ToString()); Assert.Equal(alternate1Commit.Sha, repository.GetCommit(GitObjectId.Parse(alternate1Commit.Sha)).Sha.ToString()); Assert.Equal(alternate2Commit.Sha, repository.GetCommit(GitObjectId.Parse(alternate2Commit.Sha)).Sha.ToString()); } }
public void GetInvalidTreeEntryTest() { this.InitializeSourceControl(); File.WriteAllText(Path.Combine(this.RepoPath, "hello.txt"), "Hello, World"); Commands.Stage(this.LibGit2Repository, "hello.txt"); this.AddCommits(); using (var repository = GitRepository.Create(this.RepoPath)) { var headCommit = repository.GetHeadCommit(); Assert.NotNull(headCommit); Assert.Equal(GitObjectId.Empty, repository.GetTreeEntry(headCommit.Value.Tree, Encoding.UTF8.GetBytes("goodbye.txt"))); } }
public void GetHeadMissingTest() { this.InitializeSourceControl(withInitialCommit: false); using (var repository = GitRepository.Create(this.RepoPath)) { var head = repository.GetHeadAsReferenceOrSha(); var reference = Assert.IsType <string>(head); Assert.Equal("refs/heads/master", reference); Assert.Equal(GitObjectId.Empty, repository.GetHeadCommitSha()); Assert.Null(repository.GetHeadCommit()); } }
public void GetTreeEntryTest() { this.InitializeSourceControl(); File.WriteAllText(Path.Combine(this.RepoPath, "hello.txt"), "Hello, World"); Commands.Stage(this.LibGit2Repository, "hello.txt"); this.AddCommits(); using (var repository = GitRepository.Create(this.RepoPath)) { var headCommit = repository.GetHeadCommit(); Assert.NotNull(headCommit); var helloBlobId = repository.GetTreeEntry(headCommit.Value.Tree, Encoding.UTF8.GetBytes("hello.txt")); Assert.Equal("1856e9be02756984c385482a07e42f42efd5d2f3", helloBlobId.ToString()); } }
public void GetObjectByShaTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { var commitStream = repository.GetObjectBySha(headObjectId, "commit"); Assert.NotNull(commitStream); var objectStream = Assert.IsType <GitObjectStream>(commitStream); Assert.Equal("commit", objectStream.ObjectType); Assert.Equal(186, objectStream.Length); } }
public void CreateWorkTreeTest() { this.InitializeSourceControl(); this.AddCommits(2); string workTreePath = this.CreateDirectoryForNewRepo(); Directory.Delete(workTreePath); this.LibGit2Repository.Worktrees.Add("HEAD~1", "myworktree", workTreePath, isLocked: false); using (var repository = GitRepository.Create(workTreePath)) { AssertPath(Path.Combine(this.RepoPath, ".git"), repository.CommonDirectory); AssertPath(Path.Combine(this.RepoPath, ".git", "worktrees", "myworktree"), repository.GitDirectory); AssertPath(workTreePath, repository.WorkingDirectory); AssertPath(Path.Combine(this.RepoPath, ".git", "objects"), repository.ObjectDirectory); } }
internal ManagedGitContext(string workingDirectory, string dotGitPath, string?committish = null) : base(workingDirectory, dotGitPath) { GitRepository?repo = GitRepository.Create(workingDirectory); if (repo is null) { throw new ArgumentException("No git repo found here.", nameof(workingDirectory)); } this.Commit = committish is null?repo.GetHeadCommit() : (repo.Lookup(committish) is { } objectId ? (GitCommit?)repo.GetCommit(objectId) : null); if (this.Commit is null && committish is object) { throw new ArgumentException("No matching commit found.", nameof(committish)); } this.Repository = repo; this.VersionFile = new ManagedVersionFile(this); }
public void GetHeadAsReferenceTest() { this.InitializeSourceControl(); this.AddCommits(2); var headObjectId = GitObjectId.Parse(this.LibGit2Repository.Head.Tip.Sha); using (var repository = GitRepository.Create(this.RepoPath)) { var head = repository.GetHeadAsReferenceOrSha(); var reference = Assert.IsType <string>(head); Assert.Equal("refs/heads/master", reference); Assert.Equal(headObjectId, repository.GetHeadCommitSha()); var headCommit = repository.GetHeadCommit(); Assert.NotNull(headCommit); Assert.Equal(headObjectId, headCommit.Value.Sha); } }
public void GetHeadAsShaTest() { this.InitializeSourceControl(); this.AddCommits(2); var newHead = this.LibGit2Repository.Head.Tip.Parents.Single(); var newHeadObjectId = GitObjectId.Parse(newHead.Sha); Commands.Checkout(this.LibGit2Repository, this.LibGit2Repository.Head.Tip.Parents.Single()); using (var repository = GitRepository.Create(this.RepoPath)) { var detachedHead = repository.GetHeadAsReferenceOrSha(); var reference = Assert.IsType <GitObjectId>(detachedHead); Assert.Equal(newHeadObjectId, reference); Assert.Equal(newHeadObjectId, repository.GetHeadCommitSha()); var headCommit = repository.GetHeadCommit(); Assert.NotNull(headCommit); Assert.Equal(newHeadObjectId, headCommit.Value.Sha); } }
public void UseGitClient() { GitCommitArgs ga = new GitCommitArgs(); ga.Author.Name = "Tester"; ga.Author.EmailAddress = "*****@*****.**"; ga.Signature.Name = "Other"; ga.Signature.EmailAddress = "*****@*****.**"; // Use stable time and offset to always produce the same hash DateTime ct = new DateTime(2002, 01, 01, 0, 0, 0, DateTimeKind.Utc); ga.Author.When = ct; ga.Author.TimeOffsetInMinutes = 120; ga.Signature.When = ct; ga.Signature.TimeOffsetInMinutes = 120; string repoDir = GetTempPath(); string repo2Dir = GetTempPath(); GitId firstResult; GitId lastCommit; using (GitRepository repo = GitRepository.Create(repoDir)) using (GitClient git = new GitClient()) { string ignoreFile = Path.Combine(repoDir, ".gitignore"); string file = Path.Combine(repoDir, "newfile"); string subDir = Path.Combine(repoDir, "dir"); string fileInSubDir = Path.Combine(subDir, "file2"); string file3 = Path.Combine(repoDir, "other"); string file4 = Path.Combine(repoDir, "q.ignore"); File.WriteAllText(file, "Some body"); Directory.CreateDirectory(subDir); File.WriteAllText(fileInSubDir, "Some other body"); File.WriteAllText(file3, "file3"); File.WriteAllText(ignoreFile, "*.ignore\n"); File.WriteAllText(file4, "file4"); git.Add(ignoreFile); git.Add(file); git.Commit(repoDir, ga, out firstResult); git.Add(fileInSubDir); int ticked = 0; File.AppendAllText(file, "\nExtra Line"); GitStatusArgs gsa = new GitStatusArgs(); gsa.IncludeIgnored = true; gsa.IncludeUnmodified = true; Assert.That(git.Status(repoDir, gsa, delegate(object sender, GitStatusEventArgs e) { switch (e.RelativePath) { case "newfile": //Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Added)); Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal), "newfile index normal"); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal), "newfile wc modified"); Assert.That(e.WorkingDirectoryModified); Assert.That(e.Ignored, Is.False); break; case "dir/file2": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.New), "file2 index added"); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal), "file2 wc normal"); Assert.That(e.Ignored, Is.False); break; case "other": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None)); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New)); Assert.That(e.Ignored, Is.False); break; case ".gitignore": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal)); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal)); Assert.That(e.Ignored, Is.False); break; case "q.ignore": // TODO: Make this ignored Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None)); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal)); Assert.That(e.Ignored, Is.True); break; default: Assert.Fail("Invalid node found: {0}", e.RelativePath); break; } Assert.That(e.FullPath, Is.EqualTo(Path.GetFullPath(Path.Combine(repoDir, e.RelativePath)))); ticked++; }), Is.True); Assert.That(ticked, Is.EqualTo(5), "Ticked"); ga.LogMessage = "Intermediate"; git.Commit(repoDir, ga); Assert.That(git.Delete(fileInSubDir)); Assert.That(git.Add(file)); GitId commit; ga.LogMessage = "A log message to remember"; // The passed path is currently just used to find the local repository lastCommit = new GitId("996cf198b49ed6fce3bcba232e2d88eb473560f9"); Assert.That(git.Commit(repoDir, ga, out commit)); Assert.That(commit, Is.EqualTo(lastCommit)); File.Move(file, file + ".a"); ticked = 0; gsa.IncludeIgnored = false; gsa.IncludeUnversioned = true; gsa.IncludeUnmodified = false; Assert.That(git.Status(repoDir, gsa, delegate(object sender, GitStatusEventArgs e) { switch (e.RelativePath) { /*case "dir": * Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal), "dir index normal"); * Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "dir wc normal"); * break;*/ case "newfile": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "newfile index normal"); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Deleted), "newfile wc deleted"); break; case "newfile.a": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "newfile.a index normal"); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "newfile.a wc new"); break; case "other": Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "other index normal"); Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "other wc normal"); break; default: Assert.Fail("Invalid node found: {0}", e.RelativePath); break; } Assert.That(e.FullPath, Is.EqualTo(Path.GetFullPath(Path.Combine(repoDir, e.RelativePath)))); ticked++; }), Is.True); Assert.That(ticked, Is.EqualTo(3)); GitCloneArgs gc = new GitCloneArgs(); gc.Synchronous = true; git.Clone(repoDir, repo2Dir, gc); GitCommit theCommit; Assert.That(repo.Lookup(commit, out theCommit)); Assert.That(repo.Branches.Create(theCommit, "vNext")); Assert.That(repo.Branches, Is.Not.Empty); } using (GitRepository repo1 = new GitRepository(repoDir)) using (GitRepository repo2 = new GitRepository(repo2Dir)) { GitReference head = repo1.HeadReference; Assert.That(head, Is.Not.Null, "Has head"); Assert.That(head.Name, Is.EqualTo("refs/heads/master")); //Assert.That(repo2.Head, Is.Not.Null); GitId headId; Assert.That(repo1.ResolveReference(repo1.HeadReference, out headId)); Assert.That(headId, Is.EqualTo(lastCommit)); GitCommit commit; Assert.That(repo1.Lookup(headId, out commit)); Assert.That(commit, Is.Not.Null, "Have a commit"); Assert.That(commit.Id, Is.EqualTo(lastCommit)); Assert.That(commit.Ancestors, Is.Not.Empty); Assert.That(commit.Ancestor, Is.Not.Null); Assert.That(commit.Ancestor.Ancestor, Is.Not.Null); Assert.That(commit.Ancestor.Ancestor.Ancestor, Is.Null); Assert.That(commit.Ancestor.Ancestor.Id, Is.EqualTo(firstResult)); Assert.That(commit.Author, Is.Not.Null); Assert.That(commit.Author.Name, Is.EqualTo("Tester")); Assert.That(commit.Author.EmailAddress, Is.EqualTo("*****@*****.**")); Assert.That(commit.Committer, Is.Not.Null); Assert.That(commit.Committer.Name, Is.EqualTo("Other")); Assert.That(commit.Committer.EmailAddress, Is.EqualTo("*****@*****.**")); Assert.That(commit.Committer.TimeOffsetInMinutes, Is.EqualTo(120), "Time offset"); // CEST dependent Assert.That(commit.Committer.When, Is.EqualTo(ct), "Exact time"); Assert.That(commit.LogMessage, Is.EqualTo("A log message to remember\n")); Assert.That(commit.Parents, Is.Not.Empty); Assert.That(commit.ParentIds, Is.Not.Empty); Assert.That(commit.Tree, Is.Not.Empty); Assert.That(commit.Tree.Count, Is.EqualTo(2)); Assert.That(commit.Ancestor.Tree.Count, Is.EqualTo(3)); Assert.That(commit.Ancestor.Ancestor.Tree.Count, Is.EqualTo(2)); Assert.That(commit.Tree.Id, Is.Not.EqualTo(commit.Ancestor.Tree.Id)); GitId id; Assert.That(repo1.LookupViaPrefix(commit.Id.ToString(), out id)); Assert.That(id, Is.EqualTo(commit.Id)); Assert.That(repo1.LookupViaPrefix(commit.Id.ToString().Substring(0, 10), out id)); Assert.That(id, Is.EqualTo(commit.Id)); Assert.That(commit.Peel <GitObject>().Id, Is.EqualTo(commit.Tree.Id)); Assert.That(commit.Peel <GitTree>(), Is.EqualTo(commit.Tree)); // Compares members Assert.That(commit.Tree.Peel <GitObject>(), Is.Null); GitTagArgs ta = new GitTagArgs(); ta.Signature.When = ct; ta.Signature.Name = "Me"; ta.Signature.EmailAddress = "[email protected]"; ta.LogMessage = "Some message"; ga.Author.TimeOffsetInMinutes = 120; Assert.That(commit.Tag("MyTag", ta, out id)); Assert.That(id, Is.EqualTo(new GitId("db31f8333fc64d7e7921ea91f6e007b755dcfcbb"))); GitTag tag; Assert.That(repo1.Lookup(id, out tag)); Assert.That(tag, Is.Not.Null); Assert.That(tag.Name, Is.EqualTo("MyTag")); Assert.That(tag.LogMessage, Is.EqualTo("Some message\n")); Assert.That(tag.Tagger.Name, Is.EqualTo("Me")); Assert.That(tag.Target.Id, Is.EqualTo(commit.Id)); Assert.That(tag.Peel <GitTree>(), Is.EqualTo(commit.Peel <GitTree>())); repo1.CheckOut(commit.Tree); //Console.WriteLine("1:"); //foreach (GitTreeEntry e in commit.Tree) //{ // Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count)); //} //Console.WriteLine("2:"); //foreach (GitTreeEntry e in commit.Ancestor.Tree) //{ // Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count)); //} //Console.WriteLine("3:"); //foreach (GitTreeEntry e in commit.Ancestor.Ancestor.Tree) //{ // Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count)); //} //Console.WriteLine("-"); } }
/// <summary> /// Initializes a new instance of the <see cref="VersionGenerator"/> class. /// </summary> /// <param name="path_to_version_file">A full or relative path to a JSON version file.</param> public VersionGenerator(string path_to_version_file) { string full_version_file_path = Path.GetFullPath(path_to_version_file); FileInfo version_file_info = new FileInfo(full_version_file_path); VersionStruct versionStruct; using (StreamReader fileStream = File.OpenText(full_version_file_path)) { versionStruct = JsonSerializer.CreateDefault().Deserialize <VersionStruct>(new JsonTextReader(fileStream)); } SemVersion version_from_file; if (string.IsNullOrEmpty(versionStruct.Version) || !SemVersion.TryParse(versionStruct.Version, out version_from_file, true)) { throw new ArgumentException("Version JSON file does not contain proper Version value", "path_to_version_file"); } DirectoryInfo repository_directory = version_file_info.Directory; while (!repository_directory.GetDirectories().Where(info => info.Name == ".git").Any()) { repository_directory = repository_directory.Parent; if (repository_directory == null) { throw new ArgumentException("Version file is not contained in any git repository"); } } using (GitRepository repo = GitRepository.Create(repository_directory.FullName)) { if (repo.GetHeadCommit() == null) { throw new ArgumentException("Version file is contained in the repository without commits or git HEAD is corrupted"); } if (repo.GetAllTags().Any(t => t.Target == repo.GetHeadCommit().Value.Sha)) { GitTag commitTag = repo.GetAllTags().FirstOrDefault(t => t.Target == repo.GetHeadCommit().Value.Sha); branch_name = "tag " + commitTag.Name; } else { object head = repo.GetHeadAsReferenceOrSha(); if (head is string headName) { branch_name = headName.Substring("refs/heads/".Length); } else { branch_name = "detached HEAD"; } } StringBuilder version_string_builder = new StringBuilder(); Regex non_semver_characters_regex = new Regex(@"[^0-9A-Za-z-]+", RegexOptions.ECMAScript | RegexOptions.Compiled); string normalized_head_name = non_semver_characters_regex.Replace(branch_name, "-"); version_string_builder.Append(version_from_file.Major); version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Minor); version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Patch); if (!string.IsNullOrEmpty(version_from_file.Prerelease)) { version_string_builder.Append('-'); version_string_builder.Append(version_from_file.Prerelease); DateTime commit_time = repo.GetHeadCommit().Value.Committer.Date.UtcDateTime; DateTimeOffset commit_time_offset = new DateTimeOffset(commit_time); // The numerical constant here is UNIX time of January 1st, 2020 12:00 AM UTC long commit_time_in_seconds = commit_time_offset.ToUnixTimeSeconds() - 1577836800; version_string_builder.Append('.'); version_string_builder.Append(commit_time_in_seconds); version_string_builder.Append('.'); version_string_builder.Append(normalized_head_name); } version_without_build_data = version_string_builder.ToString(); version_string_builder.Append('+'); Regex codename_regex = new Regex(@"^[0-9A-Za-z-]+$", RegexOptions.ECMAScript | RegexOptions.Compiled); if (!string.IsNullOrEmpty(versionStruct.Codename) && codename_regex.IsMatch(versionStruct.Codename)) { version_string_builder.Append("codename"); version_string_builder.Append('.'); version_string_builder.Append(versionStruct.Codename); version_string_builder.Append('.'); } version_string_builder.Append("head"); version_string_builder.Append('.'); version_string_builder.Append(normalized_head_name); version_string_builder.Append('.'); version_string_builder.Append("commit"); version_string_builder.Append('.'); commit_hash = repo.GetHeadCommit().Value.Sha.ToString(); version_string_builder.Append(commit_hash); if (!string.IsNullOrEmpty(version_from_file.Build)) { version_string_builder.Append('.'); version_string_builder.Append(version_from_file.Build); } full_version = version_string_builder.ToString(); } }