setup.c 20.2 KB
Newer Older
1
#include "cache.h"
2 3 4 5
#include "dir.h"

static int inside_git_dir = -1;
static int inside_work_tree = -1;
6

7
char *prefix_path(const char *prefix, int len, const char *path)
8 9
{
	const char *orig = path;
10 11
	char *sanitized;
	if (is_absolute_path(orig)) {
12
		const char *temp = real_path(path);
13 14 15 16
		sanitized = xmalloc(len + strlen(temp) + 1);
		strcpy(sanitized, temp);
	} else {
		sanitized = xmalloc(len + strlen(path) + 1);
17 18 19
		if (len)
			memcpy(sanitized, prefix, len);
		strcpy(sanitized + len, path);
20
	}
21
	if (normalize_path_copy(sanitized, sanitized))
22
		goto error_out;
23
	if (is_absolute_path(orig)) {
24
		size_t root_len, len, total;
25
		const char *work_tree = get_git_work_tree();
26 27 28
		if (!work_tree)
			goto error_out;
		len = strlen(work_tree);
29
		root_len = offset_1st_component(work_tree);
30
		total = strlen(sanitized) + 1;
31
		if (strncmp(sanitized, work_tree, len) ||
32
		    (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
33
		error_out:
34
			die("'%s' is outside repository", orig);
35 36 37 38 39 40
		}
		if (sanitized[len] == '/')
			len++;
		memmove(sanitized, sanitized + len, total - len);
	}
	return sanitized;
41 42
}

43 44 45 46 47 48 49 50 51 52 53 54 55
int check_filename(const char *prefix, const char *arg)
{
	const char *name;
	struct stat st;

	name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
	if (!lstat(name, &st))
		return 1; /* file exists */
	if (errno == ENOENT || errno == ENOTDIR)
		return 0; /* file does not exist */
	die_errno("failed to stat '%s'", arg);
}

56 57 58 59
static void NORETURN die_verify_filename(const char *prefix, const char *arg)
{
	unsigned char sha1[20];
	unsigned mode;
60 61 62 63 64 65 66 67 68 69 70

	/*
	 * Saying "'(icase)foo' does not exist in the index" when the
	 * user gave us ":(icase)foo" is just stupid.  A magic pathspec
	 * begins with a colon and is followed by a non-alnum; do not
	 * let get_sha1_with_mode_1(only_to_die=1) to even trigger.
	 */
	if (!(arg[0] == ':' && !isalnum(arg[1])))
		/* try a detailed diagnostic ... */
		get_sha1_with_mode_1(arg, sha1, &mode, 1, prefix);

71 72 73 74 75 76
	/* ... or fall back the most general message. */
	die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
	    "Use '--' to separate paths from revisions", arg);

}

77 78 79 80 81 82 83 84 85 86 87
/*
 * Verify a filename that we got as an argument for a pathspec
 * entry. Note that a filename that begins with "-" never verifies
 * as true, because even if such a filename were to exist, we want
 * it to be preceded by the "--" marker (or we want the user to
 * use a format like "./-filename")
 */
void verify_filename(const char *prefix, const char *arg)
{
	if (*arg == '-')
		die("bad flag '%s' used after filename", arg);
88
	if (check_filename(prefix, arg))
89
		return;
90
	die_verify_filename(prefix, arg);
91 92
}

93 94 95 96 97 98 99
/*
 * Opposite of the above: the command line did not have -- marker
 * and we parsed the arg as a refname.  It should not be interpretable
 * as a filename.
 */
void verify_non_filename(const char *prefix, const char *arg)
{
100
	if (!is_inside_work_tree() || is_inside_git_dir())
101
		return;
102 103
	if (*arg == '-')
		return; /* flag */
104 105 106 107
	if (!check_filename(prefix, arg))
		return;
	die("ambiguous argument '%s': both revision and filename\n"
	    "Use '--' to separate filenames from revisions", arg);
108 109
}

110 111 112 113 114 115 116 117 118 119
/*
 * Magic pathspec
 *
 * NEEDSWORK: These need to be moved to dir.h or even to a new
 * pathspec.h when we restructure get_pathspec() users to use the
 * "struct pathspec" interface.
 *
 * Possible future magic semantics include stuff like:
 *
 *	{ PATHSPEC_NOGLOB, '!', "noglob" },
120
 *	{ PATHSPEC_ICASE, '\0', "icase" },
121 122 123 124 125 126
 *	{ PATHSPEC_RECURSIVE, '*', "recursive" },
 *	{ PATHSPEC_REGEXP, '\0', "regexp" },
 *
 */
#define PATHSPEC_FROMTOP    (1<<0)

127
static struct pathspec_magic {
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	unsigned bit;
	char mnemonic; /* this cannot be ':'! */
	const char *name;
} pathspec_magic[] = {
	{ PATHSPEC_FROMTOP, '/', "top" },
};

/*
 * Take an element of a pathspec and check for magic signatures.
 * Append the result to the prefix.
 *
 * For now, we only parse the syntax and throw out anything other than
 * "top" magic.
 *
 * NEEDSWORK: This needs to be rewritten when we start migrating
 * get_pathspec() users to use the "struct pathspec" interface.  For
 * example, a pathspec element may be marked as case-insensitive, but
 * the prefix part must always match literally, and a single stupid
 * string cannot express such a case.
 */
148
static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
149 150 151
{
	unsigned magic = 0;
	const char *copyfrom = elt;
152
	int i;
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

	if (elt[0] != ':') {
		; /* nothing to do */
	} else if (elt[1] == '(') {
		/* longhand */
		const char *nextat;
		for (copyfrom = elt + 2;
		     *copyfrom && *copyfrom != ')';
		     copyfrom = nextat) {
			size_t len = strcspn(copyfrom, ",)");
			if (copyfrom[len] == ')')
				nextat = copyfrom + len;
			else
				nextat = copyfrom + len + 1;
			if (!len)
				continue;
			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
				if (strlen(pathspec_magic[i].name) == len &&
				    !strncmp(pathspec_magic[i].name, copyfrom, len)) {
					magic |= pathspec_magic[i].bit;
					break;
				}
			if (ARRAY_SIZE(pathspec_magic) <= i)
				die("Invalid pathspec magic '%.*s' in '%s'",
				    (int) len, copyfrom, elt);
		}
		if (*copyfrom == ')')
			copyfrom++;
	} else {
		/* shorthand */
		for (copyfrom = elt + 1;
		     *copyfrom && *copyfrom != ':';
		     copyfrom++) {
			char ch = *copyfrom;
187 188 189

			if (!is_pathspec_magic(ch))
				break;
190 191 192 193 194 195
			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
				if (pathspec_magic[i].mnemonic == ch) {
					magic |= pathspec_magic[i].bit;
					break;
				}
			if (ARRAY_SIZE(pathspec_magic) <= i)
196 197
				die("Unimplemented pathspec magic '%c' in '%s'",
				    ch, elt);
198 199 200 201 202 203
		}
		if (*copyfrom == ':')
			copyfrom++;
	}

	if (magic & PATHSPEC_FROMTOP)
204
		return xstrdup(copyfrom);
205
	else
206
		return prefix_path(prefix, prefixlen, copyfrom);
207 208
}

J
Junio C Hamano 已提交
209
const char **get_pathspec(const char *prefix, const char **pathspec)
210
{
J
Junio C Hamano 已提交
211
	const char *entry = *pathspec;
212
	const char **src, **dst;
213 214
	int prefixlen;

215 216
	if (!prefix && !entry)
		return NULL;
217 218 219 220 221 222 223 224 225

	if (!entry) {
		static const char *spec[2];
		spec[0] = prefix;
		spec[1] = NULL;
		return spec;
	}

	/* Otherwise we have to re-write the entries.. */
226 227
	src = pathspec;
	dst = pathspec;
228
	prefixlen = prefix ? strlen(prefix) : 0;
229
	while (*src) {
230
		*(dst++) = prefix_pathspec(prefix, prefixlen, *src);
231 232 233 234 235 236
		src++;
	}
	*dst = NULL;
	if (!*pathspec)
		return NULL;
	return pathspec;
237 238
}

239
/*
240
 * Test if it looks like we're at a git directory.
241
 * We want to see:
242
 *
243
 *  - either an objects/ directory _or_ the proper
244
 *    GIT_OBJECT_DIRECTORY environment variable
245
 *  - a refs/ directory
J
Junio C Hamano 已提交
246
 *  - either a HEAD symlink or a HEAD file that is formatted as
J
Junio C Hamano 已提交
247 248
 *    a proper "ref:", or a regular file HEAD that has a properly
 *    formatted sha1 object name.
249
 */
250
int is_git_directory(const char *suspect)
251
{
252 253 254
	char path[PATH_MAX];
	size_t len = strlen(suspect);

255 256
	if (PATH_MAX <= len + strlen("/objects"))
		die("Too long path: %.*s", 60, suspect);
257 258 259 260 261 262 263 264 265 266 267 268 269
	strcpy(path, suspect);
	if (getenv(DB_ENVIRONMENT)) {
		if (access(getenv(DB_ENVIRONMENT), X_OK))
			return 0;
	}
	else {
		strcpy(path + len, "/objects");
		if (access(path, X_OK))
			return 0;
	}

	strcpy(path + len, "/refs");
	if (access(path, X_OK))
J
Junio C Hamano 已提交
270
		return 0;
271 272

	strcpy(path + len, "/HEAD");
J
Junio C Hamano 已提交
273
	if (validate_headref(path))
274 275
		return 0;

J
Junio C Hamano 已提交
276
	return 1;
277 278
}

279 280
int is_inside_git_dir(void)
{
281 282 283
	if (inside_git_dir < 0)
		inside_git_dir = is_inside_dir(get_git_dir());
	return inside_git_dir;
284 285 286 287
}

int is_inside_work_tree(void)
{
288 289 290
	if (inside_work_tree < 0)
		inside_work_tree = is_inside_dir(get_git_work_tree());
	return inside_work_tree;
291 292
}

293 294
void setup_work_tree(void)
{
295 296 297 298 299 300 301
	const char *work_tree, *git_dir;
	static int initialized = 0;

	if (initialized)
		return;
	work_tree = get_git_work_tree();
	git_dir = get_git_dir();
M
Mike Hommey 已提交
302
	if (!is_absolute_path(git_dir))
303
		git_dir = real_path(get_git_dir());
M
Mike Hommey 已提交
304 305
	if (!work_tree || chdir(work_tree))
		die("This operation must be run in a work tree");
306 307 308 309 310 311 312 313

	/*
	 * Make sure subsequent git processes find correct worktree
	 * if $GIT_WORK_TREE is set relative
	 */
	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);

314
	set_git_dir(relative_path(git_dir, work_tree));
315
	initialized = 1;
M
Mike Hommey 已提交
316 317
}

318
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
319
{
320 321 322 323 324 325 326 327 328 329 330 331 332
	char repo_config[PATH_MAX+1];

	/*
	 * git_config() can't be used here because it calls git_pathdup()
	 * to get $GIT_CONFIG/config. That call will make setup_git_env()
	 * set git_dir to ".git".
	 *
	 * We are in gitdir setup, no git dir has been found useable yet.
	 * Use a gentler version of git_config() to check if this repo
	 * is a good one.
	 */
	snprintf(repo_config, PATH_MAX, "%s/config", gitdir);
	git_config_early(check_repository_format_version, NULL, repo_config);
333 334 335 336 337 338 339 340 341 342 343 344 345
	if (GIT_REPO_VERSION < repository_format_version) {
		if (!nongit_ok)
			die ("Expected git repo version <= %d, found %d",
			     GIT_REPO_VERSION, repository_format_version);
		warning("Expected git repo version <= %d, found %d",
			GIT_REPO_VERSION, repository_format_version);
		warning("Please upgrade Git");
		*nongit_ok = -1;
		return -1;
	}
	return 0;
}

346 347 348 349
/*
 * Try to read the location of the git directory from the .git file,
 * return path to git directory if found.
 */
350
const char *read_gitfile(const char *path)
351 352
{
	char *buf;
353 354
	char *dir;
	const char *slash;
355 356
	struct stat st;
	int fd;
357
	ssize_t len;
358 359 360 361 362 363 364

	if (stat(path, &st))
		return NULL;
	if (!S_ISREG(st.st_mode))
		return NULL;
	fd = open(path, O_RDONLY);
	if (fd < 0)
365
		die_errno("Error opening '%s'", path);
366 367 368 369 370 371 372 373 374 375 376 377 378
	buf = xmalloc(st.st_size + 1);
	len = read_in_full(fd, buf, st.st_size);
	close(fd);
	if (len != st.st_size)
		die("Error reading %s", path);
	buf[len] = '\0';
	if (prefixcmp(buf, "gitdir: "))
		die("Invalid gitfile format: %s", path);
	while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
		len--;
	if (len < 9)
		die("No path in gitfile: %s", path);
	buf[len] = '\0';
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
	dir = buf + 8;

	if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) {
		size_t pathlen = slash+1 - path;
		size_t dirlen = pathlen + len - 8;
		dir = xmalloc(dirlen + 1);
		strncpy(dir, path, pathlen);
		strncpy(dir + pathlen, buf + 8, len - 8);
		dir[dirlen] = '\0';
		free(buf);
		buf = dir;
	}

	if (!is_git_directory(dir))
		die("Not a git repository: %s", dir);
394
	path = real_path(dir);
395

396 397 398 399
	free(buf);
	return path;
}

400
static const char *setup_explicit_git_dir(const char *gitdirenv,
401 402
					  char *cwd, int len,
					  int *nongit_ok)
403
{
404 405 406
	const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
	const char *worktree;
	char *gitfile;
407
	int offset;
408 409 410

	if (PATH_MAX - 40 < strlen(gitdirenv))
		die("'$%s' too big", GIT_DIR_ENVIRONMENT);
411

412
	gitfile = (char*)read_gitfile(gitdirenv);
413 414 415 416 417
	if (gitfile) {
		gitfile = xstrdup(gitfile);
		gitdirenv = gitfile;
	}

418 419 420
	if (!is_git_directory(gitdirenv)) {
		if (nongit_ok) {
			*nongit_ok = 1;
421
			free(gitfile);
422 423 424 425
			return NULL;
		}
		die("Not a git repository: '%s'", gitdirenv);
	}
426 427 428 429

	if (check_repository_format_gently(gitdirenv, nongit_ok)) {
		free(gitfile);
		return NULL;
430
	}
431 432 433 434 435 436 437 438 439 440 441

	/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */
	if (work_tree_env)
		set_git_work_tree(work_tree_env);
	else if (is_bare_repository_cfg > 0) {
		if (git_work_tree_cfg) /* #22.2, #30 */
			die("core.bare and core.worktree do not make sense");

		/* #18, #26 */
		set_git_dir(gitdirenv);
		free(gitfile);
442
		return NULL;
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
	}
	else if (git_work_tree_cfg) { /* #6, #14 */
		if (is_absolute_path(git_work_tree_cfg))
			set_git_work_tree(git_work_tree_cfg);
		else {
			char core_worktree[PATH_MAX];
			if (chdir(gitdirenv))
				die_errno("Could not chdir to '%s'", gitdirenv);
			if (chdir(git_work_tree_cfg))
				die_errno("Could not chdir to '%s'", git_work_tree_cfg);
			if (!getcwd(core_worktree, PATH_MAX))
				die_errno("Could not get directory '%s'", git_work_tree_cfg);
			if (chdir(cwd))
				die_errno("Could not come back to cwd");
			set_git_work_tree(core_worktree);
		}
	}
	else /* #2, #10 */
		set_git_work_tree(".");

	/* set_git_work_tree() must have been called by now */
	worktree = get_git_work_tree();

	/* both get_git_work_tree() and cwd are already normalized */
	if (!strcmp(cwd, worktree)) { /* cwd == worktree */
		set_git_dir(gitdirenv);
		free(gitfile);
470
		return NULL;
471
	}
472

473 474
	offset = dir_inside_of(cwd, worktree);
	if (offset >= 0) {	/* cwd inside worktree? */
475
		set_git_dir(real_path(gitdirenv));
476 477 478 479 480
		if (chdir(worktree))
			die_errno("Could not chdir to '%s'", worktree);
		cwd[len++] = '/';
		cwd[len] = '\0';
		free(gitfile);
481
		return cwd + offset;
482
	}
483 484 485 486 487

	/* cwd outside worktree */
	set_git_dir(gitdirenv);
	free(gitfile);
	return NULL;
488 489
}

490 491 492
static const char *setup_discovered_git_dir(const char *gitdir,
					    char *cwd, int offset, int len,
					    int *nongit_ok)
493
{
494 495
	if (check_repository_format_gently(gitdir, nongit_ok))
		return NULL;
496

497 498 499
	/* --work-tree is set without --git-dir; use discovered one */
	if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
		if (offset != len && !is_absolute_path(gitdir))
500
			gitdir = xstrdup(real_path(gitdir));
501 502 503 504 505
		if (chdir(cwd))
			die_errno("Could not come back to cwd");
		return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
	}

506 507
	/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
	if (is_bare_repository_cfg > 0) {
508
		set_git_dir(offset == len ? gitdir : real_path(gitdir));
509 510
		if (chdir(cwd))
			die_errno("Could not come back to cwd");
511
		return NULL;
512
	}
513

514 515 516 517
	/* #0, #1, #5, #8, #9, #12, #13 */
	set_git_work_tree(".");
	if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT))
		set_git_dir(gitdir);
518
	inside_git_dir = 0;
519
	inside_work_tree = 1;
520 521 522 523 524 525 526 527 528 529
	if (offset == len)
		return NULL;

	/* Make "offset" point to past the '/', and add a '/' at the end */
	offset++;
	cwd[len++] = '/';
	cwd[len] = 0;
	return cwd + offset;
}

530 531
/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
532 533 534
{
	int root_len;

535 536 537
	if (check_repository_format_gently(".", nongit_ok))
		return NULL;

538 539 540 541 542 543 544 545 546 547
	/* --work-tree is set without --git-dir; use discovered one */
	if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
		const char *gitdir;

		gitdir = offset == len ? "." : xmemdupz(cwd, offset);
		if (chdir(cwd))
			die_errno("Could not come back to cwd");
		return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
	}

548
	inside_git_dir = 1;
549
	inside_work_tree = 0;
550
	if (offset != len) {
551 552
		if (chdir(cwd))
			die_errno("Cannot come back to cwd");
553 554 555
		root_len = offset_1st_component(cwd);
		cwd[offset > root_len ? offset : root_len] = '\0';
		set_git_dir(cwd);
556
	}
557
	else
558 559 560 561
		set_git_dir(".");
	return NULL;
}

562 563 564 565 566 567 568 569 570 571
static const char *setup_nongit(const char *cwd, int *nongit_ok)
{
	if (!nongit_ok)
		die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
	if (chdir(cwd))
		die_errno("Cannot come back to cwd");
	*nongit_ok = 1;
	return NULL;
}

572
static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_len)
573 574
{
	struct stat buf;
575 576 577
	if (stat(path, &buf)) {
		die_errno("failed to stat '%*s%s%s'",
				prefix_len,
578 579
				prefix ? prefix : "",
				prefix ? "/" : "", path);
580
	}
581 582 583
	return buf.st_dev;
}

584 585 586 587
/*
 * We cannot decide in this function whether we are in the work tree or
 * not, since the config can only be read _after_ this function was called.
 */
588
static const char *setup_git_directory_gently_1(int *nongit_ok)
589
{
590
	const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
591
	static char cwd[PATH_MAX+1];
592 593
	const char *gitdirenv, *ret;
	char *gitfile;
594
	int len, offset, offset_parent, ceil_offset;
595 596
	dev_t current_device = 0;
	int one_filesystem = 1;
597

598 599 600 601 602 603 604 605
	/*
	 * Let's assume that we are in a git repository.
	 * If it turns out later that we are somewhere else, the value will be
	 * updated accordingly.
	 */
	if (nongit_ok)
		*nongit_ok = 0;

606 607 608 609
	if (!getcwd(cwd, sizeof(cwd)-1))
		die_errno("Unable to read current working directory");
	offset = len = strlen(cwd);

610 611 612 613 614
	/*
	 * If GIT_DIR is set explicitly, we're not going
	 * to do any discovery, but we still do repository
	 * validation.
	 */
615
	gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
616
	if (gitdirenv)
617
		return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
618

619
	ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
J
Junio C Hamano 已提交
620 621
	if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
		ceil_offset = 1;
622

623
	/*
624
	 * Test in the following order (relative to the cwd):
625
	 * - .git (file containing "gitdir: <path>")
626 627
	 * - .git/
	 * - ./ (bare)
628
	 * - ../.git
629 630 631 632
	 * - ../.git/
	 * - ../ (bare)
	 * - ../../.git/
	 *   etc.
633
	 */
634
	one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
635
	if (one_filesystem)
636
		current_device = get_device_or_die(".", NULL, 0);
637
	for (;;) {
638
		gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
		if (gitfile)
			gitdirenv = gitfile = xstrdup(gitfile);
		else {
			if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
				gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
		}

		if (gitdirenv) {
			ret = setup_discovered_git_dir(gitdirenv,
						       cwd, offset, len,
						       nongit_ok);
			free(gitfile);
			return ret;
		}
		free(gitfile);

655
		if (is_git_directory("."))
656 657
			return setup_bare_git_dir(cwd, offset, len, nongit_ok);

658 659 660
		offset_parent = offset;
		while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
		if (offset_parent <= ceil_offset)
661
			return setup_nongit(cwd, nongit_ok);
662
		if (one_filesystem) {
663
			dev_t parent_device = get_device_or_die("..", cwd, offset);
664
			if (parent_device != current_device) {
665 666 667 668 669 670 671
				if (nongit_ok) {
					if (chdir(cwd))
						die_errno("Cannot come back to cwd");
					*nongit_ok = 1;
					return NULL;
				}
				cwd[offset] = '\0';
672
				die("Not a git repository (or any parent up to mount point %s)\n"
673
				"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
674 675
			}
		}
676 677
		if (chdir("..")) {
			cwd[offset] = '\0';
678
			die_errno("Cannot change to '%s/..'", cwd);
679
		}
680
		offset = offset_parent;
681
	}
682
}
683

684 685 686 687 688
const char *setup_git_directory_gently(int *nongit_ok)
{
	const char *prefix;

	prefix = setup_git_directory_gently_1(nongit_ok);
689 690 691 692 693
	if (prefix)
		setenv("GIT_PREFIX", prefix, 1);
	else
		setenv("GIT_PREFIX", "", 1);

694
	if (startup_info) {
695
		startup_info->have_repository = !nongit_ok || !*nongit_ok;
696 697
		startup_info->prefix = prefix;
	}
698 699 700
	return prefix;
}

701 702
int git_config_perm(const char *var, const char *value)
{
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
	int i;
	char *endptr;

	if (value == NULL)
		return PERM_GROUP;

	if (!strcmp(value, "umask"))
		return PERM_UMASK;
	if (!strcmp(value, "group"))
		return PERM_GROUP;
	if (!strcmp(value, "all") ||
	    !strcmp(value, "world") ||
	    !strcmp(value, "everybody"))
		return PERM_EVERYBODY;

	/* Parse octal numbers */
	i = strtol(value, &endptr, 8);

	/* If not an octal number, maybe true/false? */
	if (*endptr != 0)
		return git_config_bool(var, value) ? PERM_GROUP : PERM_UMASK;

	/*
	 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is
727
	 * a chmod value to restrict to.
728 729 730 731 732 733 734 735
	 */
	switch (i) {
	case PERM_UMASK:               /* 0 */
		return PERM_UMASK;
	case OLD_PERM_GROUP:           /* 1 */
		return PERM_GROUP;
	case OLD_PERM_EVERYBODY:       /* 2 */
		return PERM_EVERYBODY;
736
	}
737 738 739 740 741 742 743 744 745 746 747 748

	/* A filemode value was given: 0xxx */

	if ((i & 0600) != 0600)
		die("Problem with core.sharedRepository filemode value "
		    "(0%.3o).\nThe owner of files must always have "
		    "read and write permissions.", i);

	/*
	 * Mask filemode value. Others can not get write permission.
	 * x flags for directories are handled separately.
	 */
749
	return -(i & 0666);
750 751
}

752
int check_repository_format_version(const char *var, const char *value, void *cb)
J
Junio C Hamano 已提交
753
{
754 755
	if (strcmp(var, "core.repositoryformatversion") == 0)
		repository_format_version = git_config_int(var, value);
756
	else if (strcmp(var, "core.sharedrepository") == 0)
757
		shared_repository = git_config_perm(var, value);
758 759 760 761 762
	else if (strcmp(var, "core.bare") == 0) {
		is_bare_repository_cfg = git_config_bool(var, value);
		if (is_bare_repository_cfg == 1)
			inside_work_tree = -1;
	} else if (strcmp(var, "core.worktree") == 0) {
763 764
		if (!value)
			return config_error_nonbool(var);
765
		free(git_work_tree_cfg);
766 767 768
		git_work_tree_cfg = xstrdup(value);
		inside_work_tree = -1;
	}
769
	return 0;
J
Junio C Hamano 已提交
770 771 772 773
}

int check_repository_format(void)
{
774
	return check_repository_format_gently(get_git_dir(), NULL);
J
Junio C Hamano 已提交
775 776
}

C
Clemens Buchacher 已提交
777 778 779 780 781 782
/*
 * Returns the "prefix", a path to the current working directory
 * relative to the work tree root, or NULL, if the current working
 * directory is not a strict subdirectory of the work tree root. The
 * prefix always ends with a '/' character.
 */
783 784
const char *setup_git_directory(void)
{
785
	return setup_git_directory_gently(NULL);
786
}
787 788 789 790 791

const char *resolve_gitdir(const char *suspect)
{
	if (is_git_directory(suspect))
		return suspect;
792
	return read_gitfile(suspect);
793
}