X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=init-db.c;h=ff294960f29c8763e34e28060dee04b799bd55fd;hb=7f732c632ff7a1adc2309257becdc0c1fe76b514;hp=1fb3f7fa79136f296ece9e04f6fdbf34bb40eeeb;hpb=2b64f88f09ae2169ec85652b46897574e352936d;p=git.git diff --git a/init-db.c b/init-db.c index 1fb3f7fa..ff294960 100644 --- a/init-db.c +++ b/init-db.c @@ -9,7 +9,7 @@ #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/" #endif -static void safe_create_dir(const char *dir) +static void safe_create_dir(const char *dir, int share) { if (mkdir(dir, 0777) < 0) { if (errno != EEXIST) { @@ -17,11 +17,13 @@ static void safe_create_dir(const char *dir) exit(1); } } + else if (share && adjust_shared_perm(dir)) + die("Could not make %s writable by group\n", dir); } static int copy_file(const char *dst, const char *src, int mode) { - int fdi, fdo; + int fdi, fdo, status; mode = (mode & 0111) ? 0777 : 0666; if ((fdi = open(src, O_RDONLY)) < 0) @@ -30,30 +32,13 @@ static int copy_file(const char *dst, const char *src, int mode) close(fdi); return fdo; } - while (1) { - char buf[BUFSIZ]; - ssize_t leni, leno, ofs; - leni = read(fdi, buf, sizeof(buf)); - if (leni < 0) { - error_return: - close(fdo); - close(fdi); - return -1; - } - if (!leni) - break; - ofs = 0; - do { - leno = write(fdo, buf+ofs, leni); - if (leno < 0) - goto error_return; - leni -= leno; - ofs += leno; - } while (0 < leni); - } + status = copy_fd(fdi, fdo); close(fdo); - close(fdi); - return 0; + + if (!status && adjust_shared_perm(dst)) + return -1; + + return status; } static void copy_templates_1(char *path, int baselen, @@ -69,7 +54,7 @@ static void copy_templates_1(char *path, int baselen, * with the way the namespace under .git/ is organized, should * be really carefully chosen. */ - safe_create_dir(path); + safe_create_dir(path, 1); while ((de = readdir(dir)) != NULL) { struct stat st_git, st_template; int namelen; @@ -153,18 +138,38 @@ static void copy_templates(const char *git_dir, int len, char *template_dir) 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); + path[len] = 0; copy_templates_1(path, len, template_path, template_len, dir); closedir(dir); } -static void create_default_files(const char *git_dir, - char *template_path) +static void create_default_files(const char *git_dir, char *template_path) { unsigned len = strlen(git_dir); static char path[PATH_MAX]; + unsigned char sha1[20]; + struct stat st1; + char repo_version_string[10]; if (len > sizeof(path)-50) die("insane git directory %s", git_dir); @@ -177,28 +182,51 @@ static void create_default_files(const char *git_dir, * Create .git/refs/{heads,tags} */ strcpy(path + len, "refs"); - safe_create_dir(path); + safe_create_dir(path, 1); strcpy(path + len, "refs/heads"); - safe_create_dir(path); + safe_create_dir(path, 1); strcpy(path + len, "refs/tags"); - safe_create_dir(path); + safe_create_dir(path, 1); + + /* 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" - * branch + * branch, if it does not exist yet. */ strcpy(path + len, "HEAD"); - if (symlink("refs/heads/master", path) < 0) { - if (errno != EEXIST) { - perror(path); + if (read_ref(path, sha1) < 0) { + if (create_symref(path, "refs/heads/master") < 0) exit(1); - } } - copy_templates(path, len, template_path); + + /* 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; + strcpy(path + len, "config"); + + /* Check filemode trustability */ + if (!lstat(path, &st1)) { + struct stat st2; + int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && + !lstat(path, &st2) && + st1.st_mode != st2.st_mode); + git_config_set("core.filemode", + filemode ? "true" : "false"); + } } static const char init_db_usage[] = -"git-init-db [--template=]"; +"git-init-db [--template=] [--shared]"; /* * If you want to, you can share the DB area with any number of branches. @@ -215,10 +243,10 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++, argv++) { char *arg = argv[1]; - if (arg[0] != '-') - break; - else if (!strncmp(arg, "--template=", 11)) + if (!strncmp(arg, "--template=", 11)) template_dir = arg+11; + else if (!strcmp(arg, "--shared")) + shared_repository = 1; else die(init_db_usage); } @@ -226,12 +254,20 @@ int main(int argc, char **argv) /* * Set up the default .git directory contents */ - git_dir = gitenv(GIT_DIR_ENVIRONMENT); + git_dir = getenv(GIT_DIR_ENVIRONMENT); if (!git_dir) { git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; fprintf(stderr, "defaulting to local storage area\n"); } - safe_create_dir(git_dir); + safe_create_dir(git_dir, 0); + + /* 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); /* @@ -242,12 +278,14 @@ int main(int argc, char **argv) path = xmalloc(len + 40); memcpy(path, sha1_dir, len); - safe_create_dir(sha1_dir); - for (i = 0; i < 256; i++) { - sprintf(path+len, "/%02x", i); - safe_create_dir(path); - } + safe_create_dir(sha1_dir, 1); strcpy(path+len, "/pack"); - safe_create_dir(path); + safe_create_dir(path, 1); + strcpy(path+len, "/info"); + safe_create_dir(path, 1); + + if (shared_repository) + git_config_set("core.sharedRepository", "true"); + return 0; }