Skip to content

Commit 7924b6a

Browse files
committed
Adding more testing for writing multiple pack file.
Exposing libgit2 method to get the pack file hash. Minor fixes for PackBuilder, PackBuilderResults, and PackBuilderFixture.
1 parent 45fe76f commit 7924b6a

File tree

5 files changed

+183
-86
lines changed

5 files changed

+183
-86
lines changed

LibGit2Sharp.Tests/PackBuilderFixture.cs

Lines changed: 150 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using LibGit2Sharp.Tests.TestHelpers;
55
using Xunit;
6+
using System.Collections.Generic;
67

78
namespace LibGit2Sharp.Tests
89
{
@@ -11,85 +12,71 @@ public class PackBuilderFixture : BaseFixture
1112
[Fact]
1213
public void TestDefaultPackDelegate()
1314
{
14-
TestIfSameRepoAfterPacking(null);
15+
TestBody((repo, options) =>
16+
{
17+
PackBuilderResults results = repo.ObjectDatabase.Pack(options);
18+
});
1519
}
1620

1721
[Fact]
1822
public void TestCommitsPerBranchPackDelegate()
1923
{
20-
TestIfSameRepoAfterPacking(AddingObjectIdsTestDelegate);
24+
TestBody((repo, options) =>
25+
{
26+
PackBuilderResults results = repo.ObjectDatabase.Pack(options, builder =>
27+
{
28+
foreach (Branch branch in repo.Branches)
29+
{
30+
foreach (Commit commit in branch.Commits)
31+
{
32+
builder.AddRecursively(commit);
33+
}
34+
}
35+
36+
foreach (Tag tag in repo.Tags)
37+
{
38+
builder.Add(tag.Target);
39+
}
40+
});
41+
});
2142
}
2243

2344
[Fact]
2445
public void TestCommitsPerBranchIdsPackDelegate()
2546
{
26-
TestIfSameRepoAfterPacking(AddingObjectsTestDelegate);
27-
}
28-
29-
internal void TestIfSameRepoAfterPacking(Action<IRepository, PackBuilder> packDelegate)
30-
{
31-
// read a repo
32-
// pack with the provided action
33-
// write the pack file in a mirror repo
34-
// read new repo
35-
// compare
36-
37-
string orgRepoPath = SandboxPackBuilderTestRepo();
38-
string mrrRepoPath = SandboxPackBuilderTestRepo();
39-
string mrrRepoPackDirPath = Path.Combine(mrrRepoPath + "/.git/objects");
40-
41-
DirectoryHelper.DeleteDirectory(mrrRepoPackDirPath);
42-
Directory.CreateDirectory(mrrRepoPackDirPath + "/pack");
43-
44-
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(mrrRepoPackDirPath + "/pack");
45-
46-
using (Repository orgRepo = new Repository(orgRepoPath))
47+
TestBody((repo, options) =>
4748
{
48-
PackBuilderResults results;
49-
if (packDelegate != null)
50-
results = orgRepo.ObjectDatabase.Pack(packBuilderOptions, b => packDelegate(orgRepo, b));
51-
else
52-
results = orgRepo.ObjectDatabase.Pack(packBuilderOptions);
53-
54-
// written objects count is the same as in objects database
55-
Assert.Equal(orgRepo.ObjectDatabase.Count(), results.WrittenObjectsCount);
56-
57-
// loading a repo from the written pack file.
58-
using (Repository mrrRepo = new Repository(mrrRepoPath))
49+
PackBuilderResults results = repo.ObjectDatabase.Pack(options, builder =>
5950
{
60-
// make sure the objects of the original repo are the same as the ones in the mirror repo
61-
// doing that by making sure the count is the same, and the set difference is empty
62-
Assert.True(mrrRepo.ObjectDatabase.Count() == orgRepo.ObjectDatabase.Count() && !mrrRepo.ObjectDatabase.Except(orgRepo.ObjectDatabase).Any());
51+
foreach (Branch branch in repo.Branches)
52+
{
53+
foreach (Commit commit in branch.Commits)
54+
{
55+
builder.AddRecursively(commit.Id);
56+
}
57+
}
6358

64-
Assert.Equal(orgRepo.Commits.Count(), mrrRepo.Commits.Count());
65-
Assert.Equal(orgRepo.Branches.Count(), mrrRepo.Branches.Count());
66-
Assert.Equal(orgRepo.Refs.Count(), mrrRepo.Refs.Count());
67-
}
68-
}
59+
foreach (Tag tag in repo.Tags)
60+
{
61+
builder.Add(tag.Target.Id);
62+
}
63+
});
64+
});
6965
}
7066

7167
[Fact]
72-
internal void TestCreatingMultiplePackFiles()
68+
public void TestCreatingMultiplePackFilesByType()
7369
{
74-
string orgRepoPath = SandboxPackBuilderTestRepo();
75-
string mrrRepoPath = SandboxPackBuilderTestRepo();
76-
string mrrRepoPackDirPath = Path.Combine(mrrRepoPath + "/.git/objects");
77-
78-
DirectoryHelper.DeleteDirectory(mrrRepoPackDirPath);
79-
Directory.CreateDirectory(mrrRepoPackDirPath + "/pack");
80-
81-
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(mrrRepoPackDirPath + "/pack");
82-
83-
using (Repository orgRepo = new Repository(orgRepoPath))
70+
TestBody((repo, options) =>
8471
{
8572
long totalNumberOfWrittenObjects = 0;
8673
PackBuilderResults results;
8774

8875
for (int i = 0; i < 3; i++)
8976
{
90-
results = results = orgRepo.ObjectDatabase.Pack(packBuilderOptions, b =>
77+
results = repo.ObjectDatabase.Pack(options, b =>
9178
{
92-
foreach (GitObject obj in orgRepo.ObjectDatabase)
79+
foreach (GitObject obj in repo.ObjectDatabase)
9380
{
9481
if (i == 0 && obj is Commit)
9582
b.Add(obj.Id);
@@ -100,55 +87,97 @@ internal void TestCreatingMultiplePackFiles()
10087
}
10188
});
10289

90+
// assert the pack file is written
91+
Assert.True(File.Exists(Path.Combine(options.PackDirectoryPath, "pack-" + results.PackHash + ".pack")));
92+
Assert.True(File.Exists(Path.Combine(options.PackDirectoryPath, "pack-" + results.PackHash + ".idx")));
93+
10394
totalNumberOfWrittenObjects += results.WrittenObjectsCount;
10495
}
10596

106-
// written objects count is the same as in objects database
107-
Assert.Equal(orgRepo.ObjectDatabase.Count(), totalNumberOfWrittenObjects);
97+
// assert total number of written objects count is the same as in objects database
98+
Assert.Equal(repo.ObjectDatabase.Count(), totalNumberOfWrittenObjects);
99+
});
100+
}
108101

109-
// loading a repo from the written pack file.
110-
using (Repository mrrRepo = new Repository(mrrRepoPath))
102+
[Fact]
103+
public void TestCreatingMultiplePackFilesByCount()
104+
{
105+
TestBody((repo, options) =>
106+
{
107+
long totalNumberOfWrittenObjects = 0;
108+
PackBuilderResults results;
109+
110+
List<GitObject> objectsList = repo.ObjectDatabase.ToList();
111+
int totalObjectCount = objectsList.Count;
112+
113+
int currentObject = 0;
114+
115+
while (currentObject < totalObjectCount)
111116
{
112-
// make sure the objects of the original repo are the same as the ones in the mirror repo
113-
// doing that by making sure the count is the same, and the set difference is empty
114-
Assert.True(mrrRepo.ObjectDatabase.Count() == orgRepo.ObjectDatabase.Count() && !mrrRepo.ObjectDatabase.Except(orgRepo.ObjectDatabase).Any());
117+
results = repo.ObjectDatabase.Pack(options, b =>
118+
{
119+
while (currentObject < totalObjectCount)
120+
{
121+
b.Add(objectsList[currentObject]);
115122

116-
Assert.Equal(orgRepo.Commits.Count(), mrrRepo.Commits.Count());
117-
Assert.Equal(orgRepo.Branches.Count(), mrrRepo.Branches.Count());
118-
Assert.Equal(orgRepo.Refs.Count(), mrrRepo.Refs.Count());
123+
if (currentObject++ % 100 == 0)
124+
break;
125+
}
126+
});
127+
128+
// assert the pack file is written
129+
Assert.True(File.Exists(Path.Combine(options.PackDirectoryPath, "pack-" + results.PackHash + ".pack")));
130+
Assert.True(File.Exists(Path.Combine(options.PackDirectoryPath, "pack-" + results.PackHash + ".idx")));
131+
132+
totalNumberOfWrittenObjects += results.WrittenObjectsCount;
119133
}
120-
}
134+
135+
// assert total number of written objects count is the same as in objects database
136+
Assert.Equal(repo.ObjectDatabase.Count(), totalNumberOfWrittenObjects);
137+
});
121138
}
122139

123-
internal void AddingObjectIdsTestDelegate(IRepository repo, PackBuilder builder)
140+
[Fact]
141+
public void CanWritePackAndIndexFiles()
124142
{
125-
foreach (Branch branch in repo.Branches)
143+
using (Repository repo = new Repository(SandboxStandardTestRepo()))
126144
{
127-
foreach (Commit commit in branch.Commits)
128-
{
129-
builder.AddRecursively(commit.Id);
130-
}
131-
}
145+
string path = Path.GetTempPath();
146+
PackBuilderResults results = repo.ObjectDatabase.Pack(new PackBuilderOptions(path));
132147

133-
foreach (Tag tag in repo.Tags)
134-
{
135-
builder.Add(tag.Target.Id);
148+
Assert.Equal(repo.ObjectDatabase.Count(), results.WrittenObjectsCount);
149+
150+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".pack")));
151+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".idx")));
136152
}
137153
}
138154

139-
internal void AddingObjectsTestDelegate(IRepository repo, PackBuilder builder)
155+
[Fact]
156+
public void TestEmptyPackFile()
140157
{
141-
foreach (Branch branch in repo.Branches)
158+
using (Repository repo = new Repository(SandboxPackBuilderTestRepo()))
142159
{
143-
foreach (Commit commit in branch.Commits)
160+
string path = Path.GetTempPath();
161+
PackBuilderResults results = repo.ObjectDatabase.Pack(new PackBuilderOptions(path), b =>
144162
{
145-
builder.AddRecursively(commit);
146-
}
163+
164+
});
165+
166+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".pack")));
167+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".idx")));
147168
}
169+
}
148170

149-
foreach (Tag tag in repo.Tags)
171+
[Fact]
172+
public void TestPackFileForEmptyRepository()
173+
{
174+
using (Repository repo = new Repository(InitNewRepository()))
150175
{
151-
builder.Add(tag.Target);
176+
string path = Path.GetTempPath();
177+
PackBuilderResults results = repo.ObjectDatabase.Pack(new PackBuilderOptions(path));
178+
179+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".pack")));
180+
Assert.True(File.Exists(Path.Combine(path, "pack-" + results.PackHash + ".idx")));
152181
}
153182
}
154183

@@ -240,5 +269,43 @@ public void ExceptionIfAddRecursivelyNullObjectID()
240269
});
241270
}
242271
}
272+
273+
internal void TestBody(Action<IRepository, PackBuilderOptions> fullPackingAction)
274+
{
275+
// read a repo, pack with the provided action, write the pack file in a mirror repo, read new repo, compare
276+
277+
string orgRepoPath = SandboxPackBuilderTestRepo();
278+
string mrrRepoPath = SandboxPackBuilderTestRepo();
279+
string mrrRepoPackDirPath = Path.Combine(mrrRepoPath + "/.git/objects");
280+
281+
DirectoryHelper.DeleteDirectory(mrrRepoPackDirPath);
282+
Directory.CreateDirectory(mrrRepoPackDirPath + "/pack");
283+
284+
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(mrrRepoPackDirPath + "/pack");
285+
286+
using (Repository orgRepo = new Repository(orgRepoPath))
287+
{
288+
fullPackingAction(orgRepo, packBuilderOptions);
289+
290+
// loading the mirror repo from the written pack file and make sure it's identical to the original.
291+
using (Repository mrrRepo = new Repository(mrrRepoPath))
292+
{
293+
AssertIfNotIdenticalRepositories(orgRepo, mrrRepo);
294+
}
295+
}
296+
}
297+
298+
internal void AssertIfNotIdenticalRepositories(IRepository repo1, IRepository repo2)
299+
{
300+
// make sure the objects of the original repo are the same as the ones in the mirror repo
301+
// doing that by making sure the count is the same, and the set difference is empty
302+
Assert.True(repo1.ObjectDatabase.Count() == repo2.ObjectDatabase.Count()
303+
&& !repo2.ObjectDatabase.Except(repo1.ObjectDatabase).Any());
304+
305+
Assert.Equal(repo1.Commits.Count(), repo2.Commits.Count());
306+
Assert.Equal(repo1.Branches.Count(), repo2.Branches.Count());
307+
Assert.Equal(repo1.Refs.Count(), repo2.Refs.Count());
308+
Assert.Equal(repo1.Tags.Count(), repo2.Tags.Count());
309+
}
243310
}
244311
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,9 @@ internal static extern int git_packbuilder_write(
983983
[DllImport(libgit2)]
984984
internal static extern UInt32 git_packbuilder_written(PackBuilderSafeHandle packbuilder);
985985

986+
[DllImport(libgit2)]
987+
internal static extern OidSafeHandle git_packbuilder_hash(PackBuilderSafeHandle packbuilder);
988+
986989
[DllImport(libgit2)]
987990
internal static extern int git_reference_create(
988991
out ReferenceSafeHandle reference,

LibGit2Sharp/Core/Proxy.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,12 @@ public static uint git_packbuilder_written(PackBuilderSafeHandle packbuilder)
16161616
{
16171617
return NativeMethods.git_packbuilder_written(packbuilder);
16181618
}
1619+
1620+
public static ObjectId git_packbuilder_hash(PackBuilderSafeHandle packbuilder)
1621+
{
1622+
return NativeMethods.git_packbuilder_hash(packbuilder).MarshalAsObjectId();
1623+
}
1624+
16191625
#endregion
16201626

16211627
#region git_rebase

LibGit2Sharp/ObjectDatabase.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ private PackBuilderResults InternalPack(PackBuilderOptions options, Action<PackB
690690
using (PackBuilder builder = new PackBuilder(repo))
691691
{
692692
// set pre-build options
693-
builder.SetMaximumNumberOfThreads(options.MaximumNumberOfThreads);
693+
results.ActualNumberOfThreads = builder.SetMaximumNumberOfThreads(options.MaximumNumberOfThreads);
694694

695695
// call the provided action
696696
packDelegate(builder);
@@ -700,6 +700,7 @@ private PackBuilderResults InternalPack(PackBuilderOptions options, Action<PackB
700700

701701
// adding the results to the PackBuilderResults object
702702
results.WrittenObjectsCount = builder.WrittenObjectsCount;
703+
results.PackHash = builder.PackHash;
703704
}
704705

705706
return results;

LibGit2Sharp/PackBuilder.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,21 @@ internal int SetMaximumNumberOfThreads(int nThread)
105105
/// <summary>
106106
/// Number of objects the PackBuilder will write out.
107107
/// </summary>
108-
internal long ObjectsCount
108+
public long ObjectsCount
109109
{
110110
get { return Proxy.git_packbuilder_object_count(packBuilderHandle); }
111111
}
112112

113+
/// <summary>
114+
/// Gets the pack file's hash
115+
/// A pack file's name is derived from the sorted hashing of all object names.
116+
/// This is only correct after the pack file has been written.
117+
/// </summary>
118+
internal string PackHash
119+
{
120+
get { return Proxy.git_packbuilder_hash(packBuilderHandle).Sha; }
121+
}
122+
113123
/// <summary>
114124
/// Number of objects the PackBuilder has already written out.
115125
/// This is only correct after the pack file has been written.
@@ -131,9 +141,19 @@ internal PackBuilderSafeHandle Handle
131141
public struct PackBuilderResults
132142
{
133143
/// <summary>
134-
/// Number of objects the PackBuilder has already written out.
144+
/// Number of objects that the PackBuilder has already written out.
135145
/// </summary>
136146
public long WrittenObjectsCount { get; internal set; }
147+
148+
/// <summary>
149+
/// Hash of the pack file that the PackBuilder has already written out.
150+
/// </summary>
151+
public string PackHash { get; internal set; }
152+
153+
/// <summary>
154+
/// Number of actual threads that the PackBuilder has already used.
155+
/// </summary>
156+
public int ActualNumberOfThreads { get; internal set; }
137157
}
138158

139159
/// <summary>

0 commit comments

Comments
 (0)