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 * Magic pathspec 159 * 160 * NEEDSWORK: These need to be moved to dir.h or even to a new 161 * pathspec.h when we restructure get_pathspec() users to use the 162 * "struct pathspec" interface. 163 * 164 * Possible future magic semantics include stuff like: 165 * 166 * { PATHSPEC_NOGLOB, '!', "noglob" }, 167 * { PATHSPEC_ICASE, '\0', "icase" }, 168 * { PATHSPEC_RECURSIVE, '*', "recursive" }, 169 * { PATHSPEC_REGEXP, '\0', "regexp" }, 170 * 171 */ 172#define PATHSPEC_FROMTOP (1<<0) 173 174static struct pathspec_magic { 175unsigned bit; 176char mnemonic;/* this cannot be ':'! */ 177const char*name; 178} pathspec_magic[] = { 179{ PATHSPEC_FROMTOP,'/',"top"}, 180}; 181 182/* 183 * Take an element of a pathspec and check for magic signatures. 184 * Append the result to the prefix. 185 * 186 * For now, we only parse the syntax and throw out anything other than 187 * "top" magic. 188 * 189 * NEEDSWORK: This needs to be rewritten when we start migrating 190 * get_pathspec() users to use the "struct pathspec" interface. For 191 * example, a pathspec element may be marked as case-insensitive, but 192 * the prefix part must always match literally, and a single stupid 193 * string cannot express such a case. 194 */ 195static const char*prefix_pathspec(const char*prefix,int prefixlen,const char*elt) 196{ 197unsigned magic =0; 198const char*copyfrom = elt; 199int i; 200 201if(elt[0] !=':') { 202;/* nothing to do */ 203}else if(elt[1] =='(') { 204/* longhand */ 205const char*nextat; 206for(copyfrom = elt +2; 207*copyfrom && *copyfrom !=')'; 208 copyfrom = nextat) { 209size_t len =strcspn(copyfrom,",)"); 210if(copyfrom[len] ==',') 211 nextat = copyfrom + len +1; 212else 213/* handle ')' and '\0' */ 214 nextat = copyfrom + len; 215if(!len) 216continue; 217for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 218if(strlen(pathspec_magic[i].name) == len && 219!strncmp(pathspec_magic[i].name, copyfrom, len)) { 220 magic |= pathspec_magic[i].bit; 221break; 222} 223if(ARRAY_SIZE(pathspec_magic) <= i) 224die("Invalid pathspec magic '%.*s' in '%s'", 225(int) len, copyfrom, elt); 226} 227if(*copyfrom !=')') 228die("Missing ')' at the end of pathspec magic in '%s'", elt); 229 copyfrom++; 230}else{ 231/* shorthand */ 232for(copyfrom = elt +1; 233*copyfrom && *copyfrom !=':'; 234 copyfrom++) { 235char ch = *copyfrom; 236 237if(!is_pathspec_magic(ch)) 238break; 239for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 240if(pathspec_magic[i].mnemonic == ch) { 241 magic |= pathspec_magic[i].bit; 242break; 243} 244if(ARRAY_SIZE(pathspec_magic) <= i) 245die("Unimplemented pathspec magic '%c' in '%s'", 246 ch, elt); 247} 248if(*copyfrom ==':') 249 copyfrom++; 250} 251 252if(magic & PATHSPEC_FROMTOP) 253returnxstrdup(copyfrom); 254else 255returnprefix_path(prefix, prefixlen, copyfrom); 256} 257 258/* 259 * N.B. get_pathspec() is deprecated in favor of the "struct pathspec" 260 * based interface - see pathspec_magic above. 261 * 262 * Arguments: 263 * - prefix - a path relative to the root of the working tree 264 * - pathspec - a list of paths underneath the prefix path 265 * 266 * Iterates over pathspec, prepending each path with prefix, 267 * and return the resulting list. 268 * 269 * If pathspec is empty, return a singleton list containing prefix. 270 * 271 * If pathspec and prefix are both empty, return an empty list. 272 * 273 * This is typically used by built-in commands such as add.c, in order 274 * to normalize argv arguments provided to the built-in into a list of 275 * paths to process, all relative to the root of the working tree. 276 */ 277const char**get_pathspec(const char*prefix,const char**pathspec) 278{ 279const char*entry = *pathspec; 280const char**src, **dst; 281int prefixlen; 282 283if(!prefix && !entry) 284return NULL; 285 286if(!entry) { 287static const char*spec[2]; 288 spec[0] = prefix; 289 spec[1] = NULL; 290return spec; 291} 292 293/* Otherwise we have to re-write the entries.. */ 294 src = pathspec; 295 dst = pathspec; 296 prefixlen = prefix ?strlen(prefix) :0; 297while(*src) { 298*(dst++) =prefix_pathspec(prefix, prefixlen, *src); 299 src++; 300} 301*dst = NULL; 302if(!*pathspec) 303return NULL; 304return pathspec; 305} 306 307/* 308 * Test if it looks like we're at a git directory. 309 * We want to see: 310 * 311 * - either an objects/ directory _or_ the proper 312 * GIT_OBJECT_DIRECTORY environment variable 313 * - a refs/ directory 314 * - either a HEAD symlink or a HEAD file that is formatted as 315 * a proper "ref:", or a regular file HEAD that has a properly 316 * formatted sha1 object name. 317 */ 318intis_git_directory(const char*suspect) 319{ 320char path[PATH_MAX]; 321size_t len =strlen(suspect); 322 323if(PATH_MAX <= len +strlen("/objects")) 324die("Too long path: %.*s",60, suspect); 325strcpy(path, suspect); 326if(getenv(DB_ENVIRONMENT)) { 327if(access(getenv(DB_ENVIRONMENT), X_OK)) 328return0; 329} 330else{ 331strcpy(path + len,"/objects"); 332if(access(path, X_OK)) 333return0; 334} 335 336strcpy(path + len,"/refs"); 337if(access(path, X_OK)) 338return0; 339 340strcpy(path + len,"/HEAD"); 341if(validate_headref(path)) 342return0; 343 344return1; 345} 346 347intis_inside_git_dir(void) 348{ 349if(inside_git_dir <0) 350 inside_git_dir =is_inside_dir(get_git_dir()); 351return inside_git_dir; 352} 353 354intis_inside_work_tree(void) 355{ 356if(inside_work_tree <0) 357 inside_work_tree =is_inside_dir(get_git_work_tree()); 358return inside_work_tree; 359} 360 361voidsetup_work_tree(void) 362{ 363struct strbuf sb = STRBUF_INIT; 364const char*work_tree, *git_dir; 365static int initialized =0; 366 367if(initialized) 368return; 369 work_tree =get_git_work_tree(); 370 git_dir =get_git_dir(); 371if(!is_absolute_path(git_dir)) 372 git_dir =real_path(get_git_dir()); 373if(!work_tree ||chdir(work_tree)) 374die("This operation must be run in a work tree"); 375 376/* 377 * Make sure subsequent git processes find correct worktree 378 * if $GIT_WORK_TREE is set relative 379 */ 380if(getenv(GIT_WORK_TREE_ENVIRONMENT)) 381setenv(GIT_WORK_TREE_ENVIRONMENT,".",1); 382 383set_git_dir(relative_path(git_dir, work_tree, &sb)); 384 initialized =1; 385 386strbuf_release(&sb); 387} 388 389static intcheck_repository_format_gently(const char*gitdir,int*nongit_ok) 390{ 391char repo_config[PATH_MAX+1]; 392 393/* 394 * git_config() can't be used here because it calls git_pathdup() 395 * to get $GIT_CONFIG/config. That call will make setup_git_env() 396 * set git_dir to ".git". 397 * 398 * We are in gitdir setup, no git dir has been found useable yet. 399 * Use a gentler version of git_config() to check if this repo 400 * is a good one. 401 */ 402snprintf(repo_config, PATH_MAX,"%s/config", gitdir); 403git_config_early(check_repository_format_version, NULL, repo_config); 404if(GIT_REPO_VERSION < repository_format_version) { 405if(!nongit_ok) 406die("Expected git repo version <=%d, found%d", 407 GIT_REPO_VERSION, repository_format_version); 408warning("Expected git repo version <=%d, found%d", 409 GIT_REPO_VERSION, repository_format_version); 410warning("Please upgrade Git"); 411*nongit_ok = -1; 412return-1; 413} 414return0; 415} 416 417/* 418 * Try to read the location of the git directory from the .git file, 419 * return path to git directory if found. 420 */ 421const char*read_gitfile(const char*path) 422{ 423char*buf; 424char*dir; 425const char*slash; 426struct stat st; 427int fd; 428 ssize_t len; 429 430if(stat(path, &st)) 431return NULL; 432if(!S_ISREG(st.st_mode)) 433return NULL; 434 fd =open(path, O_RDONLY); 435if(fd <0) 436die_errno("Error opening '%s'", path); 437 buf =xmalloc(st.st_size +1); 438 len =read_in_full(fd, buf, st.st_size); 439close(fd); 440if(len != st.st_size) 441die("Error reading%s", path); 442 buf[len] ='\0'; 443if(prefixcmp(buf,"gitdir: ")) 444die("Invalid gitfile format:%s", path); 445while(buf[len -1] =='\n'|| buf[len -1] =='\r') 446 len--; 447if(len <9) 448die("No path in gitfile:%s", path); 449 buf[len] ='\0'; 450 dir = buf +8; 451 452if(!is_absolute_path(dir) && (slash =strrchr(path,'/'))) { 453size_t pathlen = slash+1- path; 454size_t dirlen = pathlen + len -8; 455 dir =xmalloc(dirlen +1); 456strncpy(dir, path, pathlen); 457strncpy(dir + pathlen, buf +8, len -8); 458 dir[dirlen] ='\0'; 459free(buf); 460 buf = dir; 461} 462 463if(!is_git_directory(dir)) 464die("Not a git repository:%s", dir); 465 path =real_path(dir); 466 467free(buf); 468return path; 469} 470 471static const char*setup_explicit_git_dir(const char*gitdirenv, 472char*cwd,int len, 473int*nongit_ok) 474{ 475const char*work_tree_env =getenv(GIT_WORK_TREE_ENVIRONMENT); 476const char*worktree; 477char*gitfile; 478int offset; 479 480if(PATH_MAX -40<strlen(gitdirenv)) 481die("'$%s' too big", GIT_DIR_ENVIRONMENT); 482 483 gitfile = (char*)read_gitfile(gitdirenv); 484if(gitfile) { 485 gitfile =xstrdup(gitfile); 486 gitdirenv = gitfile; 487} 488 489if(!is_git_directory(gitdirenv)) { 490if(nongit_ok) { 491*nongit_ok =1; 492free(gitfile); 493return NULL; 494} 495die("Not a git repository: '%s'", gitdirenv); 496} 497 498if(check_repository_format_gently(gitdirenv, nongit_ok)) { 499free(gitfile); 500return NULL; 501} 502 503/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */ 504if(work_tree_env) 505set_git_work_tree(work_tree_env); 506else if(is_bare_repository_cfg >0) { 507if(git_work_tree_cfg)/* #22.2, #30 */ 508die("core.bare and core.worktree do not make sense"); 509 510/* #18, #26 */ 511set_git_dir(gitdirenv); 512free(gitfile); 513return NULL; 514} 515else if(git_work_tree_cfg) {/* #6, #14 */ 516if(is_absolute_path(git_work_tree_cfg)) 517set_git_work_tree(git_work_tree_cfg); 518else{ 519char core_worktree[PATH_MAX]; 520if(chdir(gitdirenv)) 521die_errno("Could not chdir to '%s'", gitdirenv); 522if(chdir(git_work_tree_cfg)) 523die_errno("Could not chdir to '%s'", git_work_tree_cfg); 524if(!getcwd(core_worktree, PATH_MAX)) 525die_errno("Could not get directory '%s'", git_work_tree_cfg); 526if(chdir(cwd)) 527die_errno("Could not come back to cwd"); 528set_git_work_tree(core_worktree); 529} 530} 531else if(!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,1)) { 532/* #16d */ 533set_git_dir(gitdirenv); 534free(gitfile); 535return NULL; 536} 537else/* #2, #10 */ 538set_git_work_tree("."); 539 540/* set_git_work_tree() must have been called by now */ 541 worktree =get_git_work_tree(); 542 543/* both get_git_work_tree() and cwd are already normalized */ 544if(!strcmp(cwd, worktree)) {/* cwd == worktree */ 545set_git_dir(gitdirenv); 546free(gitfile); 547return NULL; 548} 549 550 offset =dir_inside_of(cwd, worktree); 551if(offset >=0) {/* cwd inside worktree? */ 552set_git_dir(real_path(gitdirenv)); 553if(chdir(worktree)) 554die_errno("Could not chdir to '%s'", worktree); 555 cwd[len++] ='/'; 556 cwd[len] ='\0'; 557free(gitfile); 558return cwd + offset; 559} 560 561/* cwd outside worktree */ 562set_git_dir(gitdirenv); 563free(gitfile); 564return NULL; 565} 566 567static const char*setup_discovered_git_dir(const char*gitdir, 568char*cwd,int offset,int len, 569int*nongit_ok) 570{ 571if(check_repository_format_gently(gitdir, nongit_ok)) 572return NULL; 573 574/* --work-tree is set without --git-dir; use discovered one */ 575if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 576if(offset != len && !is_absolute_path(gitdir)) 577 gitdir =xstrdup(real_path(gitdir)); 578if(chdir(cwd)) 579die_errno("Could not come back to cwd"); 580returnsetup_explicit_git_dir(gitdir, cwd, len, nongit_ok); 581} 582 583/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ 584if(is_bare_repository_cfg >0) { 585set_git_dir(offset == len ? gitdir :real_path(gitdir)); 586if(chdir(cwd)) 587die_errno("Could not come back to cwd"); 588return NULL; 589} 590 591/* #0, #1, #5, #8, #9, #12, #13 */ 592set_git_work_tree("."); 593if(strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) 594set_git_dir(gitdir); 595 inside_git_dir =0; 596 inside_work_tree =1; 597if(offset == len) 598return NULL; 599 600/* Make "offset" point to past the '/', and add a '/' at the end */ 601 offset++; 602 cwd[len++] ='/'; 603 cwd[len] =0; 604return cwd + offset; 605} 606 607/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */ 608static const char*setup_bare_git_dir(char*cwd,int offset,int len,int*nongit_ok) 609{ 610int root_len; 611 612if(check_repository_format_gently(".", nongit_ok)) 613return NULL; 614 615setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,"0",1); 616 617/* --work-tree is set without --git-dir; use discovered one */ 618if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 619const char*gitdir; 620 621 gitdir = offset == len ?".":xmemdupz(cwd, offset); 622if(chdir(cwd)) 623die_errno("Could not come back to cwd"); 624returnsetup_explicit_git_dir(gitdir, cwd, len, nongit_ok); 625} 626 627 inside_git_dir =1; 628 inside_work_tree =0; 629if(offset != len) { 630if(chdir(cwd)) 631die_errno("Cannot come back to cwd"); 632 root_len =offset_1st_component(cwd); 633 cwd[offset > root_len ? offset : root_len] ='\0'; 634set_git_dir(cwd); 635} 636else 637set_git_dir("."); 638return NULL; 639} 640 641static const char*setup_nongit(const char*cwd,int*nongit_ok) 642{ 643if(!nongit_ok) 644die("Not a git repository (or any of the parent directories):%s", DEFAULT_GIT_DIR_ENVIRONMENT); 645if(chdir(cwd)) 646die_errno("Cannot come back to cwd"); 647*nongit_ok =1; 648return NULL; 649} 650 651static dev_t get_device_or_die(const char*path,const char*prefix,int prefix_len) 652{ 653struct stat buf; 654if(stat(path, &buf)) { 655die_errno("failed to stat '%*s%s%s'", 656 prefix_len, 657 prefix ? prefix :"", 658 prefix ?"/":"", path); 659} 660return buf.st_dev; 661} 662 663/* 664 * A "string_list_each_func_t" function that canonicalizes an entry 665 * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or 666 * discards it if unusable. The presence of an empty entry in 667 * GIT_CEILING_DIRECTORIES turns off canonicalization for all 668 * subsequent entries. 669 */ 670static intcanonicalize_ceiling_entry(struct string_list_item *item, 671void*cb_data) 672{ 673int*empty_entry_found = cb_data; 674char*ceil = item->string; 675 676if(!*ceil) { 677*empty_entry_found =1; 678return0; 679}else if(!is_absolute_path(ceil)) { 680return0; 681}else if(*empty_entry_found) { 682/* Keep entry but do not canonicalize it */ 683return1; 684}else{ 685const char*real_path =real_path_if_valid(ceil); 686if(!real_path) 687return0; 688free(item->string); 689 item->string =xstrdup(real_path); 690return1; 691} 692} 693 694/* 695 * We cannot decide in this function whether we are in the work tree or 696 * not, since the config can only be read _after_ this function was called. 697 */ 698static const char*setup_git_directory_gently_1(int*nongit_ok) 699{ 700const char*env_ceiling_dirs =getenv(CEILING_DIRECTORIES_ENVIRONMENT); 701struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; 702static char cwd[PATH_MAX+1]; 703const char*gitdirenv, *ret; 704char*gitfile; 705int len, offset, offset_parent, ceil_offset = -1; 706 dev_t current_device =0; 707int one_filesystem =1; 708 709/* 710 * Let's assume that we are in a git repository. 711 * If it turns out later that we are somewhere else, the value will be 712 * updated accordingly. 713 */ 714if(nongit_ok) 715*nongit_ok =0; 716 717if(!getcwd(cwd,sizeof(cwd)-1)) 718die_errno("Unable to read current working directory"); 719 offset = len =strlen(cwd); 720 721/* 722 * If GIT_DIR is set explicitly, we're not going 723 * to do any discovery, but we still do repository 724 * validation. 725 */ 726 gitdirenv =getenv(GIT_DIR_ENVIRONMENT); 727if(gitdirenv) 728returnsetup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok); 729 730if(env_ceiling_dirs) { 731int empty_entry_found =0; 732 733string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1); 734filter_string_list(&ceiling_dirs,0, 735 canonicalize_ceiling_entry, &empty_entry_found); 736 ceil_offset =longest_ancestor_length(cwd, &ceiling_dirs); 737string_list_clear(&ceiling_dirs,0); 738} 739 740if(ceil_offset <0&&has_dos_drive_prefix(cwd)) 741 ceil_offset =1; 742 743/* 744 * Test in the following order (relative to the cwd): 745 * - .git (file containing "gitdir: <path>") 746 * - .git/ 747 * - ./ (bare) 748 * - ../.git 749 * - ../.git/ 750 * - ../ (bare) 751 * - ../../.git/ 752 * etc. 753 */ 754 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM",0); 755if(one_filesystem) 756 current_device =get_device_or_die(".", NULL,0); 757for(;;) { 758 gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); 759if(gitfile) 760 gitdirenv = gitfile =xstrdup(gitfile); 761else{ 762if(is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) 763 gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; 764} 765 766if(gitdirenv) { 767 ret =setup_discovered_git_dir(gitdirenv, 768 cwd, offset, len, 769 nongit_ok); 770free(gitfile); 771return ret; 772} 773free(gitfile); 774 775if(is_git_directory(".")) 776returnsetup_bare_git_dir(cwd, offset, len, nongit_ok); 777 778 offset_parent = offset; 779while(--offset_parent > ceil_offset && cwd[offset_parent] !='/'); 780if(offset_parent <= ceil_offset) 781returnsetup_nongit(cwd, nongit_ok); 782if(one_filesystem) { 783 dev_t parent_device =get_device_or_die("..", cwd, offset); 784if(parent_device != current_device) { 785if(nongit_ok) { 786if(chdir(cwd)) 787die_errno("Cannot come back to cwd"); 788*nongit_ok =1; 789return NULL; 790} 791 cwd[offset] ='\0'; 792die("Not a git repository (or any parent up to mount point%s)\n" 793"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd); 794} 795} 796if(chdir("..")) { 797 cwd[offset] ='\0'; 798die_errno("Cannot change to '%s/..'", cwd); 799} 800 offset = offset_parent; 801} 802} 803 804const char*setup_git_directory_gently(int*nongit_ok) 805{ 806const char*prefix; 807 808 prefix =setup_git_directory_gently_1(nongit_ok); 809if(prefix) 810setenv(GIT_PREFIX_ENVIRONMENT, prefix,1); 811else 812setenv(GIT_PREFIX_ENVIRONMENT,"",1); 813 814if(startup_info) { 815 startup_info->have_repository = !nongit_ok || !*nongit_ok; 816 startup_info->prefix = prefix; 817} 818return prefix; 819} 820 821intgit_config_perm(const char*var,const char*value) 822{ 823int i; 824char*endptr; 825 826if(value == NULL) 827return PERM_GROUP; 828 829if(!strcmp(value,"umask")) 830return PERM_UMASK; 831if(!strcmp(value,"group")) 832return PERM_GROUP; 833if(!strcmp(value,"all") || 834!strcmp(value,"world") || 835!strcmp(value,"everybody")) 836return PERM_EVERYBODY; 837 838/* Parse octal numbers */ 839 i =strtol(value, &endptr,8); 840 841/* If not an octal number, maybe true/false? */ 842if(*endptr !=0) 843returngit_config_bool(var, value) ? PERM_GROUP : PERM_UMASK; 844 845/* 846 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is 847 * a chmod value to restrict to. 848 */ 849switch(i) { 850case PERM_UMASK:/* 0 */ 851return PERM_UMASK; 852case OLD_PERM_GROUP:/* 1 */ 853return PERM_GROUP; 854case OLD_PERM_EVERYBODY:/* 2 */ 855return PERM_EVERYBODY; 856} 857 858/* A filemode value was given: 0xxx */ 859 860if((i &0600) !=0600) 861die("Problem with core.sharedRepository filemode value " 862"(0%.3o).\nThe owner of files must always have " 863"read and write permissions.", i); 864 865/* 866 * Mask filemode value. Others can not get write permission. 867 * x flags for directories are handled separately. 868 */ 869return-(i &0666); 870} 871 872intcheck_repository_format_version(const char*var,const char*value,void*cb) 873{ 874if(strcmp(var,"core.repositoryformatversion") ==0) 875 repository_format_version =git_config_int(var, value); 876else if(strcmp(var,"core.sharedrepository") ==0) 877 shared_repository =git_config_perm(var, value); 878else if(strcmp(var,"core.bare") ==0) { 879 is_bare_repository_cfg =git_config_bool(var, value); 880if(is_bare_repository_cfg ==1) 881 inside_work_tree = -1; 882}else if(strcmp(var,"core.worktree") ==0) { 883if(!value) 884returnconfig_error_nonbool(var); 885free(git_work_tree_cfg); 886 git_work_tree_cfg =xstrdup(value); 887 inside_work_tree = -1; 888} 889return0; 890} 891 892intcheck_repository_format(void) 893{ 894returncheck_repository_format_gently(get_git_dir(), NULL); 895} 896 897/* 898 * Returns the "prefix", a path to the current working directory 899 * relative to the work tree root, or NULL, if the current working 900 * directory is not a strict subdirectory of the work tree root. The 901 * prefix always ends with a '/' character. 902 */ 903const char*setup_git_directory(void) 904{ 905returnsetup_git_directory_gently(NULL); 906} 907 908const char*resolve_gitdir(const char*suspect) 909{ 910if(is_git_directory(suspect)) 911return suspect; 912returnread_gitfile(suspect); 913} 914 915/* if any standard file descriptor is missing open it to /dev/null */ 916voidsanitize_stdfds(void) 917{ 918int fd =open("/dev/null", O_RDWR,0); 919while(fd != -1&& fd <2) 920 fd =dup(fd); 921if(fd == -1) 922die_errno("open /dev/null or dup failed"); 923if(fd >2) 924close(fd); 925}