]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/init-db.c
Merge branch 'mp/rebase-label-length-limit' into maint-2.42
[thirdparty/git.git] / builtin / init-db.c
CommitLineData
8bc9a0c7
LT
1/*
2 * GIT - The information manager from hell
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
bc5c5ec0 6#include "builtin.h"
0b027f6c 7#include "abspath.h"
b2141fc1 8#include "config.h"
32a8f510 9#include "environment.h"
f394e093 10#include "gettext.h"
87bed179 11#include "object-file.h"
596f91ee 12#include "parse-options.h"
d1cbe1e6 13#include "path.h"
e38da487 14#include "setup.h"
88e4e183 15#include "strbuf.h"
e83c5163 16
f225aeb2 17static int guess_repository_type(const char *git_dir)
6adcca3f 18{
6adcca3f 19 const char *slash;
56b9f6e7
RS
20 char *cwd;
21 int cwd_is_git_dir;
6adcca3f 22
6adcca3f
JH
23 /*
24 * "GIT_DIR=. git init" is always bare.
25 * "GIT_DIR=`pwd` git init" too.
26 */
27 if (!strcmp(".", git_dir))
f225aeb2 28 return 1;
56b9f6e7
RS
29 cwd = xgetcwd();
30 cwd_is_git_dir = !strcmp(git_dir, cwd);
31 free(cwd);
32 if (cwd_is_git_dir)
f225aeb2 33 return 1;
6adcca3f
JH
34 /*
35 * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
36 */
37 if (!strcmp(git_dir, ".git"))
f225aeb2 38 return 0;
6adcca3f
JH
39 slash = strrchr(git_dir, '/');
40 if (slash && !strcmp(slash, "/.git"))
f225aeb2 41 return 0;
6adcca3f
JH
42
43 /*
44 * Otherwise it is often bare. At this point
45 * we are just guessing.
46 */
f225aeb2 47 return 1;
6adcca3f
JH
48}
49
596f91ee
MK
50static int shared_callback(const struct option *opt, const char *arg, int unset)
51{
517fe807 52 BUG_ON_OPT_NEG(unset);
596f91ee
MK
53 *((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
54 return 0;
55}
56
57static const char *const init_db_usage[] = {
5af8b61c 58 N_("git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
d9054a19
ÆAB
59 " [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
60 " [-b <branch-name> | --initial-branch=<branch-name>]\n"
5af8b61c 61 " [--shared[=<permissions>]] [<directory>]"),
596f91ee
MK
62 NULL
63};
d3af621b 64
4696cb93
ZW
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 */
a633fca0 71int cmd_init_db(int argc, const char **argv, const char *prefix)
e83c5163 72{
cad88fdf 73 const char *git_dir;
b57fb80a 74 const char *real_git_dir = NULL;
83518360 75 const char *work_tree;
c3c8835f 76 const char *template_dir = NULL;
f225aeb2 77 unsigned int flags = 0;
8b8f7189 78 const char *object_format = NULL;
32ba12da 79 const char *initial_branch = NULL;
8b8f7189 80 int hash_algo = GIT_HASH_UNKNOWN;
fc817350 81 int init_shared_repository = -1;
596f91ee 82 const struct option init_db_options[] = {
ce4a5e53
NTND
83 OPT_STRING(0, "template", &template_dir, N_("template-directory"),
84 N_("directory from which templates will be used")),
596f91ee 85 OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
ce4a5e53 86 N_("create a bare repository"), 1),
596f91ee 87 { OPTION_CALLBACK, 0, "shared", &init_shared_repository,
ce4a5e53
NTND
88 N_("permissions"),
89 N_("specify that the git repository is to be shared amongst several users"),
596f91ee 90 PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
ce4a5e53
NTND
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")),
32ba12da
JS
94 OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
95 N_("override the name of the initial branch")),
8b8f7189 96 OPT_STRING(0, "object-format", &object_format, N_("hash"),
97 N_("specify the hash algorithm to use")),
596f91ee
MK
98 OPT_END()
99 };
100
0397ff24
JH
101 argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
102
ccf236a2 103 if (real_git_dir && is_bare_repository_cfg == 1)
43ea635c 104 die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
ccf236a2 105
b57fb80a 106 if (real_git_dir && !is_absolute_path(real_git_dir))
ce83eadd 107 real_git_dir = real_pathdup(real_git_dir, 1);
b57fb80a 108
04fe4d75 109 if (template_dir && *template_dir && !is_absolute_path(template_dir)) {
e1df7fe4 110 template_dir = absolute_pathdup(template_dir);
04fe4d75
AH
111 UNLEAK(template_dir);
112 }
e1df7fe4 113
0397ff24 114 if (argc == 1) {
53d48885
NS
115 int mkdir_tried = 0;
116 retry:
0397ff24 117 if (chdir(argv[0]) < 0) {
53d48885
NS
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 */
7875acb6
JK
125 saved = get_shared_repository();
126 set_shared_repository(0);
0397ff24 127 switch (safe_create_leading_directories_const(argv[0])) {
f3565c0c
MH
128 case SCLD_OK:
129 case SCLD_PERMS:
130 break;
0be0521b 131 case SCLD_EXISTS:
53d48885
NS
132 errno = EEXIST;
133 /* fallthru */
53d48885 134 default:
f3565c0c 135 die_errno(_("cannot mkdir %s"), argv[0]);
53d48885
NS
136 break;
137 }
7875acb6 138 set_shared_repository(saved);
0397ff24 139 if (mkdir(argv[0], 0777) < 0)
33e92e47 140 die_errno(_("cannot mkdir %s"), argv[0]);
53d48885
NS
141 mkdir_tried = 1;
142 goto retry;
143 }
33e92e47 144 die_errno(_("cannot chdir to %s"), argv[0]);
53d48885 145 }
0397ff24
JH
146 } else if (0 < argc) {
147 usage(init_db_usage[0]);
d3af621b 148 }
0397ff24 149 if (is_bare_repository_cfg == 1) {
4d3ab44d
RS
150 char *cwd = xgetcwd();
151 setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
152 free(cwd);
d3af621b
JH
153 }
154
8b8f7189 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
5a688fe4 161 if (init_shared_repository != -1)
7875acb6 162 set_shared_repository(init_shared_repository);
5a688fe4 163
6adcca3f
JH
164 /*
165 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
166 * without --bare. Catch the error early.
167 */
e5b07c53
JK
168 git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
169 work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
83518360 170 if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
33e92e47
ÆAB
171 die(_("%s (or --work-tree=<directory>) not allowed without "
172 "specifying %s (or --git-dir=<directory>)"),
6adcca3f
JH
173 GIT_WORK_TREE_ENVIRONMENT,
174 GIT_DIR_ENVIRONMENT);
175
cad88fdf
LT
176 /*
177 * Set up the default .git directory contents
178 */
ef0a89a6 179 if (!git_dir)
cad88fdf 180 git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
af6e277c 181
59d876cc
ES
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
f225aeb2
DB
206 if (is_bare_repository_cfg < 0)
207 is_bare_repository_cfg = guess_repository_type(git_dir);
208
209 if (!is_bare_repository_cfg) {
b31d2022
NTND
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);
ce83eadd 213 git_work_tree_cfg = real_pathdup(rel, 1);
b31d2022 214 free(rel);
f225aeb2 215 }
56b9f6e7
RS
216 if (!git_work_tree_cfg)
217 git_work_tree_cfg = xgetcwd();
83518360 218 if (work_tree)
2d186c8b 219 set_git_work_tree(work_tree);
83518360
NTND
220 else
221 set_git_work_tree(git_work_tree_cfg);
f225aeb2 222 if (access(get_git_work_tree(), X_OK))
33e92e47 223 die_errno (_("Cannot access work tree '%s'"),
0721c314 224 get_git_work_tree());
94df2506 225 }
83518360 226 else {
ccf236a2
ES
227 if (real_git_dir)
228 die(_("--separate-git-dir incompatible with bare repository"));
83518360 229 if (work_tree)
2d186c8b 230 set_git_work_tree(work_tree);
83518360 231 }
af6e277c 232
0e5bba53 233 UNLEAK(real_git_dir);
e5b07c53
JK
234 UNLEAK(git_dir);
235 UNLEAK(work_tree);
0e5bba53 236
33158701 237 flags |= INIT_DB_EXIST_OK;
32ba12da 238 return init_db(git_dir, real_git_dir, template_dir, hash_algo,
fc817350 239 initial_branch, init_shared_repository, flags);
e83c5163 240}