Skip to content

Commit faa6d83

Browse files
committed
Merge branch 'bc/sha-256-part-1-of-4' into pu
* bc/sha-256-part-1-of-4: (24 commits) fast-import: add options for rewriting submodules fast-import: add a generic function to iterate over marks fast-import: make find_marks work on any mark set fast-import: add helper function for inserting mark object entries fast-import: permit reading multiple marks files tag: store SHA-256 signatures in a header gpg-interface: improve interface for parsing tags commit: use expected signature header for SHA-256 worktree: allow repository version 1 init-db: move writing repo version into a function builtin/init-db: add environment variable for new repo hash builtin/init-db: allow specifying hash algorithm on command line setup: allow check_repository_format to read repository format t/helper: make repository tests hash independent t/helper: initialize repository if necessary t/helper/test-dump-split-index: initialize git repository t6300: make hash algorithm independent t6300: abstract away SHA-1-specific constants t: use hash-specific lookup tables to define test constants repository: require a build flag to use SHA-256 ...
2 parents 4dab768 + e8356e2 commit faa6d83

Some content is hidden

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

41 files changed

+809
-196
lines changed

Documentation/git-fast-import.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ Locations of Marks Files
122122
Relative and non-relative marks may be combined by interweaving
123123
--(no-)-relative-marks with the --(import|export)-marks= options.
124124

125+
Submodule Rewriting
126+
~~~~~~~~~~~~~~~~~~~
127+
128+
--rewrite-submodules-from=<name>:<file>::
129+
--rewrite-submodules-to=<name>:<file>::
130+
Rewrite the object IDs for the submodule specified by <name> from the values
131+
used in the from <file> to those used in the to <file>. The from marks should
132+
have been created by `git fast-export`, and the to marks should have been
133+
created by `git fast-import` when importing that same submodule.
134+
+
135+
<name> may be any arbitrary string not containing a colon character, but the
136+
same value must be used with both options when specifying corresponding marks.
137+
Multiple submodules may be specified with different values for <name>. It is an
138+
error not to use these options in corresponding pairs.
139+
+
140+
These options are primarily useful when converting a repository from one hash
141+
algorithm to another; without them, fast-import will fail if it encounters a
142+
submodule because it has no way of writing the object ID into the new hash
143+
algorithm.
144+
125145
Performance and Compression Tuning
126146
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127147

Documentation/git-init.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SYNOPSIS
1010
--------
1111
[verse]
1212
'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
13-
[--separate-git-dir <git dir>]
13+
[--separate-git-dir <git dir>] [--object-format=<format]
1414
[--shared[=<permissions>]] [directory]
1515

1616

@@ -48,6 +48,11 @@ Only print error and warning messages; all other output will be suppressed.
4848
Create a bare repository. If `GIT_DIR` environment is not set, it is set to the
4949
current working directory.
5050

51+
--object-format=<format>::
52+
53+
Specify the given object format (hash algorithm) for the repository. The valid
54+
values are 'sha1' and (if enabled) 'sha256'. 'sha1' is the default.
55+
5156
--template=<template_directory>::
5257

5358
Specify the directory from which templates will be used. (See the "TEMPLATE

Documentation/git.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,12 @@ double-quotes and respecting backslash escapes. E.g., the value
493493
details. This variable has lower precedence than other path
494494
variables such as GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY...
495495

496+
`GIT_DEFAULT_HASH_ALGORITHM`::
497+
If this variable is set, the default hash algorithm for new
498+
repositories will be set to this value. This value is currently
499+
ignored when cloning; the setting of the remote repository
500+
is used instead. The default is "sha1".
501+
496502
Git Commits
497503
~~~~~~~~~~~
498504
`GIT_AUTHOR_NAME`::

builtin/clone.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11021102
}
11031103
}
11041104

1105-
init_db(git_dir, real_git_dir, option_template, INIT_DB_QUIET);
1105+
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, INIT_DB_QUIET);
11061106

11071107
if (real_git_dir)
11081108
git_dir = real_git_dir;

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16911691
}
16921692

16931693
if (amend) {
1694-
const char *exclude_gpgsig[2] = { "gpgsig", NULL };
1694+
const char *exclude_gpgsig[3] = { "gpgsig", "gpgsig-sha256", NULL };
16951695
extra = read_commit_extra_headers(current_head, exclude_gpgsig);
16961696
} else {
16971697
struct commit_extra_header **tail = &extra;

builtin/fmt-merge-msg.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ static void fmt_tag_signature(struct strbuf *tagbuf,
472472
const char *buf,
473473
unsigned long len)
474474
{
475+
475476
const char *tag_body = strstr(buf, "\n\n");
476477
if (tag_body) {
477478
tag_body += 2;
@@ -492,24 +493,31 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
492493
for (i = 0; i < origins.nr; i++) {
493494
struct object_id *oid = origins.items[i].util;
494495
enum object_type type;
495-
unsigned long size, len;
496-
char *buf = read_object_file(oid, &type, &size);
496+
unsigned long size;
497+
char *buf = read_object_file(oid, &type, &size), *orig = buf;
497498
struct signature_check sigc = { 0 };
499+
struct strbuf payload = STRBUF_INIT;
500+
struct strbuf signature = STRBUF_INIT;
498501
struct strbuf sig = STRBUF_INIT;
502+
size_t len = size;
499503

500504
if (!buf || type != OBJ_TAG)
501505
goto next;
502-
len = parse_signature(buf, size);
503-
504-
if (size == len)
505-
; /* merely annotated */
506-
else if (!check_signature(buf, len, buf + len, size - len,
506+
if (!parse_signature(buf, size, &payload, &signature))
507+
len = size; /* merely annotated */
508+
else if (!check_signature(payload.buf, payload.len,
509+
signature.buf, signature.len,
507510
&sigc)) {
508511
strbuf_addstr(&sig, sigc.gpg_output);
509512
signature_check_clear(&sigc);
510513
} else
511514
strbuf_addstr(&sig, "gpg verification failed.\n");
512515

516+
if (payload.len) {
517+
buf = payload.buf;
518+
len = payload.len;
519+
}
520+
513521
if (!tag_number++) {
514522
fmt_tag_signature(&tagbuf, &sig, buf, len);
515523
first_tag = i;
@@ -531,8 +539,10 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
531539
fmt_tag_signature(&tagbuf, &sig, buf, len);
532540
}
533541
strbuf_release(&sig);
542+
strbuf_release(&payload);
543+
strbuf_release(&signature);
534544
next:
535-
free(buf);
545+
free(orig);
536546
}
537547
if (tagbuf.len) {
538548
strbuf_addch(out, '\n');

builtin/init-db.c

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define TEST_FILEMODE 1
2121
#endif
2222

23+
#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
24+
2325
static int init_is_bare_repository = 0;
2426
static int init_shared_repository = -1;
2527
static const char *init_db_template_dir;
@@ -176,13 +178,36 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree)
176178
return 1;
177179
}
178180

181+
void initialize_repository_version(int hash_algo)
182+
{
183+
char repo_version_string[10];
184+
int repo_version = GIT_REPO_VERSION;
185+
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+
191+
if (hash_algo != GIT_HASH_SHA1)
192+
repo_version = GIT_REPO_VERSION_READ;
193+
194+
/* This forces creation of new config file */
195+
xsnprintf(repo_version_string, sizeof(repo_version_string),
196+
"%d", repo_version);
197+
git_config_set("core.repositoryformatversion", repo_version_string);
198+
199+
if (hash_algo != GIT_HASH_SHA1)
200+
git_config_set("extensions.objectformat",
201+
hash_algos[hash_algo].name);
202+
}
203+
179204
static int create_default_files(const char *template_path,
180-
const char *original_git_dir)
205+
const char *original_git_dir,
206+
const struct repository_format *fmt)
181207
{
182208
struct stat st1;
183209
struct strbuf buf = STRBUF_INIT;
184210
char *path;
185-
char repo_version_string[10];
186211
char junk[2];
187212
int reinit;
188213
int filemode;
@@ -244,10 +269,7 @@ static int create_default_files(const char *template_path,
244269
exit(1);
245270
}
246271

247-
/* This forces creation of new config file */
248-
xsnprintf(repo_version_string, sizeof(repo_version_string),
249-
"%d", GIT_REPO_VERSION);
250-
git_config_set("core.repositoryformatversion", repo_version_string);
272+
initialize_repository_version(fmt->hash_algo);
251273

252274
/* Check filemode trustability */
253275
path = git_path_buf(&buf, "config");
@@ -340,12 +362,33 @@ static void separate_git_dir(const char *git_dir, const char *git_link)
340362
write_file(git_link, "gitdir: %s", git_dir);
341363
}
342364

365+
static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash)
366+
{
367+
const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
368+
/*
369+
* If we already have an initialized repo, don't allow the user to
370+
* specify a different algorithm, as that could cause corruption.
371+
* Otherwise, if the user has specified one on the command line, use it.
372+
*/
373+
if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
374+
die(_("attempt to reinitialize repository with different hash"));
375+
else if (hash != GIT_HASH_UNKNOWN)
376+
repo_fmt->hash_algo = hash;
377+
else if (env) {
378+
int env_algo = hash_algo_by_name(env);
379+
if (env_algo == GIT_HASH_UNKNOWN)
380+
die(_("unknown hash algorithm '%s'"), env);
381+
repo_fmt->hash_algo = env_algo;
382+
}
383+
}
384+
343385
int init_db(const char *git_dir, const char *real_git_dir,
344-
const char *template_dir, unsigned int flags)
386+
const char *template_dir, int hash, unsigned int flags)
345387
{
346388
int reinit;
347389
int exist_ok = flags & INIT_DB_EXIST_OK;
348390
char *original_git_dir = real_pathdup(git_dir, 1);
391+
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
349392

350393
if (real_git_dir) {
351394
struct stat st;
@@ -378,9 +421,11 @@ int init_db(const char *git_dir, const char *real_git_dir,
378421
* config file, so this will not fail. What we are catching
379422
* is an attempt to reinitialize new repository with an old tool.
380423
*/
381-
check_repository_format();
424+
check_repository_format(&repo_fmt);
382425

383-
reinit = create_default_files(template_dir, original_git_dir);
426+
validate_hash_algorithm(&repo_fmt, hash);
427+
428+
reinit = create_default_files(template_dir, original_git_dir, &repo_fmt);
384429

385430
create_object_directory();
386431

@@ -482,6 +527,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
482527
const char *work_tree;
483528
const char *template_dir = NULL;
484529
unsigned int flags = 0;
530+
const char *object_format = NULL;
531+
int hash_algo = GIT_HASH_UNKNOWN;
485532
const struct option init_db_options[] = {
486533
OPT_STRING(0, "template", &template_dir, N_("template-directory"),
487534
N_("directory from which templates will be used")),
@@ -494,6 +541,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
494541
OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
495542
OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
496543
N_("separate git dir from working tree")),
544+
OPT_STRING(0, "object-format", &object_format, N_("hash"),
545+
N_("specify the hash algorithm to use")),
497546
OPT_END()
498547
};
499548

@@ -546,6 +595,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
546595
free(cwd);
547596
}
548597

598+
if (object_format) {
599+
hash_algo = hash_algo_by_name(object_format);
600+
if (hash_algo == GIT_HASH_UNKNOWN)
601+
die(_("unknown hash algorithm '%s'"), object_format);
602+
}
603+
549604
if (init_shared_repository != -1)
550605
set_shared_repository(init_shared_repository);
551606

@@ -597,5 +652,5 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
597652
UNLEAK(work_tree);
598653

599654
flags |= INIT_DB_EXIST_OK;
600-
return init_db(git_dir, real_git_dir, template_dir, flags);
655+
return init_db(git_dir, real_git_dir, template_dir, hash_algo, flags);
601656
}

builtin/mktag.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@ static int verify_tag(char *buffer, unsigned long size)
144144
(uintmax_t) (tagger_line - buffer));
145145
tagger_line += 6;
146146

147+
if (hash_algo_by_ptr(the_hash_algo) == GIT_HASH_SHA256 &&
148+
!memcmp(tagger_line, "gpgsig-sha256 ", 14)) {
149+
char *p = strpbrk(tagger_line + 1, "\n");
150+
if (!p)
151+
return error("char%"PRIuMAX": could not find end of line",
152+
(uintmax_t) (tagger_line - buffer));
153+
tagger_line = p + 1;
154+
while (*tagger_line == ' ' && (p = strpbrk(tagger_line, "\n")))
155+
tagger_line = p + 1;
156+
if (!p)
157+
return error("char%"PRIuMAX": could not find end of line",
158+
(uintmax_t) (tagger_line - buffer));
159+
}
160+
147161
/* Verify the blank line separating the header from the body */
148162
if (*tagger_line != '\n')
149163
return error("char%"PRIuMAX": trailing garbage in tag header",

builtin/pack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ static void write_reused_pack_one(size_t pos, struct hashfile *out,
880880
len = encode_in_pack_object_header(header, sizeof(header),
881881
OBJ_REF_DELTA, size);
882882
hashwrite(out, header, len);
883-
hashwrite(out, base_oid.hash, 20);
883+
hashwrite(out, base_oid.hash, the_hash_algo->rawsz);
884884
copy_pack_data(out, reuse_packfile, w_curs, cur, next - cur);
885885
return;
886886
}

builtin/receive-pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ static void prepare_push_cert_sha1(struct child_process *proc)
637637

638638
memset(&sigcheck, '\0', sizeof(sigcheck));
639639

640-
bogs = parse_signature(push_cert.buf, push_cert.len);
640+
bogs = parse_signed_buffer(push_cert.buf, push_cert.len);
641641
check_signature(push_cert.buf, bogs, push_cert.buf + bogs,
642642
push_cert.len - bogs, &sigcheck);
643643

@@ -1570,7 +1570,7 @@ static void queue_commands_from_cert(struct command **tail,
15701570
die("malformed push certificate %.*s", 100, push_cert->buf);
15711571
else
15721572
boc += 2;
1573-
eoc = push_cert->buf + parse_signature(push_cert->buf, push_cert->len);
1573+
eoc = push_cert->buf + parse_signed_buffer(push_cert->buf, push_cert->len);
15741574

15751575
while (boc < eoc) {
15761576
const char *eol = memchr(boc, '\n', eoc - boc);

builtin/tag.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ static int verify_tag(const char *name, const char *ref,
128128

129129
static int do_sign(struct strbuf *buffer)
130130
{
131-
return sign_buffer(buffer, buffer, get_signing_key());
131+
if (hash_algo_by_ptr(the_hash_algo) == GIT_HASH_SHA1)
132+
return sign_buffer(buffer, buffer, get_signing_key());
133+
return sign_with_header(buffer, get_signing_key());
132134
}
133135

134136
static const char tag_template[] =
@@ -174,11 +176,17 @@ static void write_tag_body(int fd, const struct object_id *oid)
174176
{
175177
unsigned long size;
176178
enum object_type type;
177-
char *buf, *sp;
179+
char *buf, *sp, *orig;
180+
struct strbuf payload = STRBUF_INIT;
181+
struct strbuf signature = STRBUF_INIT;
178182

179-
buf = read_object_file(oid, &type, &size);
183+
orig = buf = read_object_file(oid, &type, &size);
180184
if (!buf)
181185
return;
186+
if (parse_signature(buf, size, &payload, &signature)) {
187+
buf = payload.buf;
188+
size = payload.len;
189+
}
182190
/* skip header */
183191
sp = strstr(buf, "\n\n");
184192

@@ -187,9 +195,11 @@ static void write_tag_body(int fd, const struct object_id *oid)
187195
return;
188196
}
189197
sp += 2; /* skip the 2 LFs */
190-
write_or_die(fd, sp, parse_signature(sp, buf + size - sp));
198+
write_or_die(fd, sp, buf + size - sp);
191199

192-
free(buf);
200+
free(orig);
201+
strbuf_release(&payload);
202+
strbuf_release(&signature);
193203
}
194204

195205
static int build_tag_object(struct strbuf *buf, int sign, struct object_id *result)

0 commit comments

Comments
 (0)