Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2sharp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryorah <yoram.harmelin@gmail.com>2013-01-11 19:42:42 +0400
committeryorah <yoram.harmelin@gmail.com>2013-12-13 17:26:41 +0400
commit36d40bd80e858004c3c8b92553082e3ceca4cf46 (patch)
treefcb428288a08894ae4b7264a386bbb237d851e71 /LibGit2Sharp/TarArchiver.cs
parentf2d5b19c35d703738d406d48e6c63b679246513d (diff)
Add archive as tar functionality
Implemented as an extension method of `ObjectDatabase`. Lots of logic taken from [archive-tar.c](https://github.com/git/git/blob/master/archive-tar.c).
Diffstat (limited to 'LibGit2Sharp/TarArchiver.cs')
-rw-r--r--LibGit2Sharp/TarArchiver.cs88
1 files changed, 88 insertions, 0 deletions
diff --git a/LibGit2Sharp/TarArchiver.cs b/LibGit2Sharp/TarArchiver.cs
new file mode 100644
index 00000000..f6fe7520
--- /dev/null
+++ b/LibGit2Sharp/TarArchiver.cs
@@ -0,0 +1,88 @@
+using System;
+using System.IO;
+using System.Text;
+using LibGit2Sharp.Core;
+
+namespace LibGit2Sharp
+{
+ /// <summary>
+ /// Logic for tar archiving (not the actual tar format, but the overal logic related to tar+git) is taken
+ /// from https://github.com/git/git/blob/master/archive-tar.c.
+ /// </summary>
+ internal class TarArchiver : ArchiverBase, IDisposable
+ {
+ private readonly TarWriter writer;
+
+ public TarArchiver(FileStream output)
+ {
+ writer = new TarWriter(output);
+ }
+
+ #region Overrides of ArchiverBase
+
+ public override void BeforeArchiving(Tree tree, ObjectId oid, DateTimeOffset modificationTime)
+ {
+ if (oid == null)
+ {
+ return;
+ }
+
+ // Store the sha in the pax_global_header
+ using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(string.Format("52 comment={0}\n", oid.Sha))))
+ {
+ writer.Write("pax_global_header", stream, modificationTime, "666".OctalToInt32(),
+ "0", "0", 'g', "root", "root", "0", "0", oid.Sha, false);
+ }
+ }
+
+ protected override void AddTreeEntry(string path, TreeEntry entry, DateTimeOffset modificationTime)
+ {
+ switch (entry.Mode)
+ {
+ case Mode.GitLink:
+ case Mode.Directory:
+ writer.Write(path + "/", null, modificationTime, "775".OctalToInt32(),
+ "0", "0", '5', "root", "root", "0", "0", entry.TargetId.Sha, false);
+ break;
+ case Mode.ExecutableFile:
+ case Mode.NonExecutableFile:
+ case Mode.NonExecutableGroupWritableFile:
+ var blob = ((Blob) entry.Target);
+
+ WriteStream(path, entry, modificationTime,
+ () => blob.IsBinary ? blob.GetContentStream() : blob.GetContentStream(new FilteringOptions(path)));
+ break;
+ case Mode.SymbolicLink:
+ using (Stream contentStream = ((Blob)entry.Target).GetContentStream(new FilteringOptions(path)))
+ {
+ writer.Write(path, contentStream, modificationTime, "777".OctalToInt32(),
+ "0", "0", '2', "root", "root", "0", "0", entry.TargetId.Sha, true);
+ }
+ break;
+ default:
+ throw new InvalidOperationException(string.Format("Unsupported file mode: {0} (sha1: {1}).", entry.Mode, entry.TargetId.Sha));
+ }
+ }
+
+ private void WriteStream(string path, TreeEntry entry, DateTimeOffset modificationTime, Func<Stream> streamer)
+ {
+ using (Stream contentStream = streamer())
+ {
+ writer.Write(path, contentStream, modificationTime,
+ (entry.Mode == Mode.ExecutableFile) ? "775".OctalToInt32() : "664".OctalToInt32(),
+ "0", "0", '0', "root", "root", "0", "0", entry.TargetId.Sha, false);
+ }
+ }
+
+ #endregion
+
+ #region Implementation of IDisposable
+
+ public void Dispose()
+ {
+ writer.Dispose();
+ }
+
+ #endregion
+ }
+}