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