Add new move function, `gitfo_mv_force` Forces a move by creating the folder for the destination file, if it doesn't exist. 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
diff --git a/src/filebuf.c b/src/filebuf.c
index a71c57a..73f0a70 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -192,7 +192,7 @@ int git_filebuf_commit(git_filebuf *file)
gitfo_close(file->fd);
file->fd = -1;
- error = gitfo_move_file(file->path_lock, file->path_original);
+ error = gitfo_mv(file->path_lock, file->path_original);
cleanup:
git_filebuf_cleanup(file);
diff --git a/src/fileops.c b/src/fileops.c
index 9938011..7691129 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -142,7 +142,7 @@ void gitfo_free_buf(gitfo_buf *obj)
obj->data = NULL;
}
-int gitfo_move_file(char *from, char *to)
+int gitfo_mv(const char *from, const char *to)
{
#ifdef GIT_WIN32
/*
@@ -165,6 +165,29 @@ int gitfo_move_file(char *from, char *to)
#endif
}
+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;
+ }
+
+ return gitfo_mv(from, to);
+}
+
int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
{
if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < GIT_SUCCESS)
diff --git a/src/fileops.h b/src/fileops.h
index 16e7103..fd150df 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -68,7 +68,13 @@ extern git_off_t gitfo_size(git_file fd);
extern int gitfo_read_file(gitfo_buf *obj, const char *path);
extern void gitfo_free_buf(gitfo_buf *obj);
-extern int gitfo_move_file(char *from, char *to);
+
+/* Move (rename) a file; this operation is atomic */
+extern int gitfo_mv(const char *from, const char *to);
+
+/* Move a file (forced); this will create the destination
+ * path if it doesn't exist */
+extern int gitfo_mv_force(const char *from, const char *to);
#define gitfo_stat(p,b) stat(p, b)
#define gitfo_fstat(f,b) fstat(f, b)
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 735d939..4e2d9a6 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -528,7 +528,7 @@ static int write_obj(gitfo_buf *buf, git_oid *id, loose_backend *backend)
gitfo_close(fd);
gitfo_chmod(temp, 0444);
- if (gitfo_move_file(temp, file) < 0) {
+ if (gitfo_mv(temp, file) < 0) {
gitfo_unlink(temp);
return GIT_EOSERR;
}
diff --git a/src/refs.c b/src/refs.c
index 19f5406..5bbc777 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1183,7 +1183,7 @@ int git_reference_rename(git_reference *ref, const char *new_name)
git__joinpath(old_path, ref->owner->path_repository, old_name);
git__joinpath(new_path, ref->owner->path_repository, ref->name);
- error = gitfo_move_file(old_path, new_path);
+ error = gitfo_mv_force(old_path, new_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -1218,7 +1218,7 @@ rename_loose_to_old_name:
git__joinpath(new_path, ref->owner->path_repository, old_name);
/* No error checking. We'll return the initial error */
- gitfo_move_file(old_path, new_path);
+ gitfo_mv_force(old_path, new_path);
/* restore the old name */
free(ref->name);