1#include"cache.h" 2#include"dir.h" 3 4static int inside_git_dir = -1; 5static int inside_work_tree = -1; 6 7char*prefix_path(const char*prefix,int len,const char*path) 8{ 9const char*orig = path; 10char*sanitized; 11if(is_absolute_path(orig)) { 12const char*temp =real_path(path); 13 sanitized =xmalloc(len +strlen(temp) +1); 14strcpy(sanitized, temp); 15}else{ 16 sanitized =xmalloc(len +strlen(path) +1); 17if(len) 18memcpy(sanitized, prefix, len); 19strcpy(sanitized + len, path); 20} 21if(normalize_path_copy(sanitized, sanitized)) 22goto error_out; 23if(is_absolute_path(orig)) { 24size_t root_len, len, total; 25const char*work_tree =get_git_work_tree(); 26if(!work_tree) 27goto error_out; 28 len =strlen(work_tree); 29 root_len =offset_1st_component(work_tree); 30 total =strlen(sanitized) +1; 31if(strncmp(sanitized, work_tree, len) || 32(len > root_len && sanitized[len] !='\0'&& sanitized[len] !='/')) { 33 error_out: 34die("'%s' is outside repository", orig); 35} 36if(sanitized[len] =='/') 37 len++; 38memmove(sanitized, sanitized + len, total - len); 39} 40return sanitized; 41} 42 43intcheck_filename(const char*prefix,const char*arg) 44{ 45const char*name; 46struct stat st; 47 48 name = prefix ?prefix_filename(prefix,strlen(prefix), arg) : arg; 49if(!lstat(name, &st)) 50return1;/* file exists */ 51if(errno == ENOENT || errno == ENOTDIR) 52return0;/* file does not exist */ 53die_errno("failed to stat '%s'", arg); 54} 55 56static void NORETURN die_verify_filename(const char*prefix, 57const char*arg, 58int diagnose_misspelt_rev) 59{ 60unsigned char sha1[20]; 61unsigned mode; 62 63if(!diagnose_misspelt_rev) 64die("%s: no such path in the working tree.\n" 65"Use '-- <path>...' to specify paths that do not exist locally.", 66 arg); 67/* 68 * Saying "'(icase)foo' does not exist in the index" when the 69 * user gave us ":(icase)foo" is just stupid. A magic pathspec 70 * begins with a colon and is followed by a non-alnum; do not 71 * let get_sha1_with_mode_1(only_to_die=1) to even trigger. 72 */ 73if(!(arg[0] ==':'&& !isalnum(arg[1]))) 74/* try a detailed diagnostic ... */ 75get_sha1_with_mode_1(arg, sha1, &mode,1, prefix); 76 77/* ... or fall back the most general message. */ 78die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" 79"Use '--' to separate paths from revisions", arg); 80 81} 82 83/* 84 * Verify a filename that we got as an argument for a pathspec 85 * entry. Note that a filename that begins with "-" never verifies 86 * as true, because even if such a filename were to exist, we want 87 * it to be preceded by the "--" marker (or we want the user to 88 * use a format like "./-filename") 89 * 90 * The "diagnose_misspelt_rev" is used to provide a user-friendly 91 * diagnosis when dying upon finding that "name" is not a pathname. 92 * If set to 1, the diagnosis will try to diagnose "name" as an 93 * invalid object name (e.g. HEAD:foo). If set to 0, the diagnosis 94 * will only complain about an inexisting file. 95 * 96 * This function is typically called to check that a "file or rev" 97 * argument is unambiguous. In this case, the caller will want 98 * diagnose_misspelt_rev == 1 when verifying the first non-rev 99 * argument (which could have been a revision), and 100 * diagnose_misspelt_rev == 0 for the next ones (because we already 101 * saw a filename, there's not ambiguity anymore). 102 */ 103voidverify_filename(const char*prefix, 104const char*arg, 105int diagnose_misspelt_rev) 106{ 107if(*arg =='-') 108die("bad flag '%s' used after filename", arg); 109if(check_filename(prefix, arg)) 110return; 111die_verify_filename(prefix, arg, diagnose_misspelt_rev); 112} 113 114/* 115 * Opposite of the above: the command line did not have -- marker 116 * and we parsed the arg as a refname. It should not be interpretable 117 * as a filename. 118 */ 119voidverify_non_filename(const char*prefix,const char*arg) 120{ 121if(!is_inside_work_tree() ||is_inside_git_dir()) 122return; 123if(*arg =='-') 124return;/* flag */ 125if(!check_filename(prefix, arg)) 126return; 127die("ambiguous argument '%s': both revision and filename\n" 128"Use '--' to separate filenames from revisions", arg); 129} 130 131/* 132 * Magic pathspec 133 * 134 * NEEDSWORK: These need to be moved to dir.h or even to a new 135 * pathspec.h when we restructure get_pathspec() users to use the 136 * "struct pathspec" interface. 137 * 138 * Possible future magic semantics include stuff like: 139 * 140 * { PATHSPEC_NOGLOB, '!', "noglob" }, 141 * { PATHSPEC_ICASE, '\0', "icase" }, 142 * { PATHSPEC_RECURSIVE, '*', "recursive" }, 143 * { PATHSPEC_REGEXP, '\0', "regexp" }, 144 * 145 */ 146#define PATHSPEC_FROMTOP (1<<0) 147 148static struct pathspec_magic { 149unsigned bit; 150char mnemonic;/* this cannot be ':'! */ 151const char*name; 152} pathspec_magic[] = { 153{ PATHSPEC_FROMTOP,'/',"top"}, 154}; 155 156/* 157 * Take an element of a pathspec and check for magic signatures. 158 * Append the result to the prefix. 159 * 160 * For now, we only parse the syntax and throw out anything other than 161 * "top" magic. 162 * 163 * NEEDSWORK: This needs to be rewritten when we start migrating 164 * get_pathspec() users to use the "struct pathspec" interface. For 165 * example, a pathspec element may be marked as case-insensitive, but 166 * the prefix part must always match literally, and a single stupid 167 * string cannot express such a case. 168 */ 169static const char*prefix_pathspec(const char*prefix,int prefixlen,const char*elt) 170{ 171unsigned magic =0; 172const char*copyfrom = elt; 173int i; 174 175if(elt[0] !=':') { 176;/* nothing to do */ 177}else if(elt[1] =='(') { 178/* longhand */ 179const char*nextat; 180for(copyfrom = elt +2; 181*copyfrom && *copyfrom !=')'; 182 copyfrom = nextat) { 183size_t len =strcspn(copyfrom,",)"); 184if(copyfrom[len] ==')') 185 nextat = copyfrom + len; 186else 187 nextat = copyfrom + len +1; 188if(!len) 189continue; 190for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 191if(strlen(pathspec_magic[i].name) == len && 192!strncmp(pathspec_magic[i].name, copyfrom, len)) { 193 magic |= pathspec_magic[i].bit; 194break; 195} 196if(ARRAY_SIZE(pathspec_magic) <= i) 197die("Invalid pathspec magic '%.*s' in '%s'", 198(int) len, copyfrom, elt); 199} 200if(*copyfrom ==')') 201 copyfrom++; 202}else{ 203/* shorthand */ 204for(copyfrom = elt +1; 205*copyfrom && *copyfrom !=':'; 206 copyfrom++) { 207char ch = *copyfrom; 208 209if(!is_pathspec_magic(ch)) 210break; 211for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 212if(pathspec_magic[i].mnemonic == ch) { 213 magic |= pathspec_magic[i].bit; 214break; 215} 216if(ARRAY_SIZE(pathspec_magic) <= i) 217die("Unimplemented pathspec magic '%c' in '%s'", 218 ch, elt); 219} 220if(*copyfrom ==':') 221 copyfrom++; 222} 223 224if(magic & PATHSPEC_FROMTOP) 225returnxstrdup(copyfrom); 226else 227returnprefix_path(prefix, prefixlen, copyfrom); 228} 229 230const char**get_pathspec(const char*prefix,const char**pathspec) 231{ 232const char*entry = *pathspec; 233const char**src, **dst; 234int prefixlen; 235 236if(!prefix && !entry) 237return NULL; 238 239if(!entry) { 240static const char*spec[2]; 241 spec[0] = prefix; 242 spec[1] = NULL; 243return spec; 244} 245 246/* Otherwise we have to re-write the entries.. */ 247 src = pathspec; 248 dst = pathspec; 249 prefixlen = prefix ?strlen(prefix) :0; 250while(*src) { 251*(dst++) =prefix_pathspec(prefix, prefixlen, *src); 252 src++; 253} 254*dst = NULL; 255if(!*pathspec) 256return NULL; 257return pathspec; 258} 259 260/* 261 * Test if it looks like we're at a git directory. 262 * We want to see: 263 * 264 * - either an objects/ directory _or_ the proper 265 * GIT_OBJECT_DIRECTORY environment variable 266 * - a refs/ directory 267 * - either a HEAD symlink or a HEAD file that is formatted as 268 * a proper "ref:", or a regular file HEAD that has a properly 269 * formatted sha1 object name. 270 */ 271intis_git_directory(const char*suspect) 272{ 273char path[PATH_MAX]; 274size_t len =strlen(suspect); 275 276if(PATH_MAX <= len +strlen("/objects")) 277die("Too long path: %.*s",60, suspect); 278strcpy(path, suspect); 279if(getenv(DB_ENVIRONMENT)) { 280if(access(getenv(DB_ENVIRONMENT), X_OK)) 281return0; 282} 283else{ 284strcpy(path + len,"/objects"); 285if(access(path, X_OK)) 286return0; 287} 288 289strcpy(path + len,"/refs"); 290if(access(path, X_OK)) 291return0; 292 293strcpy(path + len,"/HEAD"); 294if(validate_headref(path)) 295return0; 296 297return1; 298} 299 300intis_inside_git_dir(void) 301{ 302if(inside_git_dir <0) 303 inside_git_dir =is_inside_dir(get_git_dir()); 304return inside_git_dir; 305} 306 307intis_inside_work_tree(void) 308{ 309if(inside_work_tree <0) 310 inside_work_tree =is_inside_dir(get_git_work_tree()); 311return inside_work_tree; 312} 313 314voidsetup_work_tree(void) 315{ 316const char*work_tree, *git_dir; 317static int initialized =0; 318 319if(initialized) 320return; 321 work_tree =get_git_work_tree(); 322 git_dir =get_git_dir(); 323if(!is_absolute_path(git_dir)) 324 git_dir =real_path(get_git_dir()); 325if(!work_tree ||chdir(work_tree)) 326die("This operation must be run in a work tree"); 327 328/* 329 * Make sure subsequent git processes find correct worktree 330 * if $GIT_WORK_TREE is set relative 331 */ 332if(getenv(GIT_WORK_TREE_ENVIRONMENT)) 333setenv(GIT_WORK_TREE_ENVIRONMENT,".",1); 334 335set_git_dir(relative_path(git_dir, work_tree)); 336 initialized =1; 337} 338 339static intcheck_repository_format_gently(const char*gitdir,int*nongit_ok) 340{ 341char repo_config[PATH_MAX+1]; 342 343/* 344 * git_config() can't be used here because it calls git_pathdup() 345 * to get $GIT_CONFIG/config. That call will make setup_git_env() 346 * set git_dir to ".git". 347 * 348 * We are in gitdir setup, no git dir has been found useable yet. 349 * Use a gentler version of git_config() to check if this repo 350 * is a good one. 351 */ 352snprintf(repo_config, PATH_MAX,"%s/config", gitdir); 353git_config_early(check_repository_format_version, NULL, repo_config); 354if(GIT_REPO_VERSION < repository_format_version) { 355if(!nongit_ok) 356die("Expected git repo version <=%d, found%d", 357 GIT_REPO_VERSION, repository_format_version); 358warning("Expected git repo version <=%d, found%d", 359 GIT_REPO_VERSION, repository_format_version); 360warning("Please upgrade Git"); 361*nongit_ok = -1; 362return-1; 363} 364return0; 365} 366 367/* 368 * Try to read the location of the git directory from the .git file, 369 * return path to git directory if found. 370 */ 371const char*read_gitfile(const char*path) 372{ 373char*buf; 374char*dir; 375const char*slash; 376struct stat st; 377int fd; 378 ssize_t len; 379 380if(stat(path, &st)) 381return NULL; 382if(!S_ISREG(st.st_mode)) 383return NULL; 384 fd =open(path, O_RDONLY); 385if(fd <0) 386die_errno("Error opening '%s'", path); 387 buf =xmalloc(st.st_size +1); 388 len =read_in_full(fd, buf, st.st_size); 389close(fd); 390if(len != st.st_size) 391die("Error reading%s", path); 392 buf[len] ='\0'; 393if(prefixcmp(buf,"gitdir: ")) 394die("Invalid gitfile format:%s", path); 395while(buf[len -1] =='\n'|| buf[len -1] =='\r') 396 len--; 397if(len <9) 398die("No path in gitfile:%s", path); 399 buf[len] ='\0'; 400 dir = buf +8; 401 402if(!is_absolute_path(dir) && (slash =strrchr(path,'/'))) { 403size_t pathlen = slash+1- path; 404size_t dirlen = pathlen + len -8; 405 dir =xmalloc(dirlen +1); 406strncpy(dir, path, pathlen); 407strncpy(dir + pathlen, buf +8, len -8); 408 dir[dirlen] ='\0'; 409free(buf); 410 buf = dir; 411} 412 413if(!is_git_directory(dir)) 414die("Not a git repository:%s", dir); 415 path =real_path(dir); 416 417free(buf); 418return path; 419} 420 421static const char*setup_explicit_git_dir(const char*gitdirenv, 422char*cwd,int len, 423int*nongit_ok) 424{ 425const char*work_tree_env =getenv(GIT_WORK_TREE_ENVIRONMENT); 426const char*worktree; 427char*gitfile; 428int offset; 429 430if(PATH_MAX -40<strlen(gitdirenv)) 431die("'$%s' too big", GIT_DIR_ENVIRONMENT); 432 433 gitfile = (char*)read_gitfile(gitdirenv); 434if(gitfile) { 435 gitfile =xstrdup(gitfile); 436 gitdirenv = gitfile; 437} 438 439if(!is_git_directory(gitdirenv)) { 440if(nongit_ok) { 441*nongit_ok =1; 442free(gitfile); 443return NULL; 444} 445die("Not a git repository: '%s'", gitdirenv); 446} 447 448if(check_repository_format_gently(gitdirenv, nongit_ok)) { 449free(gitfile); 450return NULL; 451} 452 453/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */ 454if(work_tree_env) 455set_git_work_tree(work_tree_env); 456else if(is_bare_repository_cfg >0) { 457if(git_work_tree_cfg)/* #22.2, #30 */ 458die("core.bare and core.worktree do not make sense"); 459 460/* #18, #26 */ 461set_git_dir(gitdirenv); 462free(gitfile); 463return NULL; 464} 465else if(git_work_tree_cfg) {/* #6, #14 */ 466if(is_absolute_path(git_work_tree_cfg)) 467set_git_work_tree(git_work_tree_cfg); 468else{ 469char core_worktree[PATH_MAX]; 470if(chdir(gitdirenv)) 471die_errno("Could not chdir to '%s'", gitdirenv); 472if(chdir(git_work_tree_cfg)) 473die_errno("Could not chdir to '%s'", git_work_tree_cfg); 474if(!getcwd(core_worktree, PATH_MAX)) 475die_errno("Could not get directory '%s'", git_work_tree_cfg); 476if(chdir(cwd)) 477die_errno("Could not come back to cwd"); 478set_git_work_tree(core_worktree); 479} 480} 481else/* #2, #10 */ 482set_git_work_tree("."); 483 484/* set_git_work_tree() must have been called by now */ 485 worktree =get_git_work_tree(); 486 487/* both get_git_work_tree() and cwd are already normalized */ 488if(!strcmp(cwd, worktree)) {/* cwd == worktree */ 489set_git_dir(gitdirenv); 490free(gitfile); 491return NULL; 492} 493 494 offset =dir_inside_of(cwd, worktree); 495if(offset >=0) {/* cwd inside worktree? */ 496set_git_dir(real_path(gitdirenv)); 497if(chdir(worktree)) 498die_errno("Could not chdir to '%s'", worktree); 499 cwd[len++] ='/'; 500 cwd[len] ='\0'; 501free(gitfile); 502return cwd + offset; 503} 504 505/* cwd outside worktree */ 506set_git_dir(gitdirenv); 507free(gitfile); 508return NULL; 509} 510 511static const char*setup_discovered_git_dir(const char*gitdir, 512char*cwd,int offset,int len, 513int*nongit_ok) 514{ 515if(check_repository_format_gently(gitdir, nongit_ok)) 516return NULL; 517 518/* --work-tree is set without --git-dir; use discovered one */ 519if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 520if(offset != len && !is_absolute_path(gitdir)) 521 gitdir =xstrdup(real_path(gitdir)); 522if(chdir(cwd)) 523die_errno("Could not come back to cwd"); 524returnsetup_explicit_git_dir(gitdir, cwd, len, nongit_ok); 525} 526 527/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ 528if(is_bare_repository_cfg >0) { 529set_git_dir(offset == len ? gitdir :real_path(gitdir)); 530if(chdir(cwd)) 531die_errno("Could not come back to cwd"); 532return NULL; 533} 534 535/* #0, #1, #5, #8, #9, #12, #13 */ 536set_git_work_tree("."); 537if(strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) 538set_git_dir(gitdir); 539 inside_git_dir =0; 540 inside_work_tree =1; 541if(offset == len) 542return NULL; 543 544/* Make "offset" point to past the '/', and add a '/' at the end */ 545 offset++; 546 cwd[len++] ='/'; 547 cwd[len] =0; 548return cwd + offset; 549} 550 551/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */ 552static const char*setup_bare_git_dir(char*cwd,int offset,int len,int*nongit_ok) 553{ 554int root_len; 555 556if(check_repository_format_gently(".", nongit_ok)) 557return NULL; 558 559/* --work-tree is set without --git-dir; use discovered one */ 560if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 561const char*gitdir; 562 563 gitdir = offset == len ?".":xmemdupz(cwd, offset); 564if(chdir(cwd)) 565die_errno("Could not come back to cwd"); 566returnsetup_explicit_git_dir(gitdir, cwd, len, nongit_ok); 567} 568 569 inside_git_dir =1; 570 inside_work_tree =0; 571if(offset != len) { 572if(chdir(cwd)) 573die_errno("Cannot come back to cwd"); 574 root_len =offset_1st_component(cwd); 575 cwd[offset > root_len ? offset : root_len] ='\0'; 576set_git_dir(cwd); 577} 578else 579set_git_dir("."); 580return NULL; 581} 582 583static const char*setup_nongit(const char*cwd,int*nongit_ok) 584{ 585if(!nongit_ok) 586die("Not a git repository (or any of the parent directories):%s", DEFAULT_GIT_DIR_ENVIRONMENT); 587if(chdir(cwd)) 588die_errno("Cannot come back to cwd"); 589*nongit_ok =1; 590return NULL; 591} 592 593static dev_t get_device_or_die(const char*path,const char*prefix,int prefix_len) 594{ 595struct stat buf; 596if(stat(path, &buf)) { 597die_errno("failed to stat '%*s%s%s'", 598 prefix_len, 599 prefix ? prefix :"", 600 prefix ?"/":"", path); 601} 602return buf.st_dev; 603} 604 605/* 606 * We cannot decide in this function whether we are in the work tree or 607 * not, since the config can only be read _after_ this function was called. 608 */ 609static const char*setup_git_directory_gently_1(int*nongit_ok) 610{ 611const char*env_ceiling_dirs =getenv(CEILING_DIRECTORIES_ENVIRONMENT); 612static char cwd[PATH_MAX+1]; 613const char*gitdirenv, *ret; 614char*gitfile; 615int len, offset, offset_parent, ceil_offset; 616 dev_t current_device =0; 617int one_filesystem =1; 618 619/* 620 * Let's assume that we are in a git repository. 621 * If it turns out later that we are somewhere else, the value will be 622 * updated accordingly. 623 */ 624if(nongit_ok) 625*nongit_ok =0; 626 627if(!getcwd(cwd,sizeof(cwd)-1)) 628die_errno("Unable to read current working directory"); 629 offset = len =strlen(cwd); 630 631/* 632 * If GIT_DIR is set explicitly, we're not going 633 * to do any discovery, but we still do repository 634 * validation. 635 */ 636 gitdirenv =getenv(GIT_DIR_ENVIRONMENT); 637if(gitdirenv) 638returnsetup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok); 639 640 ceil_offset =longest_ancestor_length(cwd, env_ceiling_dirs); 641if(ceil_offset <0&&has_dos_drive_prefix(cwd)) 642 ceil_offset =1; 643 644/* 645 * Test in the following order (relative to the cwd): 646 * - .git (file containing "gitdir: <path>") 647 * - .git/ 648 * - ./ (bare) 649 * - ../.git 650 * - ../.git/ 651 * - ../ (bare) 652 * - ../../.git/ 653 * etc. 654 */ 655 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM",0); 656if(one_filesystem) 657 current_device =get_device_or_die(".", NULL,0); 658for(;;) { 659 gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); 660if(gitfile) 661 gitdirenv = gitfile =xstrdup(gitfile); 662else{ 663if(is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) 664 gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; 665} 666 667if(gitdirenv) { 668 ret =setup_discovered_git_dir(gitdirenv, 669 cwd, offset, len, 670 nongit_ok); 671free(gitfile); 672return ret; 673} 674free(gitfile); 675 676if(is_git_directory(".")) 677returnsetup_bare_git_dir(cwd, offset, len, nongit_ok); 678 679 offset_parent = offset; 680while(--offset_parent > ceil_offset && cwd[offset_parent] !='/'); 681if(offset_parent <= ceil_offset) 682returnsetup_nongit(cwd, nongit_ok); 683if(one_filesystem) { 684 dev_t parent_device =get_device_or_die("..", cwd, offset); 685if(parent_device != current_device) { 686if(nongit_ok) { 687if(chdir(cwd)) 688die_errno("Cannot come back to cwd"); 689*nongit_ok =1; 690return NULL; 691} 692 cwd[offset] ='\0'; 693die("Not a git repository (or any parent up to mount point%s)\n" 694"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd); 695} 696} 697if(chdir("..")) { 698 cwd[offset] ='\0'; 699die_errno("Cannot change to '%s/..'", cwd); 700} 701 offset = offset_parent; 702} 703} 704 705const char*setup_git_directory_gently(int*nongit_ok) 706{ 707const char*prefix; 708 709 prefix =setup_git_directory_gently_1(nongit_ok); 710if(prefix) 711setenv("GIT_PREFIX", prefix,1); 712else 713setenv("GIT_PREFIX","",1); 714 715if(startup_info) { 716 startup_info->have_repository = !nongit_ok || !*nongit_ok; 717 startup_info->prefix = prefix; 718} 719return prefix; 720} 721 722intgit_config_perm(const char*var,const char*value) 723{ 724int i; 725char*endptr; 726 727if(value == NULL) 728return PERM_GROUP; 729 730if(!strcmp(value,"umask")) 731return PERM_UMASK; 732if(!strcmp(value,"group")) 733return PERM_GROUP; 734if(!strcmp(value,"all") || 735!strcmp(value,"world") || 736!strcmp(value,"everybody")) 737return PERM_EVERYBODY; 738 739/* Parse octal numbers */ 740 i =strtol(value, &endptr,8); 741 742/* If not an octal number, maybe true/false? */ 743if(*endptr !=0) 744returngit_config_bool(var, value) ? PERM_GROUP : PERM_UMASK; 745 746/* 747 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is 748 * a chmod value to restrict to. 749 */ 750switch(i) { 751case PERM_UMASK:/* 0 */ 752return PERM_UMASK; 753case OLD_PERM_GROUP:/* 1 */ 754return PERM_GROUP; 755case OLD_PERM_EVERYBODY:/* 2 */ 756return PERM_EVERYBODY; 757} 758 759/* A filemode value was given: 0xxx */ 760 761if((i &0600) !=0600) 762die("Problem with core.sharedRepository filemode value " 763"(0%.3o).\nThe owner of files must always have " 764"read and write permissions.", i); 765 766/* 767 * Mask filemode value. Others can not get write permission. 768 * x flags for directories are handled separately. 769 */ 770return-(i &0666); 771} 772 773intcheck_repository_format_version(const char*var,const char*value,void*cb) 774{ 775if(strcmp(var,"core.repositoryformatversion") ==0) 776 repository_format_version =git_config_int(var, value); 777else if(strcmp(var,"core.sharedrepository") ==0) 778 shared_repository =git_config_perm(var, value); 779else if(strcmp(var,"core.bare") ==0) { 780 is_bare_repository_cfg =git_config_bool(var, value); 781if(is_bare_repository_cfg ==1) 782 inside_work_tree = -1; 783}else if(strcmp(var,"core.worktree") ==0) { 784if(!value) 785returnconfig_error_nonbool(var); 786free(git_work_tree_cfg); 787 git_work_tree_cfg =xstrdup(value); 788 inside_work_tree = -1; 789} 790return0; 791} 792 793intcheck_repository_format(void) 794{ 795returncheck_repository_format_gently(get_git_dir(), NULL); 796} 797 798/* 799 * Returns the "prefix", a path to the current working directory 800 * relative to the work tree root, or NULL, if the current working 801 * directory is not a strict subdirectory of the work tree root. The 802 * prefix always ends with a '/' character. 803 */ 804const char*setup_git_directory(void) 805{ 806returnsetup_git_directory_gently(NULL); 807} 808 809const char*resolve_gitdir(const char*suspect) 810{ 811if(is_git_directory(suspect)) 812return suspect; 813returnread_gitfile(suspect); 814}