Repository: Added some util functions that we'll need to discover repository path. retrieve_device returns the file device for a given path (so that we can detect device change while walking through parent directories). abspath returns a canonicalized path, symbolic link free. retrieive_ceiling_directories_offset returns the biggest path offset that path match in the ceiling directory list (so that we can stop at ceiling directories).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
diff --git a/src/fileops.c b/src/fileops.c
index c407515..56bf292 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -334,7 +334,7 @@ int gitfo_dirent(
return GIT_SUCCESS;
}
-static void posixify_path(char *path)
+void gitfo_posixify_path(char *path)
{
#if GIT_PLATFORM_PATH_SEP != '/'
while (*path) {
@@ -456,7 +456,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
return git__throw(GIT_EOVERFLOW, "Failed to prettify dir path: the base path is too long for the buffer.");
strcpy(buffer_out, base_path);
- posixify_path(buffer_out);
+ gitfo_posixify_path(buffer_out);
git__joinpath(buffer_out, buffer_out, "");
}
@@ -587,7 +587,7 @@ int gitfo_getcwd(char *buffer_out, size_t size)
if (cwd_buffer == NULL)
return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
- posixify_path(buffer_out);
+ gitfo_posixify_path(buffer_out);
git__joinpath(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash
diff --git a/src/fileops.h b/src/fileops.h
index 23f1654..4a86e1c 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -198,6 +198,8 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
*/
int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, const char *base_path);
+void gitfo_posixify_path(char *path);
+
int gitfo_retrieve_path_root_offset(const char *path);
#endif /* INCLUDE_fileops_h__ */
diff --git a/src/repository.c b/src/repository.c
index 76042c2..59d1b80 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -299,6 +299,81 @@ cleanup:
return git__rethrow(error, "Failed to open repository");
}
+static int abspath(char *buffer_out, size_t size, const char *path)
+{
+ assert(buffer_out && size >= GIT_PATH_MAX);
+
+ #ifdef GIT_WIN32
+ if (_fullpath(buffer_out, path, size) == NULL)
+ return git__throw(GIT_EOSERR, "Failed to retrieve real path: %s causing errors", buffer_out);
+ #else
+ if (realpath(path, buffer_out) == NULL)
+ return git__throw(GIT_EOSERR, "Failed to retrieve real path: %s causing errors", buffer_out);
+ #endif
+
+ gitfo_posixify_path(buffer_out);
+
+ return GIT_SUCCESS;
+}
+
+static dev_t retrieve_device(dev_t *device_out, const char *path)
+{
+ struct stat path_info;
+
+ assert(device_out);
+
+ if (gitfo_stat(path, &path_info))
+ return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
+
+ *device_out = path_info.st_dev;
+
+ return GIT_SUCCESS;
+}
+
+static int retrieve_ceiling_directories_offset(const char *path, const char *ceiling_directories)
+{
+ char buf[GIT_PATH_MAX + 1];
+ char buf2[GIT_PATH_MAX + 1];
+ const char *ceil, *sep;
+ int len, max_len = -1;
+ int min_len;
+
+ assert(path);
+
+ min_len = gitfo_retrieve_path_root_offset(path) + 1;
+
+ if (ceiling_directories == NULL || min_len == 0)
+ return min_len;
+
+ for (sep = ceil = ceiling_directories; *sep; ceil = sep + 1) {
+ for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
+ len = sep - ceil;
+
+ if (len == 0 || len > GIT_PATH_MAX || gitfo_retrieve_path_root_offset(ceil) == -1)
+ continue;
+
+ strncpy(buf, ceil, len);
+ buf[len] = '\0';
+
+ gitfo_posixify_path(buf);
+ if (gitfo_prettify_dir_path(buf2, sizeof(buf2), buf, NULL) < GIT_SUCCESS)
+ continue;
+
+ len = strlen(buf2);
+ if (len > 0 && buf2[len-1] == '/')
+ buf[--len] = '\0';
+
+ if (!strncmp(path, buf2, len) &&
+ path[len] == '/' &&
+ len > max_len)
+ {
+ max_len = len;
+ }
+ }
+
+ return max_len <= min_len ? min_len : max_len;
+}
+
void git_repository_free(git_repository *repo)
{
if (repo == NULL)