completion: For consistency, change "git rev-parse" to __gitdir calls
[gitweb.git] / abspath.c
index 4f95a954d5e20e2d42549141ac23794f681559e1..649f34f83365db3513c5166b897c4f033831444d 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -1,5 +1,16 @@
 #include "cache.h"
 
+/*
+ * Do not use this for inspecting *tracked* content.  When path is a
+ * symlink to a directory, we do not want to say it is a directory when
+ * dealing with tracked content in the working tree.
+ */
+int is_directory(const char *path)
+{
+       struct stat st;
+       return (!stat(path, &st) && S_ISDIR(st.st_mode));
+}
+
 /* We allow "recursive" symbolic links. Only within reason, though. */
 #define MAXDEPTH 5
 
@@ -17,7 +28,7 @@ const char *make_absolute_path(const char *path)
                die ("Too long path: %.*s", 60, path);
 
        while (depth--) {
-               if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
+               if (!is_directory(buf)) {
                        char *last_slash = strrchr(buf, '/');
                        if (last_slash) {
                                *last_slash = '\0';
@@ -53,6 +64,8 @@ const char *make_absolute_path(const char *path)
                        len = readlink(buf, next_buf, PATH_MAX);
                        if (len < 0)
                                die ("Invalid symlink: %s", buf);
+                       if (PATH_MAX <= len)
+                               die("symbolic link too long: %s", buf);
                        next_buf[len] = '\0';
                        buf = next_buf;
                        buf_index = 1 - buf_index;
@@ -66,3 +79,39 @@ const char *make_absolute_path(const char *path)
 
        return buf;
 }
+
+static const char *get_pwd_cwd(void)
+{
+       static char cwd[PATH_MAX + 1];
+       char *pwd;
+       struct stat cwd_stat, pwd_stat;
+       if (getcwd(cwd, PATH_MAX) == NULL)
+               return NULL;
+       pwd = getenv("PWD");
+       if (pwd && strcmp(pwd, cwd)) {
+               stat(cwd, &cwd_stat);
+               if (!stat(pwd, &pwd_stat) &&
+                   pwd_stat.st_dev == cwd_stat.st_dev &&
+                   pwd_stat.st_ino == cwd_stat.st_ino) {
+                       strlcpy(cwd, pwd, PATH_MAX);
+               }
+       }
+       return cwd;
+}
+
+const char *make_nonrelative_path(const char *path)
+{
+       static char buf[PATH_MAX + 1];
+
+       if (is_absolute_path(path)) {
+               if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+                       die("Too long path: %.*s", 60, path);
+       } else {
+               const char *cwd = get_pwd_cwd();
+               if (!cwd)
+                       die("Cannot determine the current working directory");
+               if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
+                       die("Too long path: %.*s", 60, path);
+       }
+       return buf;
+}