Skip to content
/ git Public
forked from git/git

Commit e0ad957

Browse files
committed
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 ...
2 parents 4f0a8be + e023ff0 commit e0ad957

File tree

74 files changed

+633
-351
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+633
-351
lines changed

Documentation/config.txt

+2
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ include::config/diff.txt[]
348348

349349
include::config/difftool.txt[]
350350

351+
include::config/extensions.txt[]
352+
351353
include::config/fastimport.txt[]
352354

353355
include::config/feature.txt[]

Documentation/config/extensions.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
extensions.objectFormat::
2+
Specify the hash algorithm to use. The acceptable values are `sha1` and
3+
`sha256`. If not specified, `sha1` is assumed. It is an error to specify
4+
this key unless `core.repositoryFormatVersion` is 1.
5+
+
6+
Note that this setting should only be set by linkgit:git-init[1] or
7+
linkgit:git-clone[1]. Trying to change it after initialization will not
8+
work and will produce hard-to-diagnose issues.

Documentation/git-bundle.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ git-bundle - Move objects and refs by archive
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied] <file> <git-rev-list-args>
12+
'git bundle' create [-q | --quiet | --progress | --all-progress] [--all-progress-implied]
13+
[--version=<version>] <file> <git-rev-list-args>
1314
'git bundle' verify [-q | --quiet] <file>
1415
'git bundle' list-heads <file> [<refname>...]
1516
'git bundle' unbundle <file> [<refname>...]
@@ -102,6 +103,12 @@ unbundle <file>::
102103
is activated. Unlike --all-progress this flag doesn't actually
103104
force any progress display by itself.
104105

106+
--version=<version>::
107+
Specify the bundle version. Version 2 is the older format and can only be
108+
used with SHA-1 repositories; the newer version 3 contains capabilities that
109+
permit extensions. The default is the oldest supported format, based on the
110+
hash algorithm in use.
111+
105112
-q::
106113
--quiet::
107114
This flag makes the command not to report its progress

Documentation/technical/bundle-format.txt

+29-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ The Git bundle format is a format that represents both refs and Git objects.
77
We will use ABNF notation to define the Git bundle format. See
88
protocol-common.txt for the details.
99

10+
A v2 bundle looks like this:
11+
1012
----
1113
bundle = signature *prerequisite *reference LF pack
1214
signature = "# v2 git bundle" LF
@@ -18,9 +20,28 @@ reference = obj-id SP refname LF
1820
pack = ... ; packfile
1921
----
2022

23+
A v3 bundle looks like this:
24+
25+
----
26+
bundle = signature *capability *prerequisite *reference LF pack
27+
signature = "# v3 git bundle" LF
28+
29+
capability = "@" key ["=" value] LF
30+
prerequisite = "-" obj-id SP comment LF
31+
comment = *CHAR
32+
reference = obj-id SP refname LF
33+
key = 1*(ALPHA / DIGIT / "-")
34+
value = *(%01-09 / %0b-FF)
35+
36+
pack = ... ; packfile
37+
----
38+
2139
== Semantics
2240

23-
A Git bundle consists of three parts.
41+
A Git bundle consists of several parts.
42+
43+
* "Capabilities", which are only in the v3 format, indicate functionality that
44+
the bundle requires to be read properly.
2445

2546
* "Prerequisites" lists the objects that are NOT included in the bundle and the
2647
reader of the bundle MUST already have, in order to use the data in the
@@ -46,3 +67,10 @@ put any string here. The reader of the bundle MUST ignore the comment.
4667
Note that the prerequisites does not represent a shallow-clone boundary. The
4768
semantics of the prerequisites and the shallow-clone boundaries are different,
4869
and the Git bundle v2 format cannot represent a shallow clone repository.
70+
71+
== Capabilities
72+
73+
Because there is no opportunity for negotiation, unknown capabilities cause 'git
74+
bundle' to abort. The only known capability is `object-format`, which specifies
75+
the hash algorithm in use, and can take the same values as the
76+
`extensions.objectFormat` configuration value.

builtin/bundle.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
6060
int all_progress_implied = 0;
6161
int progress = isatty(STDERR_FILENO);
6262
struct strvec pack_opts;
63+
int version = -1;
6364

6465
struct option options[] = {
6566
OPT_SET_INT('q', "quiet", &progress,
@@ -71,6 +72,8 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
7172
OPT_BOOL(0, "all-progress-implied",
7273
&all_progress_implied,
7374
N_("similar to --all-progress when progress meter is shown")),
75+
OPT_INTEGER(0, "version", &version,
76+
N_("specify bundle format version")),
7477
OPT_END()
7578
};
7679
const char* bundle_file;
@@ -91,7 +94,7 @@ static int cmd_bundle_create(int argc, const char **argv, const char *prefix) {
9194

9295
if (!startup_info->have_repository)
9396
die(_("Need a repository to create a bundle."));
94-
return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts);
97+
return !!create_bundle(the_repository, bundle_file, argc, argv, &pack_opts, version);
9598
}
9699

97100
static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {

builtin/init-db.c

-5
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,6 @@ void initialize_repository_version(int hash_algo)
183183
char repo_version_string[10];
184184
int repo_version = GIT_REPO_VERSION;
185185

186-
#ifndef ENABLE_SHA256
187-
if (hash_algo != GIT_HASH_SHA1)
188-
die(_("The hash algorithm %s is not supported in this build."), hash_algos[hash_algo].name);
189-
#endif
190-
191186
if (hash_algo != GIT_HASH_SHA1)
192187
repo_version = GIT_REPO_VERSION_READ;
193188

builtin/verify-pack.c

+15-8
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,26 @@
77
#define VERIFY_PACK_VERBOSE 01
88
#define VERIFY_PACK_STAT_ONLY 02
99

10-
static int verify_one_pack(const char *path, unsigned int flags)
10+
static int verify_one_pack(const char *path, unsigned int flags, const char *hash_algo)
1111
{
1212
struct child_process index_pack = CHILD_PROCESS_INIT;
13-
const char *argv[] = {"index-pack", NULL, NULL, NULL };
13+
struct strvec *argv = &index_pack.args;
1414
struct strbuf arg = STRBUF_INIT;
1515
int verbose = flags & VERIFY_PACK_VERBOSE;
1616
int stat_only = flags & VERIFY_PACK_STAT_ONLY;
1717
int err;
1818

19+
strvec_push(argv, "index-pack");
20+
1921
if (stat_only)
20-
argv[1] = "--verify-stat-only";
22+
strvec_push(argv, "--verify-stat-only");
2123
else if (verbose)
22-
argv[1] = "--verify-stat";
24+
strvec_push(argv, "--verify-stat");
2325
else
24-
argv[1] = "--verify";
26+
strvec_push(argv, "--verify");
27+
28+
if (hash_algo)
29+
strvec_pushf(argv, "--object-format=%s", hash_algo);
2530

2631
/*
2732
* In addition to "foo.pack" we accept "foo.idx" and "foo";
@@ -31,9 +36,8 @@ static int verify_one_pack(const char *path, unsigned int flags)
3136
if (strbuf_strip_suffix(&arg, ".idx") ||
3237
!ends_with(arg.buf, ".pack"))
3338
strbuf_addstr(&arg, ".pack");
34-
argv[2] = arg.buf;
39+
strvec_push(argv, arg.buf);
3540

36-
index_pack.argv = argv;
3741
index_pack.git_cmd = 1;
3842

3943
err = run_command(&index_pack);
@@ -60,12 +64,15 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
6064
{
6165
int err = 0;
6266
unsigned int flags = 0;
67+
const char *object_format = NULL;
6368
int i;
6469
const struct option verify_pack_options[] = {
6570
OPT_BIT('v', "verbose", &flags, N_("verbose"),
6671
VERIFY_PACK_VERBOSE),
6772
OPT_BIT('s', "stat-only", &flags, N_("show statistics only"),
6873
VERIFY_PACK_STAT_ONLY),
74+
OPT_STRING(0, "object-format", &object_format, N_("hash"),
75+
N_("specify the hash algorithm to use")),
6976
OPT_END()
7077
};
7178

@@ -75,7 +82,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
7582
if (argc < 1)
7683
usage_with_options(verify_pack_usage, verify_pack_options);
7784
for (i = 0; i < argc; i++) {
78-
if (verify_one_pack(argv[i], flags))
85+
if (verify_one_pack(argv[i], flags, object_format))
7986
err = 1;
8087
}
8188

bundle.c

+62-21
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@
1212
#include "refs.h"
1313
#include "strvec.h"
1414

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+
};
1625

1726
static void add_to_ref_list(const struct object_id *oid, const char *name,
1827
struct ref_list *list)
@@ -23,15 +32,30 @@ static void add_to_ref_list(const struct object_id *oid, const char *name,
2332
list->nr++;
2433
}
2534

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)
2749
{
28-
size_t len = strcspn(buf->buf, " \n");
29-
int algo;
50+
int i;
3051

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;
3559
}
3660

3761
static int parse_bundle_header(int fd, struct bundle_header *header,
@@ -42,34 +66,36 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
4266

4367
/* The bundle header begins with the signature */
4468
if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
45-
strcmp(buf.buf, bundle_signature)) {
69+
parse_bundle_signature(header, buf.buf)) {
4670
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"),
4872
report_path);
4973
status = -1;
5074
goto abort;
5175
}
5276

77+
header->hash_algo = the_hash_algo;
78+
5379
/* The bundle header ends with an empty line */
5480
while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
5581
buf.len && buf.buf[0] != '\n') {
5682
struct object_id oid;
5783
int is_prereq = 0;
5884
const char *p;
5985

60-
if (*buf.buf == '-') {
61-
is_prereq = 1;
62-
strbuf_remove(&buf, 0, 1);
63-
}
6486
strbuf_rtrim(&buf);
6587

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)) {
7090
status = -1;
7191
break;
7292
}
93+
continue;
94+
}
95+
96+
if (*buf.buf == '-') {
97+
is_prereq = 1;
98+
strbuf_remove(&buf, 0, 1);
7399
}
74100

75101
/*
@@ -449,13 +475,14 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
449475
}
450476

451477
int create_bundle(struct repository *r, const char *path,
452-
int argc, const char **argv, struct strvec *pack_options)
478+
int argc, const char **argv, struct strvec *pack_options, int version)
453479
{
454480
struct lock_file lock = LOCK_INIT;
455481
int bundle_fd = -1;
456482
int bundle_to_stdout;
457483
int ref_count = 0;
458484
struct rev_info revs;
485+
int min_version = the_hash_algo == &hash_algos[GIT_HASH_SHA1] ? 2 : 3;
459486

460487
bundle_to_stdout = !strcmp(path, "-");
461488
if (bundle_to_stdout)
@@ -464,8 +491,22 @@ int create_bundle(struct repository *r, const char *path,
464491
bundle_fd = hold_lock_file_for_update(&lock, path,
465492
LOCK_DIE_ON_ERROR);
466493

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+
}
469510

470511
/* init revs to list objects for pack-objects later */
471512
save_commit_buffer = 0;

bundle.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct ref_list {
1313
};
1414

1515
struct bundle_header {
16+
unsigned version;
1617
struct ref_list prerequisites;
1718
struct ref_list references;
1819
const struct git_hash_algo *hash_algo;
@@ -21,7 +22,8 @@ struct bundle_header {
2122
int is_bundle(const char *path, int quiet);
2223
int read_bundle_header(const char *path, struct bundle_header *header);
2324
int create_bundle(struct repository *r, const char *path,
24-
int argc, const char **argv, struct strvec *pack_options);
25+
int argc, const char **argv, struct strvec *pack_options,
26+
int version);
2527
int verify_bundle(struct repository *r, struct bundle_header *header, int verbose);
2628
#define BUNDLE_VERBOSE 1
2729
int unbundle(struct repository *r, struct bundle_header *header,

ci/run-build-and-tests.sh

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ linux-gcc)
2424
export GIT_TEST_ADD_I_USE_BUILTIN=1
2525
make test
2626
;;
27+
linux-clang)
28+
export GIT_TEST_DEFAULT_HASH=sha1
29+
make test
30+
export GIT_TEST_DEFAULT_HASH=sha256
31+
make test
32+
;;
2733
linux-gcc-4.8)
2834
# Don't run the tests; we only care about whether Git can be
2935
# built with GCC 4.8, as it errors out on some undesired (C99)

config.mak.dev

-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ DEVELOPER_CFLAGS += -Wstrict-prototypes
1616
DEVELOPER_CFLAGS += -Wunused
1717
DEVELOPER_CFLAGS += -Wvla
1818

19-
DEVELOPER_CFLAGS += -DENABLE_SHA256
20-
2119
ifndef COMPILER_FEATURES
2220
COMPILER_FEATURES := $(shell ./detect-compiler $(CC))
2321
endif

0 commit comments

Comments
 (0)