Git 用于 Windows Blob 压缩
Git for Windows Blob Compression
我正在尝试制作一个工具,该工具可与 GIT 为 Windows 创建的原始 git 存储库一起使用。我需要从 .git/objects
目录中解压一个原始的 object。这是 object 的十六进制转储:
00000000 78 01 2b 29 4a 4d 55 30 36 63 30 34 30 30 33 31 |x.+)JMU06c040031|
00000010 51 c8 4d cc cc d3 2b a9 28 61 e8 a9 8b 4a ab 97 |QÈMÌÌÓ+©(aè©.J«.|
00000020 2e 97 70 ff d7 71 40 c6 f6 b1 8b f0 c2 4d 0a 00 |..pÿ×q@Æö±.ðÂM..|
00000030 33 56 0f 42 |3V.B|
如果我用 GIT 为 Windows 转储它,我会收到以下内容:
$ git cat-file -p 9171a57695205f9d7f03f1d2872b110b0ee538e9
100644 blob 8c7e5a667f1b771847fe88c01c3de34413a1b220 main.txt
当我尝试使用 DotNetZip library and also an online tool 解压缩它时,它没有正确解压缩。我的程序在尝试解压缩时产生的输出是:
00000000 74 72 65 65 20 33 36 00 31 30 30 36 34 34 20 6d |tree 36.100644 m|
00000010 61 69 6e 2e 74 78 74 00 8c 7e 5a 66 7f 1b 77 18 |ain.txt..~Zf..w.|
00000020 47 fe 88 c0 1c 3d e3 44 13 a1 b2 20 |Gþ.À.=ãD.¡² |
我知道 git cat-file
去掉了 object header,所以这是一个区别,但为什么 object 的其余部分没有正确充气?
我用来尝试inflate的代码,依赖于nuget包"Zlib.Portable.Signed":
using Ionic.Zlib;
using System.IO;
namespace TestInflate
{
class Program
{
static void Main(string[] args)
{
using (var lFrom = File.OpenRead("IN"))
using (var lInflate = new ZlibStream(lFrom, CompressionMode.Decompress))
using (var lTo = File.Create("OUT"))
lInflate.CopyTo(lTo);
}
}
}
根据评论,您的解压器没问题。问题是您正在检查引用子树和 blob 的 tree object。
所有 object 都以 header 开头,给出 object 的类型,以及以字节为单位的总体大小,但表示为 ASCII 字符串。所以tree 36
表示这是一棵树,树长36字节。之后是 ASCII NUL、0x00 或 CTRL-@。之后是树条目。
每个条目的格式为 mode space name CTRL-@哈希。散列是 binary,并且始终恰好 20 个字节长(至少在 Git 切换到新散列之前;如何指示和编码尚未确定) .你的 mode
是 100644
而你的 name
是 main.txt
,所以你有 6 +1+8+1+20 = 36字节,也就是header中的长度,所以就是整棵树。
我正在尝试制作一个工具,该工具可与 GIT 为 Windows 创建的原始 git 存储库一起使用。我需要从 .git/objects
目录中解压一个原始的 object。这是 object 的十六进制转储:
00000000 78 01 2b 29 4a 4d 55 30 36 63 30 34 30 30 33 31 |x.+)JMU06c040031|
00000010 51 c8 4d cc cc d3 2b a9 28 61 e8 a9 8b 4a ab 97 |QÈMÌÌÓ+©(aè©.J«.|
00000020 2e 97 70 ff d7 71 40 c6 f6 b1 8b f0 c2 4d 0a 00 |..pÿ×q@Æö±.ðÂM..|
00000030 33 56 0f 42 |3V.B|
如果我用 GIT 为 Windows 转储它,我会收到以下内容:
$ git cat-file -p 9171a57695205f9d7f03f1d2872b110b0ee538e9
100644 blob 8c7e5a667f1b771847fe88c01c3de34413a1b220 main.txt
当我尝试使用 DotNetZip library and also an online tool 解压缩它时,它没有正确解压缩。我的程序在尝试解压缩时产生的输出是:
00000000 74 72 65 65 20 33 36 00 31 30 30 36 34 34 20 6d |tree 36.100644 m|
00000010 61 69 6e 2e 74 78 74 00 8c 7e 5a 66 7f 1b 77 18 |ain.txt..~Zf..w.|
00000020 47 fe 88 c0 1c 3d e3 44 13 a1 b2 20 |Gþ.À.=ãD.¡² |
我知道 git cat-file
去掉了 object header,所以这是一个区别,但为什么 object 的其余部分没有正确充气?
我用来尝试inflate的代码,依赖于nuget包"Zlib.Portable.Signed":
using Ionic.Zlib;
using System.IO;
namespace TestInflate
{
class Program
{
static void Main(string[] args)
{
using (var lFrom = File.OpenRead("IN"))
using (var lInflate = new ZlibStream(lFrom, CompressionMode.Decompress))
using (var lTo = File.Create("OUT"))
lInflate.CopyTo(lTo);
}
}
}
根据评论,您的解压器没问题。问题是您正在检查引用子树和 blob 的 tree object。
所有 object 都以 header 开头,给出 object 的类型,以及以字节为单位的总体大小,但表示为 ASCII 字符串。所以tree 36
表示这是一棵树,树长36字节。之后是 ASCII NUL、0x00 或 CTRL-@。之后是树条目。
每个条目的格式为 mode space name CTRL-@哈希。散列是 binary,并且始终恰好 20 个字节长(至少在 Git 切换到新散列之前;如何指示和编码尚未确定) .你的 mode
是 100644
而你的 name
是 main.txt
,所以你有 6 +1+8+1+20 = 36字节,也就是header中的长度,所以就是整棵树。