Как DEFLATE с помощью средства командной строки для извлечения объекта git?

Я ищу оболочку командной строки для алгоритма DEFLATE.

У меня есть файл (git blob), который сжимается с помощью DEFLATE, и я хочу распаковать его. Команда gzip, похоже, не имеет возможности напрямую использовать алгоритм DEFLATE, а не формат gzip.

В идеале я ищу стандартный инструмент Unix/Linux, который может это сделать.

edit: Это результат, который я получаю при попытке использовать gzip для моей проблемы:

$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip

gzip: stdin: not in gzip format

Ответ 1

ОБНОВЛЕНИЕ: Марк Адлер отметил, что git blobs не являются сырыми потоками DEFLATE, а потоками zlib. Они могут распаковываться с помощью инструмента pigz, который поставляется в нескольких дистрибутивах Linux:

$ cat foo.txt 
file foo.txt!

$ git ls-files -s foo.txt
100644 7a79fc625cac65001fb127f468847ab93b5f8b19 0   foo.txt

$ pigz -d < .git/objects/7a/79fc625cac65001fb127f468847ab93b5f8b19 
blob 14file foo.txt!

Мой оригинальный ответ, сохраненный по историческим причинам:

Если я понимаю подсказку в статье Википедии, упомянутой Марком ван Кемпеном, вы можете использовать puff.c от zlib непосредственно.

Это небольшой пример:

#include <assert.h>
#include <string.h>
#include "puff.h"

int main( int argc, char **argv ) {
    unsigned char dest[ 5 ];
    unsigned long destlen = 4;
    const unsigned char *source = "\x4B\x2C\x4E\x49\x03\x00";
    unsigned long sourcelen = 6;    
    assert( puff( dest, &destlen, source, &sourcelen ) == 0 );
    dest[ 4 ] = '\0';
    assert( strcmp( dest, "asdf" ) == 0 );
}

Ответ 2

Что-то вроде следующего будет печатать исходное содержимое, включая заголовок "$ type $length\0":

perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' \
     < .git/objects/27/de0a1dd5a89a94990618632967a1c86a82d577

Ответ 3

Вы можете сделать это с помощью инструмента командной строки OpenSSL:

openssl zlib -d < $IN > $OUT

К сожалению, по крайней мере, на Ubuntu подкоманда zlib отключена в конфигурации сборки по умолчанию (--no-zlib --no-zlib-dynamic), поэтому вам нужно будет скомпилировать openssl из источника, чтобы использовать ее. Но он включен по умолчанию на Arch, например.

Изменить: Кажется, что команда zlib больше не поддерживается в Arch. Этот ответ может быть не полезен больше: (

Ответ 4

pythonic one-liner:

$> python -c "import zlib,sys;print \
           repr(zlib.decompress(sys.stdin.read()))" < $IN

Ответ 5

Вы можете использовать zlib-flate, например:

cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 \
    | zlib-flate -uncompress; echo

Он там по умолчанию на моей машине, но это часть qpdf - tools for and transforming and inspecting PDF files, если вам нужно его установить.

Я вытащил echo в конце команды, так как теперь легче читать выход.

Ответ 6

Попробуйте выполнить следующую команду:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip

Никаких внешних инструментов не требуется.

Источник: Как распаковать данные zlib в UNIX? в unix SE

Ответ 7

Вот однострочный Ruby (cd.git/first и укажите путь к любому объекту):

ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208

Ответ 8

Вот пример взлома open объекта commit в Python:

$ git show
commit 0972d7651ff85bedf464fba868c2ef434543916a
# all the junk in my commit...
$ python
>>> import zlib
>>> file = open(".git/objects/09/72d7651ff85bedf464fba868c2ef434543916a")
>>> data = file.read()
>>> print data
# binary garbage
>>> unzipped_data = zlib.decompress(data)
>>> print unzipped_data
# all the junk in my commit!

То, что вы увидите, почти идентично выходу 'git cat-file -p [hash]', за исключением того, что команда не печатает заголовок ('commit', за которым следует размер содержимого и нулевой байт).

Ответ 9

Я устал от того, что у меня нет хорошего решения, поэтому я поставил что-то на NPM:

https://github.com/jezell/zlibber

Теперь вы можете просто надуть команду надувания/спускания.

Ответ 10

git объекты сжимаются zlib, а не gzip, поэтому либо с помощью zlib, чтобы распаковать его, либо git, т.е. git cat-file -p <SHA1>, для печати содержимого.

Ответ 11

Похоже, что Марк Адлер имеет в виду нас и написал пример того, как это сделать: http://www.zlib.net/zpipe.c

Он компилируется не более чем с gcc -lz и заголовками zlib. Я скопировал полученный двоичный файл в мой /usr/local/bin/zpipe, работая с файлом git.

Ответ 12

// save this as deflate.go

package main

import (
    "compress/zlib"
    "io"
    "os"
    "flag"
)

var infile = flag.String("f", "", "infile")

func main() {
    flag.Parse()
    file, _ := os.Open(*infile)

    r, err := zlib.NewReader(file)
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, r)

    r.Close()
}

$ go build deflate.go
$ ./deflate -f .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7

Ответ 13

См. http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

В нем перечислены некоторые программные реализации, включая gzip, поэтому они должны работать. Вы пытались запустить gzip в файле? Не распознает ли он формат автоматически?

Как вы знаете, что он сжат с помощью DEFLATE? Какой инструмент использовался для сжатия файла?

Ответ 14

Почему бы вам просто не использовать инструменты git для доступа к данным? Это должно быть в состоянии прочитать любой объект git:

git show --pretty=raw <object SHA-1>

Ответ 15

Я нашел этот вопрос для поиска работы с ошибкой с утилитой -text в новой версии клиента hadoop dfs, который я только что установил. Утилита -text работает как cat, за исключением того, что если считываемый файл сжимается, он прозрачно распаковывает и выводит текст с открытым текстом (отсюда и название).

Ответы, уже опубликованные, были определенно полезны, но некоторые из них имеют одну проблему при работе с размерами данных Hadoop - они читают все в памяти перед распаковкой.

Итак, вот мои варианты ответов Perl и Python выше, которые не имеют этого ограничения:

Python:

hadoop fs -cat /path/to/example.deflate |
  python -c 'import zlib,sys;map(lambda b:sys.stdout.write(zlib.decompress(b)),iter(lambda:sys.stdin.read(4096),""))'

Perl:

hadoop fs -cat /path/to/example.deflate |
  perl -MCompress::Zlib -e 'print uncompress($buf) while sysread(STDIN,$buf,4096)'

Обратите внимание на использование подкоманды -cat вместо -text. Это так, что мой рабочий процесс не прерывается после того, как они исправили ошибку. Извинения за читаемость версии python.

Ответ 16

git объекты представляют собой потоки zlib (не сырые дефлаты). pigz будет декомпрессировать их с помощью параметра -dz.

Ответ 17

pigz может сделать это:

apt-get install pigz
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7

Ответ 18

const zlib = require("zlib");
const adler32 = require("adler32");
const data = "hello world~!";
const chksum = adler32.sum(new Buffer(data)).toString(16);
console.log("789c",zlib.deflateRawSync(data).toString("hex"),chksum);
// or
console.log(zlib.deflateSync(data).toString("hex"));