Wie kann man mit einem Befehlszeilentool DEFLIEREN, um ein Git-Objekt zu extrahieren?


77

Ich suche einen Befehlszeilen-Wrapper für den DEFLATE-Algorithmus.

Ich habe eine Datei (Git Blob), die mit DEFLATE komprimiert wurde, und ich möchte sie dekomprimieren. Der Befehl gzip scheint keine Option zur direkten Verwendung des DEFLATE-Algorithmus anstelle des gzip-Formats zu haben.

Idealerweise suche ich ein Standard-Unix / Linux-Tool, das dies kann.

edit: Dies ist die Ausgabe, die ich bekomme, wenn ich versuche, gzip für mein Problem zu verwenden:

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

gzip: stdin: not in gzip format

Antworten:


17

UPDATE: Mark Adler bemerkte, dass Git-Blobs keine rohen DEFLATE-Streams sind, sondern Zlib-Streams. Diese können mit dem pigzTool entpackt werden , das in mehreren Linux-Distributionen vorinstalliert ist:

$ 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!

Bearbeiten von kriegaex: Git Bash für Windows-Benutzer werden feststellen, dass pigz standardmäßig nicht verfügbar ist. Vorkompilierte 32/64-Bit-Versionen finden Sie hier . Ich habe die 64-Bit-Version ausprobiert und sie funktioniert gut. Sie können beispielsweise pigz.exe direkt nach kopieren c:\Program Files\Git\usr\bin, um es auf den Pfad zu setzen.


Meine ursprüngliche Antwort aus historischen Gründen:

Wenn ich den Hinweis in der verstehe von Marc van Kempen erwähnten Wikipedia-Artikel , können Sie ihn direkt puff.cvon zlib verwenden .

Dies ist ein kleines Beispiel:

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

4
Ja, das habe ich mir angesehen. Aber ich würde definitiv ein allgemein verpacktes Werkzeug bevorzugen.
Felix Geisendörfer

Ok, habe jetzt eine sehr späte Bearbeitung mit einem funktionierenden Minimalbeispiel vorgenommen.
mkluwe

3
Dies wird nicht funktionieren. Git-Blobs sind Zlib-Streams, keine Rohentleerung. Diese Lösung arbeitet mit Rohentleerung. puff verarbeitet den zlib-Header und -Anhänger nicht. Wenn Sie ein Dienstprogramm wünschen, können Sie pigz verwenden , das das zlib-Format mit der -dzOption dekomprimiert und das zlib-Format mit generiert -z.
Mark Adler

1
@ MarkAdler -z, --zlib Compress to zlib (.zz) instead of gzip format. Ab sofort ist dieses Flag nur zum Komprimieren und nicht zum Dekomprimieren relevant. pigz -d < "infile" > "outfile"funktioniert gut.
Murlakatamenka

@mkluwe, ich hoffe es macht dir nichts aus, dass ich Informationen über pigz für Windows Git Bash Benutzer hinzugefügt habe. Diese Antwort ist immer noch richtig und war sehr nützlich für mich, ich wollte sie nur weiter verbessern.
Kriegaex

52

So etwas wie das Folgende druckt den Rohinhalt, einschließlich des Headers "$ type $ length \ 0":

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

[Falsch] Leere Ausgabe und Null-Exit-Code in einem Raw- Deflate-Stream ohne den 78Marker und den endgültigen CRC.
Ulidtko

Funktioniert für mich auch mit allen Daten, die direkt Cmit zlib komprimiert wurden , also tolle Antwort. Und wie immer: Am Ende sind die meisten Weltprobleme mit einem PERL-Einzeiler lösbar;)
Mecki

46

Sie können dies mit dem OpenSSL-Befehlszeilentool tun:

openssl zlib -d < $IN > $OUT

Leider ist der zlibUnterbefehl zumindest unter Ubuntu in der Standard-Build-Konfiguration ( --no-zlib --no-zlib-dynamic) deaktiviert , sodass Sie ihn opensslaus dem Quellcode kompilieren müssen, um ihn verwenden zu können. Es ist jedoch beispielsweise in Arch standardmäßig aktiviert.

Bearbeiten: Scheint, als würde der zlibBefehl auch auf Arch nicht mehr unterstützt. Diese Antwort ist möglicherweise nicht mehr nützlich :(


12
Beachten Sie, dass der zlibUnterbefehl (und die -zOption zum encUnterbefehl) nicht verfügbar ist, wenn Ihr Build von openssl mit den Standardoptionen konfiguriert wurde, einschließlich --no-zlibund --no-zlib-dynamic. Diese Antwort funktioniert also nur, wenn Ihr openssl mit dem no-Präfix kompiliert wurde, das aus einer dieser Konfigurationsoptionen entfernt wurde. Sie können erkennen, indem Sie -DZLIBin der Ausgabe vonopenssl version -f
Hercynium

@Hercynium danke! Dies gilt insbesondere für Ubuntu 14.04 :(
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Funktioniert auch auf dem Mac.
Ben

1
Funktioniert nicht auf Mac mit LibreSSL 2.2.7. Ich bekommeopenssl:Error: 'zlib' is an invalid command.
bete am

39

pythonischer Einzeiler:

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

repr(...)scheint alles in Anführungszeichen zu setzen ( '...'), also musste ich es entfernen (Dekomprimieren einer zlib-komprimierten JSON-Datei).
Adam Lindberg

Eigentlich ist es python -c "import zlib,sys;print(zlib.decompress(sys.stdin.buffer.read()).decode('utf8'))" < $IN, wenn Sie eine utf8-Datei zum Beispiel in Python 3
Cyrille Pontvieux

27

Sie können zlib-flate wie folgt verwenden:

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

Es ist standardmäßig auf meinem Computer vorhanden, aber es ist Teil von qpdf - tools for and transforming and inspecting PDF files wenn Sie es installieren müssen.

Ich habe echoam Ende des Befehls eine angezeigt , da es einfacher ist, die Ausgabe auf diese Weise zu lesen.


4
Keine Notwendigkeit für Katze: zlib-flate -uncompress <.git / object / c0 / fb67ab3fda7909000da003f4b2ce50a53f43e7
G. Sylvie Davies

20

Versuchen Sie den folgenden Befehl:

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

Es werden keine externen Tools benötigt.

Quelle: Wie dekomprimiere ich zlib-Daten unter UNIX? bei unix SE


1
Sie erhalten einen Fehler "Unerwartetes Dateiende", aber immer noch einen ordentlichen Hack.
Eric

3
Nur ein gzip-Dateikopf voranstellen. Schön :)
Jaap Versteegh

1
Dort habe ich es auch gefunden - zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)zu meinem .bashrcjetzt hinzugefügt :)
Tobias Kienzler

Netter Hack! @Eric add 2> /dev/null, um stderr auf null zu senden.
poe84it

14

Hier ist ein Ruby-Einzeiler (cd .git / first und Pfad zu einem beliebigen Objekt identifizieren):

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

um den [Blob Size] Header zu ruby -rzlib -e 'print Zlib::Inflate.inflate($stdin.read).split("\x00")[1..-1].join' < .git/objects/abc
entfernen


9

Hier ist ein Beispiel für das Aufbrechen eines Commit-Objekts in 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!

Was Sie dort sehen werden, ist fast identisch mit der Ausgabe von 'git cat-file -p [hash]', außer dass dieser Befehl den Header nicht druckt ('commit' gefolgt von der Größe des Inhalts und einem Null-Byte).


4
Abhängig vom Betriebssystem möchten Sie möglicherweise den Schalter "rb" hinzufügen für open:file = open(".git/objects/09/72d7651ff85bedf464fba868c2ef434543916a", "rb")
Igor Popov

unbekannte Komprimierungsmethode für meine.
Cybernard

7

Es sieht so aus, als hätte Mark Adler uns im Sinn und ein Beispiel dafür geschrieben: http://www.zlib.net/zpipe.c

Es wird nur mit kompiliert gcc -lzund die zlib-Header installiert. Ich habe die resultierende Binärdatei auf meine kopiert, /usr/local/bin/zpipewährend ich mit Git-Sachen gearbeitet habe.


6

Git-Objekte werden zlibeher durch als komprimiert gzip, also entweder zlibzum Dekomprimieren oder mit dem Befehl git, dh git cat-file -p <SHA1>zum Drucken von Inhalten.


3
Wie Jack oben weist darauf hin , der der Ausgang git cat-file -p <SHA1>ist nicht der gesamte Inhalt der zlib Dekompression .git/objects/<SHA1>. Der Unterschied ist der Schlüssel, wenn Sie versuchen, einen Git-Commit-Hash-Rechner zu implementieren ...
ntc2

Die hübsche Druckoption -p ist jedoch von Vorteil, wenn Sie den Inhalt des Objekts verstehen möchten. Wenn Sie ein Baumobjekt mit pigz dekomprimieren, erhalten Sie kein lesbares Ergebnis.
Vortexfive

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

Funktioniert wunderbar unter macOS 10.11, danke! Ich musste Go (was ich sowieso vorhatte) von der offiziellen Website installieren , dann funktionierte es perfekt. Hast du das selbst geschrieben? Es ist nicht sehr schön über unerwartete Argumente. :)
Wildcard

1

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

Es listet eine Reihe von Software-Implementierungen auf, einschließlich gzip, damit dies funktioniert. Haben Sie versucht, nur gzip für die Datei auszuführen? Erkennt es das Format nicht automatisch?

Woher wissen Sie, dass es mit DEFLATE komprimiert wird? Mit welchem ​​Tool wurde die Datei komprimiert?


Siehe unten auf dieser Seite: progit.org/book/ch9-2.html Gzip implementiert DEFLATE, aber es scheint nicht, dass Sie den Algorithmus direkt anwenden können. Gzip erwartet, dass die Daten im gzip-Format vorliegen (wodurch eine Reihe von Headern und Inhalten um die DEFLATE-Daten hinzugefügt werden). (Ich habe gerade meinen Beitrag bearbeitet, um die Ausgabe von gunzip aufzunehmen)
Felix Geisendörfer

2
Ah ok, also werden die Daten mit der zlib-Bibliothek komprimiert, dann liegt es nahe, dass Sie auch mit zlib dekomprimieren können! Sie können einen Ruby, Perl oder eine andere Bindung versuchen, um ein einfaches Deflate-Skript zu löschen. Oder wenn Sie keine Angst haben, sich beim Kompilieren eines AC-Programms zu versuchen, versuchen Sie Folgendes
Marc van Kempen

NB Ich habe es gerade versucht und zpipe.c funktioniert mit Git-Objekten. Kompilieren Sie mit 'gcc -o zpipe zpipe.c -I / path / to / zlib.h -L / path / to / zlib -lz'. Verwenden Sie: ./zpipe -d <.git / objects / 83 / 535d1693580f04824a2ddd22bd241fd00533d8 (benutze -d zur Dekomprimierung)
Marc van Kempen

1

Warum verwenden Sie nicht einfach die Tools von git, um auf die Daten zuzugreifen? Dies sollte in der Lage sein, jedes Git-Objekt zu lesen:

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

4
Ich bereite mich auf einen kleinen Git-Workshop vor, den ich bald geben werde. Eines der Beispiele beinhaltet das Zeigen, was 'git add' von Hand macht. Das Dekomprimieren des Blobs mit git selbst macht keinen Sinn, da ich die Unterlegungsfunktion zeigen möchte. Ich werde wahrscheinlich Rubin oder Perl verwenden, aber ich hatte gehofft, ich könnte mich an einen einfachen Bash-Oneliner halten.
Felix Geisendörfer

3
Odergit cat-file -p c0fb67ab3fda7909000da003f4b2ce50a53f43e7
Jakub Narębski

@igorw: nur solange sich das Objekt im Baum befindet. Das Wissen über das Finden einiger Git-Objekte in 'lost + found' (nachdem fsck.ext4 sie dort abgelegt hat) ist sehr praktisch ...
akira

2
Wie andere bereits betont haben, erhalten Sie nicht den vollständigen Inhalt eines Git-Objekts . Wichtig, wenn Sie versuchen, programmgesteuert an Git-Objekten zu arbeiten.
Hawkeye Parker

1

Ich fand diese Frage auf der Suche nach einer Problemumgehung mit einem Fehler im -textDienstprogramm in der neuen Version des hadoop dfsClients, den ich gerade installiert habe. Das -textDienstprogramm funktioniert wiecat folgt: Wenn die gelesene Datei komprimiert ist, wird der Klartext (daher der Name) transparent dekomprimiert und ausgegeben.

Die bereits veröffentlichten Antworten waren auf jeden Fall hilfreich, aber einige von ihnen haben ein Problem beim Umgang mit Datenmengen in Hadoop-Größe: Sie lesen alles vor dem Dekomprimieren in den Speicher.

Also, hier sind meine Variationen der Perlund PythonAntworten oben, die diese Einschränkung nicht haben:

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

Beachten Sie die Verwendung des -catUnterbefehls anstelle von -text. Dies ist so, dass meine Problemumgehung nicht unterbrochen wird, nachdem der Fehler behoben wurde. Entschuldigung für die Lesbarkeit der Python-Version.


1

Git-Objekte sind Zlib-Streams (keine Rohdaten). pigz dekomprimiert diejenigen mit der -dzOption.


1

Um die Sammlung zu erweitern, finden Sie hier Perl-Einzeiler für Deflate / Inflate / Raw Deflate / Raw Inflate.

Entleeren

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

Aufblasen

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

Rohe Entleerung

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

Rohes Aufblasen

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


0
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"));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.