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:
parent
942c1f53ae
commit
54f4b87454
1
cache.h
1
cache.h
@ -192,6 +192,7 @@ extern int diff_rename_limit_default;
|
|||||||
|
|
||||||
/* Return a statically allocated filename matching the sha1 signature */
|
/* Return a statically allocated filename matching the sha1 signature */
|
||||||
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
|
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 *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
|
||||||
extern char *sha1_file_name(const unsigned char *sha1);
|
extern char *sha1_file_name(const unsigned char *sha1);
|
||||||
extern char *sha1_pack_name(const unsigned char *sha1);
|
extern char *sha1_pack_name(const unsigned char *sha1);
|
||||||
|
72
path.c
72
path.c
@ -11,6 +11,7 @@
|
|||||||
* which is what it's designed for.
|
* which is what it's designed for.
|
||||||
*/
|
*/
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
static char pathname[PATH_MAX];
|
static char pathname[PATH_MAX];
|
||||||
static char bad_path[] = "/bad-path/";
|
static char bad_path[] = "/bad-path/";
|
||||||
@ -89,3 +90,74 @@ char *safe_strncpy(char *dest, const char *src, size_t n)
|
|||||||
|
|
||||||
return dest;
|
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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user