1 files changed, 101 insertions, 0 deletions
diff --git a/LibGit/TreeObject.cs b/LibGit/TreeObject.cs
new file mode 100644
index 0000000..7d5eb36
--- /dev/null
+++ b/LibGit/TreeObject.cs
@@ -0,0 +1,101 @@
+using System.IO.Compression;
+using System.Text.Json.Serialization;
+using LibGit.Extensions;
+using LibGit.Interfaces;
+
+namespace LibGit;
+
+public class TreeObject
+{
+ [JsonIgnore] public IRepoSource RepoSource { get; }
+ public string ObjectId { get; }
+
+ public TreeObject(IRepoSource repoSource, string objectId)
+ {
+ RepoSource = repoSource;
+ ObjectId = objectId;
+ }
+
+ private const bool _debug = false;
+
+ public string Length { get; set; }
+ public Dictionary<string, TreeObjectEntry> Entries { get; set; } = new();
+
+ public TreeObject ReadFromZlibCompressedObjFile(Stream bytes)
+ {
+ if (_debug) Console.WriteLine($"Decompressing {GetType().Name}");
+ using ZLibStream stream = new ZLibStream(bytes, CompressionMode.Decompress);
+ using var result = new MemoryStream();
+ stream.CopyTo(result);
+ stream.Flush();
+ stream.Close();
+ return ReadFromDecompressedObjFile(result);
+ }
+
+ public TreeObject ReadFromDecompressedObjFile(Stream data)
+ {
+ if (_debug) Console.WriteLine("Parsing tree object");
+ // var data = new Queue<byte>(bytes.ToArray());
+ int iters = 0;
+ data.Seek(0, SeekOrigin.Begin);
+ if (_debug) Console.WriteLine($"Iteration {iters}: starting pos: {data.Position}/+{data.Remaining()}/{data.Length}");
+ Length = data.ReadNullTerminatedField(asciiPrefix: "tree ").AsString();
+ while (data.Remaining() > 20)
+ {
+ if (_debug) Console.WriteLine($"readTree.Iteration {iters} ({data.Position}/+{data.Remaining()}/{data.Length})");
+
+ var entry = ReadFileEntry(data);
+ Entries.Add(entry.Key, entry.Value);
+ }
+
+ if (data.Remaining() > 0)
+ {
+ Console.WriteLine($"--parseTree: Unparsed data after {iters} iteration(s) of parsing TreeObject--");
+ Console.WriteLine(this.ToJson());
+ Console.WriteLine("--HexDump of remaining data--");
+ data.Peek(data.Remaining()).HexDump();
+ //Console.WriteLine($"Unparsed data: {Encoding.UTF8.GetString(data.ToArray())}");
+ }
+
+ data.Close();
+
+ if (_debug)
+ {
+ Console.WriteLine($"-- Read tree object of size {Length} --");
+ foreach (var x in Entries.ToList())
+ {
+ Console.WriteLine($"{x.Value.Mode} {x.Value.Hash} {x.Key}");
+ }
+
+ foreach (var x in Entries.ToList())
+ {
+ Console.WriteLine($"Path: {x.Key}");
+ Console.WriteLine($"Mode: {x.Value.Mode}");
+ Console.WriteLine($"Hash: {x.Value.Hash}");
+ }
+ }
+
+ return this;
+ }
+
+ //parsing
+
+ private static KeyValuePair<string, TreeObjectEntry> ReadFileEntry(Stream data)
+ {
+ if (_debug) Console.WriteLine($"--tree.ReadFileEntry--");
+ var path = "";
+ TreeObjectEntry entry = new();
+ //entry format: <mode> <path>\0<hash>
+ entry.Mode = data.ReadSpaceTerminatedField().AsString();
+ path = data.ReadNullTerminatedField().AsString();
+ entry.Hash = string.Join("", data.ReadBytes(20).Select(x => $"{x:x2}"));
+
+ return new KeyValuePair<string, TreeObjectEntry>(path, entry);
+ }
+
+ public class TreeObjectEntry
+ {
+ public string Mode { get; set; }
+ public string Hash { get; set; }
+ }
+}
\ No newline at end of file
|