Raw
1 #define USE_THE_REPOSITORY_VARIABLE
2
3 #include "git-compat-util.h"
4 #include "config.h"
5 #include "environment.h"
6 #include "gettext.h"
7 #include "hex.h"
8 #include "http.h"
9 #include "walker.h"
10 #include "setup.h"
11 #include "strvec.h"
12 #include "url.h"
13 #include "urlmatch.h"
14 #include "trace2.h"
15
16 static const char http_fetch_usage[] = "git http-fetch "
17 "[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin | --packfile=hash | commit-id] url";
18
19 static int fetch_using_walker(const char *raw_url, int get_verbosely,
20 int get_recover, int commits, char **commit_id,
21 const char **write_ref, int commits_on_stdin)
22 {
23 char *url = NULL;
24 struct walker *walker;
25 int rc;
26
27 str_end_url_with_slash(raw_url, &url);
28
29 http_init(NULL, url, 0);
30
31 walker = get_http_walker(url);
32 walker->get_verbosely = get_verbosely;
33 walker->get_recover = get_recover;
34 walker->get_progress = 0;
35
36 rc = walker_fetch(walker, commits, commit_id, write_ref, url);
37
38 if (commits_on_stdin)
39 walker_targets_free(commits, commit_id, write_ref);
40
41 if (walker->corrupt_object_found) {
42 fprintf(stderr,
43 "Some loose object were found to be corrupt, but they might be just\n"
44 "a false '404 Not Found' error message sent with incorrect HTTP\n"
45 "status code. Suggest running 'git fsck'.\n");
46 }
47
48 walker_free(walker);
49 http_cleanup();
50 free(url);
51
52 return rc;
53 }
54
55 static void fetch_single_packfile(struct object_id *packfile_hash,
56 const char *url,
57 const char **index_pack_args) {
58 struct http_pack_request *preq;
59 struct slot_results results;
60 int ret;
61
62 http_init(NULL, url, 0);
63
64 preq = new_direct_http_pack_request(packfile_hash->hash, xstrdup(url));
65 if (!preq)
66 die("couldn't create http pack request");
67 preq->slot->results = &results;
68 preq->index_pack_args = index_pack_args;
69 preq->preserve_index_pack_stdout = 1;
70
71 if (start_active_slot(preq->slot)) {
72 run_active_slot(preq->slot);
73 if (results.curl_result != CURLE_OK) {
74 struct url_info url;
75 char *nurl = url_normalize(preq->url, &url);
76 if (!nurl || !git_env_bool("GIT_TRACE_REDACT", 1)) {
77 die("unable to get pack file '%s'\n%s", preq->url,
78 curl_errorstr);
79 } else {
80 die("failed to get '%.*s' url from '%.*s' "
81 "(full URL redacted due to GIT_TRACE_REDACT setting)\n%s",
82 (int)url.scheme_len, url.url,
83 (int)url.host_len, &url.url[url.host_off], curl_errorstr);
84 }
85 }
86 } else {
87 die("Unable to start request");
88 }
89
90 if ((ret = finish_http_pack_request(preq)))
91 die("finish_http_pack_request gave result %d", ret);
92
93 release_http_pack_request(preq);
94 http_cleanup();
95 }
96
97 int cmd_main(int argc, const char **argv)
98 {
99 int commits_on_stdin = 0;
100 int commits;
101 const char **write_ref = NULL;
102 char **commit_id;
103 int arg = 1;
104 int get_verbosely = 0;
105 int get_recover = 0;
106 int packfile = 0;
107 int nongit;
108 struct object_id packfile_hash;
109 struct strvec index_pack_args = STRVEC_INIT;
110 int ret;
111
112 setup_git_directory_gently(the_repository, &nongit);
113
114 while (arg < argc && argv[arg][0] == '-') {
115 const char *p;
116
117 if (argv[arg][1] == 't') {
118 } else if (argv[arg][1] == 'c') {
119 } else if (argv[arg][1] == 'a') {
120 } else if (argv[arg][1] == 'v') {
121 get_verbosely = 1;
122 } else if (argv[arg][1] == 'w') {
123 write_ref = &argv[arg + 1];
124 arg++;
125 } else if (argv[arg][1] == 'h') {
126 usage(http_fetch_usage);
127 } else if (!strcmp(argv[arg], "--recover")) {
128 get_recover = 1;
129 } else if (!strcmp(argv[arg], "--stdin")) {
130 commits_on_stdin = 1;
131 } else if (skip_prefix(argv[arg], "--packfile=", &p)) {
132 const char *end;
133
134 if (nongit)
135 die(_("not a git repository"));
136
137 packfile = 1;
138 if (parse_oid_hex_algop(p, &packfile_hash, &end,
139 the_repository->hash_algo) || *end)
140 die(_("argument to --packfile must be a valid hash (got '%s')"), p);
141 } else if (skip_prefix(argv[arg], "--index-pack-arg=", &p)) {
142 strvec_push(&index_pack_args, p);
143 }
144 arg++;
145 }
146 if (argc != arg + 2 - (commits_on_stdin || packfile))
147 usage(http_fetch_usage);
148
149 if (nongit)
150 die(_("not a git repository"));
151
152 trace2_cmd_name("http-fetch");
153
154 repo_config(the_repository, git_default_config, NULL);
155
156 if (packfile) {
157 if (!index_pack_args.nr)
158 die(_("the option '%s' requires '%s'"), "--packfile", "--index-pack-args");
159
160 fetch_single_packfile(&packfile_hash, argv[arg],
161 index_pack_args.v);
162 ret = 0;
163 goto out;
164 }
165
166 if (index_pack_args.nr)
167 die(_("the option '%s' requires '%s'"), "--index-pack-args", "--packfile");
168
169 if (commits_on_stdin) {
170 commits = walker_targets_stdin(&commit_id, &write_ref);
171 } else {
172 commit_id = (char **) &argv[arg++];
173 commits = 1;
174 }
175
176 ret = fetch_using_walker(argv[arg], get_verbosely, get_recover,
177 commits, commit_id, write_ref,
178 commits_on_stdin);
179
180 out:
181 strvec_clear(&index_pack_args);
182 return ret;
183 }