using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { /// /// A Commit /// [DebuggerDisplay("{DebuggerDisplay,nq}")] public class Commit : GitObject { private readonly GitObjectLazyGroup group1; private readonly GitObjectLazyGroup group2; private readonly ILazy lazyTree; private readonly ILazy lazyAuthor; private readonly ILazy lazyCommitter; private readonly ILazy lazyMessage; private readonly ILazy lazyMessageShort; private readonly ILazy lazyEncoding; private readonly ParentsCollection parents; private readonly Lazy> lazyNotes; /// /// Needed for mocking purposes. /// protected Commit() { } internal Commit(Repository repo, ObjectId id) : base(repo, id) { lazyTree = GitObjectLazyGroup.Singleton(this.repo, id, obj => new Tree(this.repo, Proxy.git_commit_tree_id(obj), null)); group1 = new GitObjectLazyGroup(this.repo, id); lazyAuthor = group1.AddLazy(Proxy.git_commit_author); lazyCommitter = group1.AddLazy(Proxy.git_commit_committer); group2 = new GitObjectLazyGroup(this.repo, id); lazyMessage = group2.AddLazy(Proxy.git_commit_message); lazyMessageShort = group2.AddLazy(Proxy.git_commit_summary); lazyEncoding = group2.AddLazy(RetrieveEncodingOf); lazyNotes = new Lazy>(() => RetrieveNotesOfCommit(id).ToList()); parents = new ParentsCollection(repo, id); } /// /// Gets the pointed at by the in the . /// /// The relative path to the from the working directory. /// null if nothing has been found, the otherwise. public virtual TreeEntry this[string relativePath] { get { return Tree[relativePath]; } } /// /// Gets the commit message. /// public virtual string Message { get { return lazyMessage.Value; } } /// /// Gets the short commit message which is usually the first line of the commit. /// public virtual string MessageShort { get { return lazyMessageShort.Value; } } /// /// Gets the encoding of the message. /// public virtual string Encoding { get { return lazyEncoding.Value; } } /// /// Gets the author of this commit. /// public virtual Signature Author { get { return lazyAuthor.Value; } } /// /// Gets the committer. /// public virtual Signature Committer { get { return lazyCommitter.Value; } } /// /// Gets the Tree associated to this commit. /// public virtual Tree Tree { get { return lazyTree.Value; } } /// /// Gets the parents of this commit. This property is lazy loaded and can throw an exception if the commit no longer exists in the repo. /// public virtual IEnumerable Parents { get { return parents; } } /// /// Gets the notes of this commit. /// public virtual IEnumerable Notes { get { return lazyNotes.Value; } } private IEnumerable RetrieveNotesOfCommit(ObjectId oid) { return repo.Notes[oid]; } private static string RetrieveEncodingOf(GitObjectSafeHandle obj) { string encoding = Proxy.git_commit_message_encoding(obj); return encoding ?? "UTF-8"; } private string DebuggerDisplay { get { return string.Format(CultureInfo.InvariantCulture, "{0} {1}", Id.ToString(7), MessageShort); } } private class ParentsCollection : ICollection { private readonly Lazy> _parents; private readonly Lazy _count; public ParentsCollection(Repository repo, ObjectId commitId) { _count = new Lazy(() => Proxy.git_commit_parentcount(repo.Handle, commitId)); _parents = new Lazy>(() => RetrieveParentsOfCommit(repo, commitId)); } private ICollection RetrieveParentsOfCommit(Repository repo, ObjectId commitId) { using (var obj = new ObjectSafeWrapper(commitId, repo.Handle)) { int parentsCount = _count.Value; var parents = new List(parentsCount); for (uint i = 0; i < parentsCount; i++) { ObjectId parentCommitId = Proxy.git_commit_parent_id(obj.ObjectPtr, i); parents.Add(new Commit(repo, parentCommitId)); } return parents; } } public IEnumerator GetEnumerator() { return _parents.Value.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(Commit item) { throw new NotSupportedException(); } public void Clear() { throw new NotSupportedException(); } public bool Contains(Commit item) { return _parents.Value.Contains(item); } public void CopyTo(Commit[] array, int arrayIndex) { _parents.Value.CopyTo(array, arrayIndex); } public bool Remove(Commit item) { throw new NotSupportedException(); } public int Count { get { return _count.Value; } } public bool IsReadOnly { get { return true; } } } } }