diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
index be9654a64..0be3440c6 100644
--- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
+++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
@@ -64,6 +64,7 @@
+
diff --git a/LibGit2Sharp.Tests/PackBuilderFixture.cs b/LibGit2Sharp.Tests/PackBuilderFixture.cs
new file mode 100644
index 000000000..44e358158
--- /dev/null
+++ b/LibGit2Sharp.Tests/PackBuilderFixture.cs
@@ -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 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(() =>
+ {
+ pbo = new PackBuilderOptions("aaa");
+ });
+ }
+
+ [Fact]
+ public void ExceptionIfPathEqualsNull()
+ {
+ PackBuilderOptions pbo;
+
+ Assert.Throws(() =>
+ {
+ pbo = new PackBuilderOptions(null);
+ });
+ }
+
+ [Fact]
+ public void ExceptionIfOptionsEqualsNull()
+ {
+ string orgRepoPath = SandboxPackBuilderTestRepo();
+
+ using (Repository orgRepo = new Repository(orgRepoPath))
+ {
+ Assert.Throws(() =>
+ {
+ orgRepo.ObjectDatabase.Pack(null);
+ });
+ }
+ }
+
+ [Fact]
+ public void ExceptionIfBuildDelegateEqualsNull()
+ {
+ string orgRepoPath = SandboxPackBuilderTestRepo();
+ PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);
+
+ using (Repository orgRepo = new Repository(orgRepoPath))
+ {
+ Assert.Throws(() =>
+ {
+ orgRepo.ObjectDatabase.Pack(packBuilderOptions, null);
+ });
+ }
+ }
+
+ [Fact]
+ public void ExceptionIfNegativeNumberOfThreads()
+ {
+ string orgRepoPath = SandboxPackBuilderTestRepo();
+ PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);
+
+ Assert.Throws(() =>
+ {
+ packBuilderOptions.MaximumNumberOfThreads = -1;
+ });
+ }
+
+ [Fact]
+ public void ExceptionIfAddNullObjectID()
+ {
+ string orgRepoPath = SandboxPackBuilderTestRepo();
+ PackBuilderOptions packBuilderOptions = new PackBuilderOptions(orgRepoPath);
+
+ using (Repository orgRepo = new Repository(orgRepoPath))
+ {
+ Assert.Throws(() =>
+ {
+ 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(() =>
+ {
+ orgRepo.ObjectDatabase.Pack(packBuilderOptions, builder =>
+ {
+ builder.AddRecursively(null);
+ });
+ });
+ }
+ }
+ }
+}
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/HEAD b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/HEAD
new file mode 100644
index 000000000..cb089cd89
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/config b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/config
new file mode 100644
index 000000000..78387c50b
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/config
@@ -0,0 +1,8 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ symlinks = false
+ ignorecase = true
+ hideDotFiles = dotGitOnly
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/index
new file mode 100644
index 000000000..1af67f2d4
Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/index differ
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/87/2129051d644790636b416d1ef1ec830c5f6b90 b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/87/2129051d644790636b416d1ef1ec830c5f6b90
new file mode 100644
index 000000000..3c800a797
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/87/2129051d644790636b416d1ef1ec830c5f6b90
@@ -0,0 +1,3 @@
+xI
+B1]>'[oU/Zni"5SQhC.n=?
\ No newline at end of file
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/88/e38705fdbd3608cddbe904b67c731f3234c45b b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/88/e38705fdbd3608cddbe904b67c731f3234c45b
new file mode 100644
index 000000000..783449ff9
Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/88/e38705fdbd3608cddbe904b67c731f3234c45b differ
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/cc/628ccd10742baea8241c5924df992b5c019f71 b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/cc/628ccd10742baea8241c5924df992b5c019f71
new file mode 100644
index 000000000..6b011038d
Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/cc/628ccd10742baea8241c5924df992b5c019f71 differ
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/ce/013625030ba8dba906f756967f9e9ca394464a b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
new file mode 100644
index 000000000..6802d4949
Binary files /dev/null and b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/objects/ce/013625030ba8dba906f756967f9e9ca394464a differ
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/refs/heads/master b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/refs/heads/master
new file mode 100644
index 000000000..2ed6cd9fa
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/dot_git/refs/heads/master
@@ -0,0 +1 @@
+872129051d644790636b416d1ef1ec830c5f6b90
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/hello.txt b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/hello.txt
new file mode 100644
index 000000000..e965047ad
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/hello.txt
@@ -0,0 +1 @@
+Hello
diff --git a/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/world.txt b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/world.txt
new file mode 100644
index 000000000..216e97ce0
--- /dev/null
+++ b/LibGit2Sharp.Tests/Resources/packbuilder_testrepo_wd/world.txt
@@ -0,0 +1 @@
+World
diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
index 3c1f6e2e0..c1fbefb7f 100644
--- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
+++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
@@ -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; }
@@ -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));
}
@@ -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();
diff --git a/LibGit2Sharp/Core/Handles/PackBuilderSafeHandle.cs b/LibGit2Sharp/Core/Handles/PackBuilderSafeHandle.cs
new file mode 100644
index 000000000..060fefc10
--- /dev/null
+++ b/LibGit2Sharp/Core/Handles/PackBuilderSafeHandle.cs
@@ -0,0 +1,11 @@
+namespace LibGit2Sharp.Core.Handles
+{
+ internal class PackBuilderSafeHandle : SafeHandleBase
+ {
+ protected override bool ReleaseHandleImpl()
+ {
+ Proxy.git_packbuilder_free(handle);
+ return true;
+ }
+ }
+}
diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs
index 718fe1487..0e3d6b3fc 100644
--- a/LibGit2Sharp/Core/NativeMethods.cs
+++ b/LibGit2Sharp/Core/NativeMethods.cs
@@ -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,
diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs
index 2c9cf12bf..dec711d24 100644
--- a/LibGit2Sharp/Core/Proxy.cs
+++ b/LibGit2Sharp/Core/Proxy.cs
@@ -1547,6 +1547,77 @@ public static Tuple git_patch_line_stats(PatchSafeHandle patch)
#endregion
+ #region git_packbuilder_
+
+ public static void git_packbuilder_free(IntPtr packbuilder)
+ {
+ NativeMethods.git_packbuilder_free(packbuilder);
+ }
+
+ public static PackBuilderSafeHandle git_packbuilder_new(RepositorySafeHandle repo)
+ {
+ PackBuilderSafeHandle handle;
+
+ int res = NativeMethods.git_packbuilder_new(out handle, repo);
+ Ensure.ZeroResult(res);
+
+ return handle;
+ }
+
+ public static void git_packbuilder_insert(PackBuilderSafeHandle packbuilder, ObjectId targetId, string name)
+ {
+ GitOid oid = targetId.Oid;
+
+ int res = NativeMethods.git_packbuilder_insert(packbuilder, ref oid, name);
+ Ensure.ZeroResult(res);
+ }
+
+ internal static void git_packbuilder_insert_commit(PackBuilderSafeHandle packbuilder, ObjectId targetId)
+ {
+ GitOid oid = targetId.Oid;
+
+ int res = NativeMethods.git_packbuilder_insert_commit(packbuilder, ref oid);
+ Ensure.ZeroResult(res);
+ }
+
+ internal static void git_packbuilder_insert_tree(PackBuilderSafeHandle packbuilder, ObjectId targetId)
+ {
+ GitOid oid = targetId.Oid;
+
+ int res = NativeMethods.git_packbuilder_insert_tree(packbuilder, ref oid);
+ Ensure.ZeroResult(res);
+ }
+
+ public static void git_packbuilder_insert_recur(PackBuilderSafeHandle packbuilder, ObjectId targetId, string name)
+ {
+ GitOid oid = targetId.Oid;
+
+ int res = NativeMethods.git_packbuilder_insert_recur(packbuilder, ref oid, name);
+ Ensure.ZeroResult(res);
+ }
+
+ public static uint git_packbuilder_set_threads(PackBuilderSafeHandle packbuilder, uint numThreads)
+ {
+ return NativeMethods.git_packbuilder_set_threads(packbuilder, numThreads);
+ }
+
+ public static void git_packbuilder_write(PackBuilderSafeHandle packbuilder, FilePath path)
+ {
+ int res = NativeMethods.git_packbuilder_write(packbuilder, path, 0, IntPtr.Zero, IntPtr.Zero);
+ Ensure.ZeroResult(res);
+ }
+
+ public static uint git_packbuilder_object_count(PackBuilderSafeHandle packbuilder)
+ {
+ return NativeMethods.git_packbuilder_object_count(packbuilder);
+ }
+
+ public static uint git_packbuilder_written(PackBuilderSafeHandle packbuilder)
+ {
+ return NativeMethods.git_packbuilder_written(packbuilder);
+ }
+ #endregion
+
#region git_rebase
public static RebaseSafeHandle git_rebase_init(
diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj
index 3fc9f59b5..8254b811a 100644
--- a/LibGit2Sharp/LibGit2Sharp.csproj
+++ b/LibGit2Sharp/LibGit2Sharp.csproj
@@ -73,6 +73,7 @@
+
@@ -129,6 +130,7 @@
+
diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs
index 5376fdb87..0adb09afd 100644
--- a/LibGit2Sharp/ObjectDatabase.cs
+++ b/LibGit2Sharp/ObjectDatabase.cs
@@ -643,5 +643,66 @@ public virtual MergeTreeResult MergeCommits(Commit ours, Commit theirs, MergeTre
return mergeResult;
}
}
+
+ ///
+ /// Packs all the objects in the and write a pack (.pack) and index (.idx) files for them.
+ ///
+ /// Packing options
+ /// This method will invoke the default action of packing all objects in an arbitrary order.
+ /// Packing results
+ public virtual PackBuilderResults Pack(PackBuilderOptions options)
+ {
+ return InternalPack(options, builder =>
+ {
+ foreach (GitObject obj in repo.ObjectDatabase)
+ {
+ builder.Add(obj.Id);
+ }
+ });
+ }
+
+ ///
+ /// Packs objects in the chosen by the packDelegate action
+ /// and write a pack (.pack) and index (.idx) files for them
+ ///
+ /// Packing options
+ /// Packing action
+ /// Packing results
+ public virtual PackBuilderResults Pack(PackBuilderOptions options, Action packDelegate)
+ {
+ return InternalPack(options, packDelegate);
+ }
+
+ ///
+ /// Packs objects in the and write a pack (.pack) and index (.idx) files for them.
+ /// For internal use only.
+ ///
+ /// Packing options
+ /// Packing action
+ /// Packing results
+ private PackBuilderResults InternalPack(PackBuilderOptions options, Action packDelegate)
+ {
+ Ensure.ArgumentNotNull(options, "options");
+ Ensure.ArgumentNotNull(packDelegate, "packDelegate");
+
+ PackBuilderResults results = new PackBuilderResults();
+
+ using (PackBuilder builder = new PackBuilder(repo))
+ {
+ // set pre-build options
+ builder.SetMaximumNumberOfThreads(options.MaximumNumberOfThreads);
+
+ // call the provided action
+ packDelegate(builder);
+
+ // writing the pack and index files
+ builder.Write(options.PackDirectoryPath);
+
+ // adding the results to the PackBuilderResults object
+ results.WrittenObjectsCount = builder.WrittenObjectsCount;
+ }
+
+ return results;
+ }
}
}
diff --git a/LibGit2Sharp/PackBuilder.cs b/LibGit2Sharp/PackBuilder.cs
new file mode 100644
index 000000000..02ea76dc7
--- /dev/null
+++ b/LibGit2Sharp/PackBuilder.cs
@@ -0,0 +1,206 @@
+using System;
+using System.IO;
+using LibGit2Sharp.Core;
+using LibGit2Sharp.Core.Handles;
+
+namespace LibGit2Sharp
+{
+ ///
+ /// Representation of a git PackBuilder.
+ ///
+ public sealed class PackBuilder : IDisposable
+ {
+ private readonly PackBuilderSafeHandle packBuilderHandle;
+ private readonly Repository repo;
+
+ ///
+ /// Constructs a PackBuilder for a .
+ ///
+ internal PackBuilder(Repository repository)
+ {
+ Ensure.ArgumentNotNull(repository, "repository");
+
+ repo = repository;
+ packBuilderHandle = Proxy.git_packbuilder_new(repo.Handle);
+ }
+
+ ///
+ /// Inserts a single to the PackBuilder.
+ /// For an optimal pack it's mandatory to insert objects in recency order, commits followed by trees and blobs. (quoted from libgit2 API ref)
+ ///
+ /// The object to be inserted.
+ /// if the gitObject is null
+ public void Add(T gitObject) where T : GitObject
+ {
+ Ensure.ArgumentNotNull(gitObject, "gitObject");
+
+ Add(gitObject.Id);
+ }
+
+ ///
+ /// Recursively inserts a and its referenced objects.
+ /// Inserts the object as well as any object it references.
+ ///
+ /// The object to be inserted recursively.
+ /// if the gitObject is null
+ public void AddRecursively(T gitObject) where T : GitObject
+ {
+ Ensure.ArgumentNotNull(gitObject, "gitObject");
+
+ AddRecursively(gitObject.Id);
+ }
+
+ ///
+ /// Inserts a single object to the PackBuilder by its .
+ /// For an optimal pack it's mandatory to insert objects in recency order, commits followed by trees and blobs. (quoted from libgit2 API ref)
+ ///
+ /// The object ID to be inserted.
+ /// if the id is null
+ public void Add(ObjectId id)
+ {
+ Ensure.ArgumentNotNull(id, "id");
+
+ Proxy.git_packbuilder_insert(packBuilderHandle, id, null);
+ }
+
+ ///
+ /// Recursively inserts an object and its referenced objects by its .
+ /// Inserts the object as well as any object it references.
+ ///
+ /// The object ID to be recursively inserted.
+ /// if the id is null
+ public void AddRecursively(ObjectId id)
+ {
+ Ensure.ArgumentNotNull(id, "id");
+
+ Proxy.git_packbuilder_insert_recur(packBuilderHandle, id, null);
+ }
+
+ ///
+ /// Disposes the PackBuilder object.
+ ///
+ public void Dispose()
+ {
+ packBuilderHandle.SafeDispose();
+ }
+
+ ///
+ /// Writes the pack file and corresponding index file to path.
+ ///
+ /// The path that pack and index files will be written to it.
+ internal void Write(string path)
+ {
+ Proxy.git_packbuilder_write(packBuilderHandle, path);
+ }
+
+ ///
+ /// Sets number of threads to spawn.
+ ///
+ /// Returns the number of actual threads to be used.
+ /// The Number of threads to spawn. An argument of 0 ensures using all available CPUs
+ internal int SetMaximumNumberOfThreads(int nThread)
+ {
+ // Libgit2 set the number of threads to 1 by default, 0 ensures git_online_cpus
+ return (int)Proxy.git_packbuilder_set_threads(packBuilderHandle, (uint)nThread);
+ }
+
+ ///
+ /// Number of objects the PackBuilder will write out.
+ ///
+ internal long ObjectsCount
+ {
+ get { return Proxy.git_packbuilder_object_count(packBuilderHandle); }
+ }
+
+ ///
+ /// Number of objects the PackBuilder has already written out.
+ /// This is only correct after the pack file has been written.
+ ///
+ internal long WrittenObjectsCount
+ {
+ get { return Proxy.git_packbuilder_written(packBuilderHandle); }
+ }
+
+ internal PackBuilderSafeHandle Handle
+ {
+ get { return packBuilderHandle; }
+ }
+ }
+
+ ///
+ /// The results of pack process of the .
+ ///
+ public struct PackBuilderResults
+ {
+ ///
+ /// Number of objects the PackBuilder has already written out.
+ ///
+ public long WrittenObjectsCount { get; internal set; }
+ }
+
+ ///
+ /// Packing options of the .
+ ///
+ public sealed class PackBuilderOptions
+ {
+ ///
+ /// Constructor
+ ///
+ /// Directory path to write the pack and index files to it
+ /// The default value for maximum number of threads to spawn is 0 which ensures using all available CPUs.
+ /// if packDirectory is null or empty
+ /// if packDirectory doesn't exist
+ public PackBuilderOptions(string packDirectory)
+ {
+ PackDirectoryPath = packDirectory;
+ MaximumNumberOfThreads = 0;
+ }
+
+ ///
+ /// Directory path to write the pack and index files to it.
+ ///
+ public string PackDirectoryPath
+ {
+ set
+ {
+ Ensure.ArgumentNotNullOrEmptyString(value, "packDirectory");
+
+ if (!Directory.Exists(value))
+ {
+ throw new DirectoryNotFoundException("The Directory " + value + " does not exist.");
+ }
+
+ path = value;
+ }
+ get
+ {
+ return path;
+ }
+ }
+
+ ///
+ /// Maximum number of threads to spawn.
+ /// The default value is 0 which ensures using all available CPUs.
+ ///
+ public int MaximumNumberOfThreads
+ {
+ set
+ {
+ if (value < 0)
+ {
+ throw new ArgumentException("Argument can not be negative", "MaximumNumberOfThreads");
+ }
+
+ nThreads = value;
+ }
+ get
+ {
+ return nThreads;
+ }
+
+ }
+
+ private string path;
+ private int nThreads;
+ }
+}