Skip to content

Exposing Packbuilder capabilities of libgit2 #1183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Compile Include="FileHistoryFixture.cs" />
<Compile Include="FilterFixture.cs" />
<Compile Include="GlobalSettingsFixture.cs" />
<Compile Include="PackBuilderFixture.cs" />
<Compile Include="PatchStatsFixture.cs" />
<Compile Include="RebaseFixture.cs" />
<Compile Include="RefSpecFixture.cs" />
Expand Down
202 changes: 202 additions & 0 deletions LibGit2Sharp.Tests/PackBuilderFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
using System;
using System.IO;
using System.Linq;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;

namespace LibGit2Sharp.Tests
{
public class PackBuilderFixture : BaseFixture
{
[Fact]
public void TestDefaultPackDelegate()
{
TestIfSameRepoAfterPacking(null);
}

[Fact]
public void TestCommitsPerBranchPackDelegate()
{
TestIfSameRepoAfterPacking(AddingObjectIdsTestDelegate);
}

[Fact]
public void TestCommitsPerBranchIdsPackDelegate()
{
TestIfSameRepoAfterPacking(AddingObjectsTestDelegate);
}

internal void TestIfSameRepoAfterPacking(Action<IRepository, PackBuilder> packDelegate)
{
// read a repo
// pack with the provided action
// write the pack file in a mirror repo
// read new repo
// compare

string orgRepoPath = SandboxPackBuilderTestRepo();
string mrrRepoPath = SandboxPackBuilderTestRepo();
string mrrRepoPackDirPath = Path.Combine(mrrRepoPath + "/.git/objects");

DirectoryHelper.DeleteDirectory(mrrRepoPackDirPath);
Directory.CreateDirectory(mrrRepoPackDirPath + "/pack");

PackBuilderOptions packBuilderOptions = new PackBuilderOptions(mrrRepoPackDirPath + "/pack");

using (Repository orgRepo = new Repository(orgRepoPath))
{
PackBuilderResults results;
if (packDelegate != null)
results = orgRepo.ObjectDatabase.Pack(packBuilderOptions, b => packDelegate(orgRepo, b));
else
results = orgRepo.ObjectDatabase.Pack(packBuilderOptions);

// written objects count is the same as in objects database
Assert.Equal(orgRepo.ObjectDatabase.Count(), results.WrittenObjectsCount);

// loading a repo from the written pack file.
using (Repository mrrRepo = new Repository(mrrRepoPath))
{
// make sure the objects of the original repo are the same as the ones in the mirror repo
// doing that by making sure the count is the same, and the set difference is empty
Assert.True(mrrRepo.ObjectDatabase.Count() == orgRepo.ObjectDatabase.Count() && !mrrRepo.ObjectDatabase.Except(orgRepo.ObjectDatabase).Any());

Assert.Equal(orgRepo.Commits.Count(), mrrRepo.Commits.Count());
Assert.Equal(orgRepo.Branches.Count(), mrrRepo.Branches.Count());
Assert.Equal(orgRepo.Refs.Count(), mrrRepo.Refs.Count());
}
}
}

internal void AddingObjectIdsTestDelegate(IRepository repo, PackBuilder builder)
{
foreach (Branch branch in repo.Branches)
{
foreach (Commit commit in branch.Commits)
{
builder.AddRecursively(commit.Id);
}
}

foreach (Tag tag in repo.Tags)
{
builder.Add(tag.Target.Id);
}
}

internal void AddingObjectsTestDelegate(IRepository repo, PackBuilder builder)
{
foreach (Branch branch in repo.Branches)
{
foreach (Commit commit in branch.Commits)
{
builder.AddRecursively(commit);
}
}

foreach (Tag tag in repo.Tags)
{
builder.Add(tag.Target);
}
}

[Fact]
public void ExceptionIfPathDoesNotExist()
{
PackBuilderOptions pbo;

Assert.Throws<DirectoryNotFoundException>(() =>
{
pbo = new PackBuilderOptions("aaa");
});
}

[Fact]
public void ExceptionIfPathEqualsNull()
{
PackBuilderOptions pbo;

Assert.Throws<ArgumentNullException>(() =>
{
pbo = new PackBuilderOptions(null);
});
}

[Fact]
public void ExceptionIfOptionsEqualsNull()
{
string orgRepoPath = SandboxPackBuilderTestRepo();

using (Repository orgRepo = new Repository(orgRepoPath))
{
Assert.Throws<ArgumentNullException>(() =>
{
orgRepo.ObjectDatabase.Pack(null);
});
}
}

[Fact]
public void ExceptionIfBuildDelegateEqualsNull()
{
string orgRepoPath = SandboxPackBuilderTestRepo();
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);

using (Repository orgRepo = new Repository(orgRepoPath))
{
Assert.Throws<ArgumentNullException>(() =>
{
orgRepo.ObjectDatabase.Pack(packBuilderOptions, null);
});
}
}

[Fact]
public void ExceptionIfNegativeNumberOfThreads()
{
string orgRepoPath = SandboxPackBuilderTestRepo();
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);

Assert.Throws<ArgumentException>(() =>
{
packBuilderOptions.MaximumNumberOfThreads = -1;
});
}

[Fact]
public void ExceptionIfAddNullObjectID()
{
string orgRepoPath = SandboxPackBuilderTestRepo();
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);

using (Repository orgRepo = new Repository(orgRepoPath))
{
Assert.Throws<ArgumentNullException>(() =>
{
orgRepo.ObjectDatabase.Pack(packBuilderOptions, builder =>
{
builder.Add(null);
});
});
}
}

[Fact]
public void ExceptionIfAddRecursivelyNullObjectID()
{
string orgRepoPath = SandboxPackBuilderTestRepo();
PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);

using (Repository orgRepo = new Repository(orgRepoPath))
{
Assert.Throws<ArgumentNullException>(() =>
{
orgRepo.ObjectDatabase.Pack(packBuilderOptions, builder =>
{
builder.AddRecursively(null);
});
});
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/master
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
x��I
B1]��>��'��[����� ��o���U/�Z�n�i"���5�S�Q�hC��.��n��<I!UP�3w�WЎRfS�+U9l�Fu����\�����\�3rD��:����-��
�:� �>=?
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
872129051d644790636b416d1ef1ec830c5f6b90
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
World
7 changes: 7 additions & 0 deletions LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static BaseFixture()
private static string SubmoduleTargetTestRepoWorkingDirPath { get; set; }
private static string AssumeUnchangedRepoWorkingDirPath { get; set; }
public static string SubmoduleSmallTestRepoWorkingDirPath { get; set; }
public static string PackBuilderTestRepoPath { get; private set; }

public static DirectoryInfo ResourcesDirectory { get; private set; }

Expand Down Expand Up @@ -74,6 +75,7 @@ private static void SetUpTestEnvironment()
SubmoduleTargetTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_target_wd");
AssumeUnchangedRepoWorkingDirPath = Path.Combine(sourceRelativePath, "assume_unchanged_wd");
SubmoduleSmallTestRepoWorkingDirPath = Path.Combine(sourceRelativePath, "submodule_small_wd");
PackBuilderTestRepoPath = Path.Combine(sourceRelativePath, "packbuilder_testrepo_wd");

CleanupTestReposOlderThan(TimeSpan.FromMinutes(15));
}
Expand Down Expand Up @@ -174,6 +176,11 @@ public string SandboxSubmoduleSmallTestRepo()
return path;
}

protected string SandboxPackBuilderTestRepo()
{
return Sandbox(PackBuilderTestRepoPath);
}

protected string Sandbox(string sourceDirectoryPath, params string[] additionalSourcePaths)
{
var scd = BuildSelfCleaningDirectory();
Expand Down
11 changes: 11 additions & 0 deletions LibGit2Sharp/Core/Handles/PackBuilderSafeHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace LibGit2Sharp.Core.Handles
{
internal class PackBuilderSafeHandle : SafeHandleBase
{
protected override bool ReleaseHandleImpl()
{
Proxy.git_packbuilder_free(handle);
return true;
}
}
}
45 changes: 45 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,51 @@ internal static extern int git_patch_line_stats(
internal delegate int git_push_transfer_progress(uint current, uint total, UIntPtr bytes, IntPtr payload);
internal delegate int git_packbuilder_progress(int stage, uint current, uint total, IntPtr payload);

[DllImport(libgit2)]
internal static extern void git_packbuilder_free(IntPtr packbuilder);

[DllImport(libgit2)]
internal static extern int git_packbuilder_insert(
PackBuilderSafeHandle packbuilder,
ref GitOid id,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name);

[DllImport(libgit2)]
internal static extern int git_packbuilder_insert_commit(
PackBuilderSafeHandle packbuilder,
ref GitOid id);

[DllImport(libgit2)]
internal static extern int git_packbuilder_insert_recur(
PackBuilderSafeHandle packbuilder,
ref GitOid id,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string name);

[DllImport(libgit2)]
internal static extern int git_packbuilder_insert_tree(
PackBuilderSafeHandle packbuilder,
ref GitOid id);

[DllImport(libgit2)]
internal static extern int git_packbuilder_new(out PackBuilderSafeHandle packbuilder, RepositorySafeHandle repo);

[DllImport(libgit2)]
internal static extern UInt32 git_packbuilder_object_count(PackBuilderSafeHandle packbuilder);

[DllImport(libgit2)]
internal static extern UInt32 git_packbuilder_set_threads(PackBuilderSafeHandle packbuilder, UInt32 numThreads);

[DllImport(libgit2)]
internal static extern int git_packbuilder_write(
PackBuilderSafeHandle packbuilder,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath path,
uint mode,
IntPtr progressCallback,
IntPtr payload);

[DllImport(libgit2)]
internal static extern UInt32 git_packbuilder_written(PackBuilderSafeHandle packbuilder);

[DllImport(libgit2)]
internal static extern int git_reference_create(
out ReferenceSafeHandle reference,
Expand Down
Loading