]> git.ipfire.org Git - thirdparty/git.git/blob - builtin/init-db.c
submodule-config.c: strengthen URL fsck check
[thirdparty/git.git] / builtin / init-db.c
1 /*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
6 #include "builtin.h"
7 #include "abspath.h"
8 #include "config.h"
9 #include "environment.h"
10 #include "gettext.h"
11 #include "object-file.h"
12 #include "parse-options.h"
13 #include "path.h"
14 #include "setup.h"
15 #include "strbuf.h"
16
17 static int guess_repository_type(const char *git_dir)
18 {
19 const char *slash;
20 char *cwd;
21 int cwd_is_git_dir;
22
23 /*
24 * "GIT_DIR=. git init" is always bare.
25 * "GIT_DIR=`pwd` git init" too.
26 */
27 if (!strcmp(".", git_dir))
28 return 1;
29 cwd = xgetcwd();
30 cwd_is_git_dir = !strcmp(git_dir, cwd);
31 free(cwd);
32 if (cwd_is_git_dir)
33 return 1;
34 /*
35 * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
36 */
37 if (!strcmp(git_dir, ".git"))
38 return 0;
39 slash = strrchr(git_dir, '/');
40 if (slash && !strcmp(slash, "/.git"))
41 return 0;
42
43 /*
44 * Otherwise it is often bare. At this point
45 * we are just guessing.
46 */
47 return 1;
48 }
49
50 static int shared_callback(const struct option *opt, const char *arg, int unset)
51 {
52 BUG_ON_OPT_NEG(unset);
53 *((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
54 return 0;
55 }
56
57 static const char *const init_db_usage[] = {
58 N_("git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
59 " [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
60 " [-b <branch-name> | --initial-branch=<branch-name>]\n"
61 " [--shared[=<permissions>]] [<directory>]"),
62 NULL
63 };
64
65 /*
66 * If you want to, you can share the DB area with any number of branches.
67 * That has advantages: you can save space by sharing all the SHA1 objects.
68 * On the other hand, it might just make lookup slower and messier. You
69 * be the judge. The default case is to have one DB per managed directory.
70 */
71 int cmd_init_db(int argc, const char **argv, const char *prefix)
72 {
73 const char *git_dir;
74 const char *real_git_dir = NULL;
75 const char *work_tree;
76 const char *template_dir = NULL;
77 unsigned int flags = 0;
78 const char *object_format = NULL;
79 const char *initial_branch = NULL;
80 int hash_algo = GIT_HASH_UNKNOWN;
81 int init_shared_repository = -1;
82 const struct option init_db_options[] = {
83 OPT_STRING(0, "template", &template_dir, N_("template-directory"),
84 N_("directory from which templates will be used")),
85 OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
86 N_("create a bare repository"), 1),
87 { OPTION_CALLBACK, 0, "shared", &init_shared_repository,
88 N_("permissions"),
89 N_("specify that the git repository is to be shared amongst several users"),
90 PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
91 OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
92 OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
93 N_("separate git dir from working tree")),
94 OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
95 N_("override the name of the initial branch")),
96 OPT_STRING(0, "object-format", &object_format, N_("hash"),
97 N_("specify the hash algorithm to use")),
98 OPT_END()
99 };
100
101 argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
102
103 if (real_git_dir && is_bare_repository_cfg == 1)
104 die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
105
106 if (real_git_dir && !is_absolute_path(real_git_dir))
107 real_git_dir = real_pathdup(real_git_dir, 1);
108
109 if (template_dir && *template_dir && !is_absolute_path(template_dir)) {
110 template_dir = absolute_pathdup(template_dir);
111 UNLEAK(template_dir);
112 }
113
114 if (argc == 1) {
115 int mkdir_tried = 0;
116 retry:
117 if (chdir(argv[0]) < 0) {
118 if (!mkdir_tried) {
119 int saved;
120 /*
121 * At this point we haven't read any configuration,
122 * and we know shared_repository should always be 0;
123 * but just in case we play safe.
124 */
125 saved = get_shared_repository();
126 set_shared_repository(0);
127 switch (safe_create_leading_directories_const(argv[0])) {
128 case SCLD_OK:
129 case SCLD_PERMS:
130 break;
131 case SCLD_EXISTS:
132 errno = EEXIST;
133 /* fallthru */
134 default:
135 die_errno(_("cannot mkdir %s"), argv[0]);
136 break;
137 }
138 set_shared_repository(saved);
139 if (mkdir(argv[0], 0777) < 0)
140 die_errno(_("cannot mkdir %s"), argv[0]);
141 mkdir_tried = 1;
142 goto retry;
143 }
144 die_errno(_("cannot chdir to %s"), argv[0]);
145 }
146 } else if (0 < argc) {
147 usage(init_db_usage[0]);
148 }
149 if (is_bare_repository_cfg == 1) {
150 char *cwd = xgetcwd();
151 setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
152 free(cwd);
153 }
154
155 if (object_format) {
156 hash_algo = hash_algo_by_name(object_format);
157 if (hash_algo == GIT_HASH_UNKNOWN)
158 die(_("unknown hash algorithm '%s'"), object_format);
159 }
160
161 if (init_shared_repository != -1)
162 set_shared_repository(init_shared_repository);
163
164 /*
165 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
166 * without --bare. Catch the error early.
167 */
168 git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
169 work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
170 if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
171 die(_("%s (or --work-tree=<directory>) not allowed without "
172 "specifying %s (or --git-dir=<directory>)"),
173 GIT_WORK_TREE_ENVIRONMENT,
174 GIT_DIR_ENVIRONMENT);
175
176 /*
177 * Set up the default .git directory contents
178 */
179 if (!git_dir)
180 git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
181
182 /*
183 * When --separate-git-dir is used inside a linked worktree, take
184 * care to ensure that the common .git/ directory is relocated, not
185 * the worktree-specific .git/worktrees/<id>/ directory.
186 */
187 if (real_git_dir) {
188 int err;
189 const char *p;
190 struct strbuf sb = STRBUF_INIT;
191
192 p = read_gitfile_gently(git_dir, &err);
193 if (p && get_common_dir(&sb, p)) {
194 struct strbuf mainwt = STRBUF_INIT;
195
196 strbuf_addbuf(&mainwt, &sb);
197 strbuf_strip_suffix(&mainwt, "/.git");
198 if (chdir(mainwt.buf) < 0)
199 die_errno(_("cannot chdir to %s"), mainwt.buf);
200 strbuf_release(&mainwt);
201 git_dir = strbuf_detach(&sb, NULL);
202 }
203 strbuf_release(&sb);
204 }
205
206 if (is_bare_repository_cfg < 0)
207 is_bare_repository_cfg = guess_repository_type(git_dir);
208
209 if (!is_bare_repository_cfg) {
210 const char *git_dir_parent = strrchr(git_dir, '/');
211 if (git_dir_parent) {
212 char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
213 git_work_tree_cfg = real_pathdup(rel, 1);
214 free(rel);
215 }
216 if (!git_work_tree_cfg)
217 git_work_tree_cfg = xgetcwd();
218 if (work_tree)
219 set_git_work_tree(work_tree);
220 else
221 set_git_work_tree(git_work_tree_cfg);
222 if (access(get_git_work_tree(), X_OK))
223 die_errno (_("Cannot access work tree '%s'"),
224 get_git_work_tree());
225 }
226 else {
227 if (real_git_dir)
228 die(_("--separate-git-dir incompatible with bare repository"));
229 if (work_tree)
230 set_git_work_tree(work_tree);
231 }
232
233 UNLEAK(real_git_dir);
234 UNLEAK(git_dir);
235 UNLEAK(work_tree);
236
237 flags |= INIT_DB_EXIST_OK;
238 return init_db(git_dir, real_git_dir, template_dir, hash_algo,
239 initial_branch, init_shared_repository, flags);
240 }