From: Patrick Steinhardt <ps@pks.im>
To: git@vger.kernel.org
Subject: [PATCH 1/9] object-file: move `safe_create_leading_directories()` into "dir.c"
Date: Tue, 08 Apr 2025 12:24:09 +0200 [thread overview]
Message-ID: <20250408-pks-split-object-file-v1-1-f1fd50191143@pks.im> (raw)
In-Reply-To: <20250408-pks-split-object-file-v1-0-f1fd50191143@pks.im>
The `safe_create_leading_directories()` function and its relatives are
located in "object-file.c", which is not a good fit as they provide
generic functionality not related to objects at all. Move them into
"dir.c".
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
builtin/bugreport.c | 2 +-
builtin/credential-cache--daemon.c | 2 +-
builtin/diagnose.c | 2 +-
builtin/fsck.c | 1 +
builtin/gc.c | 2 +-
builtin/init-db.c | 2 +-
builtin/log.c | 2 +-
commit-graph.c | 1 +
dir.c | 107 ++++++++++++++++++++++++++++++++++++-
dir.h | 35 ++++++++++++
midx-write.c | 1 +
object-file.c | 106 ------------------------------------
object-file.h | 35 ------------
13 files changed, 150 insertions(+), 148 deletions(-)
diff --git a/builtin/bugreport.c b/builtin/bugreport.c
index 66d64bfd5ae..d07fa91c247 100644
--- a/builtin/bugreport.c
+++ b/builtin/bugreport.c
@@ -1,6 +1,7 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "dir.h"
#include "editor.h"
#include "gettext.h"
#include "parse-options.h"
@@ -10,7 +11,6 @@
#include "hook.h"
#include "hook-list.h"
#include "diagnose.h"
-#include "object-file.h"
#include "setup.h"
#include "version.h"
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index e707618e743..80d29b4f5c0 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -1,8 +1,8 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "dir.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
#ifndef NO_UNIX_SOCKETS
diff --git a/builtin/diagnose.c b/builtin/diagnose.c
index 33c39bd5981..d5dadd6a48b 100644
--- a/builtin/diagnose.c
+++ b/builtin/diagnose.c
@@ -2,8 +2,8 @@
#include "builtin.h"
#include "abspath.h"
+#include "dir.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
#include "diagnose.h"
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9c8a6d6a8df..32d40d8f9fc 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -1,5 +1,6 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
+#include "dir.h"
#include "gettext.h"
#include "hex.h"
#include "config.h"
diff --git a/builtin/gc.c b/builtin/gc.c
index 99431fd4674..b069629676c 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -16,6 +16,7 @@
#include "builtin.h"
#include "abspath.h"
#include "date.h"
+#include "dir.h"
#include "environment.h"
#include "hex.h"
#include "config.h"
@@ -28,7 +29,6 @@
#include "commit.h"
#include "commit-graph.h"
#include "packfile.h"
-#include "object-file.h"
#include "object-store-ll.h"
#include "pack.h"
#include "pack-objects.h"
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 196dccdd77a..39730c1b0ce 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -6,9 +6,9 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "builtin.h"
#include "abspath.h"
+#include "dir.h"
#include "environment.h"
#include "gettext.h"
-#include "object-file.h"
#include "parse-options.h"
#include "path.h"
#include "refs.h"
diff --git a/builtin/log.c b/builtin/log.c
index 0d4c579dad7..06ffaa93e86 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -10,11 +10,11 @@
#include "builtin.h"
#include "abspath.h"
#include "config.h"
+#include "dir.h"
#include "environment.h"
#include "gettext.h"
#include "hex.h"
#include "refs.h"
-#include "object-file.h"
#include "object-name.h"
#include "object-store-ll.h"
#include "pager.h"
diff --git a/commit-graph.c b/commit-graph.c
index 8286d5dda24..3fae20dc21b 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -4,6 +4,7 @@
#include "git-compat-util.h"
#include "config.h"
#include "csum-file.h"
+#include "dir.h"
#include "gettext.h"
#include "hex.h"
#include "lockfile.h"
diff --git a/dir.c b/dir.c
index 28b0e03feb4..16ae3b5169d 100644
--- a/dir.c
+++ b/dir.c
@@ -17,7 +17,6 @@
#include "environment.h"
#include "gettext.h"
#include "name-hash.h"
-#include "object-file.h"
#include "object-store-ll.h"
#include "path.h"
#include "refs.h"
@@ -4132,3 +4131,109 @@ int path_match_flags(const char *const str, const enum path_match_flags flags)
return is_xplatform_dir_sep(*p);
BUG("unreachable");
}
+
+int mkdir_in_gitdir(const char *path)
+{
+ if (mkdir(path, 0777)) {
+ int saved_errno = errno;
+ struct stat st;
+ struct strbuf sb = STRBUF_INIT;
+
+ if (errno != EEXIST)
+ return -1;
+ /*
+ * Are we looking at a path in a symlinked worktree
+ * whose original repository does not yet have it?
+ * e.g. .git/rr-cache pointing at its original
+ * repository in which the user hasn't performed any
+ * conflict resolution yet?
+ */
+ if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
+ strbuf_readlink(&sb, path, st.st_size) ||
+ !is_absolute_path(sb.buf) ||
+ mkdir(sb.buf, 0777)) {
+ strbuf_release(&sb);
+ errno = saved_errno;
+ return -1;
+ }
+ strbuf_release(&sb);
+ }
+ return adjust_shared_perm(the_repository, path);
+}
+
+static enum scld_error safe_create_leading_directories_1(char *path, int share)
+{
+ char *next_component = path + offset_1st_component(path);
+ enum scld_error ret = SCLD_OK;
+
+ while (ret == SCLD_OK && next_component) {
+ struct stat st;
+ char *slash = next_component, slash_character;
+
+ while (*slash && !is_dir_sep(*slash))
+ slash++;
+
+ if (!*slash)
+ break;
+
+ next_component = slash + 1;
+ while (is_dir_sep(*next_component))
+ next_component++;
+ if (!*next_component)
+ break;
+
+ slash_character = *slash;
+ *slash = '\0';
+ if (!stat(path, &st)) {
+ /* path exists */
+ if (!S_ISDIR(st.st_mode)) {
+ errno = ENOTDIR;
+ ret = SCLD_EXISTS;
+ }
+ } else if (mkdir(path, 0777)) {
+ if (errno == EEXIST &&
+ !stat(path, &st) && S_ISDIR(st.st_mode))
+ ; /* somebody created it since we checked */
+ else if (errno == ENOENT)
+ /*
+ * Either mkdir() failed because
+ * somebody just pruned the containing
+ * directory, or stat() failed because
+ * the file that was in our way was
+ * just removed. Either way, inform
+ * the caller that it might be worth
+ * trying again:
+ */
+ ret = SCLD_VANISHED;
+ else
+ ret = SCLD_FAILED;
+ } else if (share && adjust_shared_perm(the_repository, path)) {
+ ret = SCLD_PERMS;
+ }
+ *slash = slash_character;
+ }
+ return ret;
+}
+
+enum scld_error safe_create_leading_directories(char *path)
+{
+ return safe_create_leading_directories_1(path, 1);
+}
+
+enum scld_error safe_create_leading_directories_no_share(char *path)
+{
+ return safe_create_leading_directories_1(path, 0);
+}
+
+enum scld_error safe_create_leading_directories_const(const char *path)
+{
+ int save_errno;
+ /* path points to cache entries, so xstrdup before messing with it */
+ char *buf = xstrdup(path);
+ enum scld_error result = safe_create_leading_directories(buf);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+ return result;
+}
diff --git a/dir.h b/dir.h
index d7e71aa8daa..02c1f9420b0 100644
--- a/dir.h
+++ b/dir.h
@@ -676,4 +676,39 @@ static inline int starts_with_dot_dot_slash_native(const char *const path)
return path_match_flags(path, what | PATH_MATCH_NATIVE);
}
+/*
+ * Create the directory containing the named path, using care to be
+ * somewhat safe against races. Return one of the scld_error values to
+ * indicate success/failure. On error, set errno to describe the
+ * problem.
+ *
+ * SCLD_VANISHED indicates that one of the ancestor directories of the
+ * path existed at one point during the function call and then
+ * suddenly vanished, probably because another process pruned the
+ * directory while we were working. To be robust against this kind of
+ * race, callers might want to try invoking the function again when it
+ * returns SCLD_VANISHED.
+ *
+ * safe_create_leading_directories() temporarily changes path while it
+ * is working but restores it before returning.
+ * safe_create_leading_directories_const() doesn't modify path, even
+ * temporarily. Both these variants adjust the permissions of the
+ * created directories to honor core.sharedRepository, so they are best
+ * suited for files inside the git dir. For working tree files, use
+ * safe_create_leading_directories_no_share() instead, as it ignores
+ * the core.sharedRepository setting.
+ */
+enum scld_error {
+ SCLD_OK = 0,
+ SCLD_FAILED = -1,
+ SCLD_PERMS = -2,
+ SCLD_EXISTS = -3,
+ SCLD_VANISHED = -4
+};
+enum scld_error safe_create_leading_directories(char *path);
+enum scld_error safe_create_leading_directories_const(const char *path);
+enum scld_error safe_create_leading_directories_no_share(char *path);
+
+int mkdir_in_gitdir(const char *path);
+
#endif
diff --git a/midx-write.c b/midx-write.c
index a628ac24dcb..e01a867c583 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -3,6 +3,7 @@
#include "git-compat-util.h"
#include "abspath.h"
#include "config.h"
+#include "dir.h"
#include "hex.h"
#include "lockfile.h"
#include "packfile.h"
diff --git a/object-file.c b/object-file.c
index 772c311f188..23b2c8560be 100644
--- a/object-file.c
+++ b/object-file.c
@@ -91,112 +91,6 @@ static int get_conv_flags(unsigned flags)
}
-int mkdir_in_gitdir(const char *path)
-{
- if (mkdir(path, 0777)) {
- int saved_errno = errno;
- struct stat st;
- struct strbuf sb = STRBUF_INIT;
-
- if (errno != EEXIST)
- return -1;
- /*
- * Are we looking at a path in a symlinked worktree
- * whose original repository does not yet have it?
- * e.g. .git/rr-cache pointing at its original
- * repository in which the user hasn't performed any
- * conflict resolution yet?
- */
- if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
- strbuf_readlink(&sb, path, st.st_size) ||
- !is_absolute_path(sb.buf) ||
- mkdir(sb.buf, 0777)) {
- strbuf_release(&sb);
- errno = saved_errno;
- return -1;
- }
- strbuf_release(&sb);
- }
- return adjust_shared_perm(the_repository, path);
-}
-
-static enum scld_error safe_create_leading_directories_1(char *path, int share)
-{
- char *next_component = path + offset_1st_component(path);
- enum scld_error ret = SCLD_OK;
-
- while (ret == SCLD_OK && next_component) {
- struct stat st;
- char *slash = next_component, slash_character;
-
- while (*slash && !is_dir_sep(*slash))
- slash++;
-
- if (!*slash)
- break;
-
- next_component = slash + 1;
- while (is_dir_sep(*next_component))
- next_component++;
- if (!*next_component)
- break;
-
- slash_character = *slash;
- *slash = '\0';
- if (!stat(path, &st)) {
- /* path exists */
- if (!S_ISDIR(st.st_mode)) {
- errno = ENOTDIR;
- ret = SCLD_EXISTS;
- }
- } else if (mkdir(path, 0777)) {
- if (errno == EEXIST &&
- !stat(path, &st) && S_ISDIR(st.st_mode))
- ; /* somebody created it since we checked */
- else if (errno == ENOENT)
- /*
- * Either mkdir() failed because
- * somebody just pruned the containing
- * directory, or stat() failed because
- * the file that was in our way was
- * just removed. Either way, inform
- * the caller that it might be worth
- * trying again:
- */
- ret = SCLD_VANISHED;
- else
- ret = SCLD_FAILED;
- } else if (share && adjust_shared_perm(the_repository, path)) {
- ret = SCLD_PERMS;
- }
- *slash = slash_character;
- }
- return ret;
-}
-
-enum scld_error safe_create_leading_directories(char *path)
-{
- return safe_create_leading_directories_1(path, 1);
-}
-
-enum scld_error safe_create_leading_directories_no_share(char *path)
-{
- return safe_create_leading_directories_1(path, 0);
-}
-
-enum scld_error safe_create_leading_directories_const(const char *path)
-{
- int save_errno;
- /* path points to cache entries, so xstrdup before messing with it */
- char *buf = xstrdup(path);
- enum scld_error result = safe_create_leading_directories(buf);
-
- save_errno = errno;
- free(buf);
- errno = save_errno;
- return result;
-}
-
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
{
int fd;
diff --git a/object-file.h b/object-file.h
index 81b30d269c8..922f2bba8c9 100644
--- a/object-file.h
+++ b/object-file.h
@@ -21,41 +21,6 @@ extern int fetch_if_missing;
int index_fd(struct index_state *istate, struct object_id *oid, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
-/*
- * Create the directory containing the named path, using care to be
- * somewhat safe against races. Return one of the scld_error values to
- * indicate success/failure. On error, set errno to describe the
- * problem.
- *
- * SCLD_VANISHED indicates that one of the ancestor directories of the
- * path existed at one point during the function call and then
- * suddenly vanished, probably because another process pruned the
- * directory while we were working. To be robust against this kind of
- * race, callers might want to try invoking the function again when it
- * returns SCLD_VANISHED.
- *
- * safe_create_leading_directories() temporarily changes path while it
- * is working but restores it before returning.
- * safe_create_leading_directories_const() doesn't modify path, even
- * temporarily. Both these variants adjust the permissions of the
- * created directories to honor core.sharedRepository, so they are best
- * suited for files inside the git dir. For working tree files, use
- * safe_create_leading_directories_no_share() instead, as it ignores
- * the core.sharedRepository setting.
- */
-enum scld_error {
- SCLD_OK = 0,
- SCLD_FAILED = -1,
- SCLD_PERMS = -2,
- SCLD_EXISTS = -3,
- SCLD_VANISHED = -4
-};
-enum scld_error safe_create_leading_directories(char *path);
-enum scld_error safe_create_leading_directories_const(const char *path);
-enum scld_error safe_create_leading_directories_no_share(char *path);
-
-int mkdir_in_gitdir(const char *path);
-
int git_open_cloexec(const char *name, int flags);
#define git_open(name) git_open_cloexec(name, O_RDONLY)
--
2.49.0.682.gc9b6a7b2b0.dirty
next prev parent reply other threads:[~2025-04-08 10:24 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-08 10:24 [PATCH 0/9] Split up "object-file.c" Patrick Steinhardt
2025-04-08 10:24 ` Patrick Steinhardt [this message]
2025-04-09 14:36 ` [PATCH 1/9] object-file: move `safe_create_leading_directories()` into "dir.c" Elijah Newren
2025-04-11 9:27 ` Patrick Steinhardt
2025-04-11 17:11 ` Elijah Newren
2025-04-15 9:19 ` Patrick Steinhardt
2025-04-15 15:11 ` Junio C Hamano
2025-04-08 10:24 ` [PATCH 2/9] object-file: move `git_open_cloexec()` to "compat/open.c" Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 3/9] object-file: move `xmmap()` into "wrapper.c" Patrick Steinhardt
2025-04-09 14:36 ` Elijah Newren
2025-04-08 10:24 ` [PATCH 4/9] object-file: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 5/9] object-file: split up concerns of `HASH_*` flags Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 6/9] object-file: split out functions relating to index subsystem Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 7/9] object: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 8/9] object-store: remove global array of cached objects Patrick Steinhardt
2025-04-08 10:24 ` [PATCH 9/9] object-store: merge "object-store-ll.h" and "object-store.h" Patrick Steinhardt
2025-04-08 23:29 ` [PATCH 0/9] Split up "object-file.c" Junio C Hamano
2025-04-11 9:26 ` Patrick Steinhardt
2025-04-09 14:42 ` Elijah Newren
2025-04-11 9:27 ` Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 " Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 1/9] object-file: move `safe_create_leading_directories()` into "dir.c" Patrick Steinhardt
2025-04-11 20:09 ` Junio C Hamano
2025-04-11 21:29 ` Eric Sunshine
2025-04-15 9:19 ` Patrick Steinhardt
2025-04-15 15:09 ` Junio C Hamano
2025-04-11 9:29 ` [PATCH v2 2/9] object-file: move `git_open_cloexec()` to "compat/open.c" Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 3/9] object-file: move `xmmap()` into "wrapper.c" Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 4/9] object-file: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 5/9] object-file: split up concerns of `HASH_*` flags Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 6/9] object-file: split out functions relating to index subsystem Patrick Steinhardt
2025-04-12 8:17 ` Jeff King
2025-04-14 11:49 ` Junio C Hamano
2025-04-15 9:19 ` Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 7/9] object: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 8/9] object-store: remove global array of cached objects Patrick Steinhardt
2025-04-11 22:58 ` Junio C Hamano
2025-04-15 9:19 ` Patrick Steinhardt
2025-04-11 9:29 ` [PATCH v2 9/9] object-store: merge "object-store-ll.h" and "object-store.h" Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 00/10] Split up "object-file.c" Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 01/10] object-file: move `mkdir_in_gitdir()` into "path.c" Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 02/10] object-file: move `safe_create_leading_directories()` " Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 03/10] object-file: move `git_open_cloexec()` to "compat/open.c" Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 04/10] object-file: move `xmmap()` into "wrapper.c" Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 05/10] object-file: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 06/10] object-file: split up concerns of `HASH_*` flags Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 07/10] object-file: drop `index_blob_stream()` Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 08/10] object: split out functions relating to object store subsystem Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 09/10] object-store: remove global array of cached objects Patrick Steinhardt
2025-04-15 9:38 ` [PATCH v3 10/10] object-store: merge "object-store-ll.h" and "object-store.h" Patrick Steinhardt
2025-04-16 6:41 ` [PATCH v3 00/10] Split up "object-file.c" Elijah Newren
2025-04-16 7:44 ` Patrick Steinhardt
2025-04-16 16:21 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250408-pks-split-object-file-v1-1-f1fd50191143@pks.im \
--to=ps@pks.im \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).