Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2020-08-12 04:04:11 +0300
committerJunio C Hamano <gitster@pobox.com>2020-08-12 04:04:11 +0300
commite0ad9574ddf5bb14d9ed6808112485ce0da99fea (patch)
tree633eb1867a929588ec5b3d8af351a93ba62aac5a /bundle.c
parent4f0a8be78499454eac3985b6e7e144b8376ab0a5 (diff)
parente023ff0691ca207d421a0e75ea23c132ada9142a (diff)
Merge branch 'bc/sha-256-part-3'
The final leg of SHA-256 transition. * bc/sha-256-part-3: (39 commits) t: remove test_oid_init in tests docs: add documentation for extensions.objectFormat ci: run tests with SHA-256 t: make SHA1 prerequisite depend on default hash t: allow testing different hash algorithms via environment t: add test_oid option to select hash algorithm repository: enable SHA-256 support by default setup: add support for reading extensions.objectformat bundle: add new version for use with SHA-256 builtin/verify-pack: implement an --object-format option http-fetch: set up git directory before parsing pack hashes t0410: mark test with SHA1 prerequisite t5308: make test work with SHA-256 t9700: make hash size independent t9500: ensure that algorithm info is preserved in config t9350: make hash size independent t9301: make hash size independent t9300: use $ZERO_OID instead of hard-coded object ID t9300: abstract away SHA-1-specific constants t8011: make hash size independent ...
Diffstat (limited to 'bundle.c')
-rw-r--r--bundle.c83
1 files changed, 62 insertions, 21 deletions
diff --git a/bundle.c b/bundle.c
index 7ef9c3a7c3..995a940dfd 100644
--- a/bundle.c
+++ b/bundle.c
@@ -12,7 +12,16 @@
#include "refs.h"
#include "strvec.h"
-static const char bundle_signature[] = "# v2 git bundle\n";
+
+static const char v2_bundle_signature[] = "# v2 git bundle\n";
+static const char v3_bundle_signature[] = "# v3 git bundle\n";
+static struct {
+ int version;
+ const char *signature;
+} bundle_sigs[] = {
+ { 2, v2_bundle_signature },
+ { 3, v3_bundle_signature },
+};
static void add_to_ref_list(const struct object_id *oid, const char *name,
struct ref_list *list)
@@ -23,15 +32,30 @@ static void add_to_ref_list(const struct object_id *oid, const char *name,
list->nr++;
}
-static const struct git_hash_algo *detect_hash_algo(struct strbuf *buf)
+static int parse_capability(struct bundle_header *header, const char *capability)
+{
+ const char *arg;
+ if (skip_prefix(capability, "object-format=", &arg)) {
+ int algo = hash_algo_by_name(arg);
+ if (algo == GIT_HASH_UNKNOWN)
+ return error(_("unrecognized bundle hash algorithm: %s"), arg);
+ header->hash_algo = &hash_algos[algo];
+ return 0;
+ }
+ return error(_("unknown capability '%s'"), capability);
+}
+
+static int parse_bundle_signature(struct bundle_header *header, const char *line)
{
- size_t len = strcspn(buf->buf, " \n");
- int algo;
+ int i;
- algo = hash_algo_by_length(len / 2);
- if (algo == GIT_HASH_UNKNOWN)
- return NULL;
- return &hash_algos[algo];
+ for (i = 0; i < ARRAY_SIZE(bundle_sigs); i++) {
+ if (!strcmp(line, bundle_sigs[i].signature)) {
+ header->version = bundle_sigs[i].version;
+ return 0;
+ }
+ }
+ return -1;
}
static int parse_bundle_header(int fd, struct bundle_header *header,
@@ -42,14 +66,16 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
/* The bundle header begins with the signature */
if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
- strcmp(buf.buf, bundle_signature)) {
+ parse_bundle_signature(header, buf.buf)) {
if (report_path)
- error(_("'%s' does not look like a v2 bundle file"),
+ error(_("'%s' does not look like a v2 or v3 bundle file"),
report_path);
status = -1;
goto abort;
}
+ header->hash_algo = the_hash_algo;
+
/* The bundle header ends with an empty line */
while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
buf.len && buf.buf[0] != '\n') {
@@ -57,19 +83,19 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
int is_prereq = 0;
const char *p;
- if (*buf.buf == '-') {
- is_prereq = 1;
- strbuf_remove(&buf, 0, 1);
- }
strbuf_rtrim(&buf);
- if (!header->hash_algo) {
- header->hash_algo = detect_hash_algo(&buf);
- if (!header->hash_algo) {
- error(_("unknown hash algorithm length"));
+ if (header->version == 3 && *buf.buf == '@') {
+ if (parse_capability(header, buf.buf + 1)) {
status = -1;
break;
}
+ continue;
+ }
+
+ if (*buf.buf == '-') {
+ is_prereq = 1;
+ strbuf_remove(&buf, 0, 1);
}
/*
@@ -449,13 +475,14 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
}
int create_bundle(struct repository *r, const char *path,
- int argc, const char **argv, struct strvec *pack_options)
+ int argc, const char **argv, struct strvec *pack_options, int version)
{
struct lock_file lock = LOCK_INIT;
int bundle_fd = -1;
int bundle_to_stdout;
int ref_count = 0;
struct rev_info revs;
+ int min_version = the_hash_algo == &hash_algos[GIT_HASH_SHA1] ? 2 : 3;
bundle_to_stdout = !strcmp(path, "-");
if (bundle_to_stdout)
@@ -464,8 +491,22 @@ int create_bundle(struct repository *r, const char *path,
bundle_fd = hold_lock_file_for_update(&lock, path,
LOCK_DIE_ON_ERROR);
- /* write signature */
- write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
+ if (version == -1)
+ version = min_version;
+
+ if (version < 2 || version > 3) {
+ die(_("unsupported bundle version %d"), version);
+ } else if (version < min_version) {
+ die(_("cannot write bundle version %d with algorithm %s"), version, the_hash_algo->name);
+ } else if (version == 2) {
+ write_or_die(bundle_fd, v2_bundle_signature, strlen(v2_bundle_signature));
+ } else {
+ const char *capability = "@object-format=";
+ write_or_die(bundle_fd, v3_bundle_signature, strlen(v3_bundle_signature));
+ write_or_die(bundle_fd, capability, strlen(capability));
+ write_or_die(bundle_fd, the_hash_algo->name, strlen(the_hash_algo->name));
+ write_or_die(bundle_fd, "\n", 1);
+ }
/* init revs to list objects for pack-objects later */
save_commit_buffer = 0;