1#include"cache.h" 2#include"repository.h" 3#include"config.h" 4#include"dir.h" 5#include"string-list.h" 6#include"chdir-notify.h" 7#include"promisor-remote.h" 8 9static int inside_git_dir = -1; 10static int inside_work_tree = -1; 11static int work_tree_config_is_bogus; 12 13static struct startup_info the_startup_info; 14struct startup_info *startup_info = &the_startup_info; 15 16/* 17 * The input parameter must contain an absolute path, and it must already be 18 * normalized. 19 * 20 * Find the part of an absolute path that lies inside the work tree by 21 * dereferencing symlinks outside the work tree, for example: 22 * /dir1/repo/dir2/file (work tree is /dir1/repo) -> dir2/file 23 * /dir/file (work tree is /) -> dir/file 24 * /dir/symlink1/symlink2 (symlink1 points to work tree) -> symlink2 25 * /dir/repolink/file (repolink points to /dir/repo) -> file 26 * /dir/repo (exactly equal to work tree) -> (empty string) 27 */ 28static intabspath_part_inside_repo(char*path) 29{ 30size_t len; 31size_t wtlen; 32char*path0; 33int off; 34const char*work_tree =get_git_work_tree(); 35 36if(!work_tree) 37return-1; 38 wtlen =strlen(work_tree); 39 len =strlen(path); 40 off =offset_1st_component(path); 41 42/* check if work tree is already the prefix */ 43if(wtlen <= len && !fspathncmp(path, work_tree, wtlen)) { 44if(path[wtlen] =='/') { 45memmove(path, path + wtlen +1, len - wtlen); 46return0; 47}else if(path[wtlen -1] =='/'|| path[wtlen] =='\0') { 48/* work tree is the root, or the whole path */ 49memmove(path, path + wtlen, len - wtlen +1); 50return0; 51} 52/* work tree might match beginning of a symlink to work tree */ 53 off = wtlen; 54} 55 path0 = path; 56 path += off; 57 58/* check each '/'-terminated level */ 59while(*path) { 60 path++; 61if(*path =='/') { 62*path ='\0'; 63if(fspathcmp(real_path(path0), work_tree) ==0) { 64memmove(path0, path +1, len - (path - path0)); 65return0; 66} 67*path ='/'; 68} 69} 70 71/* check whole path */ 72if(fspathcmp(real_path(path0), work_tree) ==0) { 73*path0 ='\0'; 74return0; 75} 76 77return-1; 78} 79 80/* 81 * Normalize "path", prepending the "prefix" for relative paths. If 82 * remaining_prefix is not NULL, return the actual prefix still 83 * remains in the path. For example, prefix = sub1/sub2/ and path is 84 * 85 * foo -> sub1/sub2/foo (full prefix) 86 * ../foo -> sub1/foo (remaining prefix is sub1/) 87 * ../../bar -> bar (no remaining prefix) 88 * ../../sub1/sub2/foo -> sub1/sub2/foo (but no remaining prefix) 89 * `pwd`/../bar -> sub1/bar (no remaining prefix) 90 */ 91char*prefix_path_gently(const char*prefix,int len, 92int*remaining_prefix,const char*path) 93{ 94const char*orig = path; 95char*sanitized; 96if(is_absolute_path(orig)) { 97 sanitized =xmallocz(strlen(path)); 98if(remaining_prefix) 99*remaining_prefix =0; 100if(normalize_path_copy_len(sanitized, path, remaining_prefix)) { 101free(sanitized); 102return NULL; 103} 104if(abspath_part_inside_repo(sanitized)) { 105free(sanitized); 106return NULL; 107} 108}else{ 109 sanitized =xstrfmt("%.*s%s", len, len ? prefix :"", path); 110if(remaining_prefix) 111*remaining_prefix = len; 112if(normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) { 113free(sanitized); 114return NULL; 115} 116} 117return sanitized; 118} 119 120char*prefix_path(const char*prefix,int len,const char*path) 121{ 122char*r =prefix_path_gently(prefix, len, NULL, path); 123if(!r) 124die(_("'%s' is outside repository"), path); 125return r; 126} 127 128intpath_inside_repo(const char*prefix,const char*path) 129{ 130int len = prefix ?strlen(prefix) :0; 131char*r =prefix_path_gently(prefix, len, NULL, path); 132if(r) { 133free(r); 134return1; 135} 136return0; 137} 138 139intcheck_filename(const char*prefix,const char*arg) 140{ 141char*to_free = NULL; 142struct stat st; 143 144if(skip_prefix(arg,":/", &arg)) { 145if(!*arg)/* ":/" is root dir, always exists */ 146return1; 147 prefix = NULL; 148}else if(skip_prefix(arg,":!", &arg) || 149skip_prefix(arg,":^", &arg)) { 150if(!*arg)/* excluding everything is silly, but allowed */ 151return1; 152} 153 154if(prefix) 155 arg = to_free =prefix_filename(prefix, arg); 156 157if(!lstat(arg, &st)) { 158free(to_free); 159return1;/* file exists */ 160} 161if(is_missing_file_error(errno)) { 162free(to_free); 163return0;/* file does not exist */ 164} 165die_errno(_("failed to stat '%s'"), arg); 166} 167 168static void NORETURN die_verify_filename(struct repository *r, 169const char*prefix, 170const char*arg, 171int diagnose_misspelt_rev) 172{ 173if(!diagnose_misspelt_rev) 174die(_("%s: no such path in the working tree.\n" 175"Use 'git <command> -- <path>...' to specify paths that do not exist locally."), 176 arg); 177/* 178 * Saying "'(icase)foo' does not exist in the index" when the 179 * user gave us ":(icase)foo" is just stupid. A magic pathspec 180 * begins with a colon and is followed by a non-alnum; do not 181 * let maybe_die_on_misspelt_object_name() even trigger. 182 */ 183if(!(arg[0] ==':'&& !isalnum(arg[1]))) 184maybe_die_on_misspelt_object_name(r, arg, prefix); 185 186/* ... or fall back the most general message. */ 187die(_("ambiguous argument '%s': unknown revision or path not in the working tree.\n" 188"Use '--' to separate paths from revisions, like this:\n" 189"'git <command> [<revision>...] -- [<file>...]'"), arg); 190 191} 192 193/* 194 * Check for arguments that don't resolve as actual files, 195 * but which look sufficiently like pathspecs that we'll consider 196 * them such for the purposes of rev/pathspec DWIM parsing. 197 */ 198static intlooks_like_pathspec(const char*arg) 199{ 200/* anything with a wildcard character */ 201if(!no_wildcard(arg)) 202return1; 203 204/* long-form pathspec magic */ 205if(starts_with(arg,":(")) 206return1; 207 208return0; 209} 210 211/* 212 * Verify a filename that we got as an argument for a pathspec 213 * entry. Note that a filename that begins with "-" never verifies 214 * as true, because even if such a filename were to exist, we want 215 * it to be preceded by the "--" marker (or we want the user to 216 * use a format like "./-filename") 217 * 218 * The "diagnose_misspelt_rev" is used to provide a user-friendly 219 * diagnosis when dying upon finding that "name" is not a pathname. 220 * If set to 1, the diagnosis will try to diagnose "name" as an 221 * invalid object name (e.g. HEAD:foo). If set to 0, the diagnosis 222 * will only complain about an inexisting file. 223 * 224 * This function is typically called to check that a "file or rev" 225 * argument is unambiguous. In this case, the caller will want 226 * diagnose_misspelt_rev == 1 when verifying the first non-rev 227 * argument (which could have been a revision), and 228 * diagnose_misspelt_rev == 0 for the next ones (because we already 229 * saw a filename, there's not ambiguity anymore). 230 */ 231voidverify_filename(const char*prefix, 232const char*arg, 233int diagnose_misspelt_rev) 234{ 235if(*arg =='-') 236die(_("option '%s' must come before non-option arguments"), arg); 237if(looks_like_pathspec(arg) ||check_filename(prefix, arg)) 238return; 239die_verify_filename(the_repository, prefix, arg, diagnose_misspelt_rev); 240} 241 242/* 243 * Opposite of the above: the command line did not have -- marker 244 * and we parsed the arg as a refname. It should not be interpretable 245 * as a filename. 246 */ 247voidverify_non_filename(const char*prefix,const char*arg) 248{ 249if(!is_inside_work_tree() ||is_inside_git_dir()) 250return; 251if(*arg =='-') 252return;/* flag */ 253if(!check_filename(prefix, arg)) 254return; 255die(_("ambiguous argument '%s': both revision and filename\n" 256"Use '--' to separate paths from revisions, like this:\n" 257"'git <command> [<revision>...] -- [<file>...]'"), arg); 258} 259 260intget_common_dir(struct strbuf *sb,const char*gitdir) 261{ 262const char*git_env_common_dir =getenv(GIT_COMMON_DIR_ENVIRONMENT); 263if(git_env_common_dir) { 264strbuf_addstr(sb, git_env_common_dir); 265return1; 266}else{ 267returnget_common_dir_noenv(sb, gitdir); 268} 269} 270 271intget_common_dir_noenv(struct strbuf *sb,const char*gitdir) 272{ 273struct strbuf data = STRBUF_INIT; 274struct strbuf path = STRBUF_INIT; 275int ret =0; 276 277strbuf_addf(&path,"%s/commondir", gitdir); 278if(file_exists(path.buf)) { 279if(strbuf_read_file(&data, path.buf,0) <=0) 280die_errno(_("failed to read%s"), path.buf); 281while(data.len && (data.buf[data.len -1] =='\n'|| 282 data.buf[data.len -1] =='\r')) 283 data.len--; 284 data.buf[data.len] ='\0'; 285strbuf_reset(&path); 286if(!is_absolute_path(data.buf)) 287strbuf_addf(&path,"%s/", gitdir); 288strbuf_addbuf(&path, &data); 289strbuf_add_real_path(sb, path.buf); 290 ret =1; 291}else{ 292strbuf_addstr(sb, gitdir); 293} 294 295strbuf_release(&data); 296strbuf_release(&path); 297return ret; 298} 299 300/* 301 * Test if it looks like we're at a git directory. 302 * We want to see: 303 * 304 * - either an objects/ directory _or_ the proper 305 * GIT_OBJECT_DIRECTORY environment variable 306 * - a refs/ directory 307 * - either a HEAD symlink or a HEAD file that is formatted as 308 * a proper "ref:", or a regular file HEAD that has a properly 309 * formatted sha1 object name. 310 */ 311intis_git_directory(const char*suspect) 312{ 313struct strbuf path = STRBUF_INIT; 314int ret =0; 315size_t len; 316 317/* Check worktree-related signatures */ 318strbuf_addstr(&path, suspect); 319strbuf_complete(&path,'/'); 320strbuf_addstr(&path,"HEAD"); 321if(validate_headref(path.buf)) 322goto done; 323 324strbuf_reset(&path); 325get_common_dir(&path, suspect); 326 len = path.len; 327 328/* Check non-worktree-related signatures */ 329if(getenv(DB_ENVIRONMENT)) { 330if(access(getenv(DB_ENVIRONMENT), X_OK)) 331goto done; 332} 333else{ 334strbuf_setlen(&path, len); 335strbuf_addstr(&path,"/objects"); 336if(access(path.buf, X_OK)) 337goto done; 338} 339 340strbuf_setlen(&path, len); 341strbuf_addstr(&path,"/refs"); 342if(access(path.buf, X_OK)) 343goto done; 344 345 ret =1; 346done: 347strbuf_release(&path); 348return ret; 349} 350 351intis_nonbare_repository_dir(struct strbuf *path) 352{ 353int ret =0; 354int gitfile_error; 355size_t orig_path_len = path->len; 356assert(orig_path_len !=0); 357strbuf_complete(path,'/'); 358strbuf_addstr(path,".git"); 359if(read_gitfile_gently(path->buf, &gitfile_error) ||is_git_directory(path->buf)) 360 ret =1; 361if(gitfile_error == READ_GITFILE_ERR_OPEN_FAILED || 362 gitfile_error == READ_GITFILE_ERR_READ_FAILED) 363 ret =1; 364strbuf_setlen(path, orig_path_len); 365return ret; 366} 367 368intis_inside_git_dir(void) 369{ 370if(inside_git_dir <0) 371 inside_git_dir =is_inside_dir(get_git_dir()); 372return inside_git_dir; 373} 374 375intis_inside_work_tree(void) 376{ 377if(inside_work_tree <0) 378 inside_work_tree =is_inside_dir(get_git_work_tree()); 379return inside_work_tree; 380} 381 382voidsetup_work_tree(void) 383{ 384const char*work_tree; 385static int initialized =0; 386 387if(initialized) 388return; 389 390if(work_tree_config_is_bogus) 391die(_("unable to set up work tree using invalid config")); 392 393 work_tree =get_git_work_tree(); 394if(!work_tree ||chdir_notify(work_tree)) 395die(_("this operation must be run in a work tree")); 396 397/* 398 * Make sure subsequent git processes find correct worktree 399 * if $GIT_WORK_TREE is set relative 400 */ 401if(getenv(GIT_WORK_TREE_ENVIRONMENT)) 402setenv(GIT_WORK_TREE_ENVIRONMENT,".",1); 403 404 initialized =1; 405} 406 407static intread_worktree_config(const char*var,const char*value,void*vdata) 408{ 409struct repository_format *data = vdata; 410 411if(strcmp(var,"core.bare") ==0) { 412 data->is_bare =git_config_bool(var, value); 413}else if(strcmp(var,"core.worktree") ==0) { 414if(!value) 415returnconfig_error_nonbool(var); 416free(data->work_tree); 417 data->work_tree =xstrdup(value); 418} 419return0; 420} 421 422static intcheck_repo_format(const char*var,const char*value,void*vdata) 423{ 424struct repository_format *data = vdata; 425const char*ext; 426 427if(strcmp(var,"core.repositoryformatversion") ==0) 428 data->version =git_config_int(var, value); 429else if(skip_prefix(var,"extensions.", &ext)) { 430/* 431 * record any known extensions here; otherwise, 432 * we fall through to recording it as unknown, and 433 * check_repository_format will complain 434 */ 435if(!strcmp(ext,"noop")) 436; 437else if(!strcmp(ext,"preciousobjects")) 438 data->precious_objects =git_config_bool(var, value); 439else if(!strcmp(ext,"partialclone")) { 440if(!value) 441returnconfig_error_nonbool(var); 442 data->partial_clone =xstrdup(value); 443}else if(!strcmp(ext,"worktreeconfig")) 444 data->worktree_config =git_config_bool(var, value); 445else 446string_list_append(&data->unknown_extensions, ext); 447} 448 449returnread_worktree_config(var, value, vdata); 450} 451 452static intcheck_repository_format_gently(const char*gitdir,struct repository_format *candidate,int*nongit_ok) 453{ 454struct strbuf sb = STRBUF_INIT; 455struct strbuf err = STRBUF_INIT; 456int has_common; 457 458 has_common =get_common_dir(&sb, gitdir); 459strbuf_addstr(&sb,"/config"); 460read_repository_format(candidate, sb.buf); 461strbuf_release(&sb); 462 463/* 464 * For historical use of check_repository_format() in git-init, 465 * we treat a missing config as a silent "ok", even when nongit_ok 466 * is unset. 467 */ 468if(candidate->version <0) 469return0; 470 471if(verify_repository_format(candidate, &err) <0) { 472if(nongit_ok) { 473warning("%s", err.buf); 474strbuf_release(&err); 475*nongit_ok = -1; 476return-1; 477} 478die("%s", err.buf); 479} 480 481 repository_format_precious_objects = candidate->precious_objects; 482set_repository_format_partial_clone(candidate->partial_clone); 483 repository_format_worktree_config = candidate->worktree_config; 484string_list_clear(&candidate->unknown_extensions,0); 485 486if(repository_format_worktree_config) { 487/* 488 * pick up core.bare and core.worktree from per-worktree 489 * config if present 490 */ 491strbuf_addf(&sb,"%s/config.worktree", gitdir); 492git_config_from_file(read_worktree_config, sb.buf, candidate); 493strbuf_release(&sb); 494 has_common =0; 495} 496 497if(!has_common) { 498if(candidate->is_bare != -1) { 499 is_bare_repository_cfg = candidate->is_bare; 500if(is_bare_repository_cfg ==1) 501 inside_work_tree = -1; 502} 503if(candidate->work_tree) { 504free(git_work_tree_cfg); 505 git_work_tree_cfg =xstrdup(candidate->work_tree); 506 inside_work_tree = -1; 507} 508} 509 510return0; 511} 512 513static voidinit_repository_format(struct repository_format *format) 514{ 515const struct repository_format fresh = REPOSITORY_FORMAT_INIT; 516 517memcpy(format, &fresh,sizeof(fresh)); 518} 519 520intread_repository_format(struct repository_format *format,const char*path) 521{ 522clear_repository_format(format); 523git_config_from_file(check_repo_format, path, format); 524if(format->version == -1) 525clear_repository_format(format); 526return format->version; 527} 528 529voidclear_repository_format(struct repository_format *format) 530{ 531string_list_clear(&format->unknown_extensions,0); 532free(format->work_tree); 533free(format->partial_clone); 534init_repository_format(format); 535} 536 537intverify_repository_format(const struct repository_format *format, 538struct strbuf *err) 539{ 540if(GIT_REPO_VERSION_READ < format->version) { 541strbuf_addf(err,_("Expected git repo version <=%d, found%d"), 542 GIT_REPO_VERSION_READ, format->version); 543return-1; 544} 545 546if(format->version >=1&& format->unknown_extensions.nr) { 547int i; 548 549strbuf_addstr(err,_("unknown repository extensions found:")); 550 551for(i =0; i < format->unknown_extensions.nr; i++) 552strbuf_addf(err,"\n\t%s", 553 format->unknown_extensions.items[i].string); 554return-1; 555} 556 557return0; 558} 559 560voidread_gitfile_error_die(int error_code,const char*path,const char*dir) 561{ 562switch(error_code) { 563case READ_GITFILE_ERR_STAT_FAILED: 564case READ_GITFILE_ERR_NOT_A_FILE: 565/* non-fatal; follow return path */ 566break; 567case READ_GITFILE_ERR_OPEN_FAILED: 568die_errno(_("error opening '%s'"), path); 569case READ_GITFILE_ERR_TOO_LARGE: 570die(_("too large to be a .git file: '%s'"), path); 571case READ_GITFILE_ERR_READ_FAILED: 572die(_("error reading%s"), path); 573case READ_GITFILE_ERR_INVALID_FORMAT: 574die(_("invalid gitfile format:%s"), path); 575case READ_GITFILE_ERR_NO_PATH: 576die(_("no path in gitfile:%s"), path); 577case READ_GITFILE_ERR_NOT_A_REPO: 578die(_("not a git repository:%s"), dir); 579default: 580BUG("unknown error code"); 581} 582} 583 584/* 585 * Try to read the location of the git directory from the .git file, 586 * return path to git directory if found. The return value comes from 587 * a shared buffer. 588 * 589 * On failure, if return_error_code is not NULL, return_error_code 590 * will be set to an error code and NULL will be returned. If 591 * return_error_code is NULL the function will die instead (for most 592 * cases). 593 */ 594const char*read_gitfile_gently(const char*path,int*return_error_code) 595{ 596const int max_file_size =1<<20;/* 1MB */ 597int error_code =0; 598char*buf = NULL; 599char*dir = NULL; 600const char*slash; 601struct stat st; 602int fd; 603 ssize_t len; 604 605if(stat(path, &st)) { 606/* NEEDSWORK: discern between ENOENT vs other errors */ 607 error_code = READ_GITFILE_ERR_STAT_FAILED; 608goto cleanup_return; 609} 610if(!S_ISREG(st.st_mode)) { 611 error_code = READ_GITFILE_ERR_NOT_A_FILE; 612goto cleanup_return; 613} 614if(st.st_size > max_file_size) { 615 error_code = READ_GITFILE_ERR_TOO_LARGE; 616goto cleanup_return; 617} 618 fd =open(path, O_RDONLY); 619if(fd <0) { 620 error_code = READ_GITFILE_ERR_OPEN_FAILED; 621goto cleanup_return; 622} 623 buf =xmallocz(st.st_size); 624 len =read_in_full(fd, buf, st.st_size); 625close(fd); 626if(len != st.st_size) { 627 error_code = READ_GITFILE_ERR_READ_FAILED; 628goto cleanup_return; 629} 630if(!starts_with(buf,"gitdir: ")) { 631 error_code = READ_GITFILE_ERR_INVALID_FORMAT; 632goto cleanup_return; 633} 634while(buf[len -1] =='\n'|| buf[len -1] =='\r') 635 len--; 636if(len <9) { 637 error_code = READ_GITFILE_ERR_NO_PATH; 638goto cleanup_return; 639} 640 buf[len] ='\0'; 641 dir = buf +8; 642 643if(!is_absolute_path(dir) && (slash =strrchr(path,'/'))) { 644size_t pathlen = slash+1- path; 645 dir =xstrfmt("%.*s%.*s", (int)pathlen, path, 646(int)(len -8), buf +8); 647free(buf); 648 buf = dir; 649} 650if(!is_git_directory(dir)) { 651 error_code = READ_GITFILE_ERR_NOT_A_REPO; 652goto cleanup_return; 653} 654 path =real_path(dir); 655 656cleanup_return: 657if(return_error_code) 658*return_error_code = error_code; 659else if(error_code) 660read_gitfile_error_die(error_code, path, dir); 661 662free(buf); 663return error_code ? NULL : path; 664} 665 666static const char*setup_explicit_git_dir(const char*gitdirenv, 667struct strbuf *cwd, 668struct repository_format *repo_fmt, 669int*nongit_ok) 670{ 671const char*work_tree_env =getenv(GIT_WORK_TREE_ENVIRONMENT); 672const char*worktree; 673char*gitfile; 674int offset; 675 676if(PATH_MAX -40<strlen(gitdirenv)) 677die(_("'$%s' too big"), GIT_DIR_ENVIRONMENT); 678 679 gitfile = (char*)read_gitfile(gitdirenv); 680if(gitfile) { 681 gitfile =xstrdup(gitfile); 682 gitdirenv = gitfile; 683} 684 685if(!is_git_directory(gitdirenv)) { 686if(nongit_ok) { 687*nongit_ok =1; 688free(gitfile); 689return NULL; 690} 691die(_("not a git repository: '%s'"), gitdirenv); 692} 693 694if(check_repository_format_gently(gitdirenv, repo_fmt, nongit_ok)) { 695free(gitfile); 696return NULL; 697} 698 699/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */ 700if(work_tree_env) 701set_git_work_tree(work_tree_env); 702else if(is_bare_repository_cfg >0) { 703if(git_work_tree_cfg) { 704/* #22.2, #30 */ 705warning("core.bare and core.worktree do not make sense"); 706 work_tree_config_is_bogus =1; 707} 708 709/* #18, #26 */ 710set_git_dir(gitdirenv); 711free(gitfile); 712return NULL; 713} 714else if(git_work_tree_cfg) {/* #6, #14 */ 715if(is_absolute_path(git_work_tree_cfg)) 716set_git_work_tree(git_work_tree_cfg); 717else{ 718char*core_worktree; 719if(chdir(gitdirenv)) 720die_errno(_("cannot chdir to '%s'"), gitdirenv); 721if(chdir(git_work_tree_cfg)) 722die_errno(_("cannot chdir to '%s'"), git_work_tree_cfg); 723 core_worktree =xgetcwd(); 724if(chdir(cwd->buf)) 725die_errno(_("cannot come back to cwd")); 726set_git_work_tree(core_worktree); 727free(core_worktree); 728} 729} 730else if(!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,1)) { 731/* #16d */ 732set_git_dir(gitdirenv); 733free(gitfile); 734return NULL; 735} 736else/* #2, #10 */ 737set_git_work_tree("."); 738 739/* set_git_work_tree() must have been called by now */ 740 worktree =get_git_work_tree(); 741 742/* both get_git_work_tree() and cwd are already normalized */ 743if(!strcmp(cwd->buf, worktree)) {/* cwd == worktree */ 744set_git_dir(gitdirenv); 745free(gitfile); 746return NULL; 747} 748 749 offset =dir_inside_of(cwd->buf, worktree); 750if(offset >=0) {/* cwd inside worktree? */ 751set_git_dir(real_path(gitdirenv)); 752if(chdir(worktree)) 753die_errno(_("cannot chdir to '%s'"), worktree); 754strbuf_addch(cwd,'/'); 755free(gitfile); 756return cwd->buf + offset; 757} 758 759/* cwd outside worktree */ 760set_git_dir(gitdirenv); 761free(gitfile); 762return NULL; 763} 764 765static const char*setup_discovered_git_dir(const char*gitdir, 766struct strbuf *cwd,int offset, 767struct repository_format *repo_fmt, 768int*nongit_ok) 769{ 770if(check_repository_format_gently(gitdir, repo_fmt, nongit_ok)) 771return NULL; 772 773/* --work-tree is set without --git-dir; use discovered one */ 774if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 775char*to_free = NULL; 776const char*ret; 777 778if(offset != cwd->len && !is_absolute_path(gitdir)) 779 gitdir = to_free =real_pathdup(gitdir,1); 780if(chdir(cwd->buf)) 781die_errno(_("cannot come back to cwd")); 782 ret =setup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok); 783free(to_free); 784return ret; 785} 786 787/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ 788if(is_bare_repository_cfg >0) { 789set_git_dir(offset == cwd->len ? gitdir :real_path(gitdir)); 790if(chdir(cwd->buf)) 791die_errno(_("cannot come back to cwd")); 792return NULL; 793} 794 795/* #0, #1, #5, #8, #9, #12, #13 */ 796set_git_work_tree("."); 797if(strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) 798set_git_dir(gitdir); 799 inside_git_dir =0; 800 inside_work_tree =1; 801if(offset >= cwd->len) 802return NULL; 803 804/* Make "offset" point past the '/' (already the case for root dirs) */ 805if(offset !=offset_1st_component(cwd->buf)) 806 offset++; 807/* Add a '/' at the end */ 808strbuf_addch(cwd,'/'); 809return cwd->buf + offset; 810} 811 812/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */ 813static const char*setup_bare_git_dir(struct strbuf *cwd,int offset, 814struct repository_format *repo_fmt, 815int*nongit_ok) 816{ 817int root_len; 818 819if(check_repository_format_gently(".", repo_fmt, nongit_ok)) 820return NULL; 821 822setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,"0",1); 823 824/* --work-tree is set without --git-dir; use discovered one */ 825if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 826static const char*gitdir; 827 828 gitdir = offset == cwd->len ?".":xmemdupz(cwd->buf, offset); 829if(chdir(cwd->buf)) 830die_errno(_("cannot come back to cwd")); 831returnsetup_explicit_git_dir(gitdir, cwd, repo_fmt, nongit_ok); 832} 833 834 inside_git_dir =1; 835 inside_work_tree =0; 836if(offset != cwd->len) { 837if(chdir(cwd->buf)) 838die_errno(_("cannot come back to cwd")); 839 root_len =offset_1st_component(cwd->buf); 840strbuf_setlen(cwd, offset > root_len ? offset : root_len); 841set_git_dir(cwd->buf); 842} 843else 844set_git_dir("."); 845return NULL; 846} 847 848static dev_t get_device_or_die(const char*path,const char*prefix,int prefix_len) 849{ 850struct stat buf; 851if(stat(path, &buf)) { 852die_errno(_("failed to stat '%*s%s%s'"), 853 prefix_len, 854 prefix ? prefix :"", 855 prefix ?"/":"", path); 856} 857return buf.st_dev; 858} 859 860/* 861 * A "string_list_each_func_t" function that canonicalizes an entry 862 * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or 863 * discards it if unusable. The presence of an empty entry in 864 * GIT_CEILING_DIRECTORIES turns off canonicalization for all 865 * subsequent entries. 866 */ 867static intcanonicalize_ceiling_entry(struct string_list_item *item, 868void*cb_data) 869{ 870int*empty_entry_found = cb_data; 871char*ceil = item->string; 872 873if(!*ceil) { 874*empty_entry_found =1; 875return0; 876}else if(!is_absolute_path(ceil)) { 877return0; 878}else if(*empty_entry_found) { 879/* Keep entry but do not canonicalize it */ 880return1; 881}else{ 882char*real_path =real_pathdup(ceil,0); 883if(!real_path) { 884return0; 885} 886free(item->string); 887 item->string = real_path; 888return1; 889} 890} 891 892enum discovery_result { 893 GIT_DIR_NONE =0, 894 GIT_DIR_EXPLICIT, 895 GIT_DIR_DISCOVERED, 896 GIT_DIR_BARE, 897/* these are errors */ 898 GIT_DIR_HIT_CEILING = -1, 899 GIT_DIR_HIT_MOUNT_POINT = -2, 900 GIT_DIR_INVALID_GITFILE = -3 901}; 902 903/* 904 * We cannot decide in this function whether we are in the work tree or 905 * not, since the config can only be read _after_ this function was called. 906 * 907 * Also, we avoid changing any global state (such as the current working 908 * directory) to allow early callers. 909 * 910 * The directory where the search should start needs to be passed in via the 911 * `dir` parameter; upon return, the `dir` buffer will contain the path of 912 * the directory where the search ended, and `gitdir` will contain the path of 913 * the discovered .git/ directory, if any. If `gitdir` is not absolute, it 914 * is relative to `dir` (i.e. *not* necessarily the cwd). 915 */ 916static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir, 917struct strbuf *gitdir, 918int die_on_error) 919{ 920const char*env_ceiling_dirs =getenv(CEILING_DIRECTORIES_ENVIRONMENT); 921struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; 922const char*gitdirenv; 923int ceil_offset = -1, min_offset =offset_1st_component(dir->buf); 924 dev_t current_device =0; 925int one_filesystem =1; 926 927/* 928 * If GIT_DIR is set explicitly, we're not going 929 * to do any discovery, but we still do repository 930 * validation. 931 */ 932 gitdirenv =getenv(GIT_DIR_ENVIRONMENT); 933if(gitdirenv) { 934strbuf_addstr(gitdir, gitdirenv); 935return GIT_DIR_EXPLICIT; 936} 937 938if(env_ceiling_dirs) { 939int empty_entry_found =0; 940 941string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1); 942filter_string_list(&ceiling_dirs,0, 943 canonicalize_ceiling_entry, &empty_entry_found); 944 ceil_offset =longest_ancestor_length(dir->buf, &ceiling_dirs); 945string_list_clear(&ceiling_dirs,0); 946} 947 948if(ceil_offset <0) 949 ceil_offset = min_offset -2; 950 951if(min_offset && min_offset == dir->len && 952!is_dir_sep(dir->buf[min_offset -1])) { 953strbuf_addch(dir,'/'); 954 min_offset++; 955} 956 957/* 958 * Test in the following order (relative to the dir): 959 * - .git (file containing "gitdir: <path>") 960 * - .git/ 961 * - ./ (bare) 962 * - ../.git 963 * - ../.git/ 964 * - ../ (bare) 965 * - ../../.git 966 * etc. 967 */ 968 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM",0); 969if(one_filesystem) 970 current_device =get_device_or_die(dir->buf, NULL,0); 971for(;;) { 972int offset = dir->len, error_code =0; 973 974if(offset > min_offset) 975strbuf_addch(dir,'/'); 976strbuf_addstr(dir, DEFAULT_GIT_DIR_ENVIRONMENT); 977 gitdirenv =read_gitfile_gently(dir->buf, die_on_error ? 978 NULL : &error_code); 979if(!gitdirenv) { 980if(die_on_error || 981 error_code == READ_GITFILE_ERR_NOT_A_FILE) { 982/* NEEDSWORK: fail if .git is not file nor dir */ 983if(is_git_directory(dir->buf)) 984 gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; 985}else if(error_code != READ_GITFILE_ERR_STAT_FAILED) 986return GIT_DIR_INVALID_GITFILE; 987} 988strbuf_setlen(dir, offset); 989if(gitdirenv) { 990strbuf_addstr(gitdir, gitdirenv); 991return GIT_DIR_DISCOVERED; 992} 993 994if(is_git_directory(dir->buf)) { 995strbuf_addstr(gitdir,"."); 996return GIT_DIR_BARE; 997} 998 999if(offset <= min_offset)1000return GIT_DIR_HIT_CEILING;10011002while(--offset > ceil_offset && !is_dir_sep(dir->buf[offset]))1003;/* continue */1004if(offset <= ceil_offset)1005return GIT_DIR_HIT_CEILING;10061007strbuf_setlen(dir, offset > min_offset ? offset : min_offset);1008if(one_filesystem &&1009 current_device !=get_device_or_die(dir->buf, NULL, offset))1010return GIT_DIR_HIT_MOUNT_POINT;1011}1012}10131014intdiscover_git_directory(struct strbuf *commondir,1015struct strbuf *gitdir)1016{1017struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;1018size_t gitdir_offset = gitdir->len, cwd_len;1019size_t commondir_offset = commondir->len;1020struct repository_format candidate = REPOSITORY_FORMAT_INIT;10211022if(strbuf_getcwd(&dir))1023return-1;10241025 cwd_len = dir.len;1026if(setup_git_directory_gently_1(&dir, gitdir,0) <=0) {1027strbuf_release(&dir);1028return-1;1029}10301031/*1032 * The returned gitdir is relative to dir, and if dir does not reflect1033 * the current working directory, we simply make the gitdir absolute.1034 */1035if(dir.len < cwd_len && !is_absolute_path(gitdir->buf + gitdir_offset)) {1036/* Avoid a trailing "/." */1037if(!strcmp(".", gitdir->buf + gitdir_offset))1038strbuf_setlen(gitdir, gitdir_offset);1039else1040strbuf_addch(&dir,'/');1041strbuf_insert(gitdir, gitdir_offset, dir.buf, dir.len);1042}10431044get_common_dir(commondir, gitdir->buf + gitdir_offset);10451046strbuf_reset(&dir);1047strbuf_addf(&dir,"%s/config", commondir->buf + commondir_offset);1048read_repository_format(&candidate, dir.buf);1049strbuf_release(&dir);10501051if(verify_repository_format(&candidate, &err) <0) {1052warning("ignoring git dir '%s':%s",1053 gitdir->buf + gitdir_offset, err.buf);1054strbuf_release(&err);1055strbuf_setlen(commondir, commondir_offset);1056strbuf_setlen(gitdir, gitdir_offset);1057clear_repository_format(&candidate);1058return-1;1059}10601061clear_repository_format(&candidate);1062return0;1063}10641065const char*setup_git_directory_gently(int*nongit_ok)1066{1067static struct strbuf cwd = STRBUF_INIT;1068struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;1069const char*prefix = NULL;1070struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;10711072/*1073 * We may have read an incomplete configuration before1074 * setting-up the git directory. If so, clear the cache so1075 * that the next queries to the configuration reload complete1076 * configuration (including the per-repo config file that we1077 * ignored previously).1078 */1079git_config_clear();10801081/*1082 * Let's assume that we are in a git repository.1083 * If it turns out later that we are somewhere else, the value will be1084 * updated accordingly.1085 */1086if(nongit_ok)1087*nongit_ok =0;10881089if(strbuf_getcwd(&cwd))1090die_errno(_("Unable to read current working directory"));1091strbuf_addbuf(&dir, &cwd);10921093switch(setup_git_directory_gently_1(&dir, &gitdir,1)) {1094case GIT_DIR_EXPLICIT:1095 prefix =setup_explicit_git_dir(gitdir.buf, &cwd, &repo_fmt, nongit_ok);1096break;1097case GIT_DIR_DISCOVERED:1098if(dir.len < cwd.len &&chdir(dir.buf))1099die(_("cannot change to '%s'"), dir.buf);1100 prefix =setup_discovered_git_dir(gitdir.buf, &cwd, dir.len,1101&repo_fmt, nongit_ok);1102break;1103case GIT_DIR_BARE:1104if(dir.len < cwd.len &&chdir(dir.buf))1105die(_("cannot change to '%s'"), dir.buf);1106 prefix =setup_bare_git_dir(&cwd, dir.len, &repo_fmt, nongit_ok);1107break;1108case GIT_DIR_HIT_CEILING:1109if(!nongit_ok)1110die(_("not a git repository (or any of the parent directories):%s"),1111 DEFAULT_GIT_DIR_ENVIRONMENT);1112*nongit_ok =1;1113break;1114case GIT_DIR_HIT_MOUNT_POINT:1115if(!nongit_ok)1116die(_("not a git repository (or any parent up to mount point%s)\n"1117"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."),1118 dir.buf);1119*nongit_ok =1;1120break;1121case GIT_DIR_NONE:1122/*1123 * As a safeguard against setup_git_directory_gently_1 returning1124 * this value, fallthrough to BUG. Otherwise it is possible to1125 * set startup_info->have_repository to 1 when we did nothing to1126 * find a repository.1127 */1128default:1129BUG("unhandled setup_git_directory_1() result");1130}11311132/*1133 * At this point, nongit_ok is stable. If it is non-NULL and points1134 * to a non-zero value, then this means that we haven't found a1135 * repository and that the caller expects startup_info to reflect1136 * this.1137 *1138 * Regardless of the state of nongit_ok, startup_info->prefix and1139 * the GIT_PREFIX environment variable must always match. For details1140 * see Documentation/config/alias.txt.1141 */1142if(nongit_ok && *nongit_ok) {1143 startup_info->have_repository =0;1144 startup_info->prefix = NULL;1145setenv(GIT_PREFIX_ENVIRONMENT,"",1);1146}else{1147 startup_info->have_repository =1;1148 startup_info->prefix = prefix;1149if(prefix)1150setenv(GIT_PREFIX_ENVIRONMENT, prefix,1);1151else1152setenv(GIT_PREFIX_ENVIRONMENT,"",1);1153}11541155/*1156 * Not all paths through the setup code will call 'set_git_dir()' (which1157 * directly sets up the environment) so in order to guarantee that the1158 * environment is in a consistent state after setup, explicitly setup1159 * the environment if we have a repository.1160 *1161 * NEEDSWORK: currently we allow bogus GIT_DIR values to be set in some1162 * code paths so we also need to explicitly setup the environment if1163 * the user has set GIT_DIR. It may be beneficial to disallow bogus1164 * GIT_DIR values at some point in the future.1165 */1166if(/* GIT_DIR_EXPLICIT, GIT_DIR_DISCOVERED, GIT_DIR_BARE */1167 startup_info->have_repository ||1168/* GIT_DIR_EXPLICIT */1169getenv(GIT_DIR_ENVIRONMENT)) {1170if(!the_repository->gitdir) {1171const char*gitdir =getenv(GIT_DIR_ENVIRONMENT);1172if(!gitdir)1173 gitdir = DEFAULT_GIT_DIR_ENVIRONMENT;1174setup_git_env(gitdir);1175}1176if(startup_info->have_repository)1177repo_set_hash_algo(the_repository, repo_fmt.hash_algo);1178}11791180strbuf_release(&dir);1181strbuf_release(&gitdir);1182clear_repository_format(&repo_fmt);11831184return prefix;1185}11861187intgit_config_perm(const char*var,const char*value)1188{1189int i;1190char*endptr;11911192if(value == NULL)1193return PERM_GROUP;11941195if(!strcmp(value,"umask"))1196return PERM_UMASK;1197if(!strcmp(value,"group"))1198return PERM_GROUP;1199if(!strcmp(value,"all") ||1200!strcmp(value,"world") ||1201!strcmp(value,"everybody"))1202return PERM_EVERYBODY;12031204/* Parse octal numbers */1205 i =strtol(value, &endptr,8);12061207/* If not an octal number, maybe true/false? */1208if(*endptr !=0)1209returngit_config_bool(var, value) ? PERM_GROUP : PERM_UMASK;12101211/*1212 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is1213 * a chmod value to restrict to.1214 */1215switch(i) {1216case PERM_UMASK:/* 0 */1217return PERM_UMASK;1218case OLD_PERM_GROUP:/* 1 */1219return PERM_GROUP;1220case OLD_PERM_EVERYBODY:/* 2 */1221return PERM_EVERYBODY;1222}12231224/* A filemode value was given: 0xxx */12251226if((i &0600) !=0600)1227die(_("problem with core.sharedRepository filemode value "1228"(0%.3o).\nThe owner of files must always have "1229"read and write permissions."), i);12301231/*1232 * Mask filemode value. Others can not get write permission.1233 * x flags for directories are handled separately.1234 */1235return-(i &0666);1236}12371238voidcheck_repository_format(void)1239{1240struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;1241check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);1242 startup_info->have_repository =1;1243clear_repository_format(&repo_fmt);1244}12451246/*1247 * Returns the "prefix", a path to the current working directory1248 * relative to the work tree root, or NULL, if the current working1249 * directory is not a strict subdirectory of the work tree root. The1250 * prefix always ends with a '/' character.1251 */1252const char*setup_git_directory(void)1253{1254returnsetup_git_directory_gently(NULL);1255}12561257const char*resolve_gitdir_gently(const char*suspect,int*return_error_code)1258{1259if(is_git_directory(suspect))1260return suspect;1261returnread_gitfile_gently(suspect, return_error_code);1262}12631264/* if any standard file descriptor is missing open it to /dev/null */1265voidsanitize_stdfds(void)1266{1267int fd =open("/dev/null", O_RDWR,0);1268while(fd != -1&& fd <2)1269 fd =dup(fd);1270if(fd == -1)1271die_errno(_("open /dev/null or dup failed"));1272if(fd >2)1273close(fd);1274}12751276intdaemonize(void)1277{1278#ifdef NO_POSIX_GOODIES1279 errno = ENOSYS;1280return-1;1281#else1282switch(fork()) {1283case0:1284break;1285case-1:1286die_errno(_("fork failed"));1287default:1288exit(0);1289}1290if(setsid() == -1)1291die_errno(_("setsid failed"));1292close(0);1293close(1);1294close(2);1295sanitize_stdfds();1296return0;1297#endif1298}