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