Git fork
at reftables-rust 307 lines 7.7 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2#define DISABLE_SIGN_COMPARE_WARNINGS 3 4#include "builtin.h" 5#include "gettext.h" 6#include "hex.h" 7#include "object-file.h" 8#include "pkt-line.h" 9#include "fetch-pack.h" 10#include "remote.h" 11#include "connect.h" 12#include "oid-array.h" 13#include "protocol.h" 14 15static const char fetch_pack_usage[] = 16"git fetch-pack [--all] [--stdin] [--quiet | -q] [--keep | -k] [--thin] " 17"[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] " 18"[--no-progress] [--diag-url] [-v] [<host>:]<directory> [<refs>...]"; 19 20static void add_sought_entry(struct ref ***sought, int *nr, int *alloc, 21 const char *name) 22{ 23 struct ref *ref; 24 struct object_id oid; 25 const char *p; 26 27 if (!parse_oid_hex(name, &oid, &p)) { 28 if (*p == ' ') { 29 /* <oid> <ref>, find refname */ 30 name = p + 1; 31 } else if (*p == '\0') { 32 ; /* <oid>, leave oid as name */ 33 } else { 34 /* <ref>, clear cruft from oid */ 35 oidclr(&oid, the_repository->hash_algo); 36 } 37 } else { 38 /* <ref>, clear cruft from get_oid_hex */ 39 oidclr(&oid, the_repository->hash_algo); 40 } 41 42 ref = alloc_ref(name); 43 oidcpy(&ref->old_oid, &oid); 44 (*nr)++; 45 ALLOC_GROW(*sought, *nr, *alloc); 46 (*sought)[*nr - 1] = ref; 47} 48 49int cmd_fetch_pack(int argc, 50 const char **argv, 51 const char *prefix UNUSED, 52 struct repository *repo UNUSED) 53{ 54 int i, ret; 55 struct ref *fetched_refs = NULL, *remote_refs = NULL; 56 const char *dest = NULL; 57 struct ref **sought = NULL; 58 struct ref **sought_to_free = NULL; 59 int nr_sought = 0, alloc_sought = 0; 60 int fd[2]; 61 struct string_list pack_lockfiles = STRING_LIST_INIT_DUP; 62 struct string_list *pack_lockfiles_ptr = NULL; 63 struct child_process *conn; 64 struct fetch_pack_args args; 65 struct oid_array shallow = OID_ARRAY_INIT; 66 struct string_list deepen_not = STRING_LIST_INIT_DUP; 67 struct packet_reader reader; 68 enum protocol_version version; 69 70 fetch_if_missing = 0; 71 72 packet_trace_identity("fetch-pack"); 73 74 memset(&args, 0, sizeof(args)); 75 list_objects_filter_init(&args.filter_options); 76 args.uploadpack = "git-upload-pack"; 77 78 show_usage_if_asked(argc, argv, fetch_pack_usage); 79 80 for (i = 1; i < argc && *argv[i] == '-'; i++) { 81 const char *arg = argv[i]; 82 83 if (skip_prefix(arg, "--upload-pack=", &arg)) { 84 args.uploadpack = arg; 85 continue; 86 } 87 if (skip_prefix(arg, "--exec=", &arg)) { 88 args.uploadpack = arg; 89 continue; 90 } 91 if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) { 92 args.quiet = 1; 93 continue; 94 } 95 if (!strcmp("--keep", arg) || !strcmp("-k", arg)) { 96 args.lock_pack = args.keep_pack; 97 args.keep_pack = 1; 98 continue; 99 } 100 if (!strcmp("--thin", arg)) { 101 args.use_thin_pack = 1; 102 continue; 103 } 104 if (!strcmp("--include-tag", arg)) { 105 args.include_tag = 1; 106 continue; 107 } 108 if (!strcmp("--all", arg)) { 109 args.fetch_all = 1; 110 continue; 111 } 112 if (!strcmp("--stdin", arg)) { 113 args.stdin_refs = 1; 114 continue; 115 } 116 if (!strcmp("--diag-url", arg)) { 117 args.diag_url = 1; 118 continue; 119 } 120 if (!strcmp("-v", arg)) { 121 args.verbose = 1; 122 continue; 123 } 124 if (skip_prefix(arg, "--depth=", &arg)) { 125 args.depth = strtol(arg, NULL, 0); 126 continue; 127 } 128 if (skip_prefix(arg, "--shallow-since=", &arg)) { 129 args.deepen_since = xstrdup(arg); 130 continue; 131 } 132 if (skip_prefix(arg, "--shallow-exclude=", &arg)) { 133 string_list_append(&deepen_not, arg); 134 continue; 135 } 136 if (!strcmp(arg, "--deepen-relative")) { 137 args.deepen_relative = 1; 138 continue; 139 } 140 if (!strcmp("--no-progress", arg)) { 141 args.no_progress = 1; 142 continue; 143 } 144 if (!strcmp("--stateless-rpc", arg)) { 145 args.stateless_rpc = 1; 146 continue; 147 } 148 if (!strcmp("--lock-pack", arg)) { 149 args.lock_pack = 1; 150 pack_lockfiles_ptr = &pack_lockfiles; 151 continue; 152 } 153 if (!strcmp("--check-self-contained-and-connected", arg)) { 154 args.check_self_contained_and_connected = 1; 155 continue; 156 } 157 if (!strcmp("--cloning", arg)) { 158 args.cloning = 1; 159 continue; 160 } 161 if (!strcmp("--update-shallow", arg)) { 162 args.update_shallow = 1; 163 continue; 164 } 165 if (!strcmp("--from-promisor", arg)) { 166 args.from_promisor = 1; 167 continue; 168 } 169 if (!strcmp("--refetch", arg)) { 170 args.refetch = 1; 171 continue; 172 } 173 if (skip_prefix(arg, ("--filter="), &arg)) { 174 parse_list_objects_filter(&args.filter_options, arg); 175 continue; 176 } 177 if (!strcmp(arg, ("--no-filter"))) { 178 list_objects_filter_set_no_filter(&args.filter_options); 179 continue; 180 } 181 usage(fetch_pack_usage); 182 } 183 if (deepen_not.nr) 184 args.deepen_not = &deepen_not; 185 186 if (i < argc) 187 dest = argv[i++]; 188 else 189 usage(fetch_pack_usage); 190 191 /* 192 * Copy refs from cmdline to growable list, then append any 193 * refs from the standard input: 194 */ 195 for (; i < argc; i++) 196 add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]); 197 if (args.stdin_refs) { 198 if (args.stateless_rpc) { 199 /* in stateless RPC mode we use pkt-line to read 200 * from stdin, until we get a flush packet 201 */ 202 for (;;) { 203 char *line = packet_read_line(0, NULL); 204 if (!line) 205 break; 206 add_sought_entry(&sought, &nr_sought, &alloc_sought, line); 207 } 208 } 209 else { 210 /* read from stdin one ref per line, until EOF */ 211 struct strbuf line = STRBUF_INIT; 212 while (strbuf_getline_lf(&line, stdin) != EOF) 213 add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf); 214 strbuf_release(&line); 215 } 216 } 217 218 if (args.stateless_rpc) { 219 conn = NULL; 220 fd[0] = 0; 221 fd[1] = 1; 222 } else { 223 int flags = args.verbose ? CONNECT_VERBOSE : 0; 224 if (args.diag_url) 225 flags |= CONNECT_DIAG_URL; 226 conn = git_connect(fd, dest, "git-upload-pack", 227 args.uploadpack, flags); 228 if (!conn) 229 return args.diag_url ? 0 : 1; 230 } 231 232 packet_reader_init(&reader, fd[0], NULL, 0, 233 PACKET_READ_CHOMP_NEWLINE | 234 PACKET_READ_GENTLE_ON_EOF | 235 PACKET_READ_DIE_ON_ERR_PACKET); 236 237 version = discover_version(&reader); 238 switch (version) { 239 case protocol_v2: 240 get_remote_refs(fd[1], &reader, &remote_refs, 0, NULL, NULL, 241 args.stateless_rpc); 242 break; 243 case protocol_v1: 244 case protocol_v0: 245 get_remote_heads(&reader, &remote_refs, 0, NULL, &shallow); 246 break; 247 case protocol_unknown_version: 248 BUG("unknown protocol version"); 249 } 250 251 /* 252 * Create a shallow copy of `sought` so that we can free all of its entries. 253 * This is because `fetch_pack()` will modify the array to evict some 254 * entries, but won't free those. 255 */ 256 DUP_ARRAY(sought_to_free, sought, nr_sought); 257 258 fetched_refs = fetch_pack(&args, fd, remote_refs, sought, nr_sought, 259 &shallow, pack_lockfiles_ptr, version); 260 261 if (pack_lockfiles.nr) { 262 int i; 263 264 printf("lock %s\n", pack_lockfiles.items[0].string); 265 fflush(stdout); 266 for (i = 1; i < pack_lockfiles.nr; i++) 267 warning(_("Lockfile created but not reported: %s"), 268 pack_lockfiles.items[i].string); 269 } 270 if (args.check_self_contained_and_connected && 271 args.self_contained_and_connected) { 272 printf("connectivity-ok\n"); 273 fflush(stdout); 274 } 275 close(fd[0]); 276 close(fd[1]); 277 if (finish_connect(conn)) { 278 ret = 1; 279 goto cleanup; 280 } 281 282 ret = !fetched_refs; 283 284 /* 285 * If the heads to pull were given, we should have consumed 286 * all of them by matching the remote. Otherwise, 'git fetch 287 * remote no-such-ref' would silently succeed without issuing 288 * an error. 289 */ 290 ret |= report_unmatched_refs(sought, nr_sought); 291 292 for (struct ref *ref = fetched_refs; ref; ref = ref->next) 293 printf("%s %s\n", 294 oid_to_hex(&ref->old_oid), ref->name); 295 296cleanup: 297 for (size_t i = 0; i < nr_sought; i++) 298 free_one_ref(sought_to_free[i]); 299 free(sought_to_free); 300 free(sought); 301 free_refs(fetched_refs); 302 free_refs(remote_refs); 303 list_objects_filter_release(&args.filter_options); 304 oid_array_clear(&shallow); 305 string_list_clear(&pack_lockfiles, 0); 306 return ret; 307}