Skip to content

Commit 4b720c5

Browse files
committed
TreeDefinition: allow Add a blob by ID
Allow consumers to add a blob to a `TreeDefinition` by specifying only the object ID and mode. This lets users build tree entries without having to create a `Blob` object (and thus load the object itself) which is beneficial for users building trees with large objects. This is only useful for Blobs, since they do not need to be fetched from the object database to be realized within the tree builder. Users are not able to add Trees by ID, since we would need to load them (and cannot, since we are not guaranteed to be instantiated within the context of a repository).
1 parent 53900ea commit 4b720c5

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

LibGit2Sharp.Tests/TreeDefinitionFixture.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,49 @@ public void CanAddAnExistingBlob(string blobSha, string targetPath)
266266
}
267267
}
268268

269+
[Theory]
270+
[InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "README_TOO")]
271+
[InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "1/README")]
272+
[InlineData("45b983be36b73c0788dc9cbcb76cbb80fc7bb057", "1/another_one.txt")]
273+
[InlineData("45b983be36b73c0788dc9cbcb76cbb80fc7bb057", "another_one.txt")]
274+
public void CanAddBlobById(string blobSha, string targetPath)
275+
{
276+
string path = SandboxBareTestRepo();
277+
using (var repo = new Repository(path))
278+
{
279+
TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree);
280+
Assert.Null(td[targetPath]);
281+
282+
var objectId = new ObjectId(blobSha);
283+
284+
td.Add(targetPath, objectId, Mode.NonExecutableFile);
285+
286+
TreeEntryDefinition fetched = td[targetPath];
287+
Assert.NotNull(fetched);
288+
289+
Assert.Equal(objectId, fetched.TargetId);
290+
Assert.Equal(Mode.NonExecutableFile, fetched.Mode);
291+
}
292+
}
293+
294+
[Fact]
295+
public void CannotAddTreeById()
296+
{
297+
const string treeSha = "7f76480d939dc401415927ea7ef25c676b8ddb8f";
298+
const string targetPath = "1/2";
299+
300+
string path = SandboxBareTestRepo();
301+
using (var repo = new Repository(path))
302+
{
303+
TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree);
304+
Assert.Null(td[targetPath]);
305+
306+
var objectId = new ObjectId(treeSha);
307+
308+
Assert.Throws<ArgumentException>(() => td.Add(targetPath, objectId, Mode.Directory));
309+
}
310+
}
311+
269312
[Fact]
270313
public void CanAddAnExistingSubmodule()
271314
{

LibGit2Sharp/TreeDefinition.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,23 @@ public virtual TreeDefinition Add(string targetTreeEntryPath, string filePath, M
201201
return Add(targetTreeEntryPath, ted);
202202
}
203203

204+
/// <summary>
205+
/// Adds or replaces a <see cref="TreeEntryDefinition"/> from an existing blob specified by its Object ID at the specified <paramref name="targetTreeEntryPath"/> location.
206+
/// </summary>
207+
/// <param name="targetTreeEntryPath">The path within this <see cref="TreeDefinition"/>.</param>
208+
/// <param name="id">The object ID for this entry.</param>
209+
/// <param name="mode">The file related <see cref="Mode"/> attributes.</param>
210+
/// <returns>The current <see cref="TreeDefinition"/>.</returns>
211+
public virtual TreeDefinition Add(string targetTreeEntryPath, ObjectId id, Mode mode)
212+
{
213+
Ensure.ArgumentNotNull(id, "id");
214+
Ensure.ArgumentConformsTo(mode, m => m.HasAny(TreeEntryDefinition.BlobModes), "mode");
215+
216+
TreeEntryDefinition ted = TreeEntryDefinition.From(id, mode);
217+
218+
return Add(targetTreeEntryPath, ted);
219+
}
220+
204221
/// <summary>
205222
/// Adds or replaces a <see cref="TreeEntryDefinition"/>, dynamically built from the provided <see cref="Tree"/>, at the specified <paramref name="targetTreeEntryPath"/> location.
206223
/// </summary>

LibGit2Sharp/TreeEntryDefinition.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ internal static TreeEntryDefinition From(TreeEntry treeEntry)
5454

5555
internal static TreeEntryDefinition From(Blob blob, Mode mode)
5656
{
57+
Ensure.ArgumentNotNull(blob, "blob");
58+
5759
return new TreeEntryDefinition
5860
{
5961
Mode = mode,
@@ -63,6 +65,19 @@ internal static TreeEntryDefinition From(Blob blob, Mode mode)
6365
};
6466
}
6567

68+
internal static TreeEntryDefinition From(ObjectId id, Mode mode)
69+
{
70+
Ensure.ArgumentNotNull(id, "id");
71+
Ensure.ArgumentNotNull(mode, "mode");
72+
73+
return new TreeEntryDefinition
74+
{
75+
Mode = mode,
76+
TargetType = TreeEntryTargetType.Blob,
77+
TargetId = id
78+
};
79+
}
80+
6681
internal static TreeEntryDefinition TransientBlobFrom(string filePath, Mode mode)
6782
{
6883
Ensure.ArgumentConformsTo(mode, m => m.HasAny(BlobModes), "mode");

0 commit comments

Comments
 (0)