¿Cómo DESINFLAR con una herramienta de línea de comando para extraer un objeto git?

Estoy buscando un contenedor de línea de comando para el algoritmo DEFLATE.

Tengo un archivo (git blob) que está comprimido usando DEFLATE, y quiero descomprimirlo. El comando gzip no parece tener una opción para usar directamente el algoritmo DEFLATE, en lugar del formato gzip.

Idealmente, estoy buscando una herramienta estándar de Unix / Linux que pueda hacer esto.

editar: este es el resultado que obtengo cuando trato de usar gzip para mi problema:

$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip gzip: stdin: not in gzip format 

ACTUALIZACIÓN: Mark Adler notó que los blobs git no son flujos DEFLATE sin procesar, sino zlib. Estos pueden ser desempaquetados por la herramienta pigz , que viene preempaquetada en varias distribuciones de 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! 

Mi respuesta original, guardada por razones históricas:

Si entiendo la sugerencia en el artículo de Wikipedia mencionado por Marc van Kempen, puedes usar puff.c desde zlib directamente.

Este es un pequeño ejemplo:

 #include  #include  #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 ); } 

Algo como lo siguiente imprimirá el contenido sin formato, incluido el encabezado “$ type $ length \ 0”:

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

Puede hacer esto con la herramienta de línea de comandos de OpenSSL:

 openssl zlib -d < $IN > $OUT 

Desafortunadamente, al menos en Ubuntu, el subcomando zlib está deshabilitado en la configuración de comstackción predeterminada ( --no-zlib --no-zlib-dynamic ), por lo que necesitaría comstackr openssl desde el origen para usarlo. Pero está habilitado por defecto en Arch, por ejemplo.

Editar: parece que el comando zlib ya no es compatible con Arch. Esta respuesta puede que ya no sea útil 🙁

pythonic one-liner:

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

Puedes usar zlib-flate, así:

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

Está allí por defecto en mi máquina, pero es parte de qpdf - tools for and transforming and inspecting PDF files si necesita instalarlo.

He echo un echo al final del comando, ya que es más fácil leer la salida de esa manera.

Pruebe el siguiente comando:

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

No se necesitan herramientas externas.

Fuente: ¿Cómo descomprimir datos zlib en UNIX? en Unix SE

Aquí hay un Ruby one-liner (cd .git / first e identifica la ruta a cualquier objeto):

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

Aquí hay un ejemplo de cómo abrir un objeto de commit en 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! 

Lo que verá allí es casi idéntico al resultado de ‘git cat-file -p [hash]’, excepto que el comando no imprime el encabezado (‘commit’ seguido del tamaño del contenido y un byte nulo).

Me cansé de no tener una buena solución para esto, así que puse algo en NPM:

https://github.com/jezell/zlibber

Ahora puede simplemente canalizar para inflar / desinflar el comando.

Los objetos git son comprimidos por zlib lugar de por gzip , por lo que se usa zlib para descomprimirlo o comando git, es decir, git cat-file -p , para imprimir contenido.

Parece que Mark Adler nos tiene en cuenta y escribió un ejemplo de cómo hacer esto con: http://www.zlib.net/zpipe.c

Comstack con nada más que gcc -lz y los encabezados zlib instalados. Copié el binario resultante en mi /usr/local/bin/zpipe mientras trabajaba con git stuff.

 // 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 

Ver http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

Enumera una serie de implementaciones de software, incluido gzip, por lo que debería funcionar. ¿Intentó simplemente ejecutar gzip en el archivo? ¿No reconoce el formato automáticamente?

¿Cómo sabes que está comprimido usando DEFLATE? ¿Qué herramienta se utilizó para comprimir el archivo?

¿Por qué no utilizas las herramientas de git para acceder a los datos? Esto debería poder leer cualquier objeto git:

 git show --pretty=raw  

Encontré esta pregunta buscando una solución -text con un error con la utilidad -text en la nueva versión del cliente hadoop dfs de hadoop dfs que acabo de instalar. La utilidad -text funciona como cat , excepto si el archivo que se está leyendo está comprimido, descomprime y saca el texto sin formato (de ahí el nombre).

Las respuestas ya publicadas fueron definitivamente útiles, pero algunas tienen un problema cuando se trata de cantidades de datos del tamaño de Hadoop: leen todo en la memoria antes de descomprimir.

Entonces, aquí están mis variaciones sobre las respuestas de Perl y Python anteriores que no tienen esa limitación:

Pitón:

 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)' 

Tenga en cuenta el uso del -cat , en lugar de -text . Esto es para que mi trabajo no se rompa después de haber solucionado el error. Disculpas por la legibilidad de la versión de Python.

Los objetos git son flujos zlib (no desinflados en bruto). pigz descomprimirá aquellos con la opción -dz .

Pigz puede hacerlo:

 apt-get install pigz unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 
 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"));