mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
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
This commit is contained in:
commit
721cc4314c
|
@ -1433,7 +1433,7 @@ static void write_index_patch(const struct am_state *state)
|
||||||
if (!get_oid_tree("HEAD", &head))
|
if (!get_oid_tree("HEAD", &head))
|
||||||
tree = lookup_tree(&head);
|
tree = lookup_tree(&head);
|
||||||
else
|
else
|
||||||
tree = lookup_tree(&empty_tree_oid);
|
tree = lookup_tree(the_hash_algo->empty_tree);
|
||||||
|
|
||||||
fp = xfopen(am_path(state, "patch"), "w");
|
fp = xfopen(am_path(state, "patch"), "w");
|
||||||
init_revisions(&rev_info, NULL);
|
init_revisions(&rev_info, NULL);
|
||||||
|
|
|
@ -514,7 +514,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
||||||
}
|
}
|
||||||
tree = parse_tree_indirect(old->commit ?
|
tree = parse_tree_indirect(old->commit ?
|
||||||
&old->commit->object.oid :
|
&old->commit->object.oid :
|
||||||
&empty_tree_oid);
|
the_hash_algo->empty_tree);
|
||||||
init_tree_desc(&trees[0], tree->buffer, tree->size);
|
init_tree_desc(&trees[0], tree->buffer, tree->size);
|
||||||
tree = parse_tree_indirect(&new->commit->object.oid);
|
tree = parse_tree_indirect(&new->commit->object.oid);
|
||||||
init_tree_desc(&trees[1], tree->buffer, tree->size);
|
init_tree_desc(&trees[1], tree->buffer, tree->size);
|
||||||
|
|
|
@ -379,7 +379,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
||||||
add_head_to_pending(&rev);
|
add_head_to_pending(&rev);
|
||||||
if (!rev.pending.nr) {
|
if (!rev.pending.nr) {
|
||||||
struct tree *tree;
|
struct tree *tree;
|
||||||
tree = lookup_tree(&empty_tree_oid);
|
tree = lookup_tree(the_hash_algo->empty_tree);
|
||||||
add_pending_object(&rev, &tree->object, "HEAD");
|
add_pending_object(&rev, &tree->object, "HEAD");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -557,7 +557,7 @@ static int pull_into_void(const struct object_id *merge_head,
|
||||||
* index/worktree changes that the user already made on the unborn
|
* index/worktree changes that the user already made on the unborn
|
||||||
* branch.
|
* branch.
|
||||||
*/
|
*/
|
||||||
if (checkout_fast_forward(&empty_tree_oid, merge_head, 0))
|
if (checkout_fast_forward(the_hash_algo->empty_tree, merge_head, 0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
|
if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
|
||||||
|
|
12
cache.h
12
cache.h
|
@ -14,6 +14,7 @@
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "sha1-array.h"
|
#include "sha1-array.h"
|
||||||
|
#include "repository.h"
|
||||||
|
|
||||||
#ifndef platform_SHA_CTX
|
#ifndef platform_SHA_CTX
|
||||||
/*
|
/*
|
||||||
|
@ -77,6 +78,8 @@ struct object_id {
|
||||||
unsigned char hash[GIT_MAX_RAWSZ];
|
unsigned char hash[GIT_MAX_RAWSZ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define the_hash_algo the_repository->hash_algo
|
||||||
|
|
||||||
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
|
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
|
||||||
#define DTYPE(de) ((de)->d_type)
|
#define DTYPE(de) ((de)->d_type)
|
||||||
#else
|
#else
|
||||||
|
@ -907,6 +910,7 @@ struct repository_format {
|
||||||
int version;
|
int version;
|
||||||
int precious_objects;
|
int precious_objects;
|
||||||
int is_bare;
|
int is_bare;
|
||||||
|
int hash_algo;
|
||||||
char *work_tree;
|
char *work_tree;
|
||||||
struct string_list unknown_extensions;
|
struct string_list unknown_extensions;
|
||||||
};
|
};
|
||||||
|
@ -1039,22 +1043,22 @@ extern const struct object_id empty_blob_oid;
|
||||||
|
|
||||||
static inline int is_empty_blob_sha1(const unsigned char *sha1)
|
static inline int is_empty_blob_sha1(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
return !hashcmp(sha1, EMPTY_BLOB_SHA1_BIN);
|
return !hashcmp(sha1, the_hash_algo->empty_blob->hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_empty_blob_oid(const struct object_id *oid)
|
static inline int is_empty_blob_oid(const struct object_id *oid)
|
||||||
{
|
{
|
||||||
return !hashcmp(oid->hash, EMPTY_BLOB_SHA1_BIN);
|
return !oidcmp(oid, the_hash_algo->empty_blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_empty_tree_sha1(const unsigned char *sha1)
|
static inline int is_empty_tree_sha1(const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
return !hashcmp(sha1, EMPTY_TREE_SHA1_BIN);
|
return !hashcmp(sha1, the_hash_algo->empty_tree->hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int is_empty_tree_oid(const struct object_id *oid)
|
static inline int is_empty_tree_oid(const struct object_id *oid)
|
||||||
{
|
{
|
||||||
return !hashcmp(oid->hash, EMPTY_TREE_SHA1_BIN);
|
return !oidcmp(oid, the_hash_algo->empty_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set default permissions by passing mode arguments to open(2) */
|
/* set default permissions by passing mode arguments to open(2) */
|
||||||
|
|
|
@ -218,7 +218,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
|
||||||
} else if (revs->diffopt.ita_invisible_in_index &&
|
} else if (revs->diffopt.ita_invisible_in_index &&
|
||||||
ce_intent_to_add(ce)) {
|
ce_intent_to_add(ce)) {
|
||||||
diff_addremove(&revs->diffopt, '+', ce->ce_mode,
|
diff_addremove(&revs->diffopt, '+', ce->ce_mode,
|
||||||
&empty_tree_oid, 0,
|
the_hash_algo->empty_tree, 0,
|
||||||
ce->name, 0);
|
ce->name, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
57
hash.h
57
hash.h
|
@ -1,6 +1,8 @@
|
||||||
#ifndef HASH_H
|
#ifndef HASH_H
|
||||||
#define HASH_H
|
#define HASH_H
|
||||||
|
|
||||||
|
#include "git-compat-util.h"
|
||||||
|
|
||||||
#if defined(SHA1_PPC)
|
#if defined(SHA1_PPC)
|
||||||
#include "ppc/sha1.h"
|
#include "ppc/sha1.h"
|
||||||
#elif defined(SHA1_APPLE)
|
#elif defined(SHA1_APPLE)
|
||||||
|
@ -13,4 +15,59 @@
|
||||||
#include "block-sha1/sha1.h"
|
#include "block-sha1/sha1.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that these constants are suitable for indexing the hash_algos array and
|
||||||
|
* comparing against each other, but are otherwise arbitrary, so they should not
|
||||||
|
* be exposed to the user or serialized to disk. To know whether a
|
||||||
|
* git_hash_algo struct points to some usable hash function, test the format_id
|
||||||
|
* field for being non-zero. Use the name field for user-visible situations and
|
||||||
|
* the format_id field for fixed-length fields on disk.
|
||||||
|
*/
|
||||||
|
/* An unknown hash function. */
|
||||||
|
#define GIT_HASH_UNKNOWN 0
|
||||||
|
/* SHA-1 */
|
||||||
|
#define GIT_HASH_SHA1 1
|
||||||
|
/* Number of algorithms supported (including unknown). */
|
||||||
|
#define GIT_HASH_NALGOS (GIT_HASH_SHA1 + 1)
|
||||||
|
|
||||||
|
typedef void (*git_hash_init_fn)(void *ctx);
|
||||||
|
typedef void (*git_hash_update_fn)(void *ctx, const void *in, size_t len);
|
||||||
|
typedef void (*git_hash_final_fn)(unsigned char *hash, void *ctx);
|
||||||
|
|
||||||
|
struct git_hash_algo {
|
||||||
|
/*
|
||||||
|
* The name of the algorithm, as appears in the config file and in
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
/* A four-byte version identifier, used in pack indices. */
|
||||||
|
uint32_t format_id;
|
||||||
|
|
||||||
|
/* The size of a hash context (e.g. git_SHA_CTX). */
|
||||||
|
size_t ctxsz;
|
||||||
|
|
||||||
|
/* The length of the hash in binary. */
|
||||||
|
size_t rawsz;
|
||||||
|
|
||||||
|
/* The length of the hash in hex characters. */
|
||||||
|
size_t hexsz;
|
||||||
|
|
||||||
|
/* The hash initialization function. */
|
||||||
|
git_hash_init_fn init_fn;
|
||||||
|
|
||||||
|
/* The hash update function. */
|
||||||
|
git_hash_update_fn update_fn;
|
||||||
|
|
||||||
|
/* The hash finalization function. */
|
||||||
|
git_hash_final_fn final_fn;
|
||||||
|
|
||||||
|
/* The OID of the empty tree. */
|
||||||
|
const struct object_id *empty_tree;
|
||||||
|
|
||||||
|
/* The OID of the empty blob. */
|
||||||
|
const struct object_id *empty_blob;
|
||||||
|
};
|
||||||
|
extern const struct git_hash_algo hash_algos[GIT_HASH_NALGOS];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2082,7 +2082,7 @@ int merge_recursive(struct merge_options *o,
|
||||||
/* if there is no common ancestor, use an empty tree */
|
/* if there is no common ancestor, use an empty tree */
|
||||||
struct tree *tree;
|
struct tree *tree;
|
||||||
|
|
||||||
tree = lookup_tree(&empty_tree_oid);
|
tree = lookup_tree(the_hash_algo->empty_tree);
|
||||||
merged_common_ancestors = make_virtual_commit(tree, "ancestor");
|
merged_common_ancestors = make_virtual_commit(tree, "ancestor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -595,7 +595,7 @@ int notes_merge(struct notes_merge_options *o,
|
||||||
bases = get_merge_bases(local, remote);
|
bases = get_merge_bases(local, remote);
|
||||||
if (!bases) {
|
if (!bases) {
|
||||||
base_oid = &null_oid;
|
base_oid = &null_oid;
|
||||||
base_tree_oid = &empty_tree_oid;
|
base_tree_oid = the_hash_algo->empty_tree;
|
||||||
if (o->verbosity >= 4)
|
if (o->verbosity >= 4)
|
||||||
printf("No merge base found; doing history-less merge\n");
|
printf("No merge base found; doing history-less merge\n");
|
||||||
} else if (!bases->next) {
|
} else if (!bases->next) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
/* The main repository */
|
/* The main repository */
|
||||||
static struct repository the_repo = {
|
static struct repository the_repo = {
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, 0, 0
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, NULL, 0, 0
|
||||||
};
|
};
|
||||||
struct repository *the_repository = &the_repo;
|
struct repository *the_repository = &the_repo;
|
||||||
|
|
||||||
|
@ -64,6 +64,11 @@ void repo_set_gitdir(struct repository *repo, const char *path)
|
||||||
free(old_gitdir);
|
free(old_gitdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void repo_set_hash_algo(struct repository *repo, int hash_algo)
|
||||||
|
{
|
||||||
|
repo->hash_algo = &hash_algos[hash_algo];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
|
* Attempt to resolve and set the provided 'gitdir' for repository 'repo'.
|
||||||
* Return 0 upon success and a non-zero value upon failure.
|
* 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)
|
||||||
if (read_and_verify_repository_format(&format, repo->commondir))
|
if (read_and_verify_repository_format(&format, repo->commondir))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
repo_set_hash_algo(repo, format.hash_algo);
|
||||||
|
|
||||||
if (worktree)
|
if (worktree)
|
||||||
repo_set_worktree(repo, worktree);
|
repo_set_worktree(repo, worktree);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
struct config_set;
|
struct config_set;
|
||||||
struct index_state;
|
struct index_state;
|
||||||
struct submodule_cache;
|
struct submodule_cache;
|
||||||
|
struct git_hash_algo;
|
||||||
|
|
||||||
struct repository {
|
struct repository {
|
||||||
/* Environment */
|
/* Environment */
|
||||||
|
@ -67,6 +68,9 @@ struct repository {
|
||||||
*/
|
*/
|
||||||
struct index_state *index;
|
struct index_state *index;
|
||||||
|
|
||||||
|
/* Repository's current hash algorithm, as serialized on disk. */
|
||||||
|
const struct git_hash_algo *hash_algo;
|
||||||
|
|
||||||
/* Configurations */
|
/* Configurations */
|
||||||
/*
|
/*
|
||||||
* Bit used during initialization to indicate if repository state (like
|
* Bit used during initialization to indicate if repository state (like
|
||||||
|
@ -86,6 +90,7 @@ extern struct repository *the_repository;
|
||||||
|
|
||||||
extern void repo_set_gitdir(struct repository *repo, const char *path);
|
extern void repo_set_gitdir(struct repository *repo, const char *path);
|
||||||
extern void repo_set_worktree(struct repository *repo, const char *path);
|
extern void repo_set_worktree(struct repository *repo, const char *path);
|
||||||
|
extern void repo_set_hash_algo(struct repository *repo, int algo);
|
||||||
extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);
|
extern int repo_init(struct repository *repo, const char *gitdir, const char *worktree);
|
||||||
extern int repo_submodule_init(struct repository *submodule,
|
extern int repo_submodule_init(struct repository *submodule,
|
||||||
struct repository *superproject,
|
struct repository *superproject,
|
||||||
|
|
|
@ -347,7 +347,7 @@ static int read_oneliner(struct strbuf *buf,
|
||||||
|
|
||||||
static struct tree *empty_tree(void)
|
static struct tree *empty_tree(void)
|
||||||
{
|
{
|
||||||
return lookup_tree(&empty_tree_oid);
|
return lookup_tree(the_hash_algo->empty_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int error_dirty_index(struct replay_opts *opts)
|
static int error_dirty_index(struct replay_opts *opts)
|
||||||
|
@ -706,7 +706,7 @@ static int is_original_commit_empty(struct commit *commit)
|
||||||
oid_to_hex(&parent->object.oid));
|
oid_to_hex(&parent->object.oid));
|
||||||
ptree_oid = &parent->tree->object.oid;
|
ptree_oid = &parent->tree->object.oid;
|
||||||
} else {
|
} else {
|
||||||
ptree_oid = &empty_tree_oid; /* commit is root */
|
ptree_oid = the_hash_algo->empty_tree; /* commit is root */
|
||||||
}
|
}
|
||||||
|
|
||||||
return !oidcmp(ptree_oid, &commit->tree->object.oid);
|
return !oidcmp(ptree_oid, &commit->tree->object.oid);
|
||||||
|
@ -959,7 +959,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
|
||||||
} else {
|
} else {
|
||||||
unborn = get_oid("HEAD", &head);
|
unborn = get_oid("HEAD", &head);
|
||||||
if (unborn)
|
if (unborn)
|
||||||
oidcpy(&head, &empty_tree_oid);
|
oidcpy(&head, the_hash_algo->empty_tree);
|
||||||
if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
|
if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
|
||||||
NULL, 0))
|
NULL, 0))
|
||||||
return error_dirty_index(opts);
|
return error_dirty_index(opts);
|
||||||
|
|
49
setup.c
49
setup.c
|
@ -434,16 +434,15 @@ static int check_repo_format(const char *var, const char *value, void *vdata)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
static int check_repository_format_gently(const char *gitdir, struct repository_format *candidate, int *nongit_ok)
|
||||||
{
|
{
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
struct repository_format candidate;
|
|
||||||
int has_common;
|
int has_common;
|
||||||
|
|
||||||
has_common = get_common_dir(&sb, gitdir);
|
has_common = get_common_dir(&sb, gitdir);
|
||||||
strbuf_addstr(&sb, "/config");
|
strbuf_addstr(&sb, "/config");
|
||||||
read_repository_format(&candidate, sb.buf);
|
read_repository_format(candidate, sb.buf);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -451,10 +450,10 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
||||||
* we treat a missing config as a silent "ok", even when nongit_ok
|
* we treat a missing config as a silent "ok", even when nongit_ok
|
||||||
* is unset.
|
* is unset.
|
||||||
*/
|
*/
|
||||||
if (candidate.version < 0)
|
if (candidate->version < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (verify_repository_format(&candidate, &err) < 0) {
|
if (verify_repository_format(candidate, &err) < 0) {
|
||||||
if (nongit_ok) {
|
if (nongit_ok) {
|
||||||
warning("%s", err.buf);
|
warning("%s", err.buf);
|
||||||
strbuf_release(&err);
|
strbuf_release(&err);
|
||||||
|
@ -464,21 +463,21 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
||||||
die("%s", err.buf);
|
die("%s", err.buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
repository_format_precious_objects = candidate.precious_objects;
|
repository_format_precious_objects = candidate->precious_objects;
|
||||||
string_list_clear(&candidate.unknown_extensions, 0);
|
string_list_clear(&candidate->unknown_extensions, 0);
|
||||||
if (!has_common) {
|
if (!has_common) {
|
||||||
if (candidate.is_bare != -1) {
|
if (candidate->is_bare != -1) {
|
||||||
is_bare_repository_cfg = candidate.is_bare;
|
is_bare_repository_cfg = candidate->is_bare;
|
||||||
if (is_bare_repository_cfg == 1)
|
if (is_bare_repository_cfg == 1)
|
||||||
inside_work_tree = -1;
|
inside_work_tree = -1;
|
||||||
}
|
}
|
||||||
if (candidate.work_tree) {
|
if (candidate->work_tree) {
|
||||||
free(git_work_tree_cfg);
|
free(git_work_tree_cfg);
|
||||||
git_work_tree_cfg = candidate.work_tree;
|
git_work_tree_cfg = candidate->work_tree;
|
||||||
inside_work_tree = -1;
|
inside_work_tree = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
free(candidate.work_tree);
|
free(candidate->work_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -489,6 +488,7 @@ int read_repository_format(struct repository_format *format, const char *path)
|
||||||
memset(format, 0, sizeof(*format));
|
memset(format, 0, sizeof(*format));
|
||||||
format->version = -1;
|
format->version = -1;
|
||||||
format->is_bare = -1;
|
format->is_bare = -1;
|
||||||
|
format->hash_algo = GIT_HASH_SHA1;
|
||||||
string_list_init(&format->unknown_extensions, 1);
|
string_list_init(&format->unknown_extensions, 1);
|
||||||
git_config_from_file(check_repo_format, path, format);
|
git_config_from_file(check_repo_format, path, format);
|
||||||
return format->version;
|
return format->version;
|
||||||
|
@ -625,6 +625,7 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
|
||||||
|
|
||||||
static const char *setup_explicit_git_dir(const char *gitdirenv,
|
static const char *setup_explicit_git_dir(const char *gitdirenv,
|
||||||
struct strbuf *cwd,
|
struct strbuf *cwd,
|
||||||
|
struct repository_format *repo_fmt,
|
||||||
int *nongit_ok)
|
int *nongit_ok)
|
||||||
{
|
{
|
||||||
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
|
const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
|
||||||
|
@ -650,7 +651,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
|
||||||
die("Not a git repository: '%s'", gitdirenv);
|
die("Not a git repository: '%s'", gitdirenv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_repository_format_gently(gitdirenv, nongit_ok)) {
|
if (check_repository_format_gently(gitdirenv, repo_fmt, nongit_ok)) {
|
||||||
free(gitfile);
|
free(gitfile);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -723,9 +724,10 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
|
||||||
|
|
||||||
static const char *setup_discovered_git_dir(const char *gitdir,
|
static const char *setup_discovered_git_dir(const char *gitdir,
|
||||||
struct strbuf *cwd, int offset,
|
struct strbuf *cwd, int offset,
|
||||||
|
struct repository_format *repo_fmt,
|
||||||
int *nongit_ok)
|
int *nongit_ok)
|
||||||
{
|
{
|
||||||
if (check_repository_format_gently(gitdir, nongit_ok))
|
if (check_repository_format_gently(gitdir, repo_fmt, nongit_ok))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* --work-tree is set without --git-dir; use discovered one */
|
/* --work-tree is set without --git-dir; use discovered one */
|
||||||
|
@ -737,7 +739,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,
|
||||||
gitdir = to_free = real_pathdup(gitdir, 1);
|
gitdir = to_free = real_pathdup(gitdir, 1);
|
||||||
if (chdir(cwd->buf))
|
if (chdir(cwd->buf))
|
||||||
die_errno("Could not come back to cwd");
|
die_errno("Could not come back to cwd");
|
||||||
ret = setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
ret = setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok);
|
||||||
free(to_free);
|
free(to_free);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -769,11 +771,12 @@ static const char *setup_discovered_git_dir(const char *gitdir,
|
||||||
|
|
||||||
/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
|
/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
|
||||||
static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
|
static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
|
||||||
|
struct repository_format *repo_fmt,
|
||||||
int *nongit_ok)
|
int *nongit_ok)
|
||||||
{
|
{
|
||||||
int root_len;
|
int root_len;
|
||||||
|
|
||||||
if (check_repository_format_gently(".", nongit_ok))
|
if (check_repository_format_gently(".", repo_fmt, nongit_ok))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
|
setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
|
||||||
|
@ -785,7 +788,7 @@ static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
|
||||||
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
|
gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
|
||||||
if (chdir(cwd->buf))
|
if (chdir(cwd->buf))
|
||||||
die_errno("Could not come back to cwd");
|
die_errno("Could not come back to cwd");
|
||||||
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
|
return setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
inside_git_dir = 1;
|
inside_git_dir = 1;
|
||||||
|
@ -1026,6 +1029,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
static struct strbuf cwd = STRBUF_INIT;
|
static struct strbuf cwd = STRBUF_INIT;
|
||||||
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
struct repository_format repo_fmt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have read an incomplete configuration before
|
* We may have read an incomplete configuration before
|
||||||
|
@ -1053,18 +1057,18 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
prefix = NULL;
|
prefix = NULL;
|
||||||
break;
|
break;
|
||||||
case GIT_DIR_EXPLICIT:
|
case GIT_DIR_EXPLICIT:
|
||||||
prefix = setup_explicit_git_dir(gitdir.buf, &cwd, nongit_ok);
|
prefix = setup_explicit_git_dir(gitdir.buf, &cwd, &repo_fmt, nongit_ok);
|
||||||
break;
|
break;
|
||||||
case GIT_DIR_DISCOVERED:
|
case GIT_DIR_DISCOVERED:
|
||||||
if (dir.len < cwd.len && chdir(dir.buf))
|
if (dir.len < cwd.len && chdir(dir.buf))
|
||||||
die(_("Cannot change to '%s'"), dir.buf);
|
die(_("Cannot change to '%s'"), dir.buf);
|
||||||
prefix = setup_discovered_git_dir(gitdir.buf, &cwd, dir.len,
|
prefix = setup_discovered_git_dir(gitdir.buf, &cwd, dir.len,
|
||||||
nongit_ok);
|
&repo_fmt, nongit_ok);
|
||||||
break;
|
break;
|
||||||
case GIT_DIR_BARE:
|
case GIT_DIR_BARE:
|
||||||
if (dir.len < cwd.len && chdir(dir.buf))
|
if (dir.len < cwd.len && chdir(dir.buf))
|
||||||
die(_("Cannot change to '%s'"), dir.buf);
|
die(_("Cannot change to '%s'"), dir.buf);
|
||||||
prefix = setup_bare_git_dir(&cwd, dir.len, nongit_ok);
|
prefix = setup_bare_git_dir(&cwd, dir.len, &repo_fmt, nongit_ok);
|
||||||
break;
|
break;
|
||||||
case GIT_DIR_HIT_CEILING:
|
case GIT_DIR_HIT_CEILING:
|
||||||
prefix = setup_nongit(cwd.buf, nongit_ok);
|
prefix = setup_nongit(cwd.buf, nongit_ok);
|
||||||
|
@ -1110,6 +1114,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
|
||||||
repo_set_gitdir(the_repository, gitdir);
|
repo_set_gitdir(the_repository, gitdir);
|
||||||
setup_git_env();
|
setup_git_env();
|
||||||
}
|
}
|
||||||
|
if (startup_info->have_repository)
|
||||||
|
repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_release(&dir);
|
strbuf_release(&dir);
|
||||||
|
@ -1171,7 +1177,8 @@ int git_config_perm(const char *var, const char *value)
|
||||||
|
|
||||||
void check_repository_format(void)
|
void check_repository_format(void)
|
||||||
{
|
{
|
||||||
check_repository_format_gently(get_git_dir(), NULL);
|
struct repository_format repo_fmt;
|
||||||
|
check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
|
||||||
startup_info->have_repository = 1;
|
startup_info->have_repository = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
58
sha1_file.c
58
sha1_file.c
|
@ -39,6 +39,64 @@ const struct object_id empty_blob_oid = {
|
||||||
EMPTY_BLOB_SHA1_BIN_LITERAL
|
EMPTY_BLOB_SHA1_BIN_LITERAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void git_hash_sha1_init(void *ctx)
|
||||||
|
{
|
||||||
|
git_SHA1_Init((git_SHA_CTX *)ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void git_hash_sha1_update(void *ctx, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
git_SHA1_Update((git_SHA_CTX *)ctx, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void git_hash_sha1_final(unsigned char *hash, void *ctx)
|
||||||
|
{
|
||||||
|
git_SHA1_Final(hash, (git_SHA_CTX *)ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void git_hash_unknown_init(void *ctx)
|
||||||
|
{
|
||||||
|
die("trying to init unknown hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void git_hash_unknown_update(void *ctx, const void *data, size_t len)
|
||||||
|
{
|
||||||
|
die("trying to update unknown hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void git_hash_unknown_final(unsigned char *hash, void *ctx)
|
||||||
|
{
|
||||||
|
die("trying to finalize unknown hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = {
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
0x00000000,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
git_hash_unknown_init,
|
||||||
|
git_hash_unknown_update,
|
||||||
|
git_hash_unknown_final,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sha-1",
|
||||||
|
/* "sha1", big-endian */
|
||||||
|
0x73686131,
|
||||||
|
sizeof(git_SHA_CTX),
|
||||||
|
GIT_SHA1_RAWSZ,
|
||||||
|
GIT_SHA1_HEXSZ,
|
||||||
|
git_hash_sha1_init,
|
||||||
|
git_hash_sha1_update,
|
||||||
|
git_hash_sha1_final,
|
||||||
|
&empty_tree_oid,
|
||||||
|
&empty_blob_oid,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is meant to hold a *small* number of objects that you would
|
* This is meant to hold a *small* number of objects that you would
|
||||||
* want read_sha1_file() to be able to return, but yet you do not want
|
* want read_sha1_file() to be able to return, but yet you do not want
|
||||||
|
|
|
@ -587,7 +587,7 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path,
|
||||||
struct object_id *one, struct object_id *two,
|
struct object_id *one, struct object_id *two,
|
||||||
unsigned dirty_submodule)
|
unsigned dirty_submodule)
|
||||||
{
|
{
|
||||||
const struct object_id *old = &empty_tree_oid, *new = &empty_tree_oid;
|
const struct object_id *old = the_hash_algo->empty_tree, *new = the_hash_algo->empty_tree;
|
||||||
struct commit *left = NULL, *right = NULL;
|
struct commit *left = NULL, *right = NULL;
|
||||||
struct commit_list *merge_bases = NULL;
|
struct commit_list *merge_bases = NULL;
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
|
|
Loading…
Reference in a new issue