كيف تنفرف باستخدام أداة سطر الأوامر لاستخراج كائن GIT؟

StackOverflow https://stackoverflow.com/questions/3178566

  •  02-10-2019
  •  | 
  •  

سؤال

أنا أبحث عن غلاف سطر الأوامر لخوارزمية المنهارة.

لدي ملف (git blob) مضغوط باستخدام Deflate ، وأريد إلغاء ضغطه. لا يبدو أن الأمر GZIP لديه خيار لاستخدام خوارزمية المنافذ مباشرة ، بدلاً من تنسيق GZIP.

من الناحية المثالية ، أبحث عن أداة UNIX/Linux قياسية يمكنها القيام بذلك.

تحرير: هذا هو الإخراج الذي أحصل عليه عند محاولة استخدام GZIP لمشكلتي:

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

gzip: stdin: not in gzip format
هل كانت مفيدة؟

المحلول

تحديث: أشار مارك أدلر إلى أن النقطات GIT ليست تدفقات 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!

إجابتي الأصلية ، أبقى لأسباب تاريخية:

إذا فهمت التلميح في مقال ويكيبيديا ذكرها مارك فان كيمبن ، يمكنك استخدامها puff.c من زلب مباشرة.

هذا مثال صغير:

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

نصائح أخرى

سيؤدي شيء مثل ما يلي إلى طباعة المحتوى الخام ، بما في ذلك رأس "Type $ $ length 0":

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

يمكنك القيام بذلك باستخدام أداة سطر أوامر OpenSSL:

openssl zlib -d < $IN > $OUT

لسوء الحظ ، على الأقل في أوبونتو ، zlib يتم تعطيل المجموعة الفرعية في تكوين الإنشاء الافتراضي (--no-zlib --no-zlib-dynamic) ، لذلك ستحتاج إلى التجميع openssl من المصدر لاستخدامه. ولكن يتم تمكينه افتراضيًا على القوس ، على سبيل المثال.

تحرير: يبدو مثل zlib لم يعد الأمر مدعومًا على القوس أيضًا. قد لا تكون هذه الإجابة مفيدة بعد الآن :(

Pythonic One-Liner:

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

يمكنك استخدام Zlib-Flate ، مثل هذا:

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

إنه موجود افتراضيًا على جهازي ، لكنه جزء من qpdf - tools for and transforming and inspecting PDF files إذا كنت بحاجة إلى تثبيته.

لقد برزت echo في نهاية الأمر ، لأنه من الأسهل قراءة الإخراج بهذه الطريقة.

جرب الأمر التالي:

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

ليست هناك حاجة إلى أدوات خارجية.

مصدر: كيفية إلغاء ضغط بيانات ZLIB في UNIX؟ في Unix SE

فيما يلي أحد روبي واحد (CD .GIT/ أولاً وتحديد المسار إلى أي كائن):

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

لقد سئمت من عدم وجود حل جيد لهذا ، لذلك أضع شيئًا على NPM:

https://github.com/jezell/zlibber

الآن يمكن فقط أن تلعب إلى تنفيذ / انحراف الأمر.

إليك مثال على كسر كائن الالتزام في بيثون:

$ 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 [hash] ، باستثناء هذا الأمر لا يطبع الرأس ("الالتزام" متبوعًا بحجم المحتوى والبايت الفارغ).

يبدو أن مارك أدلر وضعنا في الاعتبار وكتب مثالاً على كيفية القيام بذلك مع: http://www.zlib.net/zpipe.c

يجمع مع لا شيء أكثر من gcc -lz ورؤوس Zlib مثبتة. لقد نسخت الثنائي الناتج إلى بلدي /usr/local/bin/zpipe أثناء العمل مع الاشياء git.

يتم ضغط كائنات GIT بواسطة zlib عوضا عن gzip, ، لذلك إما باستخدام zlib لإلغاء ضغطه ، أو أمر git ، أي git cat-file -p <SHA1>, ، لطباعة المحتوى.

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

نرى http://en.wikipedia.org/wiki/deflate#encoder_implementations

يسرد عدد من تطبيقات البرامج ، بما في ذلك GZIP ، بحيث يجب أن تعمل. هل حاولت فقط تشغيل GZIP على الملف؟ ألا يتعرف على التنسيق تلقائيًا؟

كيف تعرف أنه مضغوط باستخدام Deplate؟ ما الأداة التي تم استخدامها لضغط الملف؟

لماذا لا تستخدم فقط أدوات GIT للوصول إلى البيانات؟ يجب أن يكون هذا قادرًا على قراءة أي كائن git:

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

لقد وجدت هذا السؤال يبحث عن عمل مع خطأ مع -text فائدة في الإصدار الجديد من hadoop dfs العميل لقد قمت بتثبيته للتو. ال -text فائدة تعمل مثل cat, ، باستثناء ما إذا كان الملف الذي يجري قراءة مضغوط ، فإنه يقوم بإزالة ضغط النص العادي وإخراجه بشفافية (وبالتالي الاسم).

كانت الإجابات المنشورة بالفعل مفيدة بالتأكيد ، لكن بعضها يعاني من مشكلة واحدة عند التعامل مع كميات من البيانات بحجم Hadoop - يقرأون كل شيء في الذاكرة قبل إلغاء الضغط.

لذلك ، ها هي اختلافي على Perl و 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),""))'

بيرل:

hadoop fs -cat /path/to/example.deflate |
  perl -MCompress::Zlib -e 'print uncompress($buf) while sysread(STDIN,$buf,4096)'

لاحظ استخدام -cat موظف فرعي بدلاً من -text. هذا حتى أن عملي لا ينكسر بعد إصلاح الخلل. يعتذر عن قابلية قراءة نسخة بيثون.

كائنات GIT هي تدفقات ZLIB (وليس deflate الخام). خنزير سوف فك ضغط أولئك مع -dz اختيار.

خنزير تستطيع ان تفعل ذلك:

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"));

للإضافة إلى المجموعة ، فيما يلي Perl Liners لـ Deflate/Therting/Raw Diflate/Raw.

انحراف

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;'
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top