7

I'm implementing an option in my application to use --depth 1 to make a minimal functional clone of a git repo, and I've just realized that the dumb http transport doesn't support --depth. I'd like to automatically detect whether an http remote is dumb or smart so I can omit the --depth option when talking to dumb http repos. Is this possible?

Alternately, is there a direct way to check whether a git remote supports --depth?

Ryan C. Thompson
  • 40,856
  • 28
  • 97
  • 159
  • I'd use duck typing: assume it's a duck and throw it in the pond, if it was a cat, ask him sorry (and maybe avoid re-throwing it in the pond). – redShadow Feb 14 '12 at 01:50

2 Answers2

6

One way is by direct HTTP queries.

Smart-supporting git clients add an argument to the end of the first URL grabbed, "[repo]/info/refs?service=git-upload-pack". A dumb server will just send "info/refs" file as text ignoring the argument, while a smart server will return some binary data in front of the refs list, including text "service=git-upload-pack" and a list of features (which you might be able to figure out "depth" support from).

You can script this smart/dumb test by using wget or curl to check the MIME type: text/plain (dumb) vs. application/x-git-upload-pack-advertisement (smart).

$ curl -si http://github.com/git/git.git/info/refs?service=git-upload-pack | grep --binary-files=text '^Content-Type'
Content-Type: application/x-git-upload-pack-advertisement
$ curl -si http://git.kernel.org/pub/scm/git/git.git/info/refs?service=git-upload-pack | grep --binary-files=text '^Content-Type'
Content-Type: application/x-git-upload-pack-advertisement
$ curl -si http://repo.or.cz/r/git.git/info/refs?service=git-upload-pack | grep --binary-files=text '^Content-Type'
Content-Type: text/plain

(Pipe to grep -q "^Content-Type: application/x-git" and use the return code for true/false test.)

emsearcy
  • 116
  • 1
  • 4
  • 1
    You can also use GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone --verbose --depth 1 repo_url to use native git client instead of curl (which also handles authentication in case of private repository) – kontulai Sep 07 '15 at 19:18
6

I believe since git 1.8.2, you can check the Content-Type header.
That is why commit git/git/4656bf47 mentions:

Before parsing a suspected smart-HTTP response verify the returned Content-Type matches the standard. This protects a client from attempting to process a payload that smells like a smart-HTTP server response.

You can see an example of setting that field in commit sitaramc/gitolite/32d14d39:

my $service = ( $ENV{SSH_ORIGINAL_COMMAND} =~ /git-receive-pack/ ? 'git-receive-pack' : 'git-upload-pack' );

if ($service) {
    print "Content-Type: application/x-$service-advertisement\r\n";
}

So a Content-Type header field with x-git-receive-pack-advertisement or x-git-upload-pack-advertisement means smart http.


Another way:

Before Git 2.26 (Q1 2020), "git fetch" over HTTP walker protocol did not show any progress output.

Now, we inherently do not know how much work remains, but still we can show something not to bore users.

See commit 7655b41 (03 Mar 2020) by René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit 4a5c3e1, 09 Mar 2020)

remote-curl: show progress for fetches over dumb HTTP

Signed-off-by: René Scharfe

Fetching over dumb HTTP transport doesn't show any progress, even with the option --progress.

If the connection is slow or there is a lot of data to get then this can take a long time while the user is left to wonder if git got stuck.

We don't know the number of objects to fetch at the outset, but we can count the ones we got.

Show an open-ended progress indicator based on that number if the user asked for it.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250