Merge branch 'jh/dirstat' into next
[git/dscho.git] / setup.c
blob4f6b2dac5ff38e0d790175248c87ca615317b206
1 #include "cache.h"
2 #include "dir.h"
4 static int inside_git_dir = -1;
5 static int inside_work_tree = -1;
7 char *prefix_path(const char *prefix, int len, const char *path)
9 const char *orig = path;
10 char *sanitized;
11 if (is_absolute_path(orig)) {
12 const char *temp = real_path(path);
13 sanitized = xmalloc(len + strlen(temp) + 1);
14 strcpy(sanitized, temp);
15 } else {
16 sanitized = xmalloc(len + strlen(path) + 1);
17 if (len)
18 memcpy(sanitized, prefix, len);
19 strcpy(sanitized + len, path);
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 if (!work_tree)
27 goto error_out;
28 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);
36 if (sanitized[len] == '/')
37 len++;
38 memmove(sanitized, sanitized + len, total - len);
40 return sanitized;
44 * Unlike prefix_path, this should be used if the named file does
45 * not have to interact with index entry; i.e. name of a random file
46 * on the filesystem.
48 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
50 static char path[PATH_MAX];
51 #ifndef WIN32
52 if (!pfx_len || is_absolute_path(arg))
53 return arg;
54 memcpy(path, pfx, pfx_len);
55 strcpy(path + pfx_len, arg);
56 #else
57 char *p;
58 /* don't add prefix to absolute paths, but still replace '\' by '/' */
59 if (is_absolute_path(arg))
60 pfx_len = 0;
61 else if (pfx_len)
62 memcpy(path, pfx, pfx_len);
63 strcpy(path + pfx_len, arg);
64 for (p = path + pfx_len; *p; p++)
65 if (*p == '\\')
66 *p = '/';
67 #endif
68 return path;
71 int check_filename(const char *prefix, const char *arg)
73 const char *name;
74 struct stat st;
76 name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
77 if (!lstat(name, &st))
78 return 1; /* file exists */
79 if (errno == ENOENT || errno == ENOTDIR)
80 return 0; /* file does not exist */
81 die_errno("failed to stat '%s'", arg);
84 static void NORETURN die_verify_filename(const char *prefix, const char *arg)
86 unsigned char sha1[20];
87 unsigned mode;
88 /* try a detailed diagnostic ... */
89 get_sha1_with_mode_1(arg, sha1, &mode, 0, prefix);
90 /* ... or fall back the most general message. */
91 die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
92 "Use '--' to separate paths from revisions", arg);
97 * Verify a filename that we got as an argument for a pathspec
98 * entry. Note that a filename that begins with "-" never verifies
99 * as true, because even if such a filename were to exist, we want
100 * it to be preceded by the "--" marker (or we want the user to
101 * use a format like "./-filename")
103 void verify_filename(const char *prefix, const char *arg)
105 if (*arg == '-')
106 die("bad flag '%s' used after filename", arg);
107 if (check_filename(prefix, arg))
108 return;
109 die_verify_filename(prefix, arg);
113 * Opposite of the above: the command line did not have -- marker
114 * and we parsed the arg as a refname. It should not be interpretable
115 * as a filename.
117 void verify_non_filename(const char *prefix, const char *arg)
119 if (!is_inside_work_tree() || is_inside_git_dir())
120 return;
121 if (*arg == '-')
122 return; /* flag */
123 if (!check_filename(prefix, arg))
124 return;
125 die("ambiguous argument '%s': both revision and filename\n"
126 "Use '--' to separate filenames from revisions", arg);
130 * Magic pathspec
132 * NEEDSWORK: These need to be moved to dir.h or even to a new
133 * pathspec.h when we restructure get_pathspec() users to use the
134 * "struct pathspec" interface.
136 * Possible future magic semantics include stuff like:
138 * { PATHSPEC_NOGLOB, '!', "noglob" },
139 * { PATHSPEC_RECURSIVE, '*', "recursive" },
140 * { PATHSPEC_REGEXP, '\0', "regexp" },
143 #define PATHSPEC_FROMTOP (1<<0)
144 #define PATHSPEC_ICASE (1<<1)
146 struct pathspec_magic {
147 unsigned bit;
148 char mnemonic; /* this cannot be ':'! */
149 const char *name;
150 } pathspec_magic[] = {
151 { PATHSPEC_FROMTOP, '/', "top" },
152 { PATHSPEC_ICASE, '\0', "icase" },
156 * Take an element of a pathspec and check for magic signatures.
157 * Append the result to the prefix.
159 * For now, we only parse the syntax and throw out anything other than
160 * "top" magic.
162 * NEEDSWORK: This needs to be rewritten when we start migrating
163 * get_pathspec() users to use the "struct pathspec" interface. For
164 * example, a pathspec element may be marked as case-insensitive, but
165 * the prefix part must always match literally, and a single stupid
166 * string cannot express such a case.
168 const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
170 unsigned magic = 0;
171 const char *copyfrom = elt;
172 const char *retval;
173 int i, free_source = 0;
175 if (elt[0] != ':') {
176 ; /* nothing to do */
177 } else if (elt[1] == '(') {
178 /* longhand */
179 const char *nextat;
180 for (copyfrom = elt + 2;
181 *copyfrom && *copyfrom != ')';
182 copyfrom = nextat) {
183 size_t len = strcspn(copyfrom, ",)");
184 if (copyfrom[len] == ')')
185 nextat = copyfrom + len;
186 else
187 nextat = copyfrom + len + 1;
188 if (!len)
189 continue;
190 for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
191 if (strlen(pathspec_magic[i].name) == len &&
192 !strncmp(pathspec_magic[i].name, copyfrom, len)) {
193 magic |= pathspec_magic[i].bit;
194 break;
196 if (ARRAY_SIZE(pathspec_magic) <= i)
197 die("Invalid pathspec magic '%.*s' in '%s'",
198 (int) len, copyfrom, elt);
200 if (*copyfrom == ')')
201 copyfrom++;
202 } else if (!elt[1]) {
203 /* Just ':' -- no element! */
204 return NULL;
205 } else {
206 /* shorthand */
207 for (copyfrom = elt + 1;
208 *copyfrom && *copyfrom != ':';
209 copyfrom++) {
210 char ch = *copyfrom;
212 if (!is_pathspec_magic(ch))
213 break;
214 for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
215 if (pathspec_magic[i].mnemonic == ch) {
216 magic |= pathspec_magic[i].bit;
217 break;
219 if (ARRAY_SIZE(pathspec_magic) <= i)
220 die("Unimplemented pathspec magic '%c' in '%s'",
221 ch, elt);
223 if (*copyfrom == ':')
224 copyfrom++;
227 if (magic & PATHSPEC_ICASE) {
228 struct strbuf sb = STRBUF_INIT;
229 for (i = 0; copyfrom[i]; i++) {
230 int ch = copyfrom[i];
231 if (('a' <= ch && ch <= 'z') ||
232 ('A' <= ch && ch <= 'Z')) {
233 strbuf_addf(&sb, "[%c%c]",
234 tolower(ch), toupper(ch));
235 } else {
236 strbuf_addch(&sb, ch);
239 if (sb.len) {
240 free_source = 1;
241 copyfrom = strbuf_detach(&sb, NULL);
245 if (magic & PATHSPEC_FROMTOP)
246 retval = xstrdup(copyfrom);
247 else
248 retval = prefix_path(prefix, prefixlen, copyfrom);
249 if (free_source)
250 free((char *)copyfrom);
251 return retval;
254 const char **get_pathspec(const char *prefix, const char **pathspec)
256 const char *entry = *pathspec;
257 const char **src, **dst;
258 int prefixlen;
260 if (!prefix && !entry)
261 return NULL;
263 if (!entry) {
264 static const char *spec[2];
265 spec[0] = prefix;
266 spec[1] = NULL;
267 return spec;
270 /* Otherwise we have to re-write the entries.. */
271 src = pathspec;
272 dst = pathspec;
273 prefixlen = prefix ? strlen(prefix) : 0;
274 while (*src) {
275 *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
276 src++;
278 *dst = NULL;
279 if (!*pathspec)
280 return NULL;
281 return pathspec;
285 * Test if it looks like we're at a git directory.
286 * We want to see:
288 * - either an objects/ directory _or_ the proper
289 * GIT_OBJECT_DIRECTORY environment variable
290 * - a refs/ directory
291 * - either a HEAD symlink or a HEAD file that is formatted as
292 * a proper "ref:", or a regular file HEAD that has a properly
293 * formatted sha1 object name.
295 static int is_git_directory(const char *suspect)
297 char path[PATH_MAX];
298 size_t len = strlen(suspect);
300 if (PATH_MAX <= len + strlen("/objects"))
301 die("Too long path: %.*s", 60, suspect);
302 strcpy(path, suspect);
303 if (getenv(DB_ENVIRONMENT)) {
304 if (access(getenv(DB_ENVIRONMENT), X_OK))
305 return 0;
307 else {
308 strcpy(path + len, "/objects");
309 if (access(path, X_OK))
310 return 0;
313 strcpy(path + len, "/refs");
314 if (access(path, X_OK))
315 return 0;
317 strcpy(path + len, "/HEAD");
318 if (validate_headref(path))
319 return 0;
321 return 1;
324 int is_inside_git_dir(void)
326 if (inside_git_dir < 0)
327 inside_git_dir = is_inside_dir(get_git_dir());
328 return inside_git_dir;
331 int is_inside_work_tree(void)
333 if (inside_work_tree < 0)
334 inside_work_tree = is_inside_dir(get_git_work_tree());
335 return inside_work_tree;
338 void setup_work_tree(void)
340 const char *work_tree, *git_dir;
341 static int initialized = 0;
343 if (initialized)
344 return;
345 work_tree = get_git_work_tree();
346 git_dir = get_git_dir();
347 if (!is_absolute_path(git_dir))
348 git_dir = real_path(get_git_dir());
349 if (!work_tree || chdir(work_tree))
350 die("This operation must be run in a work tree");
353 * Make sure subsequent git processes find correct worktree
354 * if $GIT_WORK_TREE is set relative
356 if (getenv(GIT_WORK_TREE_ENVIRONMENT))
357 setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
359 set_git_dir(relative_path(git_dir, work_tree));
360 initialized = 1;
363 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
365 char repo_config[PATH_MAX+1];
368 * git_config() can't be used here because it calls git_pathdup()
369 * to get $GIT_CONFIG/config. That call will make setup_git_env()
370 * set git_dir to ".git".
372 * We are in gitdir setup, no git dir has been found useable yet.
373 * Use a gentler version of git_config() to check if this repo
374 * is a good one.
376 snprintf(repo_config, PATH_MAX, "%s/config", gitdir);
377 git_config_early(check_repository_format_version, NULL, repo_config);
378 if (GIT_REPO_VERSION < repository_format_version) {
379 if (!nongit_ok)
380 die ("Expected git repo version <= %d, found %d",
381 GIT_REPO_VERSION, repository_format_version);
382 warning("Expected git repo version <= %d, found %d",
383 GIT_REPO_VERSION, repository_format_version);
384 warning("Please upgrade Git");
385 *nongit_ok = -1;
386 return -1;
388 return 0;
392 * Try to read the location of the git directory from the .git file,
393 * return path to git directory if found.
395 const char *read_gitfile_gently(const char *path)
397 char *buf;
398 char *dir;
399 const char *slash;
400 struct stat st;
401 int fd;
402 size_t len;
404 if (stat(path, &st))
405 return NULL;
406 if (!S_ISREG(st.st_mode))
407 return NULL;
408 fd = open(path, O_RDONLY);
409 if (fd < 0)
410 die_errno("Error opening '%s'", path);
411 buf = xmalloc(st.st_size + 1);
412 len = read_in_full(fd, buf, st.st_size);
413 close(fd);
414 if (len != st.st_size)
415 die("Error reading %s", path);
416 buf[len] = '\0';
417 if (prefixcmp(buf, "gitdir: "))
418 die("Invalid gitfile format: %s", path);
419 while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
420 len--;
421 if (len < 9)
422 die("No path in gitfile: %s", path);
423 buf[len] = '\0';
424 dir = buf + 8;
426 if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) {
427 size_t pathlen = slash+1 - path;
428 size_t dirlen = pathlen + len - 8;
429 dir = xmalloc(dirlen + 1);
430 strncpy(dir, path, pathlen);
431 strncpy(dir + pathlen, buf + 8, len - 8);
432 dir[dirlen] = '\0';
433 free(buf);
434 buf = dir;
437 if (!is_git_directory(dir))
438 die("Not a git repository: %s", dir);
439 path = real_path(dir);
441 free(buf);
442 return path;
445 static const char *setup_explicit_git_dir(const char *gitdirenv,
446 char *cwd, int len,
447 int *nongit_ok)
449 const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
450 const char *worktree;
451 char *gitfile;
452 int offset;
454 if (PATH_MAX - 40 < strlen(gitdirenv))
455 die("'$%s' too big", GIT_DIR_ENVIRONMENT);
457 gitfile = (char*)read_gitfile_gently(gitdirenv);
458 if (gitfile) {
459 gitfile = xstrdup(gitfile);
460 gitdirenv = gitfile;
463 if (!is_git_directory(gitdirenv)) {
464 if (nongit_ok) {
465 *nongit_ok = 1;
466 free(gitfile);
467 return NULL;
469 die("Not a git repository: '%s'", gitdirenv);
472 if (check_repository_format_gently(gitdirenv, nongit_ok)) {
473 free(gitfile);
474 return NULL;
477 /* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */
478 if (work_tree_env)
479 set_git_work_tree(work_tree_env);
480 else if (is_bare_repository_cfg > 0) {
481 if (git_work_tree_cfg) /* #22.2, #30 */
482 die("core.bare and core.worktree do not make sense");
484 /* #18, #26 */
485 set_git_dir(gitdirenv);
486 free(gitfile);
487 return NULL;
489 else if (git_work_tree_cfg) { /* #6, #14 */
490 if (is_absolute_path(git_work_tree_cfg))
491 set_git_work_tree(git_work_tree_cfg);
492 else {
493 char core_worktree[PATH_MAX];
494 if (chdir(gitdirenv))
495 die_errno("Could not chdir to '%s'", gitdirenv);
496 if (chdir(git_work_tree_cfg))
497 die_errno("Could not chdir to '%s'", git_work_tree_cfg);
498 if (!getcwd(core_worktree, PATH_MAX))
499 die_errno("Could not get directory '%s'", git_work_tree_cfg);
500 if (chdir(cwd))
501 die_errno("Could not come back to cwd");
502 set_git_work_tree(core_worktree);
505 else /* #2, #10 */
506 set_git_work_tree(".");
508 /* set_git_work_tree() must have been called by now */
509 worktree = get_git_work_tree();
511 /* both get_git_work_tree() and cwd are already normalized */
512 if (!strcmp(cwd, worktree)) { /* cwd == worktree */
513 set_git_dir(gitdirenv);
514 free(gitfile);
515 return NULL;
518 offset = dir_inside_of(cwd, worktree);
519 if (offset >= 0) { /* cwd inside worktree? */
520 set_git_dir(real_path(gitdirenv));
521 if (chdir(worktree))
522 die_errno("Could not chdir to '%s'", worktree);
523 cwd[len++] = '/';
524 cwd[len] = '\0';
525 free(gitfile);
526 return cwd + offset;
529 /* cwd outside worktree */
530 set_git_dir(gitdirenv);
531 free(gitfile);
532 return NULL;
535 static const char *setup_discovered_git_dir(const char *gitdir,
536 char *cwd, int offset, int len,
537 int *nongit_ok)
539 if (check_repository_format_gently(gitdir, nongit_ok))
540 return NULL;
542 /* --work-tree is set without --git-dir; use discovered one */
543 if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
544 if (offset != len && !is_absolute_path(gitdir))
545 gitdir = xstrdup(real_path(gitdir));
546 if (chdir(cwd))
547 die_errno("Could not come back to cwd");
548 return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
551 /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
552 if (is_bare_repository_cfg > 0) {
553 set_git_dir(offset == len ? gitdir : real_path(gitdir));
554 if (chdir(cwd))
555 die_errno("Could not come back to cwd");
556 return NULL;
559 /* #0, #1, #5, #8, #9, #12, #13 */
560 set_git_work_tree(".");
561 if (strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT))
562 set_git_dir(gitdir);
563 inside_git_dir = 0;
564 inside_work_tree = 1;
565 if (offset == len)
566 return NULL;
568 /* Make "offset" point to past the '/', and add a '/' at the end */
569 offset++;
570 cwd[len++] = '/';
571 cwd[len] = 0;
572 return cwd + offset;
575 /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
576 static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
578 int root_len;
580 if (check_repository_format_gently(".", nongit_ok))
581 return NULL;
583 /* --work-tree is set without --git-dir; use discovered one */
584 if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
585 const char *gitdir;
587 gitdir = offset == len ? "." : xmemdupz(cwd, offset);
588 if (chdir(cwd))
589 die_errno("Could not come back to cwd");
590 return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
593 inside_git_dir = 1;
594 inside_work_tree = 0;
595 if (offset != len) {
596 if (chdir(cwd))
597 die_errno("Cannot come back to cwd");
598 root_len = offset_1st_component(cwd);
599 cwd[offset > root_len ? offset : root_len] = '\0';
600 set_git_dir(cwd);
602 else
603 set_git_dir(".");
604 return NULL;
607 static const char *setup_nongit(const char *cwd, int *nongit_ok)
609 if (!nongit_ok)
610 die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
611 if (chdir(cwd))
612 die_errno("Cannot come back to cwd");
613 *nongit_ok = 1;
614 return NULL;
617 static dev_t get_device_or_die(const char *path, const char *prefix)
619 struct stat buf;
620 if (stat(path, &buf))
621 die_errno("failed to stat '%s%s%s'",
622 prefix ? prefix : "",
623 prefix ? "/" : "", path);
624 return buf.st_dev;
628 * We cannot decide in this function whether we are in the work tree or
629 * not, since the config can only be read _after_ this function was called.
631 static const char *setup_git_directory_gently_1(int *nongit_ok)
633 const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
634 static char cwd[PATH_MAX+1];
635 const char *gitdirenv, *ret;
636 char *gitfile;
637 int len, offset, ceil_offset;
638 dev_t current_device = 0;
639 int one_filesystem = 1;
642 * Let's assume that we are in a git repository.
643 * If it turns out later that we are somewhere else, the value will be
644 * updated accordingly.
646 if (nongit_ok)
647 *nongit_ok = 0;
649 if (!getcwd(cwd, sizeof(cwd)-1))
650 die_errno("Unable to read current working directory");
651 offset = len = strlen(cwd);
654 * If GIT_DIR is set explicitly, we're not going
655 * to do any discovery, but we still do repository
656 * validation.
658 gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
659 if (gitdirenv)
660 return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
662 ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
663 if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
664 ceil_offset = 1;
667 * Test in the following order (relative to the cwd):
668 * - .git (file containing "gitdir: <path>")
669 * - .git/
670 * - ./ (bare)
671 * - ../.git
672 * - ../.git/
673 * - ../ (bare)
674 * - ../../.git/
675 * etc.
677 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
678 if (one_filesystem)
679 current_device = get_device_or_die(".", NULL);
680 for (;;) {
681 gitfile = (char*)read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);
682 if (gitfile)
683 gitdirenv = gitfile = xstrdup(gitfile);
684 else {
685 if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))
686 gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT;
689 if (gitdirenv) {
690 ret = setup_discovered_git_dir(gitdirenv,
691 cwd, offset, len,
692 nongit_ok);
693 free(gitfile);
694 return ret;
696 free(gitfile);
698 if (is_git_directory("."))
699 return setup_bare_git_dir(cwd, offset, len, nongit_ok);
701 while (--offset > ceil_offset && cwd[offset] != '/');
702 if (offset <= ceil_offset)
703 return setup_nongit(cwd, nongit_ok);
704 if (one_filesystem) {
705 dev_t parent_device = get_device_or_die("..", cwd);
706 if (parent_device != current_device) {
707 if (nongit_ok) {
708 if (chdir(cwd))
709 die_errno("Cannot come back to cwd");
710 *nongit_ok = 1;
711 return NULL;
713 cwd[offset] = '\0';
714 die("Not a git repository (or any parent up to mount parent %s)\n"
715 "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
718 if (chdir("..")) {
719 cwd[offset] = '\0';
720 die_errno("Cannot change to '%s/..'", cwd);
725 const char *setup_git_directory_gently(int *nongit_ok)
727 const char *prefix;
729 prefix = setup_git_directory_gently_1(nongit_ok);
730 if (startup_info) {
731 startup_info->have_repository = !nongit_ok || !*nongit_ok;
732 startup_info->prefix = prefix;
734 return prefix;
737 int git_config_perm(const char *var, const char *value)
739 int i;
740 char *endptr;
742 if (value == NULL)
743 return PERM_GROUP;
745 if (!strcmp(value, "umask"))
746 return PERM_UMASK;
747 if (!strcmp(value, "group"))
748 return PERM_GROUP;
749 if (!strcmp(value, "all") ||
750 !strcmp(value, "world") ||
751 !strcmp(value, "everybody"))
752 return PERM_EVERYBODY;
754 /* Parse octal numbers */
755 i = strtol(value, &endptr, 8);
757 /* If not an octal number, maybe true/false? */
758 if (*endptr != 0)
759 return git_config_bool(var, value) ? PERM_GROUP : PERM_UMASK;
762 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is
763 * a chmod value to restrict to.
765 switch (i) {
766 case PERM_UMASK: /* 0 */
767 return PERM_UMASK;
768 case OLD_PERM_GROUP: /* 1 */
769 return PERM_GROUP;
770 case OLD_PERM_EVERYBODY: /* 2 */
771 return PERM_EVERYBODY;
774 /* A filemode value was given: 0xxx */
776 if ((i & 0600) != 0600)
777 die("Problem with core.sharedRepository filemode value "
778 "(0%.3o).\nThe owner of files must always have "
779 "read and write permissions.", i);
782 * Mask filemode value. Others can not get write permission.
783 * x flags for directories are handled separately.
785 return -(i & 0666);
788 int check_repository_format_version(const char *var, const char *value, void *cb)
790 if (strcmp(var, "core.repositoryformatversion") == 0)
791 repository_format_version = git_config_int(var, value);
792 else if (strcmp(var, "core.sharedrepository") == 0)
793 shared_repository = git_config_perm(var, value);
794 else if (strcmp(var, "core.bare") == 0) {
795 is_bare_repository_cfg = git_config_bool(var, value);
796 if (is_bare_repository_cfg == 1)
797 inside_work_tree = -1;
798 } else if (strcmp(var, "core.worktree") == 0) {
799 if (!value)
800 return config_error_nonbool(var);
801 free(git_work_tree_cfg);
802 git_work_tree_cfg = xstrdup(value);
803 inside_work_tree = -1;
805 return 0;
808 int check_repository_format(void)
810 return check_repository_format_gently(get_git_dir(), NULL);
814 * Returns the "prefix", a path to the current working directory
815 * relative to the work tree root, or NULL, if the current working
816 * directory is not a strict subdirectory of the work tree root. The
817 * prefix always ends with a '/' character.
819 const char *setup_git_directory(void)
821 return setup_git_directory_gently(NULL);