Як ЗНИЖИТИ за допомогою інструмента командного рядка для вилучення об'єкта git?


78

Я шукаю обгортку командного рядка для алгоритму DEFLATE.

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

В ідеалі я шукаю стандартний інструмент Unix / Linux, який може це зробити.

редагувати: Це результат, який я отримую при спробі використовувати gzip для своєї проблеми:

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

gzip: stdin: not in gzip format

Відповіді:


19

ОНОВЛЕННЯ: Марк Адлер зауважив, що git-BLOB - це не необроблені потоки 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!

Редагувати за допомогою kriegaex: Користувачі Git Bash для Windows помітять, що pigz недоступний за замовчуванням. Ви можете знайти скомпільовані 32/64-розрядні версії тут . Я спробував 64-розрядну версію, і вона чудово працює. Ви можете, наприклад, скопіювати pigz.exe безпосередньо c:\Program Files\Git\usr\binв, щоб розмістити його на шляху.


Моя оригінальна відповідь, збережена з історичних причин:

Якщо я правильно зрозумів натяк в статті Вікіпедії згадується Марк ван Kempen, ви можете використовувати puff.cз Zlib безпосередньо.

Це невеликий приклад:


4
Так, я подивився на це. Але я б, безумовно, віддав перевагу загальноупакованому інструменту.
Felix Geisendörfer

Добре, зробив дуже пізнє редагування зараз із робочим мінімальним прикладом.
mkluwe

3
Це не спрацює. git blobs - це потоки zlib, а не сирі дефляти. Це рішення працює на сировинному спуску. puff не обробляє заголовок і причіп zlib. Якщо вам потрібна утиліта, ви можете використовувати pigz , який розпакує формат zlib з -dzопцією, а також створить формат zlib за допомогою -z.
Марк Адлер

1
@MarkAdler -z, --zlib Compress to zlib (.zz) instead of gzip format. На даний момент цей прапор актуальний лише для стиснення, а не розпакування. pigz -d < "infile" > "outfile"працює просто чудово.
мурлакатаменка

@mkluwe, сподіваюся, ви не проти, що я додав інформацію про pigz для користувачів Windows Git Bash. Ця відповідь все ще є правильною і була для мене дуже корисною, я просто хотів її вдосконалити.
kriegaex

52

Щось на зразок нижче буде надруковано необроблений вміст, включаючи заголовок "$ type $ length \ 0":

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

[Неправильно] Порожній вихідний код і нульовий код виходу на необробленому потоці дефляції без 78маркера та остаточного CRC
ulidtko

Мені також підходить для будь-яких даних, безпосередньо стиснених за Cдопомогою zlib, так що чудова відповідь. І як завжди: Врешті-решт, більшість світових проблем вирішуються
однокласниками

46

Це можна зробити за допомогою інструменту командного рядка OpenSSL:

openssl zlib -d < $IN > $OUT

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

Редагувати: Здається, zlibкоманда також більше не підтримується в Arch. Ця відповідь може бути вже не корисною :(


12
Зверніть увагу , що zlibсуб-команда (і -zопція до encпідкоманду) є НЕ доступні , якщо ваш білд OpenSSL був налаштований з параметрами за замовчуванням, які включають в себе --no-zlibі --no-zlib-dynamic. Отже, ця відповідь працює, лише якщо ваш openssl був скомпільований з no-префіксом, вилученим з одного з цих параметрів налаштування. Ви можете сказати, шукаючи -DZLIBрезультати уopenssl version -f
Герциній

@Hercynium дякую! Зокрема, це стосується Ubuntu 14.04 :(
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Працює і на Mac.
Бен,

1
Не працює на Mac з LibreSSL 2.2.7. Я розуміюopenssl:Error: 'zlib' is an invalid command.
праягупд

39

пітонічний однокласник:

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

repr(...)здається, все обертається лапками ( '...'), тому мені довелося його видалити (розпаковуючи стислий файл zlib JSON).
Адам Ліндберг,

Насправді це так python -c "import zlib,sys;print(zlib.decompress(sys.stdin.buffer.read()).decode('utf8'))" < $IN, якщо ви очікуєте файл utf8, наприклад, у Python 3
Cyrille Pontvieux

27

Ви можете використовувати zlib-flate, наприклад:

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

Він є за замовчуванням на моїй машині, але це частина, qpdf - tools for and transforming and inspecting PDF filesякщо вам потрібно його встановити.

Я натиснув echoна кінець команди, оскільки легше читати результати таким чином.


4
Не потрібно кота: zlib-flate -uncompress <.git / objects / c0 / fb67ab3fda7909000da003f4b2ce50a53f43e7
Г. Сільві Девіс

20

Спробуйте виконати таку команду:

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

Зовнішні інструменти не потрібні.

Джерело: Як розпакувати дані zlib в UNIX? на unix SE


1
У вас трапляється помилка "несподіваний кінець файлу", але все одно акуратний хак.
Ерік

3
Просто префікс із заголовком файлу gzip. Приємно :)
Jaap Versteegh

1
Ось де я його також знайшов - додано zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)до мого .bashrcзараз :)
Тобіас Кінцлер

Хороший хак! @Eric add, 2> /dev/nullщоб надіслати stderr в null.
poe84it

14

Ось однолінійний Ruby (cd .git / first та визначте шлях до будь-якого об’єкта):

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

зняти заголовок [розмір краплі] ruby -rzlib -e 'print Zlib::Inflate.inflate($stdin.read).split("\x00")[1..-1].join' < .git/objects/abc
yachi

11

Мені набридло не мати хорошого рішення для цього, тому я поклав щось на NPM:

https://github.com/jezell/zlibber

Тепер можна просто конвеєр для надування / здуття команди.


Як ви використовуєте цей пакет?
RHPT

1
@RHPT У Windows виконайте "type #### | inflate", де #### - контрольна сума об'єкта.
mhenry1384

Абоinflate < filename
Андрій Даміан-Фекете

9

Ось приклад розкриття об’єкта коміту в 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 [хеш]', за винятком того, що команда не друкує заголовок ('коміт', а потім розмір вмісту та нульовий байт).


4
Залежно від операційної системи, ви можете додати перемикач "rb", openнаприклад:file = open(".git/objects/09/72d7651ff85bedf464fba868c2ef434543916a", "rb")
Ігор Попов

невідомий спосіб стиснення для шахти.
кібернард

7

Схоже, Марк Адлер мав на увазі нас і написав приклад того, як це зробити: http://www.zlib.net/zpipe.c

Він компілюється лише із gcc -lzвстановленими заголовками zlib. Я скопіював отриманий двійковий файл у свій /usr/local/bin/zpipeпід час роботи з git-матеріалами.


6

Об'єкти git стискаються, zlibа не gzip, тому або за допомогою стиску , або за допомогою zlibкоманди git, тобто git cat-file -p <SHA1>для друку вмісту.


3
Як Джек указует вище , вихід git cat-file -p <SHA1>є НЕ повним змістом в ZLIB декомпресії .git/objects/<SHA1>. Різниця є ключовою, якщо ви намагаєтесь реалізувати хеш-калькулятор
коміту

Варіант друку -p досить є перевагою, хоча коли ви хочете зрозуміти вміст об'єкта. Розтискання об’єкта дерева за допомогою pigz не дасть вам зручного для читання результату.
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

Прекрасно працює на macOS 10.11, дякую! Мені довелося встановити Go (що я все одно мав намір зробити) з офіційного веб-сайту , тоді він спрацював чудово. Ви самі це писали? Це не дуже приємно щодо несподіваних суперечок. :)
Wildcard

1

Див. Http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

У ньому перелічено ряд програмних реалізацій, включаючи gzip, так що це повинно працювати. Ви спробували просто запустити gzip на файлі? Він не розпізнає формат автоматично?

Звідки ви знаєте, що він стискається за допомогою DEFLATE? Який інструмент був використаний для стиснення файлу?


Дивіться внизу цієї сторінки: progit.org/book/ch9-2.html Gzip дійсно реалізує DEFLATE, але, схоже, ви не можете безпосередньо застосувати алгоритм. Gzip очікує, що дані будуть у форматі gzip (що додає купу заголовків та іншої інформації навколо даних DEFLATE). (Я щойно відредагував свою публікацію, включивши результати з gunzip)
Фелікс Гейзендерфер

2
О гаразд, отже, дані стискаються за допомогою бібліотеки zlib, то, зрозуміло, ви можете також розпакувати за допомогою zlib! Ви можете спробувати рубін, perl або інший прив'язок, щоб створити простий скрипт дефляції. Або якщо ви не боїтеся спробувати свої сили
Марк ван Кемпен

Примітка: Я щойно спробував, і zpipe.c працює над об'єктами git, компілюючи за допомогою 'gcc -o zpipe zpipe.c -I / path / to / zlib.h -L / path / to / zlib -lz' use: ./zpipe -d <.git / objects / 83 / 535d1693580f04824a2ddd22bd241fd00533d8 (використовувати -d для декомпресії)
Марк ван Кемпен

1

Чому ви просто не використовуєте інструменти git для доступу до даних? Це повинно мати можливість читати будь-який об'єкт git:

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

4
Я готуюсь до невеликого git-семінару, який я збираюся провести незабаром. Один із прикладів включає показ того, що робить «git add» вручну. Декомпресія великої крапки за допомогою самого git не має сенсу, оскільки я хочу показати базову функціональність. Напевно, я в кінцевому підсумку використаю ruby ​​або perl, але я сподівався, що зможу дотримуватися простого bash oneliner.
Felix Geisendörfer

3
Абоgit cat-file -p c0fb67ab3fda7909000da003f4b2ce50a53f43e7
Якуб Нарембський

@igorw: лише поки об’єкт знаходиться у дереві. знання про пошук деяких git-об'єктів у "загублене + знайдене" (після того, як fsck.ext4 помістив їх туди) дуже зручно ...
akira,

2
Як зазначали інші, це не дає вам повного вмісту об'єкта git . Важливо, якщо ви намагаєтесь програмно працювати над об'єктами git.
Hawkeye Parker

1

Я знайшов це запитання, шукаючи обхід з помилкою з -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.



1

Щоб поповнити колекцію, ось perl однокласники для спуску / накачування / сирого здуття / сирого надування.

Здути

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

Надувати

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

Сире спущення

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

Сире надування

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"));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.