checkout: if worktree path exists and is empty, suppress mkdir failure
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
diff --git a/got/got.c b/got/got.c
index bc14b93..3d3ea43 100644
--- a/got/got.c
+++ b/got/got.c
@@ -19,6 +19,7 @@
#include <sys/limits.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <err.h>
#include <errno.h>
@@ -197,10 +198,25 @@ apply_unveil(const char *repo_path, int repo_read_only,
const char *worktree_path, int create_worktree)
{
const struct got_error *error;
+ static char err_msg[MAXPATHLEN + 36];
if (create_worktree) {
/* Pre-create work tree path to avoid unveiling its parents. */
error = got_path_mkdir(worktree_path);
+
+ if (errno == EEXIST) {
+ if (got_dir_is_empty(worktree_path)) {
+ errno = 0;
+ error = NULL;
+ } else {
+ snprintf(err_msg, sizeof(err_msg),
+ "%s: directory exists but is not empty",
+ worktree_path);
+ error = got_error_msg(GOT_ERR_BAD_PATH,
+ err_msg);
+ }
+ }
+
if (error && (error->code != GOT_ERR_ERRNO || errno != EISDIR))
return error;
}
diff --git a/include/got_path.h b/include/got_path.h
index e4dc262..b80b464 100644
--- a/include/got_path.h
+++ b/include/got_path.h
@@ -90,6 +90,9 @@ void got_pathlist_free(struct got_pathlist_head *);
/* Attempt to create a directory at a given path. */
const struct got_error *got_path_mkdir(const char *);
+/* Determine whether a directory has no files or directories in it. */
+int got_dir_is_empty(const char *);
+
/* dirname(3) with error handling and dynamically allocated result. */
const struct got_error *got_path_dirname(char **, const char *);
diff --git a/lib/path.c b/lib/path.c
index 3cbf1e5..abd5d7f 100644
--- a/lib/path.c
+++ b/lib/path.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <stdio.h>
#include <string.h>
+#include <dirent.h>
#include "got_error.h"
#include "got_path.h"
@@ -325,6 +326,29 @@ done:
return err;
}
+int
+got_dir_is_empty(const char *dir)
+{
+ DIR *d;
+ struct dirent *dent;
+ int empty = 1;
+
+ d = opendir(dir);
+ if (d == NULL)
+ return 1;
+
+ while ((dent = readdir(d)) != NULL) {
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+
+ empty = 0;
+ break;
+ }
+
+ return empty;
+}
+
const struct got_error *
got_path_dirname(char **parent, const char *path)
{