Skip to content

Commit

Permalink
Merge branch 'eb/hash-transition'
Browse files Browse the repository at this point in the history
Work to support a repository that work with both SHA-1 and SHA-256
hash algorithms has started.

* eb/hash-transition: (30 commits)
  t1016-compatObjectFormat: add tests to verify the conversion between objects
  t1006: test oid compatibility with cat-file
  t1006: rename sha1 to oid
  test-lib: compute the compatibility hash so tests may use it
  builtin/ls-tree: let the oid determine the output algorithm
  object-file: handle compat objects in check_object_signature
  tree-walk: init_tree_desc take an oid to get the hash algorithm
  builtin/cat-file: let the oid determine the output algorithm
  rev-parse: add an --output-object-format parameter
  repository: implement extensions.compatObjectFormat
  object-file: update object_info_extended to reencode objects
  object-file-convert: convert commits that embed signed tags
  object-file-convert: convert commit objects when writing
  object-file-convert: don't leak when converting tag objects
  object-file-convert: convert tag objects when writing
  object-file-convert: add a function to convert trees between algorithms
  object: factor out parse_mode out of fast-import and tree-walk into in object.h
  cache: add a function to read an OID of a specific algorithm
  tag: sign both hashes
  commit: export add_header_signature to support handling signatures on tags
  ...
  • Loading branch information
gitster committed Mar 28, 2024
2 parents c75fd8d + 7673ecd commit 1002f28
Show file tree
Hide file tree
Showing 62 changed files with 1,844 additions and 349 deletions.
12 changes: 12 additions & 0 deletions Documentation/config/extensions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ Note that this setting should only be set by linkgit:git-init[1] or
linkgit:git-clone[1]. Trying to change it after initialization will not
work and will produce hard-to-diagnose issues.

extensions.compatObjectFormat::

Specify a compatitbility hash algorithm to use. The acceptable values
are `sha1` and `sha256`. The value specified must be different from the
value of extensions.objectFormat. This allows client level
interoperability between git repositories whose objectFormat matches
this compatObjectFormat. In particular when fully implemented the
pushes and pulls from a repository in whose objectFormat matches
compatObjectFormat. As well as being able to use oids encoded in
compatObjectFormat in addition to oids encoded with objectFormat to
locally specify objects.

extensions.refStorage::
Specify the ref storage format to use. The acceptable values are:
+
Expand Down
12 changes: 12 additions & 0 deletions Documentation/git-rev-parse.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,18 @@ for another option.
unfortunately named tag "master"), and shows them as full
refnames (e.g. "refs/heads/master").

--output-object-format=(sha1|sha256|storage)::

Allow oids to be input from any object format that the current
repository supports.

Specifying "sha1" translates if necessary and returns a sha1 oid.

Specifying "sha256" translates if necessary and returns a sha256 oid.

Specifying "storage" translates if necessary and returns an oid in
encoded in the storage hash algorithm.

Options for Objects
~~~~~~~~~~~~~~~~~~~

Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ TEST_BUILTINS_OBJS += test-config.o
TEST_BUILTINS_OBJS += test-crontab.o
TEST_BUILTINS_OBJS += test-csprng.o
TEST_BUILTINS_OBJS += test-date.o
TEST_BUILTINS_OBJS += test-delete-gpgsig.o
TEST_BUILTINS_OBJS += test-delta.o
TEST_BUILTINS_OBJS += test-dir-iterator.o
TEST_BUILTINS_OBJS += test-drop-caches.o
Expand Down Expand Up @@ -1060,6 +1061,7 @@ LIB_OBJS += list-objects-filter.o
LIB_OBJS += list-objects.o
LIB_OBJS += lockfile.o
LIB_OBJS += log-tree.o
LIB_OBJS += loose.o
LIB_OBJS += ls-refs.o
LIB_OBJS += mailinfo.o
LIB_OBJS += mailmap.o
Expand All @@ -1080,6 +1082,7 @@ LIB_OBJS += notes-cache.o
LIB_OBJS += notes-merge.o
LIB_OBJS += notes-utils.o
LIB_OBJS += notes.o
LIB_OBJS += object-file-convert.o
LIB_OBJS += object-file.o
LIB_OBJS += object-name.o
LIB_OBJS += object.o
Expand Down
3 changes: 2 additions & 1 deletion archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ int write_archive_entries(struct archiver_args *args,
opts.src_index = args->repo->index;
opts.dst_index = args->repo->index;
opts.fn = oneway_merge;
init_tree_desc(&t, args->tree->buffer, args->tree->size);
init_tree_desc(&t, &args->tree->object.oid,
args->tree->buffer, args->tree->size);
if (unpack_trees(1, &t, &opts))
return -1;
git_attr_set_direction(GIT_ATTR_INDEX);
Expand Down
6 changes: 3 additions & 3 deletions builtin/am.c
Original file line number Diff line number Diff line change
Expand Up @@ -1994,8 +1994,8 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
opts.fn = twoway_merge;
init_tree_desc(&t[0], head->buffer, head->size);
init_tree_desc(&t[1], remote->buffer, remote->size);
init_tree_desc(&t[0], &head->object.oid, head->buffer, head->size);
init_tree_desc(&t[1], &remote->object.oid, remote->buffer, remote->size);

if (unpack_trees(2, t, &opts)) {
rollback_lock_file(&lock_file);
Expand Down Expand Up @@ -2029,7 +2029,7 @@ static int merge_tree(struct tree *tree)
opts.dst_index = &the_index;
opts.merge = 1;
opts.fn = oneway_merge;
init_tree_desc(&t[0], tree->buffer, tree->size);
init_tree_desc(&t[0], &tree->object.oid, tree->buffer, tree->size);

if (unpack_trees(1, t, &opts)) {
rollback_lock_file(&lock_file);
Expand Down
12 changes: 9 additions & 3 deletions builtin/cat-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
struct object_info oi = OBJECT_INFO_INIT;
struct strbuf sb = STRBUF_INIT;
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
unsigned get_oid_flags = GET_OID_RECORD_PATH | GET_OID_ONLY_TO_DIE;
unsigned get_oid_flags =
GET_OID_RECORD_PATH |
GET_OID_ONLY_TO_DIE |
GET_OID_HASH_ANY;
const char *path = force_path;
const int opt_cw = (opt == 'c' || opt == 'w');
if (!path && opt_cw)
Expand Down Expand Up @@ -226,7 +229,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
die(_("unable to read %s"), oid_to_hex(&oid));

if (!skip_prefix(buffer, "object ", &target) ||
get_oid_hex(target, &blob_oid))
get_oid_hex_algop(target, &blob_oid,
&hash_algos[oid.algo]))
die("%s not a valid tag", oid_to_hex(&oid));
free(buffer);
} else
Expand Down Expand Up @@ -517,7 +521,9 @@ static void batch_one_object(const char *obj_name,
struct expand_data *data)
{
struct object_context ctx;
int flags = opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0;
int flags =
GET_OID_HASH_ANY |
(opt->follow_symlinks ? GET_OID_FOLLOW_SYMLINKS : 0);
enum get_oid_result result;

result = get_oid_with_context(the_repository, obj_name,
Expand Down
8 changes: 5 additions & 3 deletions builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
NULL);
if (parse_tree(tree) < 0)
return 128;
init_tree_desc(&tree_desc, tree->buffer, tree->size);
init_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size);
switch (unpack_trees(1, &tree_desc, &opts)) {
case -2:
*writeout_error = 1;
Expand Down Expand Up @@ -826,11 +826,13 @@ static int merge_working_tree(const struct checkout_opts *opts,
die(_("unable to parse commit %s"),
oid_to_hex(old_commit_oid));

init_tree_desc(&trees[0], tree->buffer, tree->size);
init_tree_desc(&trees[0], &tree->object.oid,
tree->buffer, tree->size);
if (parse_tree(new_tree) < 0)
exit(128);
tree = new_tree;
init_tree_desc(&trees[1], tree->buffer, tree->size);
init_tree_desc(&trees[1], &tree->object.oid,
tree->buffer, tree->size);

ret = unpack_trees(2, trees, &topts);
clear_unpack_trees_porcelain(&topts);
Expand Down
2 changes: 1 addition & 1 deletion builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ static int checkout(int submodule_progress, int filter_submodules)
die(_("unable to parse commit %s"), oid_to_hex(&oid));
if (parse_tree(tree) < 0)
exit(128);
init_tree_desc(&t, tree->buffer, tree->size);
init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts) < 0)
die(_("unable to checkout working tree"));

Expand Down
2 changes: 1 addition & 1 deletion builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ static void create_base_index(const struct commit *current_head)
die(_("failed to unpack HEAD tree object"));
if (parse_tree(tree) < 0)
exit(128);
init_tree_desc(&t, tree->buffer, tree->size);
init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts))
exit(128); /* We've already reported the error, finish dying */
}
Expand Down
18 changes: 2 additions & 16 deletions builtin/fast-import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,20 +1236,6 @@ static void *gfi_unpack_entry(
return unpack_entry(the_repository, p, oe->idx.offset, &type, sizep);
}

static const char *get_mode(const char *str, uint16_t *modep)
{
unsigned char c;
uint16_t mode = 0;

while ((c = *str++) != ' ') {
if (c < '0' || c > '7')
return NULL;
mode = (mode << 3) + (c - '0');
}
*modep = mode;
return str;
}

static void load_tree(struct tree_entry *root)
{
struct object_id *oid = &root->versions[1].oid;
Expand Down Expand Up @@ -1287,7 +1273,7 @@ static void load_tree(struct tree_entry *root)
t->entries[t->entry_count++] = e;

e->tree = NULL;
c = get_mode(c, &e->versions[1].mode);
c = parse_mode(c, &e->versions[1].mode);
if (!c)
die("Corrupt mode in %s", oid_to_hex(oid));
e->versions[0].mode = e->versions[1].mode;
Expand Down Expand Up @@ -2280,7 +2266,7 @@ static void file_change_m(const char *p, struct branch *b)
struct object_id oid;
uint16_t mode, inline_data = 0;

p = get_mode(p, &mode);
p = parse_mode(p, &mode);
if (!p)
die("Corrupt mode: %s", command_buf.buf);
switch (mode) {
Expand Down
8 changes: 4 additions & 4 deletions builtin/grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ static int grep_submodule(struct grep_opt *opt,
strbuf_addstr(&base, filename);
strbuf_addch(&base, '/');

init_tree_desc(&tree, data, size);
init_tree_desc(&tree, oid, data, size);
hit = grep_tree(&subopt, pathspec, &tree, &base, base.len,
object_type == OBJ_COMMIT);
strbuf_release(&base);
Expand Down Expand Up @@ -573,7 +573,7 @@ static int grep_cache(struct grep_opt *opt,
&type, &size);
if (!data)
die(_("unable to read tree %s"), oid_to_hex(&ce->oid));
init_tree_desc(&tree, data, size);
init_tree_desc(&tree, &ce->oid, data, size);

hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0);
strbuf_setlen(&name, name_base_len);
Expand Down Expand Up @@ -669,7 +669,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
oid_to_hex(&entry.oid));

strbuf_addch(base, '/');
init_tree_desc(&sub, data, size);
init_tree_desc(&sub, &entry.oid, data, size);
hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
check_attr);
free(data);
Expand Down Expand Up @@ -713,7 +713,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
strbuf_add(&base, name, len);
strbuf_addch(&base, ':');
}
init_tree_desc(&tree, data, size);
init_tree_desc(&tree, &obj->oid, data, size);
hit = grep_tree(opt, pathspec, &tree, &base, base.len,
obj->type == OBJ_COMMIT);
strbuf_release(&base);
Expand Down
5 changes: 4 additions & 1 deletion builtin/ls-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
OPT_END()
};
struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
struct object_context obj_context;
int ret;

git_config(git_default_config, NULL);
Expand Down Expand Up @@ -406,7 +407,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
ls_tree_usage, ls_tree_options);
if (argc < 1)
usage_with_options(ls_tree_usage, ls_tree_options);
if (repo_get_oid(the_repository, argv[0], &oid))
if (get_oid_with_context(the_repository, argv[0],
GET_OID_HASH_ANY, &oid,
&obj_context))
die("Not a valid object name %s", argv[0]);

/*
Expand Down
3 changes: 2 additions & 1 deletion builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
cache_tree_free(&the_index.cache_tree);
for (i = 0; i < nr_trees; i++) {
parse_tree(trees[i]);
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
init_tree_desc(t+i, &trees[i]->object.oid,
trees[i]->buffer, trees[i]->size);
}
if (unpack_trees(nr_trees, t, &opts))
return -1;
Expand Down
6 changes: 4 additions & 2 deletions builtin/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1826,7 +1826,8 @@ static void add_pbase_object(struct tree_desc *tree,
tree = pbase_tree_get(&entry.oid);
if (!tree)
return;
init_tree_desc(&sub, tree->tree_data, tree->tree_size);
init_tree_desc(&sub, &tree->oid,
tree->tree_data, tree->tree_size);

add_pbase_object(&sub, down, downlen, fullname);
pbase_tree_put(tree);
Expand Down Expand Up @@ -1886,7 +1887,8 @@ static void add_preferred_base_object(const char *name)
}
else {
struct tree_desc tree;
init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size);
init_tree_desc(&tree, &it->pcache.oid,
it->pcache.tree_data, it->pcache.tree_size);
add_pbase_object(&tree, name, cmplen, name);
}
}
Expand Down
2 changes: 1 addition & 1 deletion builtin/read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
struct tree *tree = trees[i];
if (parse_tree(tree) < 0)
return 128;
init_tree_desc(t+i, tree->buffer, tree->size);
init_tree_desc(t+i, &tree->object.oid, tree->buffer, tree->size);
}
if (unpack_trees(nr_trees, t, &opts))
return 128;
Expand Down
25 changes: 24 additions & 1 deletion builtin/rev-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "submodule.h"
#include "commit-reach.h"
#include "shallow.h"
#include "object-file-convert.h"

#define DO_REVS 1
#define DO_NOREV 2
Expand Down Expand Up @@ -676,6 +677,8 @@ static void print_path(const char *path, const char *prefix, enum format_type fo
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
const struct git_hash_algo *output_algo = NULL;
const struct git_hash_algo *compat = NULL;
int did_repo_setup = 0;
int has_dashdash = 0;
int output_prefix = 0;
Expand Down Expand Up @@ -747,6 +750,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)

prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
compat = the_repository->compat_hash_algo;
}

if (!strcmp(arg, "--")) {
Expand Down Expand Up @@ -834,6 +838,22 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
flags |= GET_OID_QUIETLY;
continue;
}
if (opt_with_value(arg, "--output-object-format", &arg)) {
if (!arg)
die(_("no object format specified"));
if (!strcmp(arg, the_hash_algo->name) ||
!strcmp(arg, "storage")) {
flags |= GET_OID_HASH_ANY;
output_algo = the_hash_algo;
continue;
}
else if (compat && !strcmp(arg, compat->name)) {
flags |= GET_OID_HASH_ANY;
output_algo = compat;
continue;
}
else die(_("unsupported object format: %s"), arg);
}
if (opt_with_value(arg, "--short", &arg)) {
filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1;
Expand Down Expand Up @@ -883,7 +903,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (skip_prefix(arg, "--disambiguate=", &arg)) {
repo_for_each_abbrev(the_repository, arg,
repo_for_each_abbrev(the_repository, arg, the_hash_algo,
show_abbrev, NULL);
continue;
}
Expand Down Expand Up @@ -1091,6 +1111,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (!get_oid_with_context(the_repository, name,
flags, &oid, &unused)) {
if (output_algo)
repo_oid_to_algop(the_repository, &oid,
output_algo, &oid);
if (verify)
revs_count++;
else
Expand Down
5 changes: 3 additions & 2 deletions builtin/stash.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
if (parse_tree(tree))
return -1;

init_tree_desc(t, tree->buffer, tree->size);
init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);

opts.head_idx = 1;
opts.src_index = &the_index;
Expand Down Expand Up @@ -870,7 +870,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
tree[i] = parse_tree_indirect(oid[i]);
if (parse_tree(tree[i]) < 0)
die(_("failed to parse tree"));
init_tree_desc(&tree_desc[i], tree[i]->buffer, tree[i]->size);
init_tree_desc(&tree_desc[i], &tree[i]->object.oid,
tree[i]->buffer, tree[i]->size);
}

unpack_tree_opt.head_idx = -1;
Expand Down
Loading

0 comments on commit 1002f28

Please sign in to comment.