summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 942c1f5)
raw | patch | inline | side by side (parent: 942c1f5)
author | Andreas Ericsson <exon@op5.se> | |
Thu, 17 Nov 2005 19:37:14 +0000 (20:37 +0100) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Sun, 20 Nov 2005 04:50:37 +0000 (20:50 -0800) |
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>
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>
cache.h | patch | blob | history | |
path.c | patch | blob | history |
index f93f516815fdfdbdc105db9f825376b241bbe75f..e2be3e7b0eeb7831766a77e1d3d188524f93d235 100644 (file)
--- a/cache.h
+++ b/cache.h
/* 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);
index 495d17ca4ca371f4b5bdb6f1f3de9a6a9d84280b..5b617092ad564739829d638938f36177611acf58 100644 (file)
--- a/path.c
+++ b/path.c
* which is what it's designed for.
*/
#include "cache.h"
+#include <pwd.h>
static char pathname[PATH_MAX];
static char bad_path[] = "/bad-path/";
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;
+}