Skip to content

Commit 721cc43

Browse files
committed
Merge branch 'bc/hash-algo'
An infrastructure to define what hash function is used in Git is introduced, and an effort to plumb that throughout various codepaths has been started. * bc/hash-algo: repository: fix a sparse 'using integer as NULL pointer' warning Switch empty tree and blob lookups to use hash abstraction Integrate hash algorithm support with repo setup Add structure representing hash algorithm setup: expose enumerated repo info
2 parents 95ec6b1 + c250e02 commit 721cc43

15 files changed

Lines changed: 175 additions & 37 deletions

builtin/am.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1433,7 +1433,7 @@ static void write_index_patch(const struct am_state *state)
14331433
if (!get_oid_tree("HEAD", &head))
14341434
tree = lookup_tree(&head);
14351435
else
1436-
tree = lookup_tree(&empty_tree_oid);
1436+
tree = lookup_tree(the_hash_algo->empty_tree);
14371437

14381438
fp = xfopen(am_path(state, "patch"), "w");
14391439
init_revisions(&rev_info, NULL);

builtin/checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
514514
}
515515
tree = parse_tree_indirect(old->commit ?
516516
&old->commit->object.oid :
517-
&empty_tree_oid);
517+
the_hash_algo->empty_tree);
518518
init_tree_desc(&trees[0], tree->buffer, tree->size);
519519
tree = parse_tree_indirect(&new->commit->object.oid);
520520
init_tree_desc(&trees[1], tree->buffer, tree->size);

builtin/diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
379379
add_head_to_pending(&rev);
380380
if (!rev.pending.nr) {
381381
struct tree *tree;
382-
tree = lookup_tree(&empty_tree_oid);
382+
tree = lookup_tree(the_hash_algo->empty_tree);
383383
add_pending_object(&rev, &tree->object, "HEAD");
384384
}
385385
break;

builtin/pull.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ static int pull_into_void(const struct object_id *merge_head,
557557
* index/worktree changes that the user already made on the unborn
558558
* branch.
559559
*/
560-
if (checkout_fast_forward(&empty_tree_oid, merge_head, 0))
560+
if (checkout_fast_forward(the_hash_algo->empty_tree, merge_head, 0))
561561
return 1;
562562

563563
if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))

cache.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "hash.h"
1515
#include "path.h"
1616
#include "sha1-array.h"
17+
#include "repository.h"
1718

1819
#ifndef platform_SHA_CTX
1920
/*
@@ -77,6 +78,8 @@ struct object_id {
7778
unsigned char hash[GIT_MAX_RAWSZ];
7879
};
7980

81+
#define the_hash_algo the_repository->hash_algo
82+
8083
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
8184
#define DTYPE(de) ((de)->d_type)
8285
#else
@@ -907,6 +910,7 @@ struct repository_format {
907910
int version;
908911
int precious_objects;
909912
int is_bare;
913+
int hash_algo;
910914
char *work_tree;
911915
struct string_list unknown_extensions;
912916
};
@@ -1039,22 +1043,22 @@ extern const struct object_id empty_blob_oid;
10391043

10401044
static inline int is_empty_blob_sha1(const unsigned char *sha1)
10411045
{
1042-
return !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN);
1046+
return !hashcmp(sha1, the_hash_algo->empty_blob->hash);
10431047
}
10441048

10451049
static inline int is_empty_blob_oid(const struct object_id *oid)
10461050
{
1047-
return !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN);
1051+
return !oidcmp(oid, the_hash_algo->empty_blob);
10481052
}
10491053

10501054
static inline int is_empty_tree_sha1(const unsigned char *sha1)
10511055
{
1052-
return !hashcmp(sha1, EMPTY_TREE_SHA1_BIN);
1056+
return !hashcmp(sha1, the_hash_algo->empty_tree->hash);
10531057
}
10541058

10551059
static inline int is_empty_tree_oid(const struct object_id *oid)
10561060
{
1057-
return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);
1061+
return !oidcmp(oid, the_hash_algo->empty_tree);
10581062
}
10591063

10601064
/* set default permissions by passing mode arguments to open(2) */

diff-lib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
218218
} else if (revs->diffopt.ita_invisible_in_index &&
219219
ce_intent_to_add(ce)) {
220220
diff_addremove(&revs->diffopt, '+', ce->ce_mode,
221-
&empty_tree_oid, 0,
221+
the_hash_algo->empty_tree, 0,
222222
ce->name, 0);
223223
continue;
224224
}

hash.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef HASH_H
22
#define HASH_H
33

4+
#include "git-compat-util.h"
5+
46
#if defined(SHA1_PPC)
57
#include "ppc/sha1.h"
68
#elif defined(SHA1_APPLE)
@@ -13,4 +15,59 @@
1315
#include "block-sha1/sha1.h"
1416
#endif
1517

18+
/*
19+
* Note that these constants are suitable for indexing the hash_algos array and
20+
* comparing against each other, but are otherwise arbitrary, so they should not
21+
* be exposed to the user or serialized to disk. To know whether a
22+
* git_hash_algo struct points to some usable hash function, test the format_id
23+
* field for being non-zero. Use the name field for user-visible situations and
24+
* the format_id field for fixed-length fields on disk.
25+
*/
26+
/* An unknown hash function. */
27+
#define GIT_HASH_UNKNOWN 0
28+
/* SHA-1 */
29+
#define GIT_HASH_SHA1 1
30+
/* Number of algorithms supported (including unknown). */
31+
#define GIT_HASH_NALGOS (GIT_HASH_SHA1 + 1)
32+
33+
typedef void (*git_hash_init_fn)(void *ctx);
34+
typedef void (*git_hash_update_fn)(void *ctx, const void *in, size_t len);
35+
typedef void (*git_hash_final_fn)(unsigned char *hash, void *ctx);
36+
37+
struct git_hash_algo {
38+
/*
39+
* The name of the algorithm, as appears in the config file and in
40+
* messages.
41+
*/
42+
const char *name;
43+
44+
/* A four-byte version identifier, used in pack indices. */
45+
uint32_t format_id;
46+
47+
/* The size of a hash context (e.g. git_SHA_CTX). */
48+
size_t ctxsz;
49+
50+
/* The length of the hash in binary. */
51+
size_t rawsz;
52+
53+
/* The length of the hash in hex characters. */
54+
size_t hexsz;
55+
56+
/* The hash initialization function. */
57+
git_hash_init_fn init_fn;
58+
59+
/* The hash update function. */
60+
git_hash_update_fn update_fn;
61+
62+
/* The hash finalization function. */
63+
git_hash_final_fn final_fn;
64+
65+
/* The OID of the empty tree. */
66+
const struct object_id *empty_tree;
67+
68+
/* The OID of the empty blob. */
69+
const struct object_id *empty_blob;
70+
};
71+
extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
72+
1673
#endif

merge-recursive.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,7 @@ int merge_recursive(struct merge_options *o,
20822082
/* if there is no common ancestor, use an empty tree */
20832083
struct tree *tree;
20842084

2085-
tree = lookup_tree(&empty_tree_oid);
2085+
tree = lookup_tree(the_hash_algo->empty_tree);
20862086
merged_common_ancestors = make_virtual_commit(tree, "ancestor");
20872087
}
20882088

notes-merge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ int notes_merge(struct notes_merge_options *o,
595595
bases = get_merge_bases(local, remote);
596596
if (!bases) {
597597
base_oid = &null_oid;
598-
base_tree_oid = &empty_tree_oid;
598+
base_tree_oid = the_hash_algo->empty_tree;
599599
if (o->verbosity >= 4)
600600
printf("No merge base found; doing history-less merge\n");
601601
} else if (!bases->next) {

repository.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
/* The main repository */
77
static struct repository the_repo = {
8-
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, 0, 0
8+
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, NULL, 0, 0
99
};
1010
struct repository *the_repository = &the_repo;
1111

@@ -64,6 +64,11 @@ void repo_set_gitdir(struct repository *repo, const char *path)
6464
free(old_gitdir);
6565
}
6666

67+
void repo_set_hash_algo(struct repository *repo, int hash_algo)
68+
{
69+
repo->hash_algo = &hash_algos[hash_algo];
70+
}
71+
6772
/*
6873
* Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
6974
* Return 0 upon success and a non-zero value upon failure.
@@ -136,6 +141,8 @@ int repo_init(struct repository *repo, const char *gitdir, const char *worktree)
136141
if (read_and_verify_repository_format(&format, repo->commondir))
137142
goto error;
138143

144+
repo_set_hash_algo(repo, format.hash_algo);
145+
139146
if (worktree)
140147
repo_set_worktree(repo, worktree);
141148

0 commit comments

Comments
 (0)