remove - git tags best practices
Desinflar herramienta de lĂnea de comandos (18)
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
¿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 <object SHA-1>
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
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).
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 comprimidos por zlib
lugar de por gzip
, por lo que se usa zlib
para descomprimirlo o comando git, es decir, git cat-file -p <SHA1>
, para imprimir contenido.
Los objetos git son flujos zlib (no desinflados en bruto). pigz descomprimirá aquellos con la opción -dz
.
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.
Parece que Mark Adler nos tiene en cuenta y escribió un ejemplo de cómo hacer esto con: http://www.zlib.net/zpipe.c
Compila 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.
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
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 compilación predeterminada ( --no-zlib
--no-zlib-dynamic
), por lo que necesitaría compilar 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 :(
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.
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?
pythonic one-liner:
$> python -c "import zlib,sys;print /
repr(zlib.decompress(sys.stdin.read()))" < $IN
pigz puede hacerlo:
apt-get install pigz
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
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 <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 );
}
// 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
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"));