2013-01-18 18 views
9

मैं सामने कहूँगा कि इस सवाल का this के स्वरूप के समान है। मैं कच्चे Git प्रोटोकॉल का उपयोग करना चाहते हैं (here और here यदि आप बुनियादी पैक नेटवर्क प्रोटोकॉल से परिचित नहीं हैं): वहाँ एक महत्वपूर्ण अंतर यह है कि इस अद्वितीय बनाता है।Git दूरस्थ रिपोजिटरी से एकल फाइल लाने प्रोग्राम के

मुझे लगता है कि एक गुमनाम Git भंडार से कनेक्ट करेगा स्काला और JGit का उपयोग कर एक आवेदन लिख रहा हूँ। मैं एक ब्लॉब का अनुरोध करना चाहता हूं (सोचें "/path/to/file.txt" @ "refs/head/branch1")। आखिरकार मेरा लक्ष्य प्रोग्रामिक रूप से रिमोट रिपोजिटरी से एक फ़ाइल को पुनर्प्राप्त करना है। ऐसा करने में सक्षम होने के लिए एक बहुत उपयोगी चीज की तरह लगता है।

Anywho, मैं इस प्रोटोकॉल के आंतरिक भागों में जाने पर किया गया है। ऐसा प्रतीत होता है कि इसका मूल संस्करण "मैं इन ऑब्जेक्ट्स को चाहता हूं, मेरे पास इन ऑब्जेक्ट्स हैं" - और बम, आपके पास जो कुछ भी नहीं है उसके साथ एक पैकफाइल है। मेरे प्रश्न का मूल यह है: मैं गैर-रिकर्सिव तरीके से एक ही ऑब्जेक्ट के लिए गिट-अपलोड-पैकफाइल कैसे पूछूं? मैं एक सिंगल प्रतिबद्ध ऑब्जेक्ट डाउनलोड करने के बाद ठीक हूं, फिर पेड़ के लिए पूछ रहा हूं, फिर एक सबट्री, फिर एक और सबट्री, और फिर आखिरकार ब्लॉब। गति यहां बहुत महत्वपूर्ण नहीं है, मुख्य रूप से मैं बैंडविड्थ पर सहेजने की कोशिश कर रहा हूं। लेकिन ऐसा लगता है कि गिट-अपलोड-पैकफाइल बताने का कोई तरीका नहीं है, "कृपया मुझे केवल एक ऑब्जेक्ट दें जिसे मैंने पूछा"।

हां, "है" सूची है, जो मूल रूप से वस्तुओं को नीचे आने से बाहर कर देगी, हालांकि इसके लिए एक भंडार की सामग्री का प्राथमिक ज्ञान आवश्यक है (मेरे पास स्थानीय रिपो नहीं है, याद रखें)। मैं सभी संभावित sha1s की एक सूची उत्पन्न कर सकता हूं और उन सभी को छोड़कर उन्हें भेज सकता हूं, लेकिन यह हास्यास्पद (समय लेने वाली, बैंडविड्थ उपभोग करने और हर जगह प्रोग्रामर के खिलाफ अपराध) से परे है

एक और संभावित समाधान मैं रहा हूं इसके बजाय रिमोट साइड पर गिट-अपलोड-आर्काइव का उपयोग कर रहा है, हालांकि मैं मानता हूं कि मैंने अभी तक इसमें अधिक समय नहीं लगाया है।

मैं JGit पुनर्लेखन करने के लिए तैयार की तुलना में अधिक कर रहा हूँ अगर यह है कि करने के लिए आता है, तो के रूप में इस पढ़ नहीं करते कृपया "मैं कैसे कर सकता हूँ JGit करना ..."। मैं सिर्फ यह जानना चाहता हूं कि प्रोटोकॉल स्वयं भी इसमें सक्षम है या नहीं। मुझे लगता है कि प्रोटोकॉल का दुरुपयोग करने के लिए कुछ अद्भुत चालाक तरीका है जो मैं चाहता हूं। कोई विचार?

+0

मुझे लगता है कि इसका कोई जवाब "गिट' के साथ शुरू करना है, इस तरह से काम नहीं करता है" ... – twalberg

+0

@twalberg एक स्थानीय रिपो सुनिश्चित करता है। अगर मैं तार पर यह कर सकता हूं तो बस उत्सुक हूं। –

+0

हां, आप स्थानीय रिपो से एक ऑब्जेक्ट निकाल सकते हैं। वायर प्रोटोकॉल को ऐसा करने के लिए डिज़ाइन नहीं किया गया था। आप अपने अंतिम लक्ष्य को पूरा कर सकते हैं, मुझे लगता है कि क्लोनिंग/फ़ेचिंग (पूरे रेपो से बचने के लिए एक उथले क्लोन का उपयोग करके भी, लेकिन आप अभी भी + पेड़ + ब्लब्स) प्राप्त करने जा रहे हैं, स्थानीय रिपो में और अपनी ऑब्जेक्ट निकालने के लिए, लेकिन मैं ऐसा नहीं लगता कि आप इसे तार पर कर सकते हैं (हालांकि यदि आपके पास रिमोट तक एसएसएच पहुंच है, तो आप इसे नकली सॉर्ट कर सकते हैं)। – twalberg

उत्तर

9

मेरे अपने प्रश्न का उत्तर देना। मुझे एक स्वीकार्य (हालांकि मुश्किल से दस्तावेज) जवाब मिला। इसे समझने के लिए मुझे बहुत सी कोड के माध्यम से खोदना पड़ा।

सबसे पहले, ऊपर दी गई आवश्यकताओं git-upload-packfile का प्रयोग कर प्राप्त नहीं किया जा सकता कि बस क्या कार्यक्रम करने के लिए डिजाइन किया गया था नहीं है क्योंकि। जैसा कि मैंने संदेह किया है, सही उत्तर git-upload-archive है। अफसोस की बात है कि प्रोटोकॉल को शायद ही कभी दस्तावेज किया गया है। तो अगर किसी और के पास समान आवश्यकताएं हैं तो यहां मेरे नोट्स हैं।

git archive --format=tar --remote=ssh://[email protected]m/cornballer.git \ 
    > master plans/documents/cornballer-blueprint.pdf | tar -x 

सॉफ्टवेयर को छोड़कर, उम्मीद है कि JGit का उपयोग कर:

मूल रूप से क्या मैं यहाँ अनुकरण (स्केला में) करने के लिए कोशिश कर रहा हूँ के लिए निम्न आदेश है। अफसोस की बात है कि जेजीआईटी (अभी तक) गिट आर्काइव कमांड का समर्थन नहीं करता है। तो समर्थन जोड़ने के तरीके के बारे में यहां एक बहुत ही उच्च स्तरीय अवलोकन है (मैं जेजीआईटी को फोर्क कर सकता हूं और इसे बाद में जोड़ सकता हूं)।

के (प्रलेखन/तकनीकी/पैक प्रोटोकॉल से प्रोटोकॉल पर नजर डालते हैं।txt):

  1. दूरदराज के (या तो ssh के साथ एक परिवहन की स्थापना और उसके बाद git-upload-archive चलाने के लिए या का उपयोग गुमनाम Git प्रोटोकॉल)
  2. :

    git-proto-request = request-command SP pathname NUL [ host-parameter NUL ] 
    request-command = "git-upload-pack"/"git-receive-pack"/
            "git-upload-archive" ; case sensitive 
    pathname   = *(%x01-ff) ; exclude NUL 
    host-parameter = "host=" hostname [ ":" port ] 
    

    तो भाग प्रोटोकॉल में से एक कुछ इस तरह चला जाता है git-upload-archive /cornballer.git\0host=ssh.mycompany.com\0 (एक पैकेट लाइन के रूप में)

इस बिंदु पर कनेक्शन स्थापित किया गया है। यदि आदेश समर्थित नहीं है या कोई समस्या है तो GIt एक त्रुटि लौटा सकता है। मैंने अभी तक यह पता नहीं लगाया है कि इसके लिए कैसे जांच करें।

अगला अप्रलेखित हिस्सा आता है। हम मूल रूप से तार पर git-archive के लिए कमांड लाइन तर्क भेजते हैं। वे वास्तव में एक अपवाद के साथ git-archive आदेश के रूप में ही कर रहे हैं: वे सब argument[SPACE] लगी होती हैं। प्रत्येक तर्क एक अलग पैकेट लाइन के रूप में लिखा जाता है (कम से कम संदर्भ कार्यान्वयन में)। इसलिए उपरोक्त उदाहरण के लिए:

  1. argument --format=tar भेजें (एक पैकेट पंक्ति के रूप में)
  2. argument master भेजें (एक पैकेट पंक्ति के रूप में)
  3. argument plans/documents/cornballer-blueprint.pdf भेजें (एक पैकेट पंक्ति के रूप में)
  4. एक फ्लश पैकेट भेजें (0000)

इस बिंदु पर हमने रिमोट गिट-आर्काइव प्रक्रिया को पूरे आदेश दिया है। अब हम प्रतिक्रिया पढ़ते हैं। हम सर्वर है, जो निम्नलिखित प्रतिक्रियाओं में से एक होगी से एक पैकेट लाइन वापस पढ़ें: (- संग्रह भेजने के लिए तैयार है, जिसका अर्थ सफलता)

  • NACK [message] -

    1. ACK त्रुटि के कुछ प्रकार, केवल पाया "उपप्रक्रिया अंडे करने में असमर्थ"
    2. ERR [message] - - इसके उपयोग का एक उदाहरण एक त्रुटि

    एक ACK भेज दिया जाता है, तो यह एक फ्लश पैकेट (0000) और फिर कच्चे टी के बाद किया जाएगा हुआ आर डेटा। इस बिंदु पर आप बार-बार पैकेट लाइनों को साइडबैंड # 1 (मुख्य डेटा चैनल) पर आते हैं। जब आप फ्लश पैकेट तक पहुंचते हैं, तो आप पढ़ना बंद कर देते हैं। बहुत साधारण।

    तो अब आपके पास दूरस्थ फ़ाइल है, लेकिन क्या होगा यदि आप किसी प्रकार का चालाक कैशिंग करना चाहते हैं? एक कारण यह है कि मैं git-upload-packfile के प्रयोग पर इतना उत्साहित था कि यह मुझे रिकॉर्ड आईडी प्रतिबद्ध है और इस तरह यह स्थानीय स्तर पर कैश और केवल रूप में की जरूरत को ताज़ा करते हैं होता है। एक टैर फ़ाइल हमें उस जानकारी को सही नहीं बताती है? गलत!

    Git-संग्रह का आदमी पृष्ठ से:

    साथ ही प्रतिबद्ध आईडी एक वैश्विक बढ़ाया पैक्स शीर्षक में संग्रहीत किया जाता है, तो टार प्रारूप प्रयोग किया जाता है; इसे गिट गेट-टैर-प्रतिबद्ध-आईडी का उपयोग करके निकाला जा सकता है। ज़िप फ़ाइलों में इसे फ़ाइल टिप्पणी के रूप में संग्रहीत किया जाता है।

    अच्छा यह अच्छी खबर है! यह सचमुच सब कुछ मैं चाहता था।मामले में आप सोच रहे हैं कि शीर्ष लेख कैसा दिखता है, यहाँ एक नमूना (कोई मैं पैक्स हेडर टुकड़े करना नहीं जा रहा हूँ) है:

    pax_global_header00006660000000000000000000000064121002672560014513gustar00rootroot0000000000000052 comment=326756f834865880c9832b64238e7665632e9b67 
    
    मेरे नजरिए से

    तो, मैं बस स्वचालित रूप से एक पाइप लाइन के लिए स्थापित करने की जरूरत है उपरोक्त चरणों को चलाएं, वांछित "गिट से एक फ़ाइल लाने" कार्यक्षमता निष्पादित करने के लिए इसे एक अनार चरण (प्रोग्रामेटिक रूप से) के माध्यम से चलाएं।

  • +0

    शानदार काम! मैंने दूसरे दिन इस समस्या पर एक झटका लगा और बहुत दूर नहीं मिला (लेकिन मैं केवल 'गिट-अपलोड-पैकफाइल' देख रहा था)। –

    +0

    @ ग्रेग धन्यवाद :) –

    संबंधित मुद्दे