summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-03-05 14:34:32 +0200
committerVicent Marti <tanoku@gmail.com>2011-03-05 14:34:32 +0200
commit55ffebe37768b2b839f5501f76e77e89d9f91882 (patch)
treec9275716290855fd909df22c4163bf7797da02b8
parent246eba80af31d25a1fb14e707f79374cf91f8bb7 (diff)
downloadlibgit2-55ffebe37768b2b839f5501f76e77e89d9f91882.tar.gz
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>
-rw-r--r--src/filebuf.c7
-rw-r--r--src/fileops.c50
-rw-r--r--src/fileops.h1
-rw-r--r--src/refs.c2
4 files changed, 41 insertions, 19 deletions
diff --git a/src/filebuf.c b/src/filebuf.c
index 73f0a70f4..4fc4f1486 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 7691129f6..76e689e8a 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 fd150df5e..5aa302b54 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 10df8e0c4..2fc383e22 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) {