git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 01/10] object-file: move `mkdir_in_gitdir()` into "path.c"

From
Patrick Steinhardt <ps@pks.im>
Date
Apr 15, 2025, 09:38 UTC
Message-ID
<20250415-pks-split-object-file-v3-1-6aa7db7ad7b0@pks.im>
In-Reply-To
<20250415-pks-split-object-file-v3-0-6aa7db7ad7b0@pks.im>

The `mkdir_in_gitdir()` function is similar to `safe_create_dir()`, but the former is hosted in "object-file.c" whereas the latter is hosted in "path.c". The latter code unit makes way more sense though as the logic has nothing to do with object files in particular.

Move the file into "path.c". While at it, we:
  - Rename the function to `safe_create_dir_in_gitdir()` so that the
    function names are similar to one another.
  - Remove the dependency on `the_repository` by making the callers pass
    the repository instead.
Adjust callers accordingly.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/rebase.c |  3 ++-
 object-file.c    | 33 ++-------------------------------
 object-file.h    |  2 --
 path.c           | 29 +++++++++++++++++++++++++++++
 path.h           | 11 +++++++++++
 rerere.c         |  5 +++--
 6 files changed, 47 insertions(+), 36 deletions(-)
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 1cd802dd92a..cd9371536f8 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -267,7 +267,8 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name,
 {
 	FILE *interactive;
 
-	if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
+	if (!is_directory(merge_dir()) &&
+	    safe_create_dir_in_gitdir(the_repository, merge_dir()))
 		return error_errno(_("could not create temporary %s"), merge_dir());
 
 	refs_delete_reflog(get_main_ref_store(the_repository), "REBASE_HEAD");
diff --git a/object-file.c b/object-file.c
index 772c311f188..00451876bd0 100644
--- a/object-file.c
+++ b/object-file.c
@@ -90,36 +90,6 @@ static int get_conv_flags(unsigned flags)
 		return 0;
 }
 
-
-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);
@@ -2196,7 +2166,8 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
 		struct strbuf dir = STRBUF_INIT;
 		strbuf_add(&dir, filename.buf, dirlen);
 
-		if (mkdir_in_gitdir(dir.buf) && errno != EEXIST) {
+		if (safe_create_dir_in_gitdir(the_repository, dir.buf) &&
+		    errno != EEXIST) {
 			err = error_errno(_("unable to create directory %s"), dir.buf);
 			strbuf_release(&dir);
 			goto cleanup;
diff --git a/object-file.h b/object-file.h
index 81b30d269c8..4649a3f37d4 100644
--- a/object-file.h
+++ b/object-file.h
@@ -54,8 +54,6 @@ 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)
 
diff --git a/path.c b/path.c
index 910756c8b32..c688f874580 100644
--- a/path.c
+++ b/path.c
@@ -902,6 +902,35 @@ void safe_create_dir(struct repository *repo, const char *dir, int share)
 		die(_("Could not make %s writable by group"), dir);
 }
 
+int safe_create_dir_in_gitdir(struct repository *repo, 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(repo, path);
+}
+
 static int have_same_root(const char *path1, const char *path2)
 {
 	int is_abs1, is_abs2;
diff --git a/path.h b/path.h
index 65fe968a13a..a427516d818 100644
--- a/path.h
+++ b/path.h
@@ -221,6 +221,17 @@ char *xdg_cache_home(const char *filename);
  */
 void safe_create_dir(struct repository *repo, const char *dir, int share);
 
+/*
+ * Similar to `safe_create_dir()`, but with two differences:
+ *
+ *   - It knows to resolve gitlink files for symlinked worktrees.
+ *
+ *   - It always adjusts shared permissions.
+ *
+ * Returns a negative erorr code on error, 0 on success.
+ */
+int safe_create_dir_in_gitdir(struct repository *repo, const char *path);
+
 # ifdef USE_THE_REPOSITORY_VARIABLE
 #  include "strbuf.h"
 #  include "repository.h"
diff --git a/rerere.c b/rerere.c
index 740e8ad1a0b..0832cc54840 100644
--- a/rerere.c
+++ b/rerere.c
@@ -860,7 +860,7 @@ static int do_plain_rerere(struct repository *r,
 		string_list_insert(rr, path)->util = id;
 
 		/* Ensure that the directory exists. */
-		mkdir_in_gitdir(rerere_path(&buf, id, NULL));
+		safe_create_dir_in_gitdir(the_repository, rerere_path(&buf, id, NULL));
 	}
 
 	for (i = 0; i < rr->nr; i++)
@@ -895,7 +895,8 @@ static int is_rerere_enabled(void)
 	if (rerere_enabled < 0)
 		return rr_cache_exists;
 
-	if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache()))
+	if (!rr_cache_exists &&
+	    safe_create_dir_in_gitdir(the_repository, git_path_rr_cache()))
 		die(_("could not create directory '%s'"), git_path_rr_cache());
 	return 1;
 }
-- 
2.49.0.805.g082f7c87e0.dirty
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 41 of 53 in “Split up "object-file.c"”
  1. 0/9 Split up "object-file.c"Patrick Steinhardt, Apr 8, 2025
  2. 1/9 object-file: move `safe_create_leading_directories()` into "dir.c"Patrick Steinhardt, Apr 8, 2025
  3. Elijah NewrenApr 9, 2025
  4. Patrick SteinhardtApr 11, 2025
  5. Elijah NewrenApr 11, 2025
  6. Patrick SteinhardtApr 15, 2025
  7. Junio C HamanoApr 15, 2025
  8. 2/9 object-file: move `git_open_cloexec()` to "compat/open.c"Patrick Steinhardt, Apr 8, 2025
  9. 3/9 object-file: move `xmmap()` into "wrapper.c"Patrick Steinhardt, Apr 8, 2025
  10. Elijah NewrenApr 9, 2025
  11. 4/9 object-file: split out functions relating to object store subsystemPatrick Steinhardt, Apr 8, 2025
  12. 5/9 object-file: split up concerns of `HASH_*` flagsPatrick Steinhardt, Apr 8, 2025
  13. 6/9 object-file: split out functions relating to index subsystemPatrick Steinhardt, Apr 8, 2025
  14. 7/9 object: split out functions relating to object store subsystemPatrick Steinhardt, Apr 8, 2025
  15. 8/9 object-store: remove global array of cached objectsPatrick Steinhardt, Apr 8, 2025
  16. 9/9 object-store: merge "object-store-ll.h" and "object-store.h"Patrick Steinhardt, Apr 8, 2025
  17. Junio C HamanoApr 8, 2025
  18. Patrick SteinhardtApr 11, 2025
  19. Elijah NewrenApr 9, 2025
  20. Patrick SteinhardtApr 11, 2025
  21. 0/9 Split up "object-file.c"Patrick Steinhardt, Apr 11, 2025
  22. 1/9 object-file: move `safe_create_leading_directories()` into "dir.c"Patrick Steinhardt, Apr 11, 2025
  23. Junio C HamanoApr 11, 2025
  24. Eric SunshineApr 11, 2025
  25. Patrick SteinhardtApr 15, 2025
  26. Junio C HamanoApr 15, 2025
  27. 2/9 object-file: move `git_open_cloexec()` to "compat/open.c"Patrick Steinhardt, Apr 11, 2025
  28. 3/9 object-file: move `xmmap()` into "wrapper.c"Patrick Steinhardt, Apr 11, 2025
  29. 4/9 object-file: split out functions relating to object store subsystemPatrick Steinhardt, Apr 11, 2025
  30. 5/9 object-file: split up concerns of `HASH_*` flagsPatrick Steinhardt, Apr 11, 2025
  31. 6/9 object-file: split out functions relating to index subsystemPatrick Steinhardt, Apr 11, 2025
  32. Jeff KingApr 12, 2025
  33. Junio C HamanoApr 14, 2025
  34. Patrick SteinhardtApr 15, 2025
  35. 7/9 object: split out functions relating to object store subsystemPatrick Steinhardt, Apr 11, 2025
  36. 8/9 object-store: remove global array of cached objectsPatrick Steinhardt, Apr 11, 2025
  37. Junio C HamanoApr 11, 2025
  38. Patrick SteinhardtApr 15, 2025
  39. 9/9 object-store: merge "object-store-ll.h" and "object-store.h"Patrick Steinhardt, Apr 11, 2025
  40. 00/10 Split up "object-file.c"Patrick Steinhardt, Apr 15, 2025
  41. 01/10 object-file: move `mkdir_in_gitdir()` into "path.c"Patrick Steinhardt, Apr 15, 2025
  42. 02/10 object-file: move `safe_create_leading_directories()` into "path.c"Patrick Steinhardt, Apr 15, 2025
  43. 03/10 object-file: move `git_open_cloexec()` to "compat/open.c"Patrick Steinhardt, Apr 15, 2025
  44. 04/10 object-file: move `xmmap()` into "wrapper.c"Patrick Steinhardt, Apr 15, 2025
  45. 05/10 object-file: split out functions relating to object store subsystemPatrick Steinhardt, Apr 15, 2025
  46. 06/10 object-file: split up concerns of `HASH_*` flagsPatrick Steinhardt, Apr 15, 2025
  47. 07/10 object-file: drop `index_blob_stream()`Patrick Steinhardt, Apr 15, 2025
  48. 08/10 object: split out functions relating to object store subsystemPatrick Steinhardt, Apr 15, 2025
  49. 09/10 object-store: remove global array of cached objectsPatrick Steinhardt, Apr 15, 2025
  50. 10/10 object-store: merge "object-store-ll.h" and "object-store.h"Patrick Steinhardt, Apr 15, 2025
  51. Elijah NewrenApr 16, 2025
  52. Patrick SteinhardtApr 16, 2025
  53. Junio C HamanoApr 16, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.