protected GitId NextGitId() { var id = new GitId(m_NextCommitId.ToString("X6")); m_NextCommitId += 100; return(id); }
async ValueTask <GitId?> LoadIdFromFile(string fileName) { if (string.IsNullOrEmpty(fileName)) { throw new ArgumentNullException(nameof(fileName)); } if (!GitRepository.TryReadRefFile(fileName, null, out var body)) { return(null); } if (body.StartsWith("ref:", StringComparison.Ordinal)) { var ob = await Repository.ReferenceRepository.GetAsync(body.Substring(4).Trim()).ConfigureAwait(false); return(ob?.Id); } else if (GitId.TryParse(body, out var oid)) { return(oid); } else if (GitId.TryParse(body.Trim(), out oid)) { return(oid); } return(null); }
public ChangeLogEntry( DateTime date, CommitType type, string?scope, bool isBreakingChange, string summary, IReadOnlyList <string> body, IReadOnlyList <ChangeLogEntryFooter> footers, IReadOnlyList <string> breakingChangeDescriptions, GitId commit) { if (footers is null) { throw new ArgumentNullException(nameof(footers)); } if (breakingChangeDescriptions is null) { throw new ArgumentNullException(nameof(breakingChangeDescriptions)); } Date = date; Type = type; Scope = scope; ContainsBreakingChanges = isBreakingChange || breakingChangeDescriptions.Count > 0; Summary = summary ?? throw new ArgumentNullException(nameof(summary)); Body = body ?? throw new ArgumentNullException(nameof(body)); Footers = footers; BreakingChangeDescriptions = breakingChangeDescriptions; Commit = commit; }
protected internal override async ValueTask <GitReference?> ResolveAsync(GitReference gitReference) { string dir = gitReference.Name.Contains('/', StringComparison.Ordinal) ? GitDir : WorkTreeDir; string fileName = Path.Combine(dir, gitReference.Name); if (!File.Exists(fileName)) { return(null); } if (GitRepository.TryReadRefFile(fileName, null, out var body)) { if (body.StartsWith("ref: ", StringComparison.OrdinalIgnoreCase)) { body = body.Substring("ref: ".Length); var ob = await Repository.ReferenceRepository.GetAsync(body.Trim()).ConfigureAwait(false); if (ob is not null) { return(ob); } } else if (GitId.TryParse(body, out var id)) { return(new GitReference(Repository.ReferenceRepository, gitReference.Name, id)); } } return(gitReference); // Not symbolic, and exists. Or error and exists }
public override async ValueTask <TGitObject?> GetByIdAsync <TGitObject>(GitId id) where TGitObject : class { var name = id.ToString(); string path = Path.Combine(_objectsDir, name.Substring(0, 2), name.Substring(2)); if (!File.Exists(path)) { return(null); } var fileReader = FileBucket.OpenRead(path, false); try { var rdr = new GitObjectFileBucket(fileReader); GitObject ob = await GitObject.FromBucketAsync(Repository, rdr, id).ConfigureAwait(false); if (ob is TGitObject tg) { return(tg); } rdr.Dispose(); return(null); } catch { fileReader.Dispose(); throw; } }
protected async ValueTask <(bool Success, uint Index)> TryFindIdAsync(GitId id) { if (FanOut == null) { return(false, 0); } uint first = (id[0] == 0) ? 0 : FanOut[id[0] - 1]; uint countAfter = FanOut[id[0]]; if (first == countAfter) // Includes countAfter=0, which overflows the loop { // No need to check. return(false, 0); } uint c = countAfter; while (first + 1 < c) { uint mid = first + (c - first) / 2; var check = await GetGitIdByIndexAsync(mid).ConfigureAwait(false); int n = id.CompareTo(check); if (n == 0) { return(true, mid); } else if (n < 0) { c = mid; } else { first = mid + 1; } } if (first >= countAfter) { return(false, countAfter); } var check2 = await GetGitIdByIndexAsync(first).ConfigureAwait(false); int n2 = id.CompareTo(check2); if (n2 == 0) { return(true, first); } else if (n2 > 0) { first++; } return(false, first); }
public async ValueTask <GitId> ReadTreeIdAsync() { if (_treeId is not null) { return(_treeId); } var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 5 /* "tree " */ + GitId.MaxHashLength * 2 + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("tree ")) { throw new GitBucketException($"Expected 'tree' record at start of commit in '{Inner.Name}'"); } if (GitId.TryParse(bb.Slice(5, eol), out var id)) { _treeId = id; } else { throw new GitBucketException($"Expected valid 'tree' record at start of commit in '{Inner.Name}'"); } return(_treeId); }
private protected virtual async ValueTask ReadRefs() { string fileName = Path.Combine(GitDir, PackedRefsFile); if (!File.Exists(fileName)) { return; } try { using var sr = FileBucket.OpenRead(fileName, false); var idLength = GitId.HashLength(Repository.InternalConfig.IdType) * 2; GitRefPeel?last = null; while (true) { var(bb, eol) = await sr.ReadUntilEolFullAsync(BucketEol.LF).ConfigureAwait(false); if (bb.IsEof) { return; } bb = bb.Trim(eol); ParseLineToPeel(bb, ref last, idLength); } } catch (FileNotFoundException) { return; } }
internal override bool ContainsId(GitId id) { var name = id.ToString(); string path = Path.Combine(_objectsDir, name.Substring(0, 2), name.Substring(2)); return(File.Exists(path)); }
GitCommitInfo EnsureCommit(GitId id) { if (!Commits.TryGetValue(id, out var v)) { Commits.Add(id, v = new GitCommitInfo(id, Repository)); } return(v); }
public async Task WalkHistory(string path) { //bool small = false; if (path.Contains('>')) { path = GitTestEnvironment.GetRepository((GitTestDir)Enum.Parse(typeof(GitTestDir), path.Substring(1))); return; } using var repo = GitRepository.Open(path); if (repo.IsShallow) { return; } var r = await repo.GetPlumbing().RevisionList(new GitRevisionListArgs { MaxCount = 32, FirstParentOnly = true }).ToListAsync(); Assert.AreEqual(32, r.Count); Assert.AreEqual(32, r.Count(x => x != null)); Assert.AreEqual(32, r.Distinct().Count()); var revs = repo.Head.Revisions.Take(32).Select(x => x.Commit.Id).ToList(); if (!r.SequenceEqual(revs)) { int?nDiff = null; for (int i = 0; i < Math.Min(revs.Count, r.Count); i++) { TestContext.WriteLine($"{i:00} {r[i]} - {revs[i]}"); if (!nDiff.HasValue && r[i] != revs[i]) { nDiff = i; } } Assert.Fail($"Different list at {nDiff}"); } if (repo.Commits[GitId.Parse("b71c6c3b64bc002731bc2d6c49080a4855d2c169")] is GitCommit manyParents) { TestContext.WriteLine($"Found commit {manyParents}, so we triggered the many parent handling"); manyParents.Revisions.Take(3).ToList(); Assert.IsTrue(manyParents.Parent !.ParentCount > 3); } var id = repo.Head.Id !.ToString(); for (int i = id.Length - 1; i > 7; i--) { string searchVia = id.Substring(0, i); Assert.IsNotNull(await repo.Commits.ResolveIdAsync(searchVia), $"Able to find via {searchVia}, len={i}"); } }
internal override ValueTask <GitObjectBucket?> ResolveById(GitId id) { var name = id.ToString(); string path = Path.Combine(_objectsDir, name.Substring(0, 2), name.Substring(2)); if (!File.Exists(path)) { return(default);
public async ValueTask <(GitId, GitObjectType)> ReadObjectIdAsync() { if (_objectId is not null) { return(_objectId, _type); } var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 7 /* "object " */ + GitId.MaxHashLength * 2 + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("object ")) { throw new GitBucketException($"Expected 'object' record at start of tag in '{Inner.Name}'"); } if (GitId.TryParse(bb.Slice(7, eol), out var id)) { _objectId = id; } else { throw new GitBucketException($"Expected valid 'object' record at start of tag in '{Inner.Name}'"); } (bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 5 /* "type " */ + 6 /* "commit" */ + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("type ")) { _objectId = null; throw new GitBucketException($"Expected 'type' record of tag in '{Inner.Name}'"); } bb = bb.Slice(5, eol); if (bb.EqualsASCII("commit")) { _type = GitObjectType.Commit; } else if (bb.EqualsASCII("tree")) { _type = GitObjectType.Tree; } else if (bb.EqualsASCII("blob")) { _type = GitObjectType.Blob; } else if (bb.EqualsASCII("tag")) { _type = GitObjectType.Tag; } else { throw new GitBucketException($"Expected valid 'type' record in tag in '{Inner.Name}'"); } return(_objectId, _type); }
public VersionInfo(NuGetVersion version, GitId commit) { if (commit.IsNull) { throw new ArgumentException("Commit must not be empty", nameof(commit)); } Version = version ?? throw new ArgumentNullException(nameof(version)); Commit = commit; }
private protected override async ValueTask ReadRefs() { GitRefPeel?last = null; var idLength = GitId.HashLength(Repository.InternalConfig.IdType) * 2; await foreach (var line in Repository.WalkPlumbingCommand("show-ref", new[] { "-d", "--head" }, expectedResults: new int[] { 0 /* ok */, 1 /* no references found */ }).ConfigureAwait(false)) { ParseLineToPeel(line.Trim(), ref last, idLength); } }
private protected void ParseLineToPeel(BucketBytes line, ref GitRefPeel?last, int idLength) { if (char.IsLetterOrDigit((char)line[0]) && line.Length > idLength + 1) { if (GitId.TryParse(line.Slice(0, idLength), out var oid)) { string name = line.Slice(idLength + 1).Trim().ToUTF8String(); if (GitReference.ValidName(name, false)) { _peelRefs ![name] = last = new GitRefPeel {
protected GitId NextGitId() { var shaBytes = new byte[20]; m_CommitIdSource.NextBytes(shaBytes); var fullId = String.Join("", shaBytes.Select(x => x.ToString("x2"))); var abbreviatedId = fullId.Substring(0, 7); var id = new GitId(fullId, abbreviatedId); return(id); }
protected async ValueTask <GitId> GetGitIdByIndexAsync(uint i) { int hashLength = GitId.HashLength(IdType); byte[] oidData = new byte[hashLength]; if (await ReadFromChunkAsync("OIDL", i * hashLength, oidData).ConfigureAwait(false) != hashLength) { throw new InvalidOperationException(); } return(new GitId(IdType, oidData)); }
public void Constructor_initializes_properties() { // ARRANGE var version = NuGetVersion.Parse("1.2.3-alpha"); var commit = new GitId("123abc"); // ACT var sut = new VersionInfo(version, commit); // ASSERT Assert.Equal(version, sut.Version); Assert.Equal(commit, sut.Commit); }
private async ValueTask <byte[]> GetOffsetArrayAsync(uint start, uint count, byte[] oids) { if (count == 0) { return(Array.Empty <byte>()); } if (_ver == 2) { int sz = GitId.HashLength(_idType); byte[] data = new byte[4 * count]; long offset = 8 /* header */ + 256 * 4 /* fanout */ + sz * _fanOut ![255] // Hashes
/// <summary> /// Initializes a new instance of <see cref="CommitReferenceTextElement"/> /// </summary> /// <param name="text">The text element's text</param> /// <param name="id">The commit's id</param> public CommitReferenceTextElement(string text, GitId id) { if (String.IsNullOrWhiteSpace(text)) { throw new ArgumentException("Value must not be null or whitespace", nameof(text)); } if (id.IsNull) { throw new ArgumentException("Commit id must not be empty", nameof(id)); } Text = text; CommitId = id; }
public async ValueTask <GitId?> ReadFirstParentIdAsync() { if (_parents is not null) { return(_parents.First()); } else if (_treeId is null) { await ReadTreeIdAsync().ConfigureAwait(false); } // Typically every commit has a parent, so optimize for that case var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, requested : ParentLineReadLength).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("parent ")) { if (bb.IsEof || !bb.StartsWithASCII("author ")) { throw new GitBucketException($"Expected 'parent' or 'author', but got neither in commit {Name} Bucket"); } _parents = Array.Empty <GitId>(); // We accidentally read the first part of the author line. Let's keep things clean if (eol == BucketEol.None) { var authorBucket = (bb.Slice("author ".Length).ToArray().AsBucket() + Inner); (bb, eol) = await authorBucket.ReadUntilEolFullAsync(AcceptedEols, requested : MaxHeader).ConfigureAwait(false); } _author = GitSignatureRecord.TryReadFromBucket(bb.Slice(eol), out var author) ? author : throw new GitBucketException($"Invalid author line in {Name} Bucket"); return(null); } else if (GitId.TryParse(bb.Slice("parent ".Length, eol), out var id)) { _parents = new List <GitId>() { id }; return(id); } else { throw new GitBucketException($"Invalid parent line in '{Inner.Name}"); } }
async ValueTask <bool> GetHasBitmap() { if (ChunkReader is null) { return(false); } byte[] multiPackId = new byte[Repository.InternalConfig.IdType.HashLength()]; if (multiPackId.Length != (await ChunkReader.ReadAtAsync(AfterChunkPosition, multiPackId).ConfigureAwait(false))) { return(false); } GitId id = new GitId(Repository.InternalConfig.IdType, multiPackId); _multiPackBitmapPath = Path.Combine(_dir, $"multi-pack-index-{id}.bitmap"); return(File.Exists(_multiPackBitmapPath)); }
private async Task <Uri?> TryGetWebUriAsync(IGitLabClient gitlabClient, GitId commitId) { if (m_ProjectInfo == null) { throw new InvalidOperationException(); } m_Logger.LogDebug($"Getting web uri for commit '{commitId}'"); try { var commit = await gitlabClient.Commits.GetAsync(m_ProjectInfo.ProjectPath, commitId.Id); return(new Uri(commit.WebUrl)); } catch (Exception ex) when(ex is GitLabException gitlabException && gitlabException.HttpStatusCode == HttpStatusCode.NotFound) { return(null); } }
private async Task <Uri?> TryGetWebUriAsync(IGitHubClient githubClient, GitId commitId) { if (m_ProjectInfo == null) { throw new InvalidOperationException(); } m_Logger.LogDebug($"Getting web uri for commit '{commitId}'"); try { var commit = await githubClient.Repository.Commit.Get(m_ProjectInfo.Owner, m_ProjectInfo.Repository, commitId.Id); return(new Uri(commit.HtmlUrl)); } catch (Exception ex) when(ex is ApiValidationException || ex is NotFoundException) { return(null); } }
protected override async ValueTask InitAsync() { await base.InitAsync().ConfigureAwait(false); _haveV2 = GetChunkLength("GDA2").HasValue; if (_baseCommitGraphs > 0) { byte[] baseGraphs = new byte[_baseCommitGraphs * IdType.HashLength()]; if (baseGraphs.Length != await ReadFromChunkAsync("BASE", 0, baseGraphs).ConfigureAwait(false)) { throw new GitException($"Can't read commit-graph base chunks from {ChunkReader} Bucket"); } GitId parentId = GitId.FromByteArrayOffset(IdType, baseGraphs, (_baseCommitGraphs - 1) * IdType.HashLength()); ParentGraph = _graphRoot !.GetCommitGraph(parentId); } }
private async ValueTask <byte[]> GetOidArrayAsync(uint start, uint count) { if (count == 0) { return(Array.Empty <byte>()); } if (_ver == 2) { int sz = GitId.HashLength(_idType); byte[] data = new byte[sz * count]; long offset = 8 /* header */ + 256 * 4 /* fanout */ + sz * start; if (data.Length != await _fIdx !.ReadAtAsync(offset, data).ConfigureAwait(false)) { return(Array.Empty <byte>()); } return(data); } else if (_ver == 1) { int sz = GitId.HashLength(_idType) + 4; byte[] data = new byte[sz * count]; long offset = 256 * 4 /* fanout */ + sz * start; if (data.Length != await _fIdx !.ReadAtAsync(offset, data).ConfigureAwait(false)) { return(Array.Empty <byte>()); } return(data); } else { return(Array.Empty <byte>()); } }
private async ValueTask <GitId> GetOidAsync(int index) { int offset = OidOffset; if (index < offset) { return(await ParentGraph !.GetOidAsync(index).ConfigureAwait(false)); } index -= offset; int hashLength = GitId.HashLength(IdType); byte[] oidData = new byte[hashLength]; if (hashLength != await ReadFromChunkAsync("OIDL", index * hashLength, oidData).ConfigureAwait(false)) { throw new InvalidOperationException(); } return(new GitId(IdType, oidData)); }
public VersionInfo(NuGetVersion version, GitId commit) { Version = version ?? throw new ArgumentNullException(nameof(version)); Commit = commit; }
public GitCommitInfo(GitId from, GitRepository repo) { Id = from; _commit = repo; _parents = new GitAsyncLazy <IEnumerable <GitId> >(GetParentIds); }
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("-"); } }