10 #include <curl/curl.h>
11 #include <curl/easy.h>
18 static int commits
= 0;
22 static z_stream stream
;
27 static size_t fwrite_sha1_file(void *ptr
, size_t eltsize
, size_t nmemb
,
30 size_t size
= eltsize
* nmemb
;
33 ssize_t retval
= write(local
, ptr
+ posn
, size
- posn
);
37 } while (posn
< size
);
39 stream
.avail_in
= size
;
42 stream
.next_out
= expn
;
43 stream
.avail_out
= sizeof(expn
);
44 zret
= inflate(&stream
, Z_SYNC_FLUSH
);
45 SHA1_Update(&c
, expn
, sizeof(expn
) - stream
.avail_out
);
46 } while (stream
.avail_in
&& zret
== Z_OK
);
50 static int fetch(unsigned char *sha1
)
52 char *hex
= sha1_to_hex(sha1
);
53 char *filename
= sha1_file_name(sha1
);
58 if (has_sha1_file(sha1
)) {
62 local
= open(filename
, O_WRONLY
| O_CREAT
| O_EXCL
, 0666);
65 return error("Couldn't open %s\n", filename
);
67 memset(&stream
, 0, sizeof(stream
));
73 curl_easy_setopt(curl
, CURLOPT_FILE
, NULL
);
74 curl_easy_setopt(curl
, CURLOPT_WRITEFUNCTION
, fwrite_sha1_file
);
76 url
= malloc(strlen(base
) + 50);
78 posn
= url
+ strlen(base
);
79 strcpy(posn
, "objects/");
84 strcpy(posn
, hex
+ 2);
86 curl_easy_setopt(curl
, CURLOPT_URL
, url
);
88 /*printf("Getting %s\n", hex);*/
90 if (curl_easy_perform(curl
))
91 return error("Couldn't get %s for %s\n", url
, hex
);
95 SHA1_Final(real_sha1
, &c
);
96 if (zret
!= Z_STREAM_END
) {
98 return error("File %s (%s) corrupt\n", hex
, url
);
100 if (memcmp(sha1
, real_sha1
, 20)) {
102 return error("File %s has bad hash\n", hex
);
108 static int process_tree(unsigned char *sha1
)
110 struct tree
*tree
= lookup_tree(sha1
);
111 struct tree_entry_list
*entries
;
113 if (parse_tree(tree
))
116 for (entries
= tree
->entries
; entries
; entries
= entries
->next
) {
117 if (fetch(entries
->item
.tree
->object
.sha1
))
119 if (entries
->directory
) {
120 if (process_tree(entries
->item
.tree
->object
.sha1
))
127 static int process_commit(unsigned char *sha1
)
129 struct commit
*obj
= lookup_commit(sha1
);
134 if (parse_commit(obj
))
138 if (fetch(obj
->tree
->object
.sha1
))
140 if (process_tree(obj
->tree
->object
.sha1
))
146 struct commit_list
*parents
= obj
->parents
;
147 for (; parents
; parents
= parents
->next
) {
148 if (has_sha1_file(parents
->item
->object
.sha1
))
150 if (fetch(parents
->item
->object
.sha1
)) {
151 /* The server might not have it, and
156 if (process_commit(parents
->item
->object
.sha1
))
163 int main(int argc
, char **argv
)
168 unsigned char sha1
[20];
170 while (arg
< argc
&& argv
[arg
][0] == '-') {
171 if (argv
[arg
][1] == 't') {
173 } else if (argv
[arg
][1] == 'c') {
175 } else if (argv
[arg
][1] == 'a') {
182 if (argc
< arg
+ 2) {
183 usage("http-pull [-c] [-t] [-a] commit-id url");
186 commit_id
= argv
[arg
];
189 get_sha1_hex(commit_id
, sha1
);
191 curl_global_init(CURL_GLOBAL_ALL
);
193 curl
= curl_easy_init();
199 if (process_commit(sha1
))
202 curl_global_cleanup();