1
0
mirror of https://github.com/git/git.git synced 2024-09-28 08:49:45 +02:00

Library code for user-relative paths, take three.

This patch provides the work-horse of the user-relative paths feature,
using Linus' idea of a blind chdir() and getcwd() which makes it
remarkably simple.

Signed-off-by: Andreas Ericsson <ae@op5.se>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Andreas Ericsson 2005-11-17 20:37:14 +01:00 committed by Junio C Hamano
parent 942c1f53ae
commit 54f4b87454
2 changed files with 73 additions and 0 deletions

View File

@ -192,6 +192,7 @@ extern int diff_rename_limit_default;
/* Return a statically allocated filename matching the sha1 signature */
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *enter_repo(char *path, int strict);
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *sha1_file_name(const unsigned char *sha1);
extern char *sha1_pack_name(const unsigned char *sha1);

72
path.c
View File

@ -11,6 +11,7 @@
* which is what it's designed for.
*/
#include "cache.h"
#include <pwd.h>
static char pathname[PATH_MAX];
static char bad_path[] = "/bad-path/";
@ -89,3 +90,74 @@ char *safe_strncpy(char *dest, const char *src, size_t n)
return dest;
}
static char *current_dir()
{
return getcwd(pathname, sizeof(pathname));
}
/* Take a raw path from is_git_repo() and canonicalize it using Linus'
* idea of a blind chdir() and getcwd(). */
static const char *canonical_path(char *path, int strict)
{
char *dir = path;
if(strict && *dir != '/')
return NULL;
if(*dir == '~') { /* user-relative path */
struct passwd *pw;
char *slash = strchr(dir, '/');
dir++;
/* '~/' and '~' (no slash) means users own home-dir */
if(!*dir || *dir == '/')
pw = getpwuid(getuid());
else {
if (slash) {
*slash = '\0';
pw = getpwnam(dir);
*slash = '/';
}
else
pw = getpwnam(dir);
}
/* make sure we got something back that we can chdir() to */
if(!pw || chdir(pw->pw_dir) < 0)
return NULL;
if(!slash || !slash[1]) /* no path following username */
return current_dir();
dir = slash + 1;
}
/* ~foo/path/to/repo is now path/to/repo and we're in foo's homedir */
if(chdir(dir) < 0)
return NULL;
return current_dir();
}
char *enter_repo(char *path, int strict)
{
if(!path)
return NULL;
if(!canonical_path(path, strict)) {
if(strict || !canonical_path(mkpath("%s.git", path), strict))
return NULL;
}
/* This is perfectly safe, and people tend to think of the directory
* where they ran git-init-db as their repository, so humour them. */
(void)chdir(".git");
if(access("objects", X_OK) == 0 && access("refs", X_OK) == 0) {
putenv("GIT_DIR=.");
return current_dir();
}
return NULL;
}