setup: adopt shared init-db & clone code

The functions init_db() and initialize_repository_version() were shared by builtin/init-db.c and builtin/clone.c, and declared in cache.h. Move these functions, plus their several helpers only used by these functions, to setup.[ch]. Diff best viewed with `--color-moved`. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed May 16, 2023 at 06:33 UTC e8cf8ef5075d7805846f0f7159f8d072b07e588e
5 files changed +503 -507
Makefile
+2 -2
@@ -2742,8 +2742,8 @@ exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
2742 '-DBINDIR="$(bindir_relative_SQ)"' \
2743 '-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"'
2744
2745 -builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX
2746 -builtin/init-db.sp builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
2745 +setup.sp setup.s setup.o: GIT-PREFIX
2746 +setup.sp setup.s setup.o: EXTRA_CPPFLAGS = \
2747 -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
2748
2749 config.sp config.s config.o: GIT-PREFIX
builtin/init-db.c
-496
@@ -6,511 +6,15 @@
6 #include "cache.h"
7 #include "abspath.h"
8 #include "config.h"
9 -#include "copy.h"
9 #include "environment.h"
10 #include "gettext.h"
12 -#include "refs.h"
11 #include "builtin.h"
14 -#include "exec-cmd.h"
12 #include "object-file.h"
13 #include "parse-options.h"
14 #include "path.h"
15 #include "setup.h"
19 -#include "worktree.h"
16 #include "wrapper.h"
17
22 -#ifndef DEFAULT_GIT_TEMPLATE_DIR
23 -#define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
24 -#endif
25 -
26 -#ifdef NO_TRUSTABLE_FILEMODE
27 -#define TEST_FILEMODE 0
28 -#else
29 -#define TEST_FILEMODE 1
30 -#endif
31 -
32 -#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
33 -
34 -static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
35 - DIR *dir)
36 -{
37 - size_t path_baselen = path->len;
38 - size_t template_baselen = template_path->len;
39 - struct dirent *de;
40 -
41 - /* Note: if ".git/hooks" file exists in the repository being
42 - * re-initialized, /etc/core-git/templates/hooks/update would
43 - * cause "git init" to fail here. I think this is sane but
44 - * it means that the set of templates we ship by default, along
45 - * with the way the namespace under .git/ is organized, should
46 - * be really carefully chosen.
47 - */
48 - safe_create_dir(path->buf, 1);
49 - while ((de = readdir(dir)) != NULL) {
50 - struct stat st_git, st_template;
51 - int exists = 0;
52 -
53 - strbuf_setlen(path, path_baselen);
54 - strbuf_setlen(template_path, template_baselen);
55 -
56 - if (de->d_name[0] == '.')
57 - continue;
58 - strbuf_addstr(path, de->d_name);
59 - strbuf_addstr(template_path, de->d_name);
60 - if (lstat(path->buf, &st_git)) {
61 - if (errno != ENOENT)
62 - die_errno(_("cannot stat '%s'"), path->buf);
63 - }
64 - else
65 - exists = 1;
66 -
67 - if (lstat(template_path->buf, &st_template))
68 - die_errno(_("cannot stat template '%s'"), template_path->buf);
69 -
70 - if (S_ISDIR(st_template.st_mode)) {
71 - DIR *subdir = opendir(template_path->buf);
72 - if (!subdir)
73 - die_errno(_("cannot opendir '%s'"), template_path->buf);
74 - strbuf_addch(path, '/');
75 - strbuf_addch(template_path, '/');
76 - copy_templates_1(path, template_path, subdir);
77 - closedir(subdir);
78 - }
79 - else if (exists)
80 - continue;
81 - else if (S_ISLNK(st_template.st_mode)) {
82 - struct strbuf lnk = STRBUF_INIT;
83 - if (strbuf_readlink(&lnk, template_path->buf,
84 - st_template.st_size) < 0)
85 - die_errno(_("cannot readlink '%s'"), template_path->buf);
86 - if (symlink(lnk.buf, path->buf))
87 - die_errno(_("cannot symlink '%s' '%s'"),
88 - lnk.buf, path->buf);
89 - strbuf_release(&lnk);
90 - }
91 - else if (S_ISREG(st_template.st_mode)) {
92 - if (copy_file(path->buf, template_path->buf, st_template.st_mode))
93 - die_errno(_("cannot copy '%s' to '%s'"),
94 - template_path->buf, path->buf);
95 - }
96 - else
97 - error(_("ignoring template %s"), template_path->buf);
98 - }
99 -}
100 -
101 -static void copy_templates(const char *template_dir, const char *init_template_dir)
102 -{
103 - struct strbuf path = STRBUF_INIT;
104 - struct strbuf template_path = STRBUF_INIT;
105 - size_t template_len;
106 - struct repository_format template_format = REPOSITORY_FORMAT_INIT;
107 - struct strbuf err = STRBUF_INIT;
108 - DIR *dir;
109 - char *to_free = NULL;
110 -
111 - if (!template_dir)
112 - template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
113 - if (!template_dir)
114 - template_dir = init_template_dir;
115 - if (!template_dir)
116 - template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
117 - if (!template_dir[0]) {
118 - free(to_free);
119 - return;
120 - }
121 -
122 - strbuf_addstr(&template_path, template_dir);
123 - strbuf_complete(&template_path, '/');
124 - template_len = template_path.len;
125 -
126 - dir = opendir(template_path.buf);
127 - if (!dir) {
128 - warning(_("templates not found in %s"), template_dir);
129 - goto free_return;
130 - }
131 -
132 - /* Make sure that template is from the correct vintage */
133 - strbuf_addstr(&template_path, "config");
134 - read_repository_format(&template_format, template_path.buf);
135 - strbuf_setlen(&template_path, template_len);
136 -
137 - /*
138 - * No mention of version at all is OK, but anything else should be
139 - * verified.
140 - */
141 - if (template_format.version >= 0 &&
142 - verify_repository_format(&template_format, &err) < 0) {
143 - warning(_("not copying templates from '%s': %s"),
144 - template_dir, err.buf);
145 - strbuf_release(&err);
146 - goto close_free_return;
147 - }
148 -
149 - strbuf_addstr(&path, get_git_common_dir());
150 - strbuf_complete(&path, '/');
151 - copy_templates_1(&path, &template_path, dir);
152 -close_free_return:
153 - closedir(dir);
154 -free_return:
155 - free(to_free);
156 - strbuf_release(&path);
157 - strbuf_release(&template_path);
158 - clear_repository_format(&template_format);
159 -}
160 -
161 -/*
162 - * If the git_dir is not directly inside the working tree, then git will not
163 - * find it by default, and we need to set the worktree explicitly.
164 - */
165 -static int needs_work_tree_config(const char *git_dir, const char *work_tree)
166 -{
167 - if (!strcmp(work_tree, "/") && !strcmp(git_dir, "/.git"))
168 - return 0;
169 - if (skip_prefix(git_dir, work_tree, &git_dir) &&
170 - !strcmp(git_dir, "/.git"))
171 - return 0;
172 - return 1;
173 -}
174 -
175 -void initialize_repository_version(int hash_algo, int reinit)
176 -{
177 - char repo_version_string[10];
178 - int repo_version = GIT_REPO_VERSION;
179 -
180 - if (hash_algo != GIT_HASH_SHA1)
181 - repo_version = GIT_REPO_VERSION_READ;
182 -
183 - /* This forces creation of new config file */
184 - xsnprintf(repo_version_string, sizeof(repo_version_string),
185 - "%d", repo_version);
186 - git_config_set("core.repositoryformatversion", repo_version_string);
187 -
188 - if (hash_algo != GIT_HASH_SHA1)
189 - git_config_set("extensions.objectformat",
190 - hash_algos[hash_algo].name);
191 - else if (reinit)
192 - git_config_set_gently("extensions.objectformat", NULL);
193 -}
194 -
195 -static int create_default_files(const char *template_path,
196 - const char *original_git_dir,
197 - const char *initial_branch,
198 - const struct repository_format *fmt,
199 - int prev_bare_repository,
200 - int init_shared_repository,
201 - int quiet)
202 -{
203 - struct stat st1;
204 - struct strbuf buf = STRBUF_INIT;
205 - char *path;
206 - char junk[2];
207 - int reinit;
208 - int filemode;
209 - struct strbuf err = STRBUF_INIT;
210 - const char *init_template_dir = NULL;
211 - const char *work_tree = get_git_work_tree();
212 -
213 - /*
214 - * First copy the templates -- we might have the default
215 - * config file there, in which case we would want to read
216 - * from it after installing.
217 - *
218 - * Before reading that config, we also need to clear out any cached
219 - * values (since we've just potentially changed what's available on
220 - * disk).
221 - */
222 - git_config_get_pathname("init.templatedir", &init_template_dir);
223 - copy_templates(template_path, init_template_dir);
224 - free((char *)init_template_dir);
225 - git_config_clear();
226 - reset_shared_repository();
227 - git_config(git_default_config, NULL);
228 -
229 - /*
230 - * We must make sure command-line options continue to override any
231 - * values we might have just re-read from the config.
232 - */
233 - if (init_shared_repository != -1)
234 - set_shared_repository(init_shared_repository);
235 - /*
236 - * TODO: heed core.bare from config file in templates if no
237 - * command-line override given
238 - */
239 - is_bare_repository_cfg = prev_bare_repository || !work_tree;
240 - /* TODO (continued):
241 - *
242 - * Unfortunately, the line above is equivalent to
243 - * is_bare_repository_cfg = !work_tree;
244 - * which ignores the config entirely even if no `--[no-]bare`
245 - * command line option was present.
246 - *
247 - * To see why, note that before this function, there was this call:
248 - * prev_bare_repository = is_bare_repository()
249 - * expanding the right hand side:
250 - * = is_bare_repository_cfg && !get_git_work_tree()
251 - * = is_bare_repository_cfg && !work_tree
252 - * note that the last simplification above is valid because nothing
253 - * calls repo_init() or set_git_work_tree() between any of the
254 - * relevant calls in the code, and thus the !get_git_work_tree()
255 - * calls will return the same result each time. So, what we are
256 - * interested in computing is the right hand side of the line of
257 - * code just above this comment:
258 - * prev_bare_repository || !work_tree
259 - * = is_bare_repository_cfg && !work_tree || !work_tree
260 - * = !work_tree
261 - * because "A && !B || !B == !B" for all boolean values of A & B.
262 - */
263 -
264 - /*
265 - * We would have created the above under user's umask -- under
266 - * shared-repository settings, we would need to fix them up.
267 - */
268 - if (get_shared_repository()) {
269 - adjust_shared_perm(get_git_dir());
270 - }
271 -
272 - /*
273 - * We need to create a "refs" dir in any case so that older
274 - * versions of git can tell that this is a repository.
275 - */
276 - safe_create_dir(git_path("refs"), 1);
277 - adjust_shared_perm(git_path("refs"));
278 -
279 - if (refs_init_db(&err))
280 - die("failed to set up refs db: %s", err.buf);
281 -
282 - /*
283 - * Point the HEAD symref to the initial branch with if HEAD does
284 - * not yet exist.
285 - */
286 - path = git_path_buf(&buf, "HEAD");
287 - reinit = (!access(path, R_OK)
288 - || readlink(path, junk, sizeof(junk)-1) != -1);
289 - if (!reinit) {
290 - char *ref;
291 -
292 - if (!initial_branch)
293 - initial_branch = git_default_branch_name(quiet);
294 -
295 - ref = xstrfmt("refs/heads/%s", initial_branch);
296 - if (check_refname_format(ref, 0) < 0)
297 - die(_("invalid initial branch name: '%s'"),
298 - initial_branch);
299 -
300 - if (create_symref("HEAD", ref, NULL) < 0)
301 - exit(1);
302 - free(ref);
303 - }
304 -
305 - initialize_repository_version(fmt->hash_algo, 0);
306 -
307 - /* Check filemode trustability */
308 - path = git_path_buf(&buf, "config");
309 - filemode = TEST_FILEMODE;
310 - if (TEST_FILEMODE && !lstat(path, &st1)) {
311 - struct stat st2;
312 - filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
313 - !lstat(path, &st2) &&
314 - st1.st_mode != st2.st_mode &&
315 - !chmod(path, st1.st_mode));
316 - if (filemode && !reinit && (st1.st_mode & S_IXUSR))
317 - filemode = 0;
318 - }
319 - git_config_set("core.filemode", filemode ? "true" : "false");
320 -
321 - if (is_bare_repository())
322 - git_config_set("core.bare", "true");
323 - else {
324 - git_config_set("core.bare", "false");
325 - /* allow template config file to override the default */
326 - if (log_all_ref_updates == LOG_REFS_UNSET)
327 - git_config_set("core.logallrefupdates", "true");
328 - if (needs_work_tree_config(original_git_dir, work_tree))
329 - git_config_set("core.worktree", work_tree);
330 - }
331 -
332 - if (!reinit) {
333 - /* Check if symlink is supported in the work tree */
334 - path = git_path_buf(&buf, "tXXXXXX");
335 - if (!close(xmkstemp(path)) &&
336 - !unlink(path) &&
337 - !symlink("testing", path) &&
338 - !lstat(path, &st1) &&
339 - S_ISLNK(st1.st_mode))
340 - unlink(path); /* good */
341 - else
342 - git_config_set("core.symlinks", "false");
343 -
344 - /* Check if the filesystem is case-insensitive */
345 - path = git_path_buf(&buf, "CoNfIg");
346 - if (!access(path, F_OK))
347 - git_config_set("core.ignorecase", "true");
348 - probe_utf8_pathname_composition();
349 - }
350 -
351 - strbuf_release(&buf);
352 - return reinit;
353 -}
354 -
355 -static void create_object_directory(void)
356 -{
357 - struct strbuf path = STRBUF_INIT;
358 - size_t baselen;
359 -
360 - strbuf_addstr(&path, get_object_directory());
361 - baselen = path.len;
362 -
363 - safe_create_dir(path.buf, 1);
364 -
365 - strbuf_setlen(&path, baselen);
366 - strbuf_addstr(&path, "/pack");
367 - safe_create_dir(path.buf, 1);
368 -
369 - strbuf_setlen(&path, baselen);
370 - strbuf_addstr(&path, "/info");
371 - safe_create_dir(path.buf, 1);
372 -
373 - strbuf_release(&path);
374 -}
375 -
376 -static void separate_git_dir(const char *git_dir, const char *git_link)
377 -{
378 - struct stat st;
379 -
380 - if (!stat(git_link, &st)) {
381 - const char *src;
382 -
383 - if (S_ISREG(st.st_mode))
384 - src = read_gitfile(git_link);
385 - else if (S_ISDIR(st.st_mode))
386 - src = git_link;
387 - else
388 - die(_("unable to handle file type %d"), (int)st.st_mode);
389 -
390 - if (rename(src, git_dir))
391 - die_errno(_("unable to move %s to %s"), src, git_dir);
392 - repair_worktrees(NULL, NULL);
393 - }
394 -
395 - write_file(git_link, "gitdir: %s", git_dir);
396 -}
397 -
398 -static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash)
399 -{
400 - const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
401 - /*
402 - * If we already have an initialized repo, don't allow the user to
403 - * specify a different algorithm, as that could cause corruption.
404 - * Otherwise, if the user has specified one on the command line, use it.
405 - */
406 - if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
407 - die(_("attempt to reinitialize repository with different hash"));
408 - else if (hash != GIT_HASH_UNKNOWN)
409 - repo_fmt->hash_algo = hash;
410 - else if (env) {
411 - int env_algo = hash_algo_by_name(env);
412 - if (env_algo == GIT_HASH_UNKNOWN)
413 - die(_("unknown hash algorithm '%s'"), env);
414 - repo_fmt->hash_algo = env_algo;
415 - }
416 -}
417 -
418 -int init_db(const char *git_dir, const char *real_git_dir,
419 - const char *template_dir, int hash, const char *initial_branch,
420 - int init_shared_repository, unsigned int flags)
421 -{
422 - int reinit;
423 - int exist_ok = flags & INIT_DB_EXIST_OK;
424 - char *original_git_dir = real_pathdup(git_dir, 1);
425 - struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
426 - int prev_bare_repository;
427 -
428 - if (real_git_dir) {
429 - struct stat st;
430 -
431 - if (!exist_ok && !stat(git_dir, &st))
432 - die(_("%s already exists"), git_dir);
433 -
434 - if (!exist_ok && !stat(real_git_dir, &st))
435 - die(_("%s already exists"), real_git_dir);
436 -
437 - set_git_dir(real_git_dir, 1);
438 - git_dir = get_git_dir();
439 - separate_git_dir(git_dir, original_git_dir);
440 - }
441 - else {
442 - set_git_dir(git_dir, 1);
443 - git_dir = get_git_dir();
444 - }
445 - startup_info->have_repository = 1;
446 -
447 - /* Ensure `core.hidedotfiles` is processed */
448 - git_config(platform_core_config, NULL);
449 -
450 - safe_create_dir(git_dir, 0);
451 -
452 - prev_bare_repository = is_bare_repository();
453 -
454 - /* Check to see if the repository version is right.
455 - * Note that a newly created repository does not have
456 - * config file, so this will not fail. What we are catching
457 - * is an attempt to reinitialize new repository with an old tool.
458 - */
459 - check_repository_format(&repo_fmt);
460 -
461 - validate_hash_algorithm(&repo_fmt, hash);
462 -
463 - reinit = create_default_files(template_dir, original_git_dir,
464 - initial_branch, &repo_fmt,
465 - prev_bare_repository,
466 - init_shared_repository,
467 - flags & INIT_DB_QUIET);
468 - if (reinit && initial_branch)
469 - warning(_("re-init: ignored --initial-branch=%s"),
470 - initial_branch);
471 -
472 - create_object_directory();
473 -
474 - if (get_shared_repository()) {
475 - char buf[10];
476 - /* We do not spell "group" and such, so that
477 - * the configuration can be read by older version
478 - * of git. Note, we use octal numbers for new share modes,
479 - * and compatibility values for PERM_GROUP and
480 - * PERM_EVERYBODY.
481 - */
482 - if (get_shared_repository() < 0)
483 - /* force to the mode value */
484 - xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository());
485 - else if (get_shared_repository() == PERM_GROUP)
486 - xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
487 - else if (get_shared_repository() == PERM_EVERYBODY)
488 - xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
489 - else
490 - BUG("invalid value for shared_repository");
491 - git_config_set("core.sharedrepository", buf);
492 - git_config_set("receive.denyNonFastforwards", "true");
493 - }
494 -
495 - if (!(flags & INIT_DB_QUIET)) {
496 - int len = strlen(git_dir);
497 -
498 - if (reinit)
499 - printf(get_shared_repository()
500 - ? _("Reinitialized existing shared Git repository in %s%s\n")
501 - : _("Reinitialized existing Git repository in %s%s\n"),
502 - git_dir, len && git_dir[len-1] != '/' ? "/" : "");
503 - else
504 - printf(get_shared_repository()
505 - ? _("Initialized empty shared Git repository in %s%s\n")
506 - : _("Initialized empty Git repository in %s%s\n"),
507 - git_dir, len && git_dir[len-1] != '/' ? "/" : "");
508 - }
509 -
510 - free(original_git_dir);
511 - return 0;
512 -}
513 -
18 static int guess_repository_type(const char *git_dir)
19 {
20 const char *slash;
cache.h
-9
@@ -322,15 +322,6 @@ void prefetch_cache_entries(const struct index_state *istate,
322 extern struct index_state the_index;
323 #endif
324
325 -#define INIT_DB_QUIET 0x0001
326 -#define INIT_DB_EXIST_OK 0x0002
327 -
328 -int init_db(const char *git_dir, const char *real_git_dir,
329 - const char *template_dir, int hash_algo,
330 - const char *initial_branch, int init_shared_repository,
331 - unsigned int flags);
332 -void initialize_repository_version(int hash_algo, int reinit);
333 -
325 /* Initialize and use the cache information */
326 struct lock_file;
327 void preload_index(struct index_state *index,
setup.c
+492
@@ -1,8 +1,11 @@
1 #include "git-compat-util.h"
2 #include "abspath.h"
3 +#include "copy.h"
4 #include "environment.h"
5 +#include "exec-cmd.h"
6 #include "gettext.h"
7 #include "object-name.h"
8 +#include "refs.h"
9 #include "repository.h"
10 #include "config.h"
11 #include "dir.h"
@@ -12,6 +15,7 @@
15 #include "promisor-remote.h"
16 #include "quote.h"
17 #include "trace2.h"
18 +#include "worktree.h"
19 #include "wrapper.h"
20
21 static int inside_git_dir = -1;
@@ -1713,3 +1717,491 @@ int daemonize(void)
1717 return 0;
1718 #endif
1719 }
1720 +
1721 +#ifdef NO_TRUSTABLE_FILEMODE
1722 +#define TEST_FILEMODE 0
1723 +#else
1724 +#define TEST_FILEMODE 1
1725 +#endif
1726 +
1727 +#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
1728 +
1729 +static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
1730 + DIR *dir)
1731 +{
1732 + size_t path_baselen = path->len;
1733 + size_t template_baselen = template_path->len;
1734 + struct dirent *de;
1735 +
1736 + /* Note: if ".git/hooks" file exists in the repository being
1737 + * re-initialized, /etc/core-git/templates/hooks/update would
1738 + * cause "git init" to fail here. I think this is sane but
1739 + * it means that the set of templates we ship by default, along
1740 + * with the way the namespace under .git/ is organized, should
1741 + * be really carefully chosen.
1742 + */
1743 + safe_create_dir(path->buf, 1);
1744 + while ((de = readdir(dir)) != NULL) {
1745 + struct stat st_git, st_template;
1746 + int exists = 0;
1747 +
1748 + strbuf_setlen(path, path_baselen);
1749 + strbuf_setlen(template_path, template_baselen);
1750 +
1751 + if (de->d_name[0] == '.')
1752 + continue;
1753 + strbuf_addstr(path, de->d_name);
1754 + strbuf_addstr(template_path, de->d_name);
1755 + if (lstat(path->buf, &st_git)) {
1756 + if (errno != ENOENT)
1757 + die_errno(_("cannot stat '%s'"), path->buf);
1758 + }
1759 + else
1760 + exists = 1;
1761 +
1762 + if (lstat(template_path->buf, &st_template))
1763 + die_errno(_("cannot stat template '%s'"), template_path->buf);
1764 +
1765 + if (S_ISDIR(st_template.st_mode)) {
1766 + DIR *subdir = opendir(template_path->buf);
1767 + if (!subdir)
1768 + die_errno(_("cannot opendir '%s'"), template_path->buf);
1769 + strbuf_addch(path, '/');
1770 + strbuf_addch(template_path, '/');
1771 + copy_templates_1(path, template_path, subdir);
1772 + closedir(subdir);
1773 + }
1774 + else if (exists)
1775 + continue;
1776 + else if (S_ISLNK(st_template.st_mode)) {
1777 + struct strbuf lnk = STRBUF_INIT;
1778 + if (strbuf_readlink(&lnk, template_path->buf,
1779 + st_template.st_size) < 0)
1780 + die_errno(_("cannot readlink '%s'"), template_path->buf);
1781 + if (symlink(lnk.buf, path->buf))
1782 + die_errno(_("cannot symlink '%s' '%s'"),
1783 + lnk.buf, path->buf);
1784 + strbuf_release(&lnk);
1785 + }
1786 + else if (S_ISREG(st_template.st_mode)) {
1787 + if (copy_file(path->buf, template_path->buf, st_template.st_mode))
1788 + die_errno(_("cannot copy '%s' to '%s'"),
1789 + template_path->buf, path->buf);
1790 + }
1791 + else
1792 + error(_("ignoring template %s"), template_path->buf);
1793 + }
1794 +}
1795 +
1796 +static void copy_templates(const char *template_dir, const char *init_template_dir)
1797 +{
1798 + struct strbuf path = STRBUF_INIT;
1799 + struct strbuf template_path = STRBUF_INIT;
1800 + size_t template_len;
1801 + struct repository_format template_format = REPOSITORY_FORMAT_INIT;
1802 + struct strbuf err = STRBUF_INIT;
1803 + DIR *dir;
1804 + char *to_free = NULL;
1805 +
1806 + if (!template_dir)
1807 + template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
1808 + if (!template_dir)
1809 + template_dir = init_template_dir;
1810 + if (!template_dir)
1811 + template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
1812 + if (!template_dir[0]) {
1813 + free(to_free);
1814 + return;
1815 + }
1816 +
1817 + strbuf_addstr(&template_path, template_dir);
1818 + strbuf_complete(&template_path, '/');
1819 + template_len = template_path.len;
1820 +
1821 + dir = opendir(template_path.buf);
1822 + if (!dir) {
1823 + warning(_("templates not found in %s"), template_dir);
1824 + goto free_return;
1825 + }
1826 +
1827 + /* Make sure that template is from the correct vintage */
1828 + strbuf_addstr(&template_path, "config");
1829 + read_repository_format(&template_format, template_path.buf);
1830 + strbuf_setlen(&template_path, template_len);
1831 +
1832 + /*
1833 + * No mention of version at all is OK, but anything else should be
1834 + * verified.
1835 + */
1836 + if (template_format.version >= 0 &&
1837 + verify_repository_format(&template_format, &err) < 0) {
1838 + warning(_("not copying templates from '%s': %s"),
1839 + template_dir, err.buf);
1840 + strbuf_release(&err);
1841 + goto close_free_return;
1842 + }
1843 +
1844 + strbuf_addstr(&path, get_git_common_dir());
1845 + strbuf_complete(&path, '/');
1846 + copy_templates_1(&path, &template_path, dir);
1847 +close_free_return:
1848 + closedir(dir);
1849 +free_return:
1850 + free(to_free);
1851 + strbuf_release(&path);
1852 + strbuf_release(&template_path);
1853 + clear_repository_format(&template_format);
1854 +}
1855 +
1856 +/*
1857 + * If the git_dir is not directly inside the working tree, then git will not
1858 + * find it by default, and we need to set the worktree explicitly.
1859 + */
1860 +static int needs_work_tree_config(const char *git_dir, const char *work_tree)
1861 +{
1862 + if (!strcmp(work_tree, "/") && !strcmp(git_dir, "/.git"))
1863 + return 0;
1864 + if (skip_prefix(git_dir, work_tree, &git_dir) &&
1865 + !strcmp(git_dir, "/.git"))
1866 + return 0;
1867 + return 1;
1868 +}
1869 +
1870 +void initialize_repository_version(int hash_algo, int reinit)
1871 +{
1872 + char repo_version_string[10];
1873 + int repo_version = GIT_REPO_VERSION;
1874 +
1875 + if (hash_algo != GIT_HASH_SHA1)
1876 + repo_version = GIT_REPO_VERSION_READ;
1877 +
1878 + /* This forces creation of new config file */
1879 + xsnprintf(repo_version_string, sizeof(repo_version_string),
1880 + "%d", repo_version);
1881 + git_config_set("core.repositoryformatversion", repo_version_string);
1882 +
1883 + if (hash_algo != GIT_HASH_SHA1)
1884 + git_config_set("extensions.objectformat",
1885 + hash_algos[hash_algo].name);
1886 + else if (reinit)
1887 + git_config_set_gently("extensions.objectformat", NULL);
1888 +}
1889 +
1890 +static int create_default_files(const char *template_path,
1891 + const char *original_git_dir,
1892 + const char *initial_branch,
1893 + const struct repository_format *fmt,
1894 + int prev_bare_repository,
1895 + int init_shared_repository,
1896 + int quiet)
1897 +{
1898 + struct stat st1;
1899 + struct strbuf buf = STRBUF_INIT;
1900 + char *path;
1901 + char junk[2];
1902 + int reinit;
1903 + int filemode;
1904 + struct strbuf err = STRBUF_INIT;
1905 + const char *init_template_dir = NULL;
1906 + const char *work_tree = get_git_work_tree();
1907 +
1908 + /*
1909 + * First copy the templates -- we might have the default
1910 + * config file there, in which case we would want to read
1911 + * from it after installing.
1912 + *
1913 + * Before reading that config, we also need to clear out any cached
1914 + * values (since we've just potentially changed what's available on
1915 + * disk).
1916 + */
1917 + git_config_get_pathname("init.templatedir", &init_template_dir);
1918 + copy_templates(template_path, init_template_dir);
1919 + free((char *)init_template_dir);
1920 + git_config_clear();
1921 + reset_shared_repository();
1922 + git_config(git_default_config, NULL);
1923 +
1924 + /*
1925 + * We must make sure command-line options continue to override any
1926 + * values we might have just re-read from the config.
1927 + */
1928 + if (init_shared_repository != -1)
1929 + set_shared_repository(init_shared_repository);
1930 + /*
1931 + * TODO: heed core.bare from config file in templates if no
1932 + * command-line override given
1933 + */
1934 + is_bare_repository_cfg = prev_bare_repository || !work_tree;
1935 + /* TODO (continued):
1936 + *
1937 + * Unfortunately, the line above is equivalent to
1938 + * is_bare_repository_cfg = !work_tree;
1939 + * which ignores the config entirely even if no `--[no-]bare`
1940 + * command line option was present.
1941 + *
1942 + * To see why, note that before this function, there was this call:
1943 + * prev_bare_repository = is_bare_repository()
1944 + * expanding the right hand side:
1945 + * = is_bare_repository_cfg && !get_git_work_tree()
1946 + * = is_bare_repository_cfg && !work_tree
1947 + * note that the last simplification above is valid because nothing
1948 + * calls repo_init() or set_git_work_tree() between any of the
1949 + * relevant calls in the code, and thus the !get_git_work_tree()
1950 + * calls will return the same result each time. So, what we are
1951 + * interested in computing is the right hand side of the line of
1952 + * code just above this comment:
1953 + * prev_bare_repository || !work_tree
1954 + * = is_bare_repository_cfg && !work_tree || !work_tree
1955 + * = !work_tree
1956 + * because "A && !B || !B == !B" for all boolean values of A & B.
1957 + */
1958 +
1959 + /*
1960 + * We would have created the above under user's umask -- under
1961 + * shared-repository settings, we would need to fix them up.
1962 + */
1963 + if (get_shared_repository()) {
1964 + adjust_shared_perm(get_git_dir());
1965 + }
1966 +
1967 + /*
1968 + * We need to create a "refs" dir in any case so that older
1969 + * versions of git can tell that this is a repository.
1970 + */
1971 + safe_create_dir(git_path("refs"), 1);
1972 + adjust_shared_perm(git_path("refs"));
1973 +
1974 + if (refs_init_db(&err))
1975 + die("failed to set up refs db: %s", err.buf);
1976 +
1977 + /*
1978 + * Point the HEAD symref to the initial branch with if HEAD does
1979 + * not yet exist.
1980 + */
1981 + path = git_path_buf(&buf, "HEAD");
1982 + reinit = (!access(path, R_OK)
1983 + || readlink(path, junk, sizeof(junk)-1) != -1);
1984 + if (!reinit) {
1985 + char *ref;
1986 +
1987 + if (!initial_branch)
1988 + initial_branch = git_default_branch_name(quiet);
1989 +
1990 + ref = xstrfmt("refs/heads/%s", initial_branch);
1991 + if (check_refname_format(ref, 0) < 0)
1992 + die(_("invalid initial branch name: '%s'"),
1993 + initial_branch);
1994 +
1995 + if (create_symref("HEAD", ref, NULL) < 0)
1996 + exit(1);
1997 + free(ref);
1998 + }
1999 +
2000 + initialize_repository_version(fmt->hash_algo, 0);
2001 +
2002 + /* Check filemode trustability */
2003 + path = git_path_buf(&buf, "config");
2004 + filemode = TEST_FILEMODE;
2005 + if (TEST_FILEMODE && !lstat(path, &st1)) {
2006 + struct stat st2;
2007 + filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
2008 + !lstat(path, &st2) &&
2009 + st1.st_mode != st2.st_mode &&
2010 + !chmod(path, st1.st_mode));
2011 + if (filemode && !reinit && (st1.st_mode & S_IXUSR))
2012 + filemode = 0;
2013 + }
2014 + git_config_set("core.filemode", filemode ? "true" : "false");
2015 +
2016 + if (is_bare_repository())
2017 + git_config_set("core.bare", "true");
2018 + else {
2019 + git_config_set("core.bare", "false");
2020 + /* allow template config file to override the default */
2021 + if (log_all_ref_updates == LOG_REFS_UNSET)
2022 + git_config_set("core.logallrefupdates", "true");
2023 + if (needs_work_tree_config(original_git_dir, work_tree))
2024 + git_config_set("core.worktree", work_tree);
2025 + }
2026 +
2027 + if (!reinit) {
2028 + /* Check if symlink is supported in the work tree */
2029 + path = git_path_buf(&buf, "tXXXXXX");
2030 + if (!close(xmkstemp(path)) &&
2031 + !unlink(path) &&
2032 + !symlink("testing", path) &&
2033 + !lstat(path, &st1) &&
2034 + S_ISLNK(st1.st_mode))
2035 + unlink(path); /* good */
2036 + else
2037 + git_config_set("core.symlinks", "false");
2038 +
2039 + /* Check if the filesystem is case-insensitive */
2040 + path = git_path_buf(&buf, "CoNfIg");
2041 + if (!access(path, F_OK))
2042 + git_config_set("core.ignorecase", "true");
2043 + probe_utf8_pathname_composition();
2044 + }
2045 +
2046 + strbuf_release(&buf);
2047 + return reinit;
2048 +}
2049 +
2050 +static void create_object_directory(void)
2051 +{
2052 + struct strbuf path = STRBUF_INIT;
2053 + size_t baselen;
2054 +
2055 + strbuf_addstr(&path, get_object_directory());
2056 + baselen = path.len;
2057 +
2058 + safe_create_dir(path.buf, 1);
2059 +
2060 + strbuf_setlen(&path, baselen);
2061 + strbuf_addstr(&path, "/pack");
2062 + safe_create_dir(path.buf, 1);
2063 +
2064 + strbuf_setlen(&path, baselen);
2065 + strbuf_addstr(&path, "/info");
2066 + safe_create_dir(path.buf, 1);
2067 +
2068 + strbuf_release(&path);
2069 +}
2070 +
2071 +static void separate_git_dir(const char *git_dir, const char *git_link)
2072 +{
2073 + struct stat st;
2074 +
2075 + if (!stat(git_link, &st)) {
2076 + const char *src;
2077 +
2078 + if (S_ISREG(st.st_mode))
2079 + src = read_gitfile(git_link);
2080 + else if (S_ISDIR(st.st_mode))
2081 + src = git_link;
2082 + else
2083 + die(_("unable to handle file type %d"), (int)st.st_mode);
2084 +
2085 + if (rename(src, git_dir))
2086 + die_errno(_("unable to move %s to %s"), src, git_dir);
2087 + repair_worktrees(NULL, NULL);
2088 + }
2089 +
2090 + write_file(git_link, "gitdir: %s", git_dir);
2091 +}
2092 +
2093 +static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash)
2094 +{
2095 + const char *env = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
2096 + /*
2097 + * If we already have an initialized repo, don't allow the user to
2098 + * specify a different algorithm, as that could cause corruption.
2099 + * Otherwise, if the user has specified one on the command line, use it.
2100 + */
2101 + if (repo_fmt->version >= 0 && hash != GIT_HASH_UNKNOWN && hash != repo_fmt->hash_algo)
2102 + die(_("attempt to reinitialize repository with different hash"));
2103 + else if (hash != GIT_HASH_UNKNOWN)
2104 + repo_fmt->hash_algo = hash;
2105 + else if (env) {
2106 + int env_algo = hash_algo_by_name(env);
2107 + if (env_algo == GIT_HASH_UNKNOWN)
2108 + die(_("unknown hash algorithm '%s'"), env);
2109 + repo_fmt->hash_algo = env_algo;
2110 + }
2111 +}
2112 +
2113 +int init_db(const char *git_dir, const char *real_git_dir,
2114 + const char *template_dir, int hash, const char *initial_branch,
2115 + int init_shared_repository, unsigned int flags)
2116 +{
2117 + int reinit;
2118 + int exist_ok = flags & INIT_DB_EXIST_OK;
2119 + char *original_git_dir = real_pathdup(git_dir, 1);
2120 + struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
2121 + int prev_bare_repository;
2122 +
2123 + if (real_git_dir) {
2124 + struct stat st;
2125 +
2126 + if (!exist_ok && !stat(git_dir, &st))
2127 + die(_("%s already exists"), git_dir);
2128 +
2129 + if (!exist_ok && !stat(real_git_dir, &st))
2130 + die(_("%s already exists"), real_git_dir);
2131 +
2132 + set_git_dir(real_git_dir, 1);
2133 + git_dir = get_git_dir();
2134 + separate_git_dir(git_dir, original_git_dir);
2135 + }
2136 + else {
2137 + set_git_dir(git_dir, 1);
2138 + git_dir = get_git_dir();
2139 + }
2140 + startup_info->have_repository = 1;
2141 +
2142 + /* Ensure `core.hidedotfiles` is processed */
2143 + git_config(platform_core_config, NULL);
2144 +
2145 + safe_create_dir(git_dir, 0);
2146 +
2147 + prev_bare_repository = is_bare_repository();
2148 +
2149 + /* Check to see if the repository version is right.
2150 + * Note that a newly created repository does not have
2151 + * config file, so this will not fail. What we are catching
2152 + * is an attempt to reinitialize new repository with an old tool.
2153 + */
2154 + check_repository_format(&repo_fmt);
2155 +
2156 + validate_hash_algorithm(&repo_fmt, hash);
2157 +
2158 + reinit = create_default_files(template_dir, original_git_dir,
2159 + initial_branch, &repo_fmt,
2160 + prev_bare_repository,
2161 + init_shared_repository,
2162 + flags & INIT_DB_QUIET);
2163 + if (reinit && initial_branch)
2164 + warning(_("re-init: ignored --initial-branch=%s"),
2165 + initial_branch);
2166 +
2167 + create_object_directory();
2168 +
2169 + if (get_shared_repository()) {
2170 + char buf[10];
2171 + /* We do not spell "group" and such, so that
2172 + * the configuration can be read by older version
2173 + * of git. Note, we use octal numbers for new share modes,
2174 + * and compatibility values for PERM_GROUP and
2175 + * PERM_EVERYBODY.
2176 + */
2177 + if (get_shared_repository() < 0)
2178 + /* force to the mode value */
2179 + xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository());
2180 + else if (get_shared_repository() == PERM_GROUP)
2181 + xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
2182 + else if (get_shared_repository() == PERM_EVERYBODY)
2183 + xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
2184 + else
2185 + BUG("invalid value for shared_repository");
2186 + git_config_set("core.sharedrepository", buf);
2187 + git_config_set("receive.denyNonFastforwards", "true");
2188 + }
2189 +
2190 + if (!(flags & INIT_DB_QUIET)) {
2191 + int len = strlen(git_dir);
2192 +
2193 + if (reinit)
2194 + printf(get_shared_repository()
2195 + ? _("Reinitialized existing shared Git repository in %s%s\n")
2196 + : _("Reinitialized existing Git repository in %s%s\n"),
2197 + git_dir, len && git_dir[len-1] != '/' ? "/" : "");
2198 + else
2199 + printf(get_shared_repository()
2200 + ? _("Initialized empty shared Git repository in %s%s\n")
2201 + : _("Initialized empty Git repository in %s%s\n"),
2202 + git_dir, len && git_dir[len-1] != '/' ? "/" : "");
2203 + }
2204 +
2205 + free(original_git_dir);
2206 + return 0;
2207 +}
setup.h
+9
@@ -140,6 +140,15 @@ int verify_repository_format(const struct repository_format *format,
140 */
141 void check_repository_format(struct repository_format *fmt);
142
143 +#define INIT_DB_QUIET 0x0001
144 +#define INIT_DB_EXIST_OK 0x0002
145 +
146 +int init_db(const char *git_dir, const char *real_git_dir,
147 + const char *template_dir, int hash_algo,
148 + const char *initial_branch, int init_shared_repository,
149 + unsigned int flags);
150 +void initialize_repository_version(int hash_algo, int reinit);
151 +
152 /*
153 * NOTE NOTE NOTE!!
154 *