using System; using System.Collections; using System.Collections.Generic; using System.Linq; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { /// /// A container which references a list of other s and s. /// public class Tree : GitObject, IEnumerable { private readonly Repository repo; private readonly FilePath path; internal Tree(ObjectId id, FilePath path, int treeEntriesCount, Repository repository) : base(id) { Count = treeEntriesCount; repo = repository; this.path = path ?? ""; } /// /// Gets the number of immediately under this . /// public int Count { get; private set; } /// /// Gets the pointed at by the in this instance. /// /// The relative path to the from this instance. /// null if nothing has been found, the otherwise. public TreeEntry this[string relativePath] { get { return RetrieveFromPath(relativePath); } } private TreeEntry RetrieveFromPath(FilePath relativePath) { if (relativePath.IsNullOrEmpty()) { return null; } using (var obj = new ObjectSafeWrapper(Id, repo)) { GitObjectSafeHandle objectPtr; int res = NativeMethods.git_tree_get_subtree(out objectPtr, obj.ObjectPtr, relativePath); if (res == (int)GitErrorCode.GIT_ENOTFOUND) { return null; } Ensure.Success(res); string posixPath = relativePath.Posix; string filename = posixPath.Split('/').Last(); TreeEntrySafeHandle handle = NativeMethods.git_tree_entry_byname(objectPtr, filename); if (handle.IsInvalid) { return null; } string parentPath = posixPath.Substring(0, posixPath.Length - filename.Length); return new TreeEntry(handle, Id, repo, path.Combine(parentPath)); } } /// /// Gets the s immediately under this . /// public IEnumerable Trees { get { return this .Where(e => e.Type == GitObjectType.Tree) .Select(e => e.Target) .Cast(); } } /// /// Gets the s immediately under this . /// public IEnumerable Files { get { return this .Where(e => e.Type == GitObjectType.Blob) .Select(e => e.Target) .Cast(); } } internal string Path { get { return path.Native; } } #region IEnumerable Members /// /// Returns an enumerator that iterates through the collection. /// /// An object that can be used to iterate through the collection. public IEnumerator GetEnumerator() { using (var obj = new ObjectSafeWrapper(Id, repo)) { for (uint i = 0; i < Count; i++) { TreeEntrySafeHandle handle = NativeMethods.git_tree_entry_byindex(obj.ObjectPtr, i); yield return new TreeEntry(handle, Id, repo, path); } } } /// /// Returns an enumerator that iterates through the collection. /// /// An object that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion internal static Tree BuildFromPtr(GitObjectSafeHandle obj, ObjectId id, Repository repo, FilePath path) { var tree = new Tree(id, path, (int)NativeMethods.git_tree_entrycount(obj), repo); return tree; } } }