init-db: check template and repository format.
This makes init-db repository version aware. It checks if an existing config file says the repository being reinitialized is of a wrong version and aborts before doing further harm. When copying the templates, it makes sure the they are of the right repository format version. Otherwise the templates are ignored with an warning message. It copies the templates before creating the HEAD, and if the config file is copied from the template directory, reads it, primarily to pick up the value of core.symrefsonly. It changes the way the result of the filemode reliability test is written to the configuration file using git_config_set(). The test is done even if the config file was copied from the templates. And finally, our own repository format version is written to the config file. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
1644162ad5
commit
4f629539cd
1
cache.h
1
cache.h
@ -387,6 +387,7 @@ extern int gitfakemunmap(void *start, size_t length);
|
|||||||
|
|
||||||
typedef int (*config_fn_t)(const char *, const char *);
|
typedef int (*config_fn_t)(const char *, const char *);
|
||||||
extern int git_default_config(const char *, const char *);
|
extern int git_default_config(const char *, const char *);
|
||||||
|
extern int git_config_from_file(config_fn_t fn, const char *);
|
||||||
extern int git_config(config_fn_t fn);
|
extern int git_config(config_fn_t fn);
|
||||||
extern int git_config_int(const char *, const char *);
|
extern int git_config_int(const char *, const char *);
|
||||||
extern int git_config_bool(const char *, const char *);
|
extern int git_config_bool(const char *, const char *);
|
||||||
|
16
config.c
16
config.c
@ -11,6 +11,7 @@
|
|||||||
#define MAXNAME (256)
|
#define MAXNAME (256)
|
||||||
|
|
||||||
static FILE *config_file;
|
static FILE *config_file;
|
||||||
|
static char *config_file_name;
|
||||||
static int config_linenr;
|
static int config_linenr;
|
||||||
static int get_next_char(void)
|
static int get_next_char(void)
|
||||||
{
|
{
|
||||||
@ -186,7 +187,7 @@ static int git_parse_file(config_fn_t fn)
|
|||||||
if (get_value(fn, var, baselen+1) < 0)
|
if (get_value(fn, var, baselen+1) < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
die("bad config file line %d", config_linenr);
|
die("bad config file line %d in %s", config_linenr, config_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_int(const char *name, const char *value)
|
int git_config_int(const char *name, const char *value)
|
||||||
@ -197,7 +198,7 @@ int git_config_int(const char *name, const char *value)
|
|||||||
if (!*end)
|
if (!*end)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
die("bad config value for '%s'", name);
|
die("bad config value for '%s' in %s", name, config_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config_bool(const char *name, const char *value)
|
int git_config_bool(const char *name, const char *value)
|
||||||
@ -240,21 +241,28 @@ int git_default_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_config(config_fn_t fn)
|
int git_config_from_file(config_fn_t fn, const char *filename)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
FILE *f = fopen(git_path("config"), "r");
|
FILE *f = fopen(filename, "r");
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
if (f) {
|
if (f) {
|
||||||
config_file = f;
|
config_file = f;
|
||||||
|
config_file_name = filename;
|
||||||
config_linenr = 1;
|
config_linenr = 1;
|
||||||
ret = git_parse_file(fn);
|
ret = git_parse_file(fn);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
config_file_name = NULL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_config(config_fn_t fn)
|
||||||
|
{
|
||||||
|
return git_config_from_file(fn, git_path("config"));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find all the stuff for git_config_set() below.
|
* Find all the stuff for git_config_set() below.
|
||||||
*/
|
*/
|
||||||
|
83
init-db.c
83
init-db.c
@ -132,6 +132,23 @@ static void copy_templates(const char *git_dir, int len, char *template_dir)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure that template is from the correct vintage */
|
||||||
|
strcpy(template_path + template_len, "config");
|
||||||
|
repository_format_version = 0;
|
||||||
|
git_config_from_file(check_repository_format_version,
|
||||||
|
template_path);
|
||||||
|
template_path[template_len] = 0;
|
||||||
|
|
||||||
|
if (repository_format_version &&
|
||||||
|
repository_format_version != GIT_REPO_VERSION) {
|
||||||
|
fprintf(stderr, "warning: not copying templates of "
|
||||||
|
"a wrong format version %d from '%s'\n",
|
||||||
|
repository_format_version,
|
||||||
|
template_dir);
|
||||||
|
closedir(dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(path, git_dir, len);
|
memcpy(path, git_dir, len);
|
||||||
path[len] = 0;
|
path[len] = 0;
|
||||||
copy_templates_1(path, len,
|
copy_templates_1(path, len,
|
||||||
@ -140,12 +157,13 @@ static void copy_templates(const char *git_dir, int len, char *template_dir)
|
|||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_default_files(const char *git_dir,
|
static void create_default_files(const char *git_dir, char *template_path)
|
||||||
char *template_path)
|
|
||||||
{
|
{
|
||||||
unsigned len = strlen(git_dir);
|
unsigned len = strlen(git_dir);
|
||||||
static char path[PATH_MAX];
|
static char path[PATH_MAX];
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
struct stat st1;
|
||||||
|
char repo_version_string[10];
|
||||||
|
|
||||||
if (len > sizeof(path)-50)
|
if (len > sizeof(path)-50)
|
||||||
die("insane git directory %s", git_dir);
|
die("insane git directory %s", git_dir);
|
||||||
@ -164,6 +182,15 @@ static void create_default_files(const char *git_dir,
|
|||||||
strcpy(path + len, "refs/tags");
|
strcpy(path + len, "refs/tags");
|
||||||
safe_create_dir(path);
|
safe_create_dir(path);
|
||||||
|
|
||||||
|
/* First copy the templates -- we might have the default
|
||||||
|
* config file there, in which case we would want to read
|
||||||
|
* from it after installing.
|
||||||
|
*/
|
||||||
|
path[len] = 0;
|
||||||
|
copy_templates(path, len, template_path);
|
||||||
|
|
||||||
|
git_config(git_default_config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the default symlink from ".git/HEAD" to the "master"
|
* Create the default symlink from ".git/HEAD" to the "master"
|
||||||
* branch, if it does not exist yet.
|
* branch, if it does not exist yet.
|
||||||
@ -173,44 +200,22 @@ static void create_default_files(const char *git_dir,
|
|||||||
if (create_symref(path, "refs/heads/master") < 0)
|
if (create_symref(path, "refs/heads/master") < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This forces creation of new config file */
|
||||||
|
sprintf(repo_version_string, "%d", GIT_REPO_VERSION);
|
||||||
|
git_config_set("core.repositoryformatversion", repo_version_string);
|
||||||
|
|
||||||
path[len] = 0;
|
path[len] = 0;
|
||||||
copy_templates(path, len, template_path);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find out if we can trust the executable bit.
|
|
||||||
*/
|
|
||||||
safe_create_dir(path);
|
|
||||||
strcpy(path + len, "config");
|
strcpy(path + len, "config");
|
||||||
if (access(path, R_OK) < 0) {
|
|
||||||
static const char contents[] =
|
|
||||||
"#\n"
|
|
||||||
"# This is the config file\n"
|
|
||||||
"#\n"
|
|
||||||
"\n"
|
|
||||||
"; core variables\n"
|
|
||||||
"[core]\n"
|
|
||||||
" ; Don't trust file modes\n"
|
|
||||||
" filemode = false\n"
|
|
||||||
"\n";
|
|
||||||
FILE *config = fopen(path, "w");
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (!config)
|
/* Check filemode trustability */
|
||||||
die("Can not write to %s?", path);
|
if (!lstat(path, &st1)) {
|
||||||
|
|
||||||
fwrite(contents, sizeof(contents)-1, 1, config);
|
|
||||||
|
|
||||||
fclose(config);
|
|
||||||
|
|
||||||
if (!lstat(path, &st)) {
|
|
||||||
struct stat st2;
|
struct stat st2;
|
||||||
if (!chmod(path, st.st_mode ^ S_IXUSR) &&
|
int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
|
||||||
!lstat(path, &st2) &&
|
!lstat(path, &st2) &&
|
||||||
st.st_mode != st2.st_mode)
|
st1.st_mode != st2.st_mode);
|
||||||
unlink(path);
|
git_config_set("core.filemode",
|
||||||
else
|
filemode ? "true" : "false");
|
||||||
fprintf(stderr, "Ignoring file modes\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +254,14 @@ int main(int argc, char **argv)
|
|||||||
fprintf(stderr, "defaulting to local storage area\n");
|
fprintf(stderr, "defaulting to local storage area\n");
|
||||||
}
|
}
|
||||||
safe_create_dir(git_dir);
|
safe_create_dir(git_dir);
|
||||||
|
|
||||||
|
/* Check to see if the repository version is right.
|
||||||
|
* Note that a newly created repository does not have
|
||||||
|
* config file, so this will not fail. What we are catching
|
||||||
|
* is an attempt to reinitialize new repository with an old tool.
|
||||||
|
*/
|
||||||
|
check_repository_format();
|
||||||
|
|
||||||
create_default_files(git_dir, template_dir);
|
create_default_files(git_dir, template_dir);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user