Commit f2e6b8776e8d9f65b3edf3e3bc1ff22a495170ea

Romain Geissler 2011-06-03T23:44:38

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).

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)