2013-01-18 2 views
9

나는이 질문이 본질적으로 this과 비슷하다고 말 할 것입니다. 이 고유 한 주요 차이점은 : 원시 자식 프로토콜 (기본 팩 네트워크 프로토콜에 익숙하지 않은 경우 herehere 참조)을 사용하려고합니다.힘내 원격 저장소에서 단일 파일을 가져옵니다.

저는 익명의 자식 저장소에 연결할 스칼라와 JGit을 사용하여 응용 프로그램을 작성하고 있습니다. 하나의 blob을 요청하고 싶습니다 ("/path/to/file.txt"@ "refs/heads/branch1"라고 생각하십시오). 궁극적으로 내 목표는 프로그래밍 방식으로 원격 저장소에서 단일 파일을 검색하는 것입니다. 할 수있는 꽤 유용한 것 같아요.

누구나이 프로토콜의 내부에 대해 살펴 보았습니다. 이것의 기본 버전은 "나는이 객체들을 원합니다, 나는이 객체들을 가지고 있습니다"라고 - 그리고 bam, 당신이 가지고 있지 않은 모든 것을 가진 packfile이 있습니다. 내 질문의 핵심은 : 비 반복적 인 방식으로 단일 객체에 대해 git-upload-packfile을 어떻게 요청합니까? 하나의 커밋 객체를 다운로드 한 다음, 트리, 하위 트리, 다른 하위 트리, 마지막으로 블롭 자체를 묻는 것이 좋습니다. 여기서 속도는 중요하지 않습니다. 주로 대역폭을 절약하려고합니다. 그러나 단순히 git-upload-packfile에 "내가 요청한 객체 하나만 제공하십시오"라고 말할 방법이없는 것 같습니다.

예, 기본적으로 개체가 제외되는 목록이 있지만 저장소의 내용에 대한 사전 지식이 필요합니다 (로컬 저장소가 없음, 기억). 모든 가능한 sha1 목록을 생성하고 원하는 것을 제외하고 모두 보낼 수는 있지만 말도 안되는 것입니다 (시간이 많이 걸리고 대역폭이 많이 소모되며 모든 곳에서 프로그래머를 상대하는 범죄)

내가 해왔 던 또 다른 가능한 해결책 지금까지 많은 시간을 들여 보지 못했지만 원격 측에서 git-upload-archive를 사용하고 있습니다.

나는 그것에 대해 JGit을 재 작성하는 것이 아니라, "JGit을 어떻게 만드나요?"라고 읽지 마십시오. 프로토콜 자체가이 기능을 수행 할 수 있는지 여부를 알고 싶습니다. 내가 원한 것을 달성하기 위해 프로토콜을 악용하는 멋지고 영리한 방법이있는 것처럼 느껴집니다. 이견있는 사람?

+0

나는 이것에 대한 어떤 대답도 "git'이 그런 식으로 작동하지 않는다는 것부터 시작해야한다고 생각합니다."... – twalberg

+0

@twalberg 지역 repo가 ​​확실히합니다. 내가이 일을 할 수 있는지 궁금해. –

+0

예, 로컬 저장소에서 단일 개체를 추출 할 수 있습니다. 그러나 와이어 프로토콜은 그렇게하도록 설계되지 않았습니다. 당신은 최종 목표를 달성 할 수 있습니다, 내 생각에, 클로페/페칭 (전체 레포를 피하기 위해 얕은 복제물을 사용하지만 여전히 커밋 + 나무 + 얼룩을 얻을 것입니다)을 로컬 레포에 저장하고 개체를 추출함으로써 당신이 유선을 통해 그것을 할 수 있다고 생각하지 마십시오 (비록 당신이 리모컨에 대한 ssh 액세스가 있다면, 당신은 가짜 일 수 있습니다). – twalberg

답변

9

내 질문에 답해주세요. 나는 (비록 간신히 문서화 된) 대답을 발견했다. 나는 이것을 알아 내기 위해 많은 C 코드를 파헤쳐 야했다.

우선, 위의 요구 사항은 git-upload-packfile을 사용하여 달성 할 수 없습니다. 단순히 프로그램이 의도 한 것이 아니기 때문입니다. 내가 옳은 대답은 git-upload-archive입니다. 안타깝게도 프로토콜은 ALL에서 거의 문서화되지 않습니다. 다른 사람들이 비슷한 요구 사항을 가지고있는 경우를 대비하여 여기에 내 노트가 있습니다. 소프트웨어를 제외하고

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

, 희망 JGit를 사용 : 나는 (스칼라) 여기 시뮬레이션하기 위해 노력하고있어 기본적으로 어떤

는 다음과 같은 명령입니다. 슬프게도 JGit은 (아직) git archive 명령을 지원하지 않습니다. 그래서 여기에 지원을 추가하는 방법에 대한 매우 높은 수준의 개요가 있습니다 (JGit을 포크하고 나중에 추가 할 수 있음).

(Documentation/technical/pack-protocol의 프로토콜을 살펴 보겠습니다.TXT) :

  1. 익명 자식 프로토콜을 원격 (SSH 중 하나와 전송을 설정하고 git-upload-archive를 실행하거나 사용)
  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-archive에 대한 명령 줄 인수를 전선을 통해 보냅니다. 그들은 한가지 예외를 제외하면 git-archive 명령과 정확히 동일합니다 : 접두사는 모두 argument[SPACE]입니다. 각 인수는 별도의 패킷 행으로 작성됩니다 (최소한 참조 구현에서). 따라서 상기 예 :

  1. 는 (패킷 라인으로) argument --format=tar 보내기
  2. 는 (패킷 라인으로) argument master 보내기
  3. 는 (패킷 라인으로) argument plans/documents/cornballer-blueprint.pdf 보내기
  4. 은 (a 플러시 패킷을 보내기 0000)

이 시점에서 우리는 원격 명령을 전체 명령에 제공했습니다. 이제 우리는 그 반응을 읽습니다. 우리는 하나 개의 패킷 라인 다시 다음 응답 중 하나가 될 서버에서 읽기 : (- 아카이브 보낼 준비가 의미 성공)

  • NACK [message] -

    1. ACK 오류의 어떤 종류 만 발견 "하위 프로세스를 생성 할 수 없습니다"
    2. ERR [message] - -의 사용의 일 예는 에러가 ACK가 전송되면, 그 다음 플러쉬 패킷 (0000) 및 원료 t 하였다한다

    발생한 ar 데이터. 이 시점에서 사이드 밴드 # 1 (메인 데이터 채널)에서 들어오는 패킷 라인을 반복적으로 읽습니다. 플러시 패킷에 도달하면 읽는 것을 멈 춥니 다. 아주 간단합니다.

    이제 원격 파일이 생겼지 만 영리한 캐싱을 원한다면 어떻게 할까? git-upload-packfile을 사용하여 내가 너무 복잡하게 굴린 이유 중 하나는 커밋 ID를 기록하여 로컬로 캐시하고 필요할 때만 새로 고침을 할 수 있다는 것입니다. tar 파일은 그 정보를 우리에게 말해주지 않습니까? 잘못된! 자식 아카이브의 사람 페이지에서

    : 추가적으로 타르 형식 를 사용하는 경우 ID는 글로벌 확장 인원 헤더에 저장된 커밋

    ; 그것은 git get-tar-commit-id를 사용하여 추출 할 수 있습니다. ZIP 파일에는 파일 주석으로 저장됩니다.

    글쎄 그건 좋은 소식입니다. 그건 내가 원하는 모든 것입니다.경우 당신이 여기 샘플 (더 내가 인원 헤더를 해부하려고하지 않을거야)의 헤더가 어떻게 생겼는지 궁금 : 내 관점에서 그래서

    pax_global_header00006660000000000000000000000064121002672560014513gustar00rootroot0000000000000052 comment=326756f834865880c9832b64238e7665632e9b67 
    

    , 나는 단순히 자동으로 파이프 라인을 설정해야 위의 단계를 실행하여 untar 단계 (프로그램 방식)로 실행하여 원하는 "git에서 단일 파일 가져 오기"기능을 수행하십시오.

  • +0

    위대한 작품! 전에이 문제에 찌르다가 멀리 가지 않았다. (단지'git-upload-packfile' 만 보았습니다.) –

    +0

    @Greg thanks :) –

    관련 문제