12
#include "refs.h"
13
#include "argv-array.h"
14
15
-static const char bundle_signature[] = "# v2 git bundle\n";
15
+
16
+static const char v2_bundle_signature[] = "# v2 git bundle\n";
17
+static const char v3_bundle_signature[] = "# v3 git bundle\n";
18
+static struct {
19
+ int version;
20
+ const char *signature;
21
+} bundle_sigs[] = {
22
+ { 2, v2_bundle_signature },
23
+ { 3, v3_bundle_signature },
24
+};
25
26
static void add_to_ref_list(const struct object_id *oid, const char *name,
27
struct ref_list *list)
32
list->nr++;
33
}
34
26
-static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
35
+static int parse_capability(struct bundle_header *header, const char *capability)
36
+{
37
+ const char *arg;
38
+ if (skip_prefix(capability, "object-format=", &arg)) {
39
+ int algo = hash_algo_by_name(arg);
40
+ if (algo == GIT_HASH_UNKNOWN)
41
+ return error(_("unrecognized bundle hash algorithm: %s"), arg);
42
+ header->hash_algo = &hash_algos[algo];
43
+ return 0;
44
+ }
45
+ return error(_("unknown capability '%s'"), capability);
46
+}
47
+
48
+static int parse_bundle_signature(struct bundle_header *header, const char *line)
49
{
28
- size_t len = strcspn(buf->buf, " \n");
29
- int algo;
50
+ int i;
51
31
- algo = hash_algo_by_length(len / 2);
32
- if (algo == GIT_HASH_UNKNOWN)
33
- return NULL;
34
- return &hash_algos[algo];
52
+ for (i = 0; i < ARRAY_SIZE(bundle_sigs); i++) {
53
+ if (!strcmp(line, bundle_sigs[i].signature)) {
54
+ header->version = bundle_sigs[i].version;
55
+ return 0;
56
+ }
57
+ }
58
+ return -1;
59
}
60
61
static int parse_bundle_header(int fd, struct bundle_header *header,
66
67
/* The bundle header begins with the signature */
68
if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
45
- strcmp(buf.buf, bundle_signature)) {
69
+ parse_bundle_signature(header, buf.buf)) {
70
if (report_path)
47
- error(_("'%s' does not look like a v2 bundle file"),
71
+ error(_("'%s' does not look like a v2 or v3 bundle file"),
72
report_path);
73
status = -1;
74
goto abort;
75
}
76
77
+ header->hash_algo = the_hash_algo;
78
+
79
/* The bundle header ends with an empty line */
80
while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
81
buf.len && buf.buf[0] != '\n') {
83
int is_prereq = 0;
84
const char *p;
85
60
- if (*buf.buf == '-') {
61
- is_prereq = 1;
62
- strbuf_remove(&buf, 0, 1);
63
- }
86
strbuf_rtrim(&buf);
87
66
- if (!header->hash_algo) {
67
- header->hash_algo = detect_hash_algo(&buf);
68
- if (!header->hash_algo) {
69
- error(_("unknown hash algorithm length"));
88
+ if (header->version == 3 && *buf.buf == '@') {
89
+ if (parse_capability(header, buf.buf + 1)) {
90
status = -1;
91
break;
92
}
93
+ continue;
94
+ }
95
+
96
+ if (*buf.buf == '-') {
97
+ is_prereq = 1;
98
+ strbuf_remove(&buf, 0, 1);
99
}
100
101
/*
475
}
476
477
int create_bundle(struct repository *r, const char *path,
452
- int argc, const char **argv, struct argv_array *pack_options)
478
+ int argc, const char **argv, struct argv_array *pack_options, int version)
479
{
480
struct lock_file lock = LOCK_INIT;
481
int bundle_fd = -1;
482
int bundle_to_stdout;
483
int ref_count = 0;
484
struct rev_info revs;
485
+ int min_version = the_hash_algo == &hash_algos[GIT_HASH_SHA1] ? 2 : 3;
486
487
bundle_to_stdout = !strcmp(path, "-");
488
if (bundle_to_stdout)
491
bundle_fd = hold_lock_file_for_update(&lock, path,
492
LOCK_DIE_ON_ERROR);
493
467
- /* write signature */
468
- write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
494
+ if (version == -1)
495
+ version = min_version;
496
+
497
+ if (version < 2 || version > 3) {
498
+ die(_("unsupported bundle version %d"), version);
499
+ } else if (version < min_version) {
500
+ die(_("cannot write bundle version %d with algorithm %s"), version, the_hash_algo->name);
501
+ } else if (version == 2) {
502
+ write_or_die(bundle_fd, v2_bundle_signature, strlen(v2_bundle_signature));
503
+ } else {
504
+ const char *capability = "@object-format=";
505
+ write_or_die(bundle_fd, v3_bundle_signature, strlen(v3_bundle_signature));
506
+ write_or_die(bundle_fd, capability, strlen(capability));
507
+ write_or_die(bundle_fd, the_hash_algo->name, strlen(the_hash_algo->name));
508
+ write_or_die(bundle_fd, "\n", 1);
509
+ }
510
511
/* init revs to list objects for pack-objects later */
512
save_commit_buffer = 0;