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