web-dev-qa-db-fra.com

Comment dégonfler avec un outil en ligne de commande pour extraire un objet git?

Je recherche un wrapper de ligne de commande pour l'algorithme DEFLATE.

J'ai un fichier (git blob) qui est compressé à l'aide de DEFLATE, et je veux le décompresser. La commande gzip ne semble pas avoir une option pour utiliser directement l'algorithme DEFLATE, plutôt que le format gzip.

Idéalement, je recherche un outil Unix/Linux standard qui peut le faire.

edit: Voici la sortie que j'obtiens en essayant d'utiliser gzip pour mon problème:

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

gzip: stdin: not in gzip format
75

MISE À JOUR: Mark Adler a noté que les blobs git ne sont pas des flux DEFLATE bruts, mais des flux zlib. Ceux-ci peuvent être décompressés par l'outil pigz, qui est pré-emballé dans plusieurs distributions 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!

Ma réponse originale, conservée pour des raisons historiques:

Si je comprends l'astuce dans le article Wikipedia mentionné par Marc van Kempen, vous pouvez utiliser puff.c de zlib directement.

Voici un petit exemple:

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

Quelque chose comme ce qui suit imprimera le contenu brut, y compris l'en-tête "$ type $ length\0":

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

Vous pouvez le faire avec l'outil de ligne de commande OpenSSL:

openssl zlib -d < $IN > $OUT

Malheureusement, au moins sur Ubuntu, la sous-commande zlib est désactivée dans la configuration de build par défaut (--no-zlib--no-zlib-dynamic), vous devrez donc compiler openssl à partir de la source pour l'utiliser. Mais il est activé par défaut sur Arch, par exemple.

Edit: Il semble que la commande zlib ne soit plus prise en charge sur Arch non plus. Cette réponse pourrait ne plus être utile :(

44
Jack O'Connor

Une doublure en python:

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

Vous pouvez utiliser zlib-flate, comme ceci:

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

Il est là par défaut sur ma machine, mais il fait partie de qpdf - tools for and transforming and inspecting PDF files si vous devez l'installer.

J'ai sauté un echo à la fin de la commande, car il est plus facile de lire la sortie de cette façon.

26
seumasmac

Essayez la commande suivante:

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

Aucun outil externe n'est nécessaire.

Source: Comment décompresser les données zlib sous UNIX? sous unix SE

18
kenorb

Voici un Ruby one-liner (cd .git/first et identifiez le chemin vers n'importe quel objet):

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

J'étais fatigué de ne pas avoir de bonne solution pour cela, alors j'ai mis quelque chose sur NPM:

https://github.com/jezell/zlibber

Maintenant, il suffit de diriger la commande pour gonfler/dégonfler.

11
Jesse Ezell

Voici un exemple d'ouverture d'un objet 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!

Ce que vous verrez là-bas est presque identique à la sortie de 'git cat-file -p [hash]', sauf que la commande n'imprime pas l'en-tête ('commit' suivi de la taille du contenu et d'un octet nul).

9
Jack O'Connor

On dirait que Mark Adler nous pense et a écrit un exemple de la façon de le faire avec: http://www.zlib.net/zpipe.c

Il compile avec rien de plus que gcc -lz et les en-têtes zlib installés. J'ai copié le binaire résultant dans mon /usr/local/bin/zpipe tout en travaillant avec des trucs git.

7
Tim Caswell

les objets git sont compressés par zlib plutôt que gzip, donc soit en utilisant zlib pour le décompresser, soit en utilisant la commande git, c'est-à-dire git cat-file -p <SHA1>, pour imprimer le contenu.

6
Congbin Guo
// 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
5
agupta666

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

Il répertorie un certain nombre d'implémentations logicielles, y compris gzip, de sorte que cela devrait fonctionner. Avez-vous essayé d'exécuter gzip sur le fichier? Ne reconnaît-il pas automatiquement le format?

Comment savez-vous qu'il est compressé à l'aide de DEFLATE? Quel outil a été utilisé pour compresser le fichier?

1
Marc van Kempen

J'ai trouvé cette question à la recherche d'une solution de contournement avec un bogue avec le -text utilitaire dans la nouvelle version de hadoop dfs client que je viens d'installer. Le -text l'utilitaire fonctionne comme cat, sauf si le fichier en cours de lecture est compressé, il décompresse et affiche le texte brut de manière transparente (d'où le nom).

Les réponses déjà publiées étaient certainement utiles, mais certains d'entre eux ont un problème lorsqu'ils traitent des quantités de données de taille Hadoop - ils lisent tout en mémoire avant de décompresser.

Voici donc mes variations sur les réponses Perl et Python ci-dessus qui n'ont pas cette limitation:

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

Notez l'utilisation du -cat sous-commande, au lieu de -text. C'est ainsi que ma solution de contournement ne s'arrête pas après avoir corrigé le bogue. Toutes mes excuses pour la lisibilité de la version python.

1
Hercynium

les objets git sont des flux zlib (pas de dégonflage brut). pigz décompressera ceux avec le -dz option.

1
Mark Adler

Pourquoi n'utilisez-vous pas simplement les outils de git pour accéder aux données? Cela devrait être capable de lire n'importe quel objet git:

git show --pretty=raw <object SHA-1>
1
igorw
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"));
0
evandrix

pigz peut le faire:

apt-get install pigz
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7
0
G. Sylvie Davies

Pour compléter la collection, voici des monoplaces Perl pour dégonfler/gonfler/dégonfler brut/gonfler brut.

Dégonfler

Perl -MIO::Compress::Deflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::Deflate::deflate(\$in, \$out); print $out;'

Gonfler

Perl -MIO::Uncompress::Inflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::Inflate::inflate(\$in, \$out); print $out;'

Dégonflage brut

Perl -MIO::Compress::RawDeflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Compress::RawDeflate::rawdeflate(\$in, \$out); print $out;'

gonflage brut

Perl -MIO::Uncompress::RawInflate -e 'undef $/; my ($in, $out) = (<>, undef); IO::Uncompress::RawInflate::rawinflate(\$in, \$out); print $out;'
0
jlh