我如何使用智能协议(原始)通过http获取git对象? [英] How can I fetch git objects using the smart protocol (raw) over http?

查看:138
本文介绍了我如何使用智能协议(原始)通过http获取git对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过http使用git smart协议从github.com/git/git获取标签v2.4.2的注释。



//获取refs

  curl -HUser- Agent:git / 1.8.1-v https://github.com/git/git/info/refs?service=git-upload-pack 

返回参考:

  ..... 
003e2be062dfcfd1fd4aca132ec02a40b56f63776202裁判/标签/ V2.4.1
0041aaa7e0d7f8f003c0c8ab34f959083f6d191d44ca裁判/标签/ V2.4.1 ^ {}
003e29932f3915935d773dc8d52c292cadd81c81071d裁判/标签/ V2.4.2
00419eabf5b536662000f79978c4d1b6e4eff5c8d785裁判/标签/ V2.4.2 ^ {}

//制作上传包请求

  printf0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d785\\\
0024have 003e2be062dfcfd1fd4aca132ec02a40b56f63776202\\\
0000| curl -HUser-Agent:git / 1.8.1-v -d @ - https://github.com/git/git/git-upload-pack -HContent-Type:application / x-git- upload-pack-request--trace-ascii / dev / stdout

这不会返回任何结果。我想知道请求中有什么问题(例如,我错误地计算了十六进制吗?)

 警告:--trace-ascii覆盖以前的跟踪/详细选项
==信息:在DNS缓存中找不到主机名
==信息:尝试192.30.252.130 ...
==信息:连接到github.com( 192.30.252.130)端口443(#0)
==信息:使用TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
== TLS 1.2连接信息:服务器证书:github.com
==信息:服务器证书:DigiCert SHA2扩展验证服务器CA
==信息:服务器证书:DigiCert高保证EV根CA
=>发送头文件,170字节(0xaa)
0000:POST / git / git / git-upload-pack HTTP / 1.1
0028:Host:github.com
003a:Accept:* / *
0047:User-Agent:git / 1.8.1
005e:Content-Type:application / x-git-upload-pack-request
0093:Content-Length:110
00a8:
=>发送数据,110个字节(0x6e)
0000:0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d7850024包含00
0040:3e2be062dfcfd1fd4aca132ec02a40b56f637762020000
==信息:上传完全发送:110个字节中110个
<= Recv头文件,17字节(0x11)
0000:HTTP / 1.1 200 OK
==信息:服务器GitHub Babel 2.0未列入黑名单
<= Recv头,26字节(0x1a)
0000:服务器:GitHub Babel 2.0
<= Recv标题,52字节(0x34)
0000:Content-Type:application / x-git-upload-pack-result
< ; = Recv头,28字节(0x1c)
0000:传输编码:分块
<= Recv头,40字节(0x28)
0000:到期日:1980年1月1日星期五:00:00 GMT
<= Recv标题,18字节(0x12)
0000:Pragma:no-cache
<= Recv标题,53字节(0x35)
0000:缓存控制:no-cache,max-age = 0,必须重新验证
<= Recv标题,23字节(0x17)
0000:变化:接受编码
< ; = Recv头,2字节(0x2)
0000:
<= Recv数据,5字节(0x5)
0000:0
0003:
==信息:连接#0到主机github.com保持完好

我为什么要这么做?


  • 对文件系统有写访问权限
  • 避免获取不必要的数据(即提交)
  • 标准API /协议


解决方案

提交十六进制



您没有错误计算十六进制,但你没有传递正确的值。请记住,智能协议之前有一个长度计数:

 < length>< data> 

因此,对于如下所示的行:

  00419eabf5b536662000f79978c4d1b6e4eff5c8d785 refs / tags / v2.4.2 ^ {} 

你需要丢弃前四个字符,这使得实际提交十六进制:

  9eabf5b536662000f79978c4d1b6e4eff5c8d785 


请求格式



POST 一个请求,想要行应该用换行符分隔,但如果你看看 curl 的输出,你可以看到没有换行符:

  =>发送数据,110字节(0x6e)
0000:0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d7850024 has 00
0040:3e2be062dfcfd1fd4aca132ec02a40b56f637762020000

您需要使用 - data-binary 而不是 - data

   -  data-binary @  -  

您需要为这些行加上长度计数的前缀,并且您需要以 0000 组成的行结束:

  0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785 
0032have 2be062dfcfd1fd4aca132ec02a40b56f63776202
0000



调试提示



您可以在您的环境中设置 GIT_TRACE_PACKET = 1 来自 git 的丰富的调试信息能够准确地查看它来回发送的内容。



这就是他写的 h2>

即使有以上信息,我也无法自己得到回复,但我认为这会有所帮助。



更新



所以,这很有趣。 b
$ b

我在本地设置了一个git服务器(使用 git http-backend thttpd ),并运行 tcpdump 来获取由 git远程更新操作。事实证明,你需要用一个空命令来分隔 want 有指令,该命令是 0000 (不换行,因为长度也对新行进行编码)。即:

 < length> want< commitid>< newline> 
0000< length>有< commitid>< newline>
< length>完成

例如:

  0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785 
00000032have 2be062dfcfd1fd4aca132ec02a40b56f63776202
0009done

这给了我:

  0000:POST / git / git / git-upload-pack HTTP / 1.1 
0028:Host:github.com
003a:接受:* / *
0047:Content-type:application / x-git-upload-pack-request
007c:User -agent:git / 1.8
0091:Content-Length:113
00a6:
=>发送数据,113字节(0x71)
0000:0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785.00000032需要2
0040:be062dfcfd1fd4aca132ec02a40b56f63776202.0009done。
== Info:上传完全发送:113个字节中的113个
<= Recv头,17个字节(0x11)
0000:HTTP / 1.1 200 OK
< = Recv头,26字节(0x1a)
0000:服务器:GitHub Babel 2.0
<= Recv标头,52字节(0x34)
0000:Content-Type:application / x-git -upload-pack-result
<= Recv头,28字节(0x1c)
0000:传输编码:分块
<= Recv头,40字节(0x28)
0000:到期日:1980年1月1日星期五00:00:00 GMT
<= Recv标题,18字节(0x12)
0000:Pragma:no-cache
<= Recv 53字节(0x35)
0000:缓存控制:no-cache,max-age = 0,必须重新验证
<= Recv头,23字节(0x17)
0000 :Vary:Accept-Encoding
<= Recv头,2字节(0x2)
0000:
<= Recv数据,4字节(0x4)
0000:31
<= Recv data,51字节(0x33)
0000:0031ACK 2be062dfcfd1fd4aca132ec02a40b56f63776202。
<=接收数据,6字节(0x6)
0000:1fff
<=接收数据,1370字节(0x55a)
0000:PACK ...... [.. X ... An.0 ... z.?`..d * .. .. @ ..ž(TU ......>〜乙.....] .8
0040:2 ... j).OQ} ..#............ [.. 8K..t ..,%.S..u。 。@ l..XT ... o ......'...
[....]



双重奖励更新



您可以使用 git unpack-objects 命令提取packfile。正如你从上面的跟踪中看到的,你首先得到一个长度编码的响应(
0031ACK 2be062dfcfd1fd4aca132ec02a40b56f63776202
),然后是包数据,所以你需要放弃第一行:

  $ git init tmprepo 
$ cd temprepo
$ tail -n +2 output_from_curl | git unpack-objects
解包对象:100%(91/91),完成。
$ find .git / objects -type f |头-3
$ git cat-file -p dc940e63c453199dd9a7285533fbf2355bab03d1
/ *
* GIT - 来自地狱的信息管理员
*
*版权所有(C)Linus Torvalds, 2005
*
*这个处理基本的git sha1目标文件 - 打包,解包,
*创建等等
* /
[...]


I'm trying to fetch the annotation of tag "v2.4.2" from github.com/git/git using the git smart protocol over http.

// Get the refs

curl -H "User-Agent: git/1.8.1" -v  https://github.com/git/git/info/refs?service=git-upload-pack

Returns the refs:

.....
003e2be062dfcfd1fd4aca132ec02a40b56f63776202 refs/tags/v2.4.1
0041aaa7e0d7f8f003c0c8ab34f959083f6d191d44ca refs/tags/v2.4.1^{}
003e29932f3915935d773dc8d52c292cadd81c81071d refs/tags/v2.4.2
00419eabf5b536662000f79978c4d1b6e4eff5c8d785 refs/tags/v2.4.2^{}

// Make the upload pack request

printf "0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d785\n0024have 003e2be062dfcfd1fd4aca132ec02a40b56f63776202\n0000" | curl -H "User-Agent: git/1.8.1" -v  -d @- https://github.com/git/git/git-upload-pack -H "Content-Type: application/x-git-upload-pack-request" --trace-ascii /dev/stdout

This returns nothing. I'm wondering what's wrong in the request (i.e did I miscalculate the hex?)

Warning: --trace-ascii overrides an earlier trace/verbose option
== Info: Hostname was NOT found in DNS cache
== Info:   Trying 192.30.252.130...
== Info: Connected to github.com (192.30.252.130) port 443 (#0)
== Info: TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
== Info: Server certificate: github.com
== Info: Server certificate: DigiCert SHA2 Extended Validation Server CA
== Info: Server certificate: DigiCert High Assurance EV Root CA
=> Send header, 170 bytes (0xaa)
0000: POST /git/git/git-upload-pack HTTP/1.1
0028: Host: github.com
003a: Accept: */*
0047: User-Agent: git/1.8.1
005e: Content-Type: application/x-git-upload-pack-request
0093: Content-Length: 110
00a8: 
=> Send data, 110 bytes (0x6e)
0000: 0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d7850024have 00
0040: 3e2be062dfcfd1fd4aca132ec02a40b56f637762020000
== Info: upload completely sent off: 110 out of 110 bytes
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
== Info: Server GitHub Babel 2.0 is not blacklisted
<= Recv header, 26 bytes (0x1a)
0000: Server: GitHub Babel 2.0
<= Recv header, 52 bytes (0x34)
0000: Content-Type: application/x-git-upload-pack-result
<= Recv header, 28 bytes (0x1c)
0000: Transfer-Encoding: chunked
<= Recv header, 40 bytes (0x28)
0000: Expires: Fri, 01 Jan 1980 00:00:00 GMT
<= Recv header, 18 bytes (0x12)
0000: Pragma: no-cache
<= Recv header, 53 bytes (0x35)
0000: Cache-Control: no-cache, max-age=0, must-revalidate
<= Recv header, 23 bytes (0x17)
0000: Vary: Accept-Encoding
<= Recv header, 2 bytes (0x2)
0000: 
<= Recv data, 5 bytes (0x5)
0000: 0
0003: 
== Info: Connection #0 to host github.com left intact

Why am I trying this?

  • I don't have write access to the file system
  • Avoid fetching unnecessary data (i.e the commits)
  • Standard API/Protocol

解决方案

Commit hex

You didn't miscalculate the hex, but you're not passing the correct value. Remember that each line in the smart protocol is preceded by a length count:

<length><data>

So for a line that looks like this:

00419eabf5b536662000f79978c4d1b6e4eff5c8d785 refs/tags/v2.4.2^{}

You need to discard the first four characters, which makes the actual commit hex:

9eabf5b536662000f79978c4d1b6e4eff5c8d785

Request format

When POSTing a request, the have and want lines are supposed to be separated by a newline, but if you take a look at the output from curl, you can see that there is no newline:

=> Send data, 110 bytes (0x6e)
0000: 0031want 00419eabf5b536662000f79978c4d1b6e4eff5c8d7850024have 00
0040: 3e2be062dfcfd1fd4aca132ec02a40b56f637762020000

You need to use --data-binary instead of --data:

--data-binary @-

You need to prefix these lines with a length count, and you need to end with a line consisting of 0000:

0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785
0032have 2be062dfcfd1fd4aca132ec02a40b56f63776202
0000

Debugging tips

You can set GIT_TRACE_PACKET=1 in your environment if you want to get copious debugging information from git to see exactly what it's sending back and forth.

And that's all he wrote

I'm not able to get a response myself, even given the above information, but I figured it would help.

Update

So, this was fun.

I set up a git server locally (using git http-backend and thttpd), and ran tcpdump to grab the traffic generated by a git remote update operation. It turns out that the you need to separate the want and have directives with a null command, which is 0000 (no newline, because the length encodes newlines, too). That is:

<length>want <commitid><newline>
0000<length>have <commitid><newline>
<length>done

E.g:

0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785
00000032have 2be062dfcfd1fd4aca132ec02a40b56f63776202
0009done

That gives me:

0000: POST /git/git/git-upload-pack HTTP/1.1
0028: Host: github.com
003a: Accept: */*
0047: Content-type: application/x-git-upload-pack-request
007c: User-agent: git/1.8
0091: Content-Length: 113
00a6: 
=> Send data, 113 bytes (0x71)
0000: 0032want 9eabf5b536662000f79978c4d1b6e4eff5c8d785.00000032have 2
0040: be062dfcfd1fd4aca132ec02a40b56f63776202.0009done.
== Info: upload completely sent off: 113 out of 113 bytes
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 26 bytes (0x1a)
0000: Server: GitHub Babel 2.0
<= Recv header, 52 bytes (0x34)
0000: Content-Type: application/x-git-upload-pack-result
<= Recv header, 28 bytes (0x1c)
0000: Transfer-Encoding: chunked
<= Recv header, 40 bytes (0x28)
0000: Expires: Fri, 01 Jan 1980 00:00:00 GMT
<= Recv header, 18 bytes (0x12)
0000: Pragma: no-cache
<= Recv header, 53 bytes (0x35)
0000: Cache-Control: no-cache, max-age=0, must-revalidate
<= Recv header, 23 bytes (0x17)
0000: Vary: Accept-Encoding
<= Recv header, 2 bytes (0x2)
0000: 
<= Recv data, 4 bytes (0x4)
0000: 31
<= Recv data, 51 bytes (0x33)
0000: 0031ACK 2be062dfcfd1fd4aca132ec02a40b56f63776202.
<= Recv data, 6 bytes (0x6)
0000: 1fff
<= Recv data, 1370 bytes (0x55a)
0000: PACK.......[..x...An.0...z.?`..d.*..@..z..(.tu......>~B.....]..8
0040: 2...j).OQ}..#.....'......[..8K..t..,%.S..u..@l..XT...o......'...
[....]

Double-bonus update

You can use the git unpack-objects command to extract the packfile. As you can see from the above trace, you first get back a length-encoded response ( 0031ACK 2be062dfcfd1fd4aca132ec02a40b56f63776202) followed by the pack data, so you need to discard that first line:

$ git init tmprepo
$ cd temprepo
$ tail -n +2 output_from_curl | git unpack-objects
Unpacking objects: 100% (91/91), done.
$ find .git/objects -type f | head -3
$ git cat-file -p dc940e63c453199dd9a7285533fbf2355bab03d1
/*
 * GIT - The information manager from hell
 *
 * Copyright (C) Linus Torvalds, 2005
 *
 * This handles basic git sha1 object files - packing, unpacking,
 * creation etc.
 */
[...]

这篇关于我如何使用智能协议(原始)通过http获取git对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆