git
/
bundle.c
658 строк · 16.9 Кб
1#define USE_THE_REPOSITORY_VARIABLE
2
3#include "git-compat-util.h"
4#include "lockfile.h"
5#include "bundle.h"
6#include "environment.h"
7#include "gettext.h"
8#include "hex.h"
9#include "object-store-ll.h"
10#include "repository.h"
11#include "object.h"
12#include "commit.h"
13#include "diff.h"
14#include "revision.h"
15#include "list-objects.h"
16#include "run-command.h"
17#include "refs.h"
18#include "strvec.h"
19#include "list-objects-filter-options.h"
20#include "connected.h"
21#include "write-or-die.h"
22
23static const char v2_bundle_signature[] = "# v2 git bundle\n";
24static const char v3_bundle_signature[] = "# v3 git bundle\n";
25static struct {
26int version;
27const char *signature;
28} bundle_sigs[] = {
29{ 2, v2_bundle_signature },
30{ 3, v3_bundle_signature },
31};
32
33void bundle_header_init(struct bundle_header *header)
34{
35struct bundle_header blank = BUNDLE_HEADER_INIT;
36memcpy(header, &blank, sizeof(*header));
37}
38
39void bundle_header_release(struct bundle_header *header)
40{
41string_list_clear(&header->prerequisites, 1);
42string_list_clear(&header->references, 1);
43list_objects_filter_release(&header->filter);
44}
45
46static int parse_capability(struct bundle_header *header, const char *capability)
47{
48const char *arg;
49if (skip_prefix(capability, "object-format=", &arg)) {
50int algo = hash_algo_by_name(arg);
51if (algo == GIT_HASH_UNKNOWN)
52return error(_("unrecognized bundle hash algorithm: %s"), arg);
53header->hash_algo = &hash_algos[algo];
54return 0;
55}
56if (skip_prefix(capability, "filter=", &arg)) {
57parse_list_objects_filter(&header->filter, arg);
58return 0;
59}
60return error(_("unknown capability '%s'"), capability);
61}
62
63static int parse_bundle_signature(struct bundle_header *header, const char *line)
64{
65int i;
66
67for (i = 0; i < ARRAY_SIZE(bundle_sigs); i++) {
68if (!strcmp(line, bundle_sigs[i].signature)) {
69header->version = bundle_sigs[i].version;
70return 0;
71}
72}
73return -1;
74}
75
76int read_bundle_header_fd(int fd, struct bundle_header *header,
77const char *report_path)
78{
79struct strbuf buf = STRBUF_INIT;
80int status = 0;
81
82/* The bundle header begins with the signature */
83if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
84parse_bundle_signature(header, buf.buf)) {
85if (report_path)
86error(_("'%s' does not look like a v2 or v3 bundle file"),
87report_path);
88status = -1;
89goto abort;
90}
91
92/*
93* The default hash format for bundles is SHA1, unless told otherwise
94* by an "object-format=" capability, which is being handled in
95* `parse_capability()`.
96*/
97header->hash_algo = &hash_algos[GIT_HASH_SHA1];
98
99/* The bundle header ends with an empty line */
100while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
101buf.len && buf.buf[0] != '\n') {
102struct object_id oid;
103int is_prereq = 0;
104const char *p;
105
106strbuf_rtrim(&buf);
107
108if (header->version == 3 && *buf.buf == '@') {
109if (parse_capability(header, buf.buf + 1)) {
110status = -1;
111break;
112}
113continue;
114}
115
116if (*buf.buf == '-') {
117is_prereq = 1;
118strbuf_remove(&buf, 0, 1);
119}
120
121/*
122* Tip lines have object name, SP, and refname.
123* Prerequisites have object name that is optionally
124* followed by SP and subject line.
125*/
126if (parse_oid_hex_algop(buf.buf, &oid, &p, header->hash_algo) ||
127(*p && !isspace(*p)) ||
128(!is_prereq && !*p)) {
129if (report_path)
130error(_("unrecognized header: %s%s (%d)"),
131(is_prereq ? "-" : ""), buf.buf, (int)buf.len);
132status = -1;
133break;
134} else {
135struct object_id *dup = oiddup(&oid);
136if (is_prereq)
137string_list_append(&header->prerequisites, "")->util = dup;
138else
139string_list_append(&header->references, p + 1)->util = dup;
140}
141}
142
143abort:
144if (status) {
145close(fd);
146fd = -1;
147}
148strbuf_release(&buf);
149return fd;
150}
151
152int read_bundle_header(const char *path, struct bundle_header *header)
153{
154int fd = open(path, O_RDONLY);
155
156if (fd < 0)
157return error(_("could not open '%s'"), path);
158return read_bundle_header_fd(fd, header, path);
159}
160
161int is_bundle(const char *path, int quiet)
162{
163struct bundle_header header = BUNDLE_HEADER_INIT;
164int fd = open(path, O_RDONLY);
165
166if (fd < 0)
167return 0;
168fd = read_bundle_header_fd(fd, &header, quiet ? NULL : path);
169if (fd >= 0)
170close(fd);
171bundle_header_release(&header);
172return (fd >= 0);
173}
174
175static int list_refs(struct string_list *r, int argc, const char **argv)
176{
177int i;
178
179for (i = 0; i < r->nr; i++) {
180struct object_id *oid;
181const char *name;
182
183if (argc > 1) {
184int j;
185for (j = 1; j < argc; j++)
186if (!strcmp(r->items[i].string, argv[j]))
187break;
188if (j == argc)
189continue;
190}
191
192oid = r->items[i].util;
193name = r->items[i].string;
194printf("%s %s\n", oid_to_hex(oid), name);
195}
196return 0;
197}
198
199/* Remember to update object flag allocation in object.h */
200#define PREREQ_MARK (1u<<16)
201
202struct string_list_iterator {
203struct string_list *list;
204size_t cur;
205};
206
207static const struct object_id *iterate_ref_map(void *cb_data)
208{
209struct string_list_iterator *iter = cb_data;
210
211if (iter->cur >= iter->list->nr)
212return NULL;
213
214return iter->list->items[iter->cur++].util;
215}
216
217int verify_bundle(struct repository *r,
218struct bundle_header *header,
219enum verify_bundle_flags flags)
220{
221/*
222* Do fast check, then if any prereqs are missing then go line by line
223* to be verbose about the errors
224*/
225struct string_list *p = &header->prerequisites;
226int i, ret = 0;
227const char *message = _("Repository lacks these prerequisite commits:");
228struct string_list_iterator iter = {
229.list = p,
230};
231struct check_connected_options opts = {
232.quiet = 1,
233};
234
235if (!r || !r->objects || !r->objects->odb)
236return error(_("need a repository to verify a bundle"));
237
238for (i = 0; i < p->nr; i++) {
239struct string_list_item *e = p->items + i;
240const char *name = e->string;
241struct object_id *oid = e->util;
242struct object *o = parse_object(r, oid);
243if (o)
244continue;
245ret++;
246if (flags & VERIFY_BUNDLE_QUIET)
247continue;
248if (ret == 1)
249error("%s", message);
250error("%s %s", oid_to_hex(oid), name);
251}
252if (ret)
253goto cleanup;
254
255if ((ret = check_connected(iterate_ref_map, &iter, &opts)))
256error(_("some prerequisite commits exist in the object store, "
257"but are not connected to the repository's history"));
258
259/* TODO: preserve this verbose language. */
260if (flags & VERIFY_BUNDLE_VERBOSE) {
261struct string_list *r;
262
263r = &header->references;
264printf_ln(Q_("The bundle contains this ref:",
265"The bundle contains these %"PRIuMAX" refs:",
266r->nr),
267(uintmax_t)r->nr);
268list_refs(r, 0, NULL);
269
270r = &header->prerequisites;
271if (!r->nr) {
272printf_ln(_("The bundle records a complete history."));
273} else {
274printf_ln(Q_("The bundle requires this ref:",
275"The bundle requires these %"PRIuMAX" refs:",
276r->nr),
277(uintmax_t)r->nr);
278list_refs(r, 0, NULL);
279}
280
281printf_ln(_("The bundle uses this hash algorithm: %s"),
282header->hash_algo->name);
283if (header->filter.choice)
284printf_ln(_("The bundle uses this filter: %s"),
285list_objects_filter_spec(&header->filter));
286}
287cleanup:
288return ret;
289}
290
291int list_bundle_refs(struct bundle_header *header, int argc, const char **argv)
292{
293return list_refs(&header->references, argc, argv);
294}
295
296static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
297{
298unsigned long size;
299enum object_type type;
300char *buf = NULL, *line, *lineend;
301timestamp_t date;
302int result = 1;
303
304if (revs->max_age == -1 && revs->min_age == -1)
305goto out;
306
307buf = repo_read_object_file(the_repository, &tag->oid, &type, &size);
308if (!buf)
309goto out;
310line = memmem(buf, size, "\ntagger ", 8);
311if (!line++)
312goto out;
313lineend = memchr(line, '\n', buf + size - line);
314line = memchr(line, '>', lineend ? lineend - line : buf + size - line);
315if (!line++)
316goto out;
317date = parse_timestamp(line, NULL, 10);
318result = (revs->max_age == -1 || revs->max_age < date) &&
319(revs->min_age == -1 || revs->min_age > date);
320out:
321free(buf);
322return result;
323}
324
325
326/* Write the pack data to bundle_fd */
327static int write_pack_data(int bundle_fd, struct rev_info *revs, struct strvec *pack_options)
328{
329struct child_process pack_objects = CHILD_PROCESS_INIT;
330int i;
331
332strvec_pushl(&pack_objects.args,
333"pack-objects",
334"--stdout", "--thin", "--delta-base-offset",
335NULL);
336strvec_pushv(&pack_objects.args, pack_options->v);
337if (revs->filter.choice)
338strvec_pushf(&pack_objects.args, "--filter=%s",
339list_objects_filter_spec(&revs->filter));
340pack_objects.in = -1;
341pack_objects.out = bundle_fd;
342pack_objects.git_cmd = 1;
343
344/*
345* start_command() will close our descriptor if it's >1. Duplicate it
346* to avoid surprising the caller.
347*/
348if (pack_objects.out > 1) {
349pack_objects.out = dup(pack_objects.out);
350if (pack_objects.out < 0) {
351error_errno(_("unable to dup bundle descriptor"));
352child_process_clear(&pack_objects);
353return -1;
354}
355}
356
357if (start_command(&pack_objects))
358return error(_("Could not spawn pack-objects"));
359
360for (i = 0; i < revs->pending.nr; i++) {
361struct object *object = revs->pending.objects[i].item;
362if (object->flags & UNINTERESTING)
363write_or_die(pack_objects.in, "^", 1);
364write_or_die(pack_objects.in, oid_to_hex(&object->oid), the_hash_algo->hexsz);
365write_or_die(pack_objects.in, "\n", 1);
366}
367close(pack_objects.in);
368if (finish_command(&pack_objects))
369return error(_("pack-objects died"));
370return 0;
371}
372
373/*
374* Write out bundle refs based on the tips already
375* parsed into revs.pending. As a side effect, may
376* manipulate revs.pending to include additional
377* necessary objects (like tags).
378*
379* Returns the number of refs written, or negative
380* on error.
381*/
382static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
383{
384int i;
385int ref_count = 0;
386
387for (i = 0; i < revs->pending.nr; i++) {
388struct object_array_entry *e = revs->pending.objects + i;
389struct object_id oid;
390char *ref;
391const char *display_ref;
392int flag;
393
394if (e->item->flags & UNINTERESTING)
395continue;
396if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
397&oid, &ref, 0) != 1)
398goto skip_write_ref;
399if (refs_read_ref_full(get_main_ref_store(the_repository), e->name, RESOLVE_REF_READING, &oid, &flag))
400flag = 0;
401display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
402
403if (e->item->type == OBJ_TAG &&
404!is_tag_in_date_range(e->item, revs)) {
405e->item->flags |= UNINTERESTING;
406goto skip_write_ref;
407}
408
409/*
410* Make sure the refs we wrote out is correct; --max-count and
411* other limiting options could have prevented all the tips
412* from getting output.
413*
414* Non commit objects such as tags and blobs do not have
415* this issue as they are not affected by those extra
416* constraints.
417*/
418if (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) {
419warning(_("ref '%s' is excluded by the rev-list options"),
420e->name);
421goto skip_write_ref;
422}
423/*
424* If you run "git bundle create bndl v1.0..v2.0", the
425* name of the positive ref is "v2.0" but that is the
426* commit that is referenced by the tag, and not the tag
427* itself.
428*/
429if (!oideq(&oid, &e->item->oid)) {
430/*
431* Is this the positive end of a range expressed
432* in terms of a tag (e.g. v2.0 from the range
433* "v1.0..v2.0")?
434*/
435struct commit *one = lookup_commit_reference(revs->repo, &oid);
436struct object *obj;
437
438if (e->item == &(one->object)) {
439/*
440* Need to include e->name as an
441* independent ref to the pack-objects
442* input, so that the tag is included
443* in the output; otherwise we would
444* end up triggering "empty bundle"
445* error.
446*/
447obj = parse_object_or_die(&oid, e->name);
448obj->flags |= SHOWN;
449add_pending_object(revs, obj, e->name);
450}
451goto skip_write_ref;
452}
453
454ref_count++;
455write_or_die(bundle_fd, oid_to_hex(&e->item->oid), the_hash_algo->hexsz);
456write_or_die(bundle_fd, " ", 1);
457write_or_die(bundle_fd, display_ref, strlen(display_ref));
458write_or_die(bundle_fd, "\n", 1);
459skip_write_ref:
460free(ref);
461}
462
463/* end header */
464write_or_die(bundle_fd, "\n", 1);
465return ref_count;
466}
467
468struct bundle_prerequisites_info {
469struct object_array *pending;
470int fd;
471};
472
473static void write_bundle_prerequisites(struct commit *commit, void *data)
474{
475struct bundle_prerequisites_info *bpi = data;
476struct object *object;
477struct pretty_print_context ctx = { 0 };
478struct strbuf buf = STRBUF_INIT;
479
480if (!(commit->object.flags & BOUNDARY))
481return;
482strbuf_addf(&buf, "-%s ", oid_to_hex(&commit->object.oid));
483write_or_die(bpi->fd, buf.buf, buf.len);
484
485ctx.fmt = CMIT_FMT_ONELINE;
486ctx.output_encoding = get_log_output_encoding();
487strbuf_reset(&buf);
488pretty_print_commit(&ctx, commit, &buf);
489strbuf_trim(&buf);
490
491object = (struct object *)commit;
492object->flags |= UNINTERESTING;
493add_object_array_with_path(object, buf.buf, bpi->pending, S_IFINVALID,
494NULL);
495strbuf_addch(&buf, '\n');
496write_or_die(bpi->fd, buf.buf, buf.len);
497strbuf_release(&buf);
498}
499
500int create_bundle(struct repository *r, const char *path,
501int argc, const char **argv, struct strvec *pack_options, int version)
502{
503struct lock_file lock = LOCK_INIT;
504int bundle_fd = -1;
505int bundle_to_stdout;
506int ref_count = 0;
507struct rev_info revs, revs_copy;
508int min_version = 2;
509struct bundle_prerequisites_info bpi;
510int ret;
511int i;
512
513/* init revs to list objects for pack-objects later */
514save_commit_buffer = 0;
515repo_init_revisions(r, &revs, NULL);
516
517/*
518* Pre-initialize the '--objects' flag so we can parse a
519* --filter option successfully.
520*/
521revs.tree_objects = revs.blob_objects = 1;
522
523argc = setup_revisions(argc, argv, &revs, NULL);
524
525/*
526* Reasons to require version 3:
527*
528* 1. @object-format is required because our hash algorithm is not
529* SHA1.
530* 2. @filter is required because we parsed an object filter.
531*/
532if (the_hash_algo != &hash_algos[GIT_HASH_SHA1] || revs.filter.choice)
533min_version = 3;
534
535if (argc > 1) {
536ret = error(_("unrecognized argument: %s"), argv[1]);
537goto out;
538}
539
540bundle_to_stdout = !strcmp(path, "-");
541if (bundle_to_stdout)
542bundle_fd = 1;
543else
544bundle_fd = hold_lock_file_for_update(&lock, path,
545LOCK_DIE_ON_ERROR);
546
547if (version == -1)
548version = min_version;
549
550if (version < 2 || version > 3) {
551die(_("unsupported bundle version %d"), version);
552} else if (version < min_version) {
553die(_("cannot write bundle version %d with algorithm %s"), version, the_hash_algo->name);
554} else if (version == 2) {
555write_or_die(bundle_fd, v2_bundle_signature, strlen(v2_bundle_signature));
556} else {
557const char *capability = "@object-format=";
558write_or_die(bundle_fd, v3_bundle_signature, strlen(v3_bundle_signature));
559write_or_die(bundle_fd, capability, strlen(capability));
560write_or_die(bundle_fd, the_hash_algo->name, strlen(the_hash_algo->name));
561write_or_die(bundle_fd, "\n", 1);
562
563if (revs.filter.choice) {
564const char *value = expand_list_objects_filter_spec(&revs.filter);
565capability = "@filter=";
566write_or_die(bundle_fd, capability, strlen(capability));
567write_or_die(bundle_fd, value, strlen(value));
568write_or_die(bundle_fd, "\n", 1);
569}
570}
571
572/* save revs.pending in revs_copy for later use */
573memcpy(&revs_copy, &revs, sizeof(revs));
574revs_copy.pending.nr = 0;
575revs_copy.pending.alloc = 0;
576revs_copy.pending.objects = NULL;
577for (i = 0; i < revs.pending.nr; i++) {
578struct object_array_entry *e = revs.pending.objects + i;
579if (e)
580add_object_array_with_path(e->item, e->name,
581&revs_copy.pending,
582e->mode, e->path);
583}
584
585/* write prerequisites */
586revs.boundary = 1;
587if (prepare_revision_walk(&revs))
588die("revision walk setup failed");
589bpi.fd = bundle_fd;
590bpi.pending = &revs_copy.pending;
591
592/*
593* Remove any object walking here. We only care about commits and
594* tags here. The revs_copy has the right instances of these values.
595*/
596revs.blob_objects = revs.tree_objects = 0;
597traverse_commit_list(&revs, write_bundle_prerequisites, NULL, &bpi);
598object_array_remove_duplicates(&revs_copy.pending);
599
600/* write bundle refs */
601ref_count = write_bundle_refs(bundle_fd, &revs_copy);
602if (!ref_count) {
603die(_("Refusing to create empty bundle."));
604} else if (ref_count < 0) {
605ret = -1;
606goto out;
607}
608
609/* write pack */
610if (write_pack_data(bundle_fd, &revs_copy, pack_options)) {
611ret = -1;
612goto out;
613}
614
615if (!bundle_to_stdout) {
616if (commit_lock_file(&lock))
617die_errno(_("cannot create '%s'"), path);
618}
619
620ret = 0;
621
622out:
623object_array_clear(&revs_copy.pending);
624release_revisions(&revs);
625rollback_lock_file(&lock);
626return ret;
627}
628
629int unbundle(struct repository *r, struct bundle_header *header,
630int bundle_fd, struct strvec *extra_index_pack_args,
631enum verify_bundle_flags flags)
632{
633struct child_process ip = CHILD_PROCESS_INIT;
634
635if (verify_bundle(r, header, flags))
636return -1;
637
638strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
639
640/* If there is a filter, then we need to create the promisor pack. */
641if (header->filter.choice)
642strvec_push(&ip.args, "--promisor=from-bundle");
643
644if (flags & VERIFY_BUNDLE_FSCK)
645strvec_push(&ip.args, "--fsck-objects");
646
647if (extra_index_pack_args) {
648strvec_pushv(&ip.args, extra_index_pack_args->v);
649strvec_clear(extra_index_pack_args);
650}
651
652ip.in = bundle_fd;
653ip.no_stdout = 1;
654ip.git_cmd = 1;
655if (run_command(&ip))
656return error(_("index-pack died"));
657return 0;
658}
659