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