diff options
Diffstat (limited to 'setup.c')
| -rw-r--r-- | setup.c | 190 | 
1 files changed, 36 insertions, 154 deletions
@@ -5,7 +5,19 @@  static int inside_git_dir = -1;  static int inside_work_tree = -1; -static char *prefix_path_gently(const char *prefix, int len, const char *path) +/* + * Normalize "path", prepending the "prefix" for relative paths. If + * remaining_prefix is not NULL, return the actual prefix still + * remains in the path. For example, prefix = sub1/sub2/ and path is + * + *  foo          -> sub1/sub2/foo  (full prefix) + *  ../foo       -> sub1/foo       (remaining prefix is sub1/) + *  ../../bar    -> bar            (no remaining prefix) + *  ../../sub1/sub2/foo -> sub1/sub2/foo (but no remaining prefix) + *  `pwd`/../bar -> sub1/bar       (no remaining prefix) + */ +char *prefix_path_gently(const char *prefix, int len, +			 int *remaining_prefix, const char *path)  {  	const char *orig = path;  	char *sanitized; @@ -13,13 +25,17 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path)  		const char *temp = real_path(path);  		sanitized = xmalloc(len + strlen(temp) + 1);  		strcpy(sanitized, temp); +		if (remaining_prefix) +			*remaining_prefix = 0;  	} else {  		sanitized = xmalloc(len + strlen(path) + 1);  		if (len)  			memcpy(sanitized, prefix, len);  		strcpy(sanitized + len, path); +		if (remaining_prefix) +			*remaining_prefix = len;  	} -	if (normalize_path_copy(sanitized, sanitized)) +	if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix))  		goto error_out;  	if (is_absolute_path(orig)) {  		size_t root_len, len, total; @@ -44,7 +60,7 @@ static char *prefix_path_gently(const char *prefix, int len, const char *path)  char *prefix_path(const char *prefix, int len, const char *path)  { -	char *r = prefix_path_gently(prefix, len, path); +	char *r = prefix_path_gently(prefix, len, NULL, path);  	if (!r)  		die("'%s' is outside repository", path);  	return r; @@ -53,7 +69,7 @@ char *prefix_path(const char *prefix, int len, const char *path)  int path_inside_repo(const char *prefix, const char *path)  {  	int len = prefix ? strlen(prefix) : 0; -	char *r = prefix_path_gently(prefix, len, path); +	char *r = prefix_path_gently(prefix, len, NULL, path);  	if (r) {  		free(r);  		return 1; @@ -154,155 +170,6 @@ void verify_non_filename(const char *prefix, const char *arg)  	    "'git <command> [<revision>...] -- [<file>...]'", arg);  } -/* - * Magic pathspec - * - * NEEDSWORK: These need to be moved to dir.h or even to a new - * pathspec.h when we restructure get_pathspec() users to use the - * "struct pathspec" interface. - * - * Possible future magic semantics include stuff like: - * - *	{ PATHSPEC_NOGLOB, '!', "noglob" }, - *	{ PATHSPEC_ICASE, '\0', "icase" }, - *	{ PATHSPEC_RECURSIVE, '*', "recursive" }, - *	{ PATHSPEC_REGEXP, '\0', "regexp" }, - * - */ -#define PATHSPEC_FROMTOP    (1<<0) - -static struct pathspec_magic { -	unsigned bit; -	char mnemonic; /* this cannot be ':'! */ -	const char *name; -} pathspec_magic[] = { -	{ PATHSPEC_FROMTOP, '/', "top" }, -}; - -/* - * Take an element of a pathspec and check for magic signatures. - * Append the result to the prefix. - * - * For now, we only parse the syntax and throw out anything other than - * "top" magic. - * - * NEEDSWORK: This needs to be rewritten when we start migrating - * get_pathspec() users to use the "struct pathspec" interface.  For - * example, a pathspec element may be marked as case-insensitive, but - * the prefix part must always match literally, and a single stupid - * string cannot express such a case. - */ -static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt) -{ -	unsigned magic = 0; -	const char *copyfrom = elt; -	int i; - -	if (elt[0] != ':') { -		; /* nothing to do */ -	} else if (elt[1] == '(') { -		/* longhand */ -		const char *nextat; -		for (copyfrom = elt + 2; -		     *copyfrom && *copyfrom != ')'; -		     copyfrom = nextat) { -			size_t len = strcspn(copyfrom, ",)"); -			if (copyfrom[len] == ',') -				nextat = copyfrom + len + 1; -			else -				/* handle ')' and '\0' */ -				nextat = copyfrom + len; -			if (!len) -				continue; -			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) -				if (strlen(pathspec_magic[i].name) == len && -				    !strncmp(pathspec_magic[i].name, copyfrom, len)) { -					magic |= pathspec_magic[i].bit; -					break; -				} -			if (ARRAY_SIZE(pathspec_magic) <= i) -				die("Invalid pathspec magic '%.*s' in '%s'", -				    (int) len, copyfrom, elt); -		} -		if (*copyfrom != ')') -			die("Missing ')' at the end of pathspec magic in '%s'", elt); -		copyfrom++; -	} else { -		/* shorthand */ -		for (copyfrom = elt + 1; -		     *copyfrom && *copyfrom != ':'; -		     copyfrom++) { -			char ch = *copyfrom; - -			if (!is_pathspec_magic(ch)) -				break; -			for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) -				if (pathspec_magic[i].mnemonic == ch) { -					magic |= pathspec_magic[i].bit; -					break; -				} -			if (ARRAY_SIZE(pathspec_magic) <= i) -				die("Unimplemented pathspec magic '%c' in '%s'", -				    ch, elt); -		} -		if (*copyfrom == ':') -			copyfrom++; -	} - -	if (magic & PATHSPEC_FROMTOP) -		return xstrdup(copyfrom); -	else -		return prefix_path(prefix, prefixlen, copyfrom); -} - -/* - * N.B. get_pathspec() is deprecated in favor of the "struct pathspec" - * based interface - see pathspec_magic above. - * - * Arguments: - *  - prefix - a path relative to the root of the working tree - *  - pathspec - a list of paths underneath the prefix path - * - * Iterates over pathspec, prepending each path with prefix, - * and return the resulting list. - * - * If pathspec is empty, return a singleton list containing prefix. - * - * If pathspec and prefix are both empty, return an empty list. - * - * This is typically used by built-in commands such as add.c, in order - * to normalize argv arguments provided to the built-in into a list of - * paths to process, all relative to the root of the working tree. - */ -const char **get_pathspec(const char *prefix, const char **pathspec) -{ -	const char *entry = *pathspec; -	const char **src, **dst; -	int prefixlen; - -	if (!prefix && !entry) -		return NULL; - -	if (!entry) { -		static const char *spec[2]; -		spec[0] = prefix; -		spec[1] = NULL; -		return spec; -	} - -	/* Otherwise we have to re-write the entries.. */ -	src = pathspec; -	dst = pathspec; -	prefixlen = prefix ? strlen(prefix) : 0; -	while (*src) { -		*(dst++) = prefix_pathspec(prefix, prefixlen, *src); -		src++; -	} -	*dst = NULL; -	if (!*pathspec) -		return NULL; -	return pathspec; -}  /*   * Test if it looks like we're at a git directory. @@ -360,6 +227,7 @@ int is_inside_work_tree(void)  void setup_work_tree(void)  { +	struct strbuf sb = STRBUF_INIT;  	const char *work_tree, *git_dir;  	static int initialized = 0; @@ -379,8 +247,10 @@ void setup_work_tree(void)  	if (getenv(GIT_WORK_TREE_ENVIRONMENT))  		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1); -	set_git_dir(relative_path(git_dir, work_tree)); +	set_git_dir(relative_path(git_dir, work_tree, &sb));  	initialized = 1; + +	strbuf_release(&sb);  }  static int check_repository_format_gently(const char *gitdir, int *nongit_ok) @@ -908,3 +778,15 @@ const char *resolve_gitdir(const char *suspect)  		return suspect;  	return read_gitfile(suspect);  } + +/* if any standard file descriptor is missing open it to /dev/null */ +void sanitize_stdfds(void) +{ +	int fd = open("/dev/null", O_RDWR, 0); +	while (fd != -1 && fd < 2) +		fd = dup(fd); +	if (fd == -1) +		die_errno("open /dev/null or dup failed"); +	if (fd > 2) +		close(fd); +}  | 
