git-2.22.0/path.c
/*
 * First, one directory to try is determined by the following algorithm.
 *
 * (0) If "strict" is given, the path is used as given and no DWIM is
 *     done. Otherwise:
 * (1) "~/path" to mean path under the running user's home directory;
 * (2) "~user/path" to mean path under named user's home directory;
 * (3) "relative/path" to mean cwd relative directory; or
 * (4) "/absolute/path" to mean absolute directory.
 *
 * Unless "strict" is given, we check "%s/.git", "%s", "%s.git/.git", "%s.git"
 * in this order. We select the first one that is a valid git repository, and
 * chdir() to it. If none match, or we fail to chdir, we return NULL.
 *
 * If all goes well, we return the directory we used to chdir() (but
 * before ~user is expanded), avoiding getcwd() resolving symbolic
 * links.  User relative paths are also returned as they are given,
 * except DWIM suffixing.
 */
First, one directory to try is determined by the following algorithm.
(0) If "strict" is given, the path is used as given and no DWIM is
done.



If all goes well, we return the directory we used to chdir() (but
before ~user is expanded), avoiding getcwd() resolving symbolic
links.  User relative paths are also returned as they are given,
except DWIM suffixing.
First one directory to try is determined by the following algorithm . ( 0 ) If " strict " is given the path is used as given and no DWIM is done . If all goes well we return the directory we used to chdir () ( but before ~user is expanded ) avoiding getcwd () resolving symbolic links . User relative paths are also returned as they are given except DWIM suffixing .
const char *enter_repo(const char *path, int strict)
{
	static struct strbuf validated_path = STRBUF_INIT;
	static struct strbuf used_path = STRBUF_INIT;
	if (!path)
		return NULL;
	if (!strict) {
		static const char *suffix[] = {
			"/.git", "", ".git/.git", ".git", NULL,
		};
		const char *gitfile;
		int len = strlen(path);
		int i;
		while ((1 < len) && (path[len-1] == '/'))
			len--;
		if (PATH_MAX <= len)
			return NULL;
		strbuf_reset(&used_path);
		strbuf_reset(&validated_path);
		strbuf_add(&used_path, path, len);
		strbuf_add(&validated_path, path, len);
		if (used_path.buf[0] == '~') {
			char *newpath = expand_user_path(used_path.buf, 0);
			if (!newpath)
				return NULL;
			strbuf_attach(&used_path, newpath, strlen(newpath),
				      strlen(newpath));
		}
		for (i = 0; suffix[i]; i++) {
			struct stat st;
			size_t baselen = used_path.len;
			strbuf_addstr(&used_path, suffix[i]);
			if (!stat(used_path.buf, &st) &&
			    (S_ISREG(st.st_mode) ||
			    (S_ISDIR(st.st_mode) && is_git_directory(used_path.buf)))) {
				strbuf_addstr(&validated_path, suffix[i]);
				break;
			}
			strbuf_setlen(&used_path, baselen);
		}
		if (!suffix[i])
			return NULL;
		gitfile = read_gitfile(used_path.buf);
		if (gitfile) {
			strbuf_reset(&used_path);
			strbuf_addstr(&used_path, gitfile);
		}
		if (chdir(used_path.buf))
			return NULL;
		path = validated_path.buf;
	}
	else {
		const char *gitfile = read_gitfile(path);
		if (gitfile)
			path = gitfile;
		if (chdir(path))
			return NULL;
	}
	if (is_git_directory(".")) {
		set_git_dir(".");
		check_repository_format();
		return path;
	}
	return NULL;
}
const char * enter_repo ( const char * path , int strict ) { static struct strbuf validated_path = STRBUF_INIT ; static struct strbuf used_path = STRBUF_INIT ; if ( ! path ) return NULL ; if ( ! strict ) { static const char * suffix [ ] = { " " , " " , " " , " " , NULL , } ; const char * gitfile ; int len = strlen ( path ) ; int i ; while ( ( 1 < len ) && ( path [ len - 1 ] == ' ' ) ) len -- ; if ( PATH_MAX <= len ) return NULL ; strbuf_reset ( & used_path ) ; strbuf_reset ( & validated_path ) ; strbuf_add ( & used_path , path , len ) ; strbuf_add ( & validated_path , path , len ) ; if ( used_path . buf [ 0 ] == ' ' ) { char * newpath = expand_user_path ( used_path . buf , 0 ) ; if ( ! newpath ) return NULL ; strbuf_attach ( & used_path , newpath , strlen ( newpath ) , strlen ( newpath ) ) ; } for ( i = 0 ; suffix [ i ] ; i ++ ) { struct stat st ; size_t baselen = used_path . len ; strbuf_addstr ( & used_path , suffix [ i ] ) ; if ( ! stat ( used_path . buf , & st ) && ( S_ISREG ( st . st_mode ) || ( S_ISDIR ( st . st_mode ) && is_git_directory ( used_path . buf ) ) ) ) { strbuf_addstr ( & validated_path , suffix [ i ] ) ; break ; } strbuf_setlen ( & used_path , baselen ) ; } if ( ! suffix [ i ] ) return NULL ; gitfile = read_gitfile ( used_path . buf ) ; if ( gitfile ) { strbuf_reset ( & used_path ) ; strbuf_addstr ( & used_path , gitfile ) ; } if ( chdir ( used_path . buf ) ) return NULL ; path = validated_path . buf ; } else { const char * gitfile = read_gitfile ( path ) ; if ( gitfile ) path = gitfile ; if ( chdir ( path ) ) return NULL ; } if ( is_git_directory ( " " ) ) { set_git_dir ( " " ) ; check_repository_format ( ) ; return path ; } return NULL ; }
First, one directory to try is determined by the following algorithm.
First one directory to try is determined by the following algorithm .
/*
		 * We can handle arbitrary-sized buffers, but this remains as a
		 * sanity check on untrusted input.
		 */