Commit 55ffebe37768b2b839f5501f76e77e89d9f91882

Vicent Marti 2011-03-05T14:34:32

Fix creation of deeply-rooted references Use a new `gitfo_creat_force` that will create the full path to a file before creating it. Signed-off-by: Vicent Marti <tanoku@gmail.com>

diff --git a/src/filebuf.c b/src/filebuf.c
index 73f0a70..4fc4f14 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -39,7 +39,12 @@ static int lock_file(git_filebuf *file, int flags)
 			return GIT_EOSERR;
 	}
 
-	file->fd = gitfo_creat(file->path_lock, 0644);
+	/* create path to the file buffer is required */
+	if (flags & GIT_FILEBUF_FORCE) {
+		file->fd = gitfo_creat_force(file->path_lock, 0644);
+	} else {
+		file->fd = gitfo_creat(file->path_lock, 0644);
+	}
 
 	if (file->fd < 0)
 		return GIT_EOSERR;
diff --git a/src/fileops.c b/src/fileops.c
index 7691129..76e689e 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -2,6 +2,29 @@
 #include "fileops.h"
 #include <ctype.h>
 
+static int force_path(const char *to)
+{
+	const int mode = 0755; /* or 0777 ? */
+	int error = GIT_SUCCESS;
+	char target_folder_path[GIT_PATH_MAX];
+
+	error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to);
+	if (error < GIT_SUCCESS)
+		return error;
+
+	/* Does the containing folder exist? */
+	if (gitfo_isdir(target_folder_path)) {
+		git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
+
+		/* Let's create the tree structure */
+		error = gitfo_mkdir_recurs(target_folder_path, mode);
+		if (error < GIT_SUCCESS)
+			return error;
+	}
+
+	return GIT_SUCCESS;
+}
+
 int gitfo_open(const char *path, int flags)
 {
 	int fd = open(path, flags | O_BINARY);
@@ -14,6 +37,14 @@ int gitfo_creat(const char *path, int mode)
 	return fd >= 0 ? fd : GIT_EOSERR;
 }
 
+int gitfo_creat_force(const char *path, int mode)
+{
+	if (force_path(path) < GIT_SUCCESS)
+		return GIT_EOSERR;
+
+	return gitfo_creat(path, mode);
+}
+
 int gitfo_read(git_file fd, void *buf, size_t cnt)
 {
 	char *b = buf;
@@ -167,23 +198,8 @@ int gitfo_mv(const char *from, const char *to)
 
 int gitfo_mv_force(const char *from, const char *to)
 {
-	const int mode = 0755; /* or 0777 ? */
-	int error = GIT_SUCCESS;
-	char target_folder_path[GIT_PATH_MAX];
-
-	error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to);
-	if (error < GIT_SUCCESS)
-		return error;
-
-	/* Does the containing folder exist? */
-	if (gitfo_isdir(target_folder_path)) {
-		git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
-
-		/* Let's create the tree structure */
-		error = gitfo_mkdir_recurs(target_folder_path, mode);
-		if (error < GIT_SUCCESS)
-			return error;
-	}
+	if (force_path(to) < GIT_SUCCESS)
+		return GIT_EOSERR;
 
 	return gitfo_mv(from, to);
 }
diff --git a/src/fileops.h b/src/fileops.h
index fd150df..5aa302b 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -57,6 +57,7 @@ typedef struct {  /* file io buffer  */
 extern int gitfo_exists(const char *path);
 extern int gitfo_open(const char *path, int flags);
 extern int gitfo_creat(const char *path, int mode);
+extern int gitfo_creat_force(const char *path, int mode);
 extern int gitfo_isdir(const char *path);
 extern int gitfo_mkdir_recurs(const char *path, int mode);
 #define gitfo_close(fd) close(fd)
diff --git a/src/refs.c b/src/refs.c
index 10df8e0..2fc383e 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -291,7 +291,7 @@ static int loose_write(git_reference *ref)
 
 	git__joinpath(ref_path, ref->owner->path_repository, ref->name);
 
-	if ((error = git_filebuf_open(&file, ref_path, 0)) < GIT_SUCCESS)
+	if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
 		return error;
 
 	if (ref->type & GIT_REF_OID) {