9 #if LIBCURL_VERSION_NUM < 0x070704
10 #define curl_global_cleanup() do { /* nothing */ } while(0)
12 #if LIBCURL_VERSION_NUM < 0x070800
13 #define curl_global_init(a) do { /* nothing */ } while(0)
17 static struct curl_slist
*no_pragma_header
;
22 static z_stream stream
;
27 static int curl_ssl_verify
;
36 static size_t fwrite_buffer(void *ptr
, size_t eltsize
, size_t nmemb
,
37 struct buffer
*buffer
)
39 size_t size
= eltsize
* nmemb
;
40 if (size
> buffer
->size
- buffer
->posn
)
41 size
= buffer
->size
- buffer
->posn
;
42 memcpy(buffer
->buffer
+ buffer
->posn
, ptr
, size
);
47 static size_t fwrite_sha1_file(void *ptr
, size_t eltsize
, size_t nmemb
,
50 unsigned char expn
[4096];
51 size_t size
= eltsize
* nmemb
;
54 ssize_t retval
= write(local
, ptr
+ posn
, size
- posn
);
58 } while (posn
< size
);
60 stream
.avail_in
= size
;
63 stream
.next_out
= expn
;
64 stream
.avail_out
= sizeof(expn
);
65 zret
= inflate(&stream
, Z_SYNC_FLUSH
);
66 SHA1_Update(&c
, expn
, sizeof(expn
) - stream
.avail_out
);
67 } while (stream
.avail_in
&& zret
== Z_OK
);
71 void prefetch(unsigned char *sha1
)
75 static int got_indices
= 0;
77 static struct packed_git
*packs
= NULL
;
79 static int fetch_index(unsigned char *sha1
)
86 if (has_pack_index(sha1
))
90 fprintf(stderr
, "Getting index for pack %s\n",
93 url
= xmalloc(strlen(base
) + 64);
94 sprintf(url
, "%s/objects/pack/pack-%s.idx",
95 base
, sha1_to_hex(sha1
));
97 filename
= sha1_pack_index_name(sha1
);
98 indexfile
= fopen(filename
, "w");
100 return error("Unable to open local file %s for pack index",
103 curl_easy_setopt(curl
, CURLOPT_FILE
, indexfile
);
104 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite
);
105 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
106 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, no_pragma_header
);
108 if (curl_easy_perform(curl
)) {
110 return error("Unable to get pack index %s", url
);
117 static int setup_index(unsigned char *sha1
)
119 struct packed_git
*new_pack
;
120 if (has_pack_file(sha1
))
121 return 0; // don't list this as something we can get
123 if (fetch_index(sha1
))
126 new_pack
= parse_pack_index(sha1
);
127 new_pack
->next
= packs
;
132 static int fetch_indices(void)
134 unsigned char sha1
[20];
136 struct buffer buffer
;
143 data
= xmalloc(4096);
146 buffer
.buffer
= data
;
149 fprintf(stderr
, "Getting pack list\n");
151 url
= xmalloc(strlen(base
) + 21);
152 sprintf(url
, "%s/objects/info/packs", base
);
154 curl_easy_setopt(curl
, CURLOPT_FILE
, &buffer
);
155 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
156 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
157 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, NULL
);
159 if (curl_easy_perform(curl
)) {
160 return error("Unable to get pack index %s", url
);
167 if (i
+ 52 < buffer
.posn
&&
168 !strncmp(data
+ i
, " pack-", 6) &&
169 !strncmp(data
+ i
+ 46, ".pack\n", 6)) {
170 get_sha1_hex(data
+ i
+ 6, sha1
);
176 while (data
[i
] != '\n')
180 } while (i
< buffer
.posn
);
186 static int fetch_pack(unsigned char *sha1
)
189 struct packed_git
*target
;
190 struct packed_git
**lst
;
196 target
= find_sha1_pack(sha1
, packs
);
198 return error("Couldn't get %s: not separate or in any pack",
202 fprintf(stderr
, "Getting pack %s\n",
203 sha1_to_hex(target
->sha1
));
204 fprintf(stderr
, " which contains %s\n",
208 url
= xmalloc(strlen(base
) + 65);
209 sprintf(url
, "%s/objects/pack/pack-%s.pack",
210 base
, sha1_to_hex(target
->sha1
));
212 filename
= sha1_pack_name(target
->sha1
);
213 packfile
= fopen(filename
, "w");
215 return error("Unable to open local file %s for pack",
218 curl_easy_setopt(curl
, CURLOPT_FILE
, packfile
);
219 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite
);
220 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
221 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, no_pragma_header
);
223 if (curl_easy_perform(curl
)) {
225 return error("Unable to get pack file %s", url
);
231 while (*lst
!= target
)
232 lst
= &((*lst
)->next
);
235 install_packed_git(target
);
240 int fetch(unsigned char *sha1
)
242 char *hex
= sha1_to_hex(sha1
);
243 char *filename
= sha1_file_name(sha1
);
244 unsigned char real_sha1
[20];
248 local
= open(filename
, O_WRONLY
| O_CREAT
| O_EXCL
, 0666);
251 return error("Couldn't open local object %s\n", filename
);
253 memset(&stream
, 0, sizeof(stream
));
255 inflateInit(&stream
);
259 curl_easy_setopt(curl
, CURLOPT_FAILONERROR
, 1);
260 curl_easy_setopt(curl
, CURLOPT_FILE
, NULL
);
261 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite_sha1_file
);
262 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, no_pragma_header
);
264 url
= xmalloc(strlen(base
) + 50);
266 posn
= url
+ strlen(base
);
267 strcpy(posn
, "objects/");
269 memcpy(posn
, hex
, 2);
272 strcpy(posn
, hex
+ 2);
274 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
276 if (curl_easy_perform(curl
)) {
278 if (fetch_pack(sha1
))
279 return error("Tried %s", url
);
285 SHA1_Final(real_sha1
, &c
);
286 if (zret
!= Z_STREAM_END
) {
288 return error("File %s (%s) corrupt\n", hex
, url
);
290 if (memcmp(sha1
, real_sha1
, 20)) {
292 return error("File %s has bad hash\n", hex
);
295 pull_say("got %s\n", hex
);
299 int fetch_ref(char *ref
, unsigned char *sha1
)
303 struct buffer buffer
;
309 curl_easy_setopt(curl
, CURLOPT_FILE
, &buffer
);
310 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
311 curl_easy_setopt(curl
, CURLOPT_HTTPHEADER
, NULL
);
313 url
= xmalloc(strlen(base
) + 6 + strlen(ref
));
315 posn
= url
+ strlen(base
);
316 strcpy(posn
, "refs/");
320 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
322 if (curl_easy_perform(curl
))
323 return error("Couldn't get %s for %s\n", url
, ref
);
326 get_sha1_hex(hex
, sha1
);
330 int main(int argc
, char **argv
)
336 while (arg
< argc
&& argv
[arg
][0] == '-') {
337 if (argv
[arg
][1] == 't') {
339 } else if (argv
[arg
][1] == 'c') {
341 } else if (argv
[arg
][1] == 'a') {
345 } else if (argv
[arg
][1] == 'v') {
347 } else if (argv
[arg
][1] == 'w') {
348 write_ref
= argv
[arg
+ 1];
353 if (argc
< arg
+ 2) {
354 usage("git-http-fetch [-c] [-t] [-a] [-d] [-v] [--recover] [-w ref] commit-id url");
357 commit_id
= argv
[arg
];
360 curl_global_init(CURL_GLOBAL_ALL
);
362 curl
= curl_easy_init();
363 no_pragma_header
= curl_slist_append(no_pragma_header
, "Pragma:");
365 curl_ssl_verify
= getenv("GIT_SSL_NO_VERIFY") ? 0 : 1;
366 curl_easy_setopt(curl
, CURLOPT_SSL_VERIFYPEER
, curl_ssl_verify
);
367 #if LIBCURL_VERSION_NUM >= 0x070907
368 curl_easy_setopt(curl
, CURLOPT_NETRC
, CURL_NETRC_OPTIONAL
);
376 curl_slist_free_all(no_pragma_header
);
377 curl_global_cleanup();