-
Notifications
You must be signed in to change notification settings - Fork 892
/
Copy pathTree.cs
143 lines (124 loc) · 5 KB
/
Tree.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
using System.Text;
using System;
namespace LibGit2Sharp
{
/// <summary>
/// A container which references a list of other <see cref="Tree"/>s and <see cref="Blob"/>s.
/// </summary>
/// <remarks>
/// Since the introduction of partially cloned repositories, trees might be missing on your local repository (see https://git-scm.com/docs/partial-clone)
/// </remarks>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class Tree : GitObject, IEnumerable<TreeEntry>
{
private readonly string path;
private readonly ILazy<int> lazyCount;
/// <summary>
/// Needed for mocking purposes.
/// </summary>
protected Tree()
{ }
internal Tree(Repository repo, ObjectId id, string path)
: base(repo, id)
{
this.path = path ?? "";
lazyCount = GitObjectLazyGroup.Singleton(repo, id, Proxy.git_tree_entrycount, throwIfMissing: true);
}
/// <summary>
/// Gets the number of <see cref="TreeEntry"/> immediately under this <see cref="Tree"/>.
/// </summary>
/// <exception cref="NotFoundException">Throws if tree is missing</exception>
public virtual int Count => lazyCount.Value;
/// <summary>
/// Gets the <see cref="TreeEntry"/> pointed at by the <paramref name="relativePath"/> in this <see cref="Tree"/> instance.
/// </summary>
/// <param name="relativePath">The relative path to the <see cref="TreeEntry"/> from this instance.</param>
/// <returns><c>null</c> if nothing has been found, the <see cref="TreeEntry"/> otherwise.</returns>
/// <exception cref="NotFoundException">Throws if tree is missing</exception>
public virtual TreeEntry this[string relativePath]
{
get { return RetrieveFromPath(relativePath); }
}
private unsafe TreeEntry RetrieveFromPath(string relativePath)
{
if (string.IsNullOrEmpty(relativePath))
{
return null;
}
using (TreeEntryHandle treeEntry = Proxy.git_tree_entry_bypath(repo.Handle, Id, relativePath))
{
if (treeEntry == null)
{
return null;
}
string filename = relativePath.Split('/').Last();
string parentPath = relativePath.Substring(0, relativePath.Length - filename.Length);
return new TreeEntry(treeEntry, Id, repo, Tree.CombinePath(path, parentPath));
}
}
internal string Path => path;
#region IEnumerable<TreeEntry> Members
unsafe TreeEntry byIndex(ObjectSafeWrapper obj, uint i, ObjectId parentTreeId, Repository repo, string parentPath)
{
using (var entryHandle = Proxy.git_tree_entry_byindex(obj.ObjectPtr, i))
{
return new TreeEntry(entryHandle, parentTreeId, repo, parentPath);
}
}
internal static string CombinePath(string a, string b)
{
var bld = new StringBuilder();
bld.Append(a);
if (!string.IsNullOrEmpty(a) &&
!a.EndsWith("/", StringComparison.Ordinal) &&
!b.StartsWith("/", StringComparison.Ordinal))
{
bld.Append('/');
}
bld.Append(b);
return bld.ToString();
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>An <see cref="IEnumerator{T}"/> object that can be used to iterate through the collection.</returns>
/// <exception cref="NotFoundException">Throws if tree is missing</exception>
public virtual IEnumerator<TreeEntry> GetEnumerator()
{
using (var obj = new ObjectSafeWrapper(Id, repo.Handle, throwIfMissing: true))
{
for (uint i = 0; i < Count; i++)
{
yield return byIndex(obj, i, Id, repo, path);
}
}
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>An <see cref="IEnumerator"/> object that can be used to iterate through the collection.</returns>
/// <exception cref="NotFoundException">Throws if tree is missing</exception>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
private string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture,
"{0}, Count = {1}",
Id.ToString(7),
Count);
}
}
}
}