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
*