git

Форк
0
/
init-db.c 
253 строки · 7.3 Кб
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 "environment.h"
9
#include "gettext.h"
10
#include "object-file.h"
11
#include "parse-options.h"
12
#include "path.h"
13
#include "refs.h"
14
#include "repository.h"
15
#include "setup.h"
16
#include "strbuf.h"
17

18
static int guess_repository_type(const char *git_dir)
19
{
20
	const char *slash;
21
	char *cwd;
22
	int cwd_is_git_dir;
23

24
	/*
25
	 * "GIT_DIR=. git init" is always bare.
26
	 * "GIT_DIR=`pwd` git init" too.
27
	 */
28
	if (!strcmp(".", git_dir))
29
		return 1;
30
	cwd = xgetcwd();
31
	cwd_is_git_dir = !strcmp(git_dir, cwd);
32
	free(cwd);
33
	if (cwd_is_git_dir)
34
		return 1;
35
	/*
36
	 * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
37
	 */
38
	if (!strcmp(git_dir, ".git"))
39
		return 0;
40
	slash = strrchr(git_dir, '/');
41
	if (slash && !strcmp(slash, "/.git"))
42
		return 0;
43

44
	/*
45
	 * Otherwise it is often bare.  At this point
46
	 * we are just guessing.
47
	 */
48
	return 1;
49
}
50

51
static int shared_callback(const struct option *opt, const char *arg, int unset)
52
{
53
	BUG_ON_OPT_NEG(unset);
54
	*((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
55
	return 0;
56
}
57

58
static const char *const init_db_usage[] = {
59
	N_("git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
60
	   "         [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
61
	   "         [--ref-format=<format>]\n"
62
	   "         [-b <branch-name> | --initial-branch=<branch-name>]\n"
63
	   "         [--shared[=<permissions>]] [<directory>]"),
64
	NULL
65
};
66

67
/*
68
 * If you want to, you can share the DB area with any number of branches.
69
 * That has advantages: you can save space by sharing all the SHA1 objects.
70
 * On the other hand, it might just make lookup slower and messier. You
71
 * be the judge.  The default case is to have one DB per managed directory.
72
 */
73
int cmd_init_db(int argc, const char **argv, const char *prefix)
74
{
75
	const char *git_dir;
76
	const char *real_git_dir = NULL;
77
	const char *work_tree;
78
	const char *template_dir = NULL;
79
	unsigned int flags = 0;
80
	const char *object_format = NULL;
81
	const char *ref_format = NULL;
82
	const char *initial_branch = NULL;
83
	int hash_algo = GIT_HASH_UNKNOWN;
84
	enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
85
	int init_shared_repository = -1;
86
	const struct option init_db_options[] = {
87
		OPT_STRING(0, "template", &template_dir, N_("template-directory"),
88
				N_("directory from which templates will be used")),
89
		OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
90
				N_("create a bare repository"), 1),
91
		{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
92
			N_("permissions"),
93
			N_("specify that the git repository is to be shared amongst several users"),
94
			PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
95
		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
96
		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
97
			   N_("separate git dir from working tree")),
98
		OPT_STRING('b', "initial-branch", &initial_branch, N_("name"),
99
			   N_("override the name of the initial branch")),
100
		OPT_STRING(0, "object-format", &object_format, N_("hash"),
101
			   N_("specify the hash algorithm to use")),
102
		OPT_STRING(0, "ref-format", &ref_format, N_("format"),
103
			   N_("specify the reference format to use")),
104
		OPT_END()
105
	};
106

107
	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
108

109
	if (real_git_dir && is_bare_repository_cfg == 1)
110
		die(_("options '%s' and '%s' cannot be used together"), "--separate-git-dir", "--bare");
111

112
	if (real_git_dir && !is_absolute_path(real_git_dir))
113
		real_git_dir = real_pathdup(real_git_dir, 1);
114

115
	if (template_dir && *template_dir && !is_absolute_path(template_dir)) {
116
		template_dir = absolute_pathdup(template_dir);
117
		UNLEAK(template_dir);
118
	}
119

120
	if (argc == 1) {
121
		int mkdir_tried = 0;
122
	retry:
123
		if (chdir(argv[0]) < 0) {
124
			if (!mkdir_tried) {
125
				int saved;
126
				/*
127
				 * At this point we haven't read any configuration,
128
				 * and we know shared_repository should always be 0;
129
				 * but just in case we play safe.
130
				 */
131
				saved = get_shared_repository();
132
				set_shared_repository(0);
133
				switch (safe_create_leading_directories_const(argv[0])) {
134
				case SCLD_OK:
135
				case SCLD_PERMS:
136
					break;
137
				case SCLD_EXISTS:
138
					errno = EEXIST;
139
					/* fallthru */
140
				default:
141
					die_errno(_("cannot mkdir %s"), argv[0]);
142
					break;
143
				}
144
				set_shared_repository(saved);
145
				if (mkdir(argv[0], 0777) < 0)
146
					die_errno(_("cannot mkdir %s"), argv[0]);
147
				mkdir_tried = 1;
148
				goto retry;
149
			}
150
			die_errno(_("cannot chdir to %s"), argv[0]);
151
		}
152
	} else if (0 < argc) {
153
		usage(init_db_usage[0]);
154
	}
155
	if (is_bare_repository_cfg == 1) {
156
		char *cwd = xgetcwd();
157
		setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
158
		free(cwd);
159
	}
160

161
	if (object_format) {
162
		hash_algo = hash_algo_by_name(object_format);
163
		if (hash_algo == GIT_HASH_UNKNOWN)
164
			die(_("unknown hash algorithm '%s'"), object_format);
165
	}
166

167
	if (ref_format) {
168
		ref_storage_format = ref_storage_format_by_name(ref_format);
169
		if (ref_storage_format == REF_STORAGE_FORMAT_UNKNOWN)
170
			die(_("unknown ref storage format '%s'"), ref_format);
171
	}
172

173
	if (init_shared_repository != -1)
174
		set_shared_repository(init_shared_repository);
175

176
	/*
177
	 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
178
	 * without --bare.  Catch the error early.
179
	 */
180
	git_dir = xstrdup_or_null(getenv(GIT_DIR_ENVIRONMENT));
181
	work_tree = xstrdup_or_null(getenv(GIT_WORK_TREE_ENVIRONMENT));
182
	if ((!git_dir || is_bare_repository_cfg == 1) && work_tree)
183
		die(_("%s (or --work-tree=<directory>) not allowed without "
184
			  "specifying %s (or --git-dir=<directory>)"),
185
		    GIT_WORK_TREE_ENVIRONMENT,
186
		    GIT_DIR_ENVIRONMENT);
187

188
	/*
189
	 * Set up the default .git directory contents
190
	 */
191
	if (!git_dir)
192
		git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
193

194
	/*
195
	 * When --separate-git-dir is used inside a linked worktree, take
196
	 * care to ensure that the common .git/ directory is relocated, not
197
	 * the worktree-specific .git/worktrees/<id>/ directory.
198
	 */
199
	if (real_git_dir) {
200
		int err;
201
		const char *p;
202
		struct strbuf sb = STRBUF_INIT;
203

204
		p = read_gitfile_gently(git_dir, &err);
205
		if (p && get_common_dir(&sb, p)) {
206
			struct strbuf mainwt = STRBUF_INIT;
207

208
			strbuf_addbuf(&mainwt, &sb);
209
			strbuf_strip_suffix(&mainwt, "/.git");
210
			if (chdir(mainwt.buf) < 0)
211
				die_errno(_("cannot chdir to %s"), mainwt.buf);
212
			strbuf_release(&mainwt);
213
			git_dir = strbuf_detach(&sb, NULL);
214
		}
215
		strbuf_release(&sb);
216
	}
217

218
	if (is_bare_repository_cfg < 0)
219
		is_bare_repository_cfg = guess_repository_type(git_dir);
220

221
	if (!is_bare_repository_cfg) {
222
		const char *git_dir_parent = strrchr(git_dir, '/');
223
		if (git_dir_parent) {
224
			char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
225
			git_work_tree_cfg = real_pathdup(rel, 1);
226
			free(rel);
227
		}
228
		if (!git_work_tree_cfg)
229
			git_work_tree_cfg = xgetcwd();
230
		if (work_tree)
231
			set_git_work_tree(work_tree);
232
		else
233
			set_git_work_tree(git_work_tree_cfg);
234
		if (access(get_git_work_tree(), X_OK))
235
			die_errno (_("Cannot access work tree '%s'"),
236
				   get_git_work_tree());
237
	}
238
	else {
239
		if (real_git_dir)
240
			die(_("--separate-git-dir incompatible with bare repository"));
241
		if (work_tree)
242
			set_git_work_tree(work_tree);
243
	}
244

245
	UNLEAK(real_git_dir);
246
	UNLEAK(git_dir);
247
	UNLEAK(work_tree);
248

249
	flags |= INIT_DB_EXIST_OK;
250
	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
251
		       ref_storage_format, initial_branch,
252
		       init_shared_repository, flags);
253
}
254

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.