Git для Windows Blob Compression - PullRequest
       10

Git для Windows Blob Compression

0 голосов
/ 13 марта 2019

Я пытаюсь создать инструмент, работающий с необработанным git-репозиторием, созданным GIT для Windows.Мне нужно распаковать необработанный объект из каталога .git/objects.Вот шестнадцатеричный дамп объекта:

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 , а также онлайн-инструмент , он не распаковывается должным образом.Вывод, который моя программа выдает при попытке распаковки:

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 удаляет заголовок объекта, так что это одно отличие, но почему остальная часть объекта не надута должным образом?

Код, который я использовал для раздувания, зависит от пакета 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);
        }
    }
}

1 Ответ

0 голосов
/ 13 марта 2019

Судя по комментариям, ваш декомпрессор в порядке. Проблема в том, что вы проверяете объект tree , который ссылается на поддеревья и капли.

Все объекты начинаются с заголовка, в котором указан тип объекта и общий размер в байтах, но он выражается в виде строки ASCII. Таким образом, tree 36 указывает, что это дерево, а дерево имеет длину 36 байтов. Затем следует ASCII NUL, 0x00 или CTRL - @ . После этого идут записи дерева.

Каждая запись имеет вид mode пробел name CTRL - @ hash . Хеш имеет значение двоичный и всегда ровно 20 байт (по крайней мере, пока Git не переключится на новый хэш; как это будет указано и закодировано, еще не определено). Ваш mode равен 100644, а ваш name равен main.txt, поэтому у вас есть 6 + 1 + 8 + 1 + 20 = 36 байтов, то есть длина в заголовке, так что это все дерево.

...