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