object-file: move `safe_create_leading_directories()` into "path.c"
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 "path.c", which already hosts `safe_create_dir()` and its relative `safe_create_dir_in_gitdir()`. "path.c" is free of `the_repository`, but the moved functions depend on `the_repository` to read the "core.sharedRepository" config. Adapt the function signature to accept a repository as argument to fix the issue and adjust callers accordingly. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Apr 15, 2025 at 11:38 UTC
1a99fe8010642a71063536510c578c1543d763b4
27 files changed
+173
-167
builtin/bugreport.c
+2
-2
@@ -4,13 +4,13 @@
4
#include "editor.h"
5
#include "gettext.h"
6
#include "parse-options.h"
7
+#include "path.h"
8
#include "strbuf.h"
9
#include "help.h"
10
#include "compat/compiler.h"
11
#include "hook.h"
12
#include "hook-list.h"
13
#include "diagnose.h"
13
-#include "object-file.h"
14
#include "setup.h"
15
#include "version.h"
16
@@ -141,7 +141,7 @@ int cmd_bugreport(int argc,
141
}
142
strbuf_addstr(&report_path, ".txt");
143
144
- switch (safe_create_leading_directories(report_path.buf)) {
144
+ switch (safe_create_leading_directories(the_repository, report_path.buf)) {
145
case SCLD_OK:
146
case SCLD_EXISTS:
147
break;
builtin/clone.c
+2
-2
@@ -1090,7 +1090,7 @@ int cmd_clone(int argc,
1090
sigchain_push_common(remove_junk_on_signal);
1091
1092
if (!option_bare) {
1093
- if (safe_create_leading_directories_const(work_tree) < 0)
1093
+ if (safe_create_leading_directories_const(the_repository, work_tree) < 0)
1094
die_errno(_("could not create leading directories of '%s'"),
1095
work_tree);
1096
if (dest_exists)
@@ -1111,7 +1111,7 @@ int cmd_clone(int argc,
1111
junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
1112
junk_git_dir = git_dir;
1113
}
1114
- if (safe_create_leading_directories_const(git_dir) < 0)
1114
+ if (safe_create_leading_directories_const(the_repository, git_dir) < 0)
1115
die(_("could not create leading directories of '%s'"), git_dir);
1116
1117
if (0 <= option_verbosity) {
builtin/credential-cache--daemon.c
+2
-2
@@ -2,8 +2,8 @@
2
#include "builtin.h"
3
#include "abspath.h"
4
#include "gettext.h"
5
-#include "object-file.h"
5
#include "parse-options.h"
6
+#include "path.h"
7
8
#ifndef NO_UNIX_SOCKETS
9
@@ -271,7 +271,7 @@ static void init_socket_directory(const char *path)
271
* condition in which somebody can chdir to it, sleep, then try to open
272
* our protected socket.
273
*/
274
- if (safe_create_leading_directories_const(dir) < 0)
274
+ if (safe_create_leading_directories_const(the_repository, dir) < 0)
275
die_errno("unable to create directories for '%s'", dir);
276
if (mkdir(dir, 0700) < 0)
277
die_errno("unable to mkdir '%s'", dir);
builtin/diagnose.c
+2
-2
@@ -3,8 +3,8 @@
3
#include "builtin.h"
4
#include "abspath.h"
5
#include "gettext.h"
6
-#include "object-file.h"
6
#include "parse-options.h"
7
+#include "path.h"
8
#include "diagnose.h"
9
10
static const char * const diagnose_usage[] = {
@@ -50,7 +50,7 @@ int cmd_diagnose(int argc,
50
strbuf_addftime(&zip_path, option_suffix, localtime_r(&now, &tm), 0, 0);
51
strbuf_addstr(&zip_path, ".zip");
52
53
- switch (safe_create_leading_directories(zip_path.buf)) {
53
+ switch (safe_create_leading_directories(the_repository, zip_path.buf)) {
54
case SCLD_OK:
55
case SCLD_EXISTS:
56
break;
builtin/difftool.c
+16
-13
@@ -22,6 +22,7 @@
22
#include "gettext.h"
23
#include "hex.h"
24
#include "parse-options.h"
25
+#include "path.h"
26
#include "read-cache-ll.h"
27
#include "repository.h"
28
#include "sparse-index.h"
@@ -271,9 +272,9 @@ static void changed_files(struct repository *repo,
272
strbuf_release(&buf);
273
}
274
274
-static int ensure_leading_directories(char *path)
275
+static int ensure_leading_directories(struct repository *repo, char *path)
276
{
276
- switch (safe_create_leading_directories(path)) {
277
+ switch (safe_create_leading_directories(repo, path)) {
278
case SCLD_OK:
279
case SCLD_EXISTS:
280
return 0;
@@ -341,11 +342,12 @@ static int checkout_path(unsigned mode, struct object_id *oid,
342
return ret;
343
}
344
344
-static void write_file_in_directory(struct strbuf *dir, size_t dir_len,
345
- const char *path, const char *content)
345
+static void write_file_in_directory(struct repository *repo,
346
+ struct strbuf *dir, size_t dir_len,
347
+ const char *path, const char *content)
348
{
349
add_path(dir, dir_len, path);
348
- ensure_leading_directories(dir->buf);
350
+ ensure_leading_directories(repo, dir->buf);
351
unlink(dir->buf);
352
write_file(dir->buf, "%s", content);
353
}
@@ -356,14 +358,15 @@ static void write_file_in_directory(struct strbuf *dir, size_t dir_len,
358
* as text files, resulting in behavior that is analogous to what "git diff"
359
* displays for symlink and submodule diffs.
360
*/
359
-static void write_standin_files(struct pair_entry *entry,
360
- struct strbuf *ldir, size_t ldir_len,
361
- struct strbuf *rdir, size_t rdir_len)
361
+static void write_standin_files(struct repository *repo,
362
+ struct pair_entry *entry,
363
+ struct strbuf *ldir, size_t ldir_len,
364
+ struct strbuf *rdir, size_t rdir_len)
365
{
366
if (*entry->left)
364
- write_file_in_directory(ldir, ldir_len, entry->path, entry->left);
367
+ write_file_in_directory(repo, ldir, ldir_len, entry->path, entry->left);
368
if (*entry->right)
366
- write_file_in_directory(rdir, rdir_len, entry->path, entry->right);
369
+ write_file_in_directory(repo, rdir, rdir_len, entry->path, entry->right);
370
}
371
372
static int run_dir_diff(struct repository *repo,
@@ -533,7 +536,7 @@ static int run_dir_diff(struct repository *repo,
536
ADD_CACHE_JUST_APPEND);
537
538
add_path(&rdir, rdir_len, dst_path);
536
- if (ensure_leading_directories(rdir.buf)) {
539
+ if (ensure_leading_directories(repo, rdir.buf)) {
540
ret = error("could not create "
541
"directory for '%s'",
542
dst_path);
@@ -576,7 +579,7 @@ static int run_dir_diff(struct repository *repo,
579
*/
580
hashmap_for_each_entry(&submodules, &iter, entry,
581
entry /* member name */) {
579
- write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len);
582
+ write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len);
583
}
584
585
/*
@@ -587,7 +590,7 @@ static int run_dir_diff(struct repository *repo,
590
hashmap_for_each_entry(&symlinks2, &iter, entry,
591
entry /* member name */) {
592
590
- write_standin_files(entry, &ldir, ldir_len, &rdir, rdir_len);
593
+ write_standin_files(repo, entry, &ldir, ldir_len, &rdir, rdir_len);
594
}
595
596
strbuf_setlen(&ldir, ldir_len);
builtin/fast-import.c
+1
-1
@@ -1720,7 +1720,7 @@ static void dump_marks(void)
1720
if (!export_marks_file || (import_marks_file && !import_marks_file_done))
1721
return;
1722
1723
- if (safe_create_leading_directories_const(export_marks_file)) {
1723
+ if (safe_create_leading_directories_const(the_repository, export_marks_file)) {
1724
failure |= error_errno("unable to create leading directories of %s",
1725
export_marks_file);
1726
return;
builtin/fsck.c
+1
-1
@@ -332,7 +332,7 @@ static void check_unreachable_object(struct object *obj)
332
describe_object(&obj->oid));
333
FILE *f;
334
335
- if (safe_create_leading_directories_const(filename)) {
335
+ if (safe_create_leading_directories_const(the_repository, filename)) {
336
error(_("could not create lost-found"));
337
free(filename);
338
return;
builtin/gc.c
+3
-4
@@ -28,7 +28,6 @@
28
#include "commit.h"
29
#include "commit-graph.h"
30
#include "packfile.h"
31
-#include "object-file.h"
31
#include "object-store-ll.h"
32
#include "pack.h"
33
#include "pack-objects.h"
@@ -2099,7 +2098,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
2098
}
2099
strbuf_addstr(&plist, "</array>\n</dict>\n</plist>\n");
2100
2102
- if (safe_create_leading_directories(filename))
2101
+ if (safe_create_leading_directories(the_repository, filename))
2102
die(_("failed to create directories for '%s'"), filename);
2103
2104
if ((long)lock_file_timeout_ms < 0 &&
@@ -2565,7 +2564,7 @@ static int systemd_timer_write_timer_file(enum schedule_priority schedule,
2564
2565
filename = xdg_config_home_systemd(local_timer_name);
2566
2568
- if (safe_create_leading_directories(filename)) {
2567
+ if (safe_create_leading_directories(the_repository, filename)) {
2568
error(_("failed to create directories for '%s'"), filename);
2569
goto error;
2570
}
@@ -2638,7 +2637,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
2637
char *local_service_name = xstrfmt(SYSTEMD_UNIT_FORMAT, "", "service");
2638
2639
filename = xdg_config_home_systemd(local_service_name);
2641
- if (safe_create_leading_directories(filename)) {
2640
+ if (safe_create_leading_directories(the_repository, filename)) {
2641
error(_("failed to create directories for '%s'"), filename);
2642
goto error;
2643
}
builtin/init-db.c
+1
-2
@@ -8,7 +8,6 @@
8
#include "abspath.h"
9
#include "environment.h"
10
#include "gettext.h"
11
-#include "object-file.h"
11
#include "parse-options.h"
12
#include "path.h"
13
#include "refs.h"
@@ -134,7 +133,7 @@ int cmd_init_db(int argc,
133
*/
134
saved = repo_settings_get_shared_repository(the_repository);
135
repo_settings_set_shared_repository(the_repository, 0);
137
- switch (safe_create_leading_directories_const(argv[0])) {
136
+ switch (safe_create_leading_directories_const(the_repository, argv[0])) {
137
case SCLD_OK:
138
case SCLD_PERMS:
139
break;
builtin/log.c
+2
-2
@@ -14,7 +14,6 @@
14
#include "gettext.h"
15
#include "hex.h"
16
#include "refs.h"
17
-#include "object-file.h"
17
#include "object-name.h"
18
#include "object-store-ll.h"
19
#include "pager.h"
@@ -29,6 +28,7 @@
28
#include "tag.h"
29
#include "reflog-walk.h"
30
#include "patch-ids.h"
31
+#include "path.h"
32
#include "shortlog.h"
33
#include "remote.h"
34
#include "string-list.h"
@@ -2311,7 +2311,7 @@ int cmd_format_patch(int argc,
2311
*/
2312
saved = repo_settings_get_shared_repository(the_repository);
2313
repo_settings_set_shared_repository(the_repository, 0);
2314
- switch (safe_create_leading_directories_const(output_directory)) {
2314
+ switch (safe_create_leading_directories_const(the_repository, output_directory)) {
2315
case SCLD_OK:
2316
case SCLD_EXISTS:
2317
break;
builtin/mv.c
+2
-1
@@ -15,6 +15,7 @@
15
#include "gettext.h"
16
#include "name-hash.h"
17
#include "object-file.h"
18
+#include "path.h"
19
#include "pathspec.h"
20
#include "lockfile.h"
21
#include "dir.h"
@@ -555,7 +556,7 @@ remove_entry:
556
*/
557
char *dst_dup = xstrdup(dst);
558
string_list_append(&dirty_paths, dst);
558
- safe_create_leading_directories(dst_dup);
559
+ safe_create_leading_directories(the_repository, dst_dup);
560
FREE_AND_NULL(dst_dup);
561
rename(src, dst);
562
}
builtin/sparse-checkout.c
+3
-2
@@ -9,6 +9,7 @@
9
#include "object-file.h"
10
#include "object-name.h"
11
#include "parse-options.h"
12
+#include "path.h"
13
#include "pathspec.h"
14
#include "strbuf.h"
15
#include "string-list.h"
@@ -335,7 +336,7 @@ static int write_patterns_and_update(struct pattern_list *pl)
336
337
sparse_filename = get_sparse_checkout_filename();
338
338
- if (safe_create_leading_directories(sparse_filename))
339
+ if (safe_create_leading_directories(the_repository, sparse_filename))
340
die(_("failed to create directory for sparse-checkout file"));
341
342
hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR);
@@ -491,7 +492,7 @@ static int sparse_checkout_init(int argc, const char **argv, const char *prefix,
492
FILE *fp;
493
494
/* assume we are in a fresh repo, but update the sparse-checkout file */
494
- if (safe_create_leading_directories(sparse_filename))
495
+ if (safe_create_leading_directories(the_repository, sparse_filename))
496
die(_("unable to create leading directories of %s"),
497
sparse_filename);
498
fp = xfopen(sparse_filename, "w");
builtin/submodule--helper.c
+2
-2
@@ -1739,7 +1739,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
1739
!is_empty_dir(clone_data_path))
1740
die(_("directory not empty: '%s'"), clone_data_path);
1741
1742
- if (safe_create_leading_directories_const(sm_gitdir) < 0)
1742
+ if (safe_create_leading_directories_const(the_repository, sm_gitdir) < 0)
1743
die(_("could not create directory '%s'"), sm_gitdir);
1744
1745
prepare_possible_alternates(clone_data->name, reference);
@@ -1800,7 +1800,7 @@ static int clone_submodule(const struct module_clone_data *clone_data,
1800
if (clone_data->require_init && !stat(clone_data_path, &st) &&
1801
!is_empty_dir(clone_data_path))
1802
die(_("directory not empty: '%s'"), clone_data_path);
1803
- if (safe_create_leading_directories_const(clone_data_path) < 0)
1803
+ if (safe_create_leading_directories_const(the_repository, clone_data_path) < 0)
1804
die(_("could not create directory '%s'"), clone_data_path);
1805
path = xstrfmt("%s/index", sm_gitdir);
1806
unlink_or_warn(path);
builtin/worktree.c
+4
-4
@@ -348,7 +348,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)
348
char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir);
349
350
if (file_exists(from_file)) {
351
- if (safe_create_leading_directories(to_file) ||
351
+ if (safe_create_leading_directories(the_repository, to_file) ||
352
copy_file(to_file, from_file, 0666))
353
error(_("failed to copy '%s' to '%s'; sparse-checkout may not work correctly"),
354
from_file, to_file);
@@ -367,7 +367,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)
367
struct config_set cs = { { 0 } };
368
int bare;
369
370
- if (safe_create_leading_directories(to_file) ||
370
+ if (safe_create_leading_directories(the_repository, to_file) ||
371
copy_file(to_file, from_file, 0666)) {
372
error(_("failed to copy worktree config from '%s' to '%s'"),
373
from_file, to_file);
@@ -466,7 +466,7 @@ static int add_worktree(const char *path, const char *refname,
466
name = sb_name.buf;
467
repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name);
468
len = sb_repo.len;
469
- if (safe_create_leading_directories_const(sb_repo.buf))
469
+ if (safe_create_leading_directories_const(the_repository, sb_repo.buf))
470
die_errno(_("could not create leading directories of '%s'"),
471
sb_repo.buf);
472
@@ -498,7 +498,7 @@ static int add_worktree(const char *path, const char *refname,
498
write_file(sb.buf, _("initializing"));
499
500
strbuf_addf(&sb_git, "%s/.git", path);
501
- if (safe_create_leading_directories_const(sb_git.buf))
501
+ if (safe_create_leading_directories_const(the_repository, sb_git.buf))
502
die_errno(_("could not create leading directories of '%s'"),
503
sb_git.buf);
504
junk_work_tree = xstrdup(path);
commit-graph.c
+1
-1
@@ -2065,7 +2065,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
2065
ctx->graph_name = get_commit_graph_filename(ctx->odb);
2066
}
2067
2068
- if (safe_create_leading_directories(ctx->graph_name)) {
2068
+ if (safe_create_leading_directories(the_repository, ctx->graph_name)) {
2069
error(_("unable to create leading directories of %s"),
2070
ctx->graph_name);
2071
return -1;
dir.c
+2
-3
@@ -17,7 +17,6 @@
17
#include "environment.h"
18
#include "gettext.h"
19
#include "name-hash.h"
20
-#include "object-file.h"
20
#include "object-store-ll.h"
21
#include "path.h"
22
#include "refs.h"
@@ -4063,12 +4062,12 @@ void connect_work_tree_and_git_dir(const char *work_tree_,
4062
4063
/* Prepare .git file */
4064
strbuf_addf(&gitfile_sb, "%s/.git", work_tree_);
4066
- if (safe_create_leading_directories_const(gitfile_sb.buf))
4065
+ if (safe_create_leading_directories_const(the_repository, gitfile_sb.buf))
4066
die(_("could not create directories for %s"), gitfile_sb.buf);
4067
4068
/* Prepare config file */
4069
strbuf_addf(&cfg_sb, "%s/config", git_dir_);
4071
- if (safe_create_leading_directories_const(cfg_sb.buf))
4070
+ if (safe_create_leading_directories_const(the_repository, cfg_sb.buf))
4071
die(_("could not create directories for %s"), cfg_sb.buf);
4072
4073
git_dir = real_pathdup(git_dir_, 1);
merge-recursive.c
+2
-2
@@ -910,7 +910,7 @@ static int make_room_for_path(struct merge_options *opt, const char *path)
910
}
911
912
/* Make sure leading directories are created */
913
- status = safe_create_leading_directories_const(path);
913
+ status = safe_create_leading_directories_const(the_repository, path);
914
if (status) {
915
if (status == SCLD_EXISTS)
916
/* something else exists */
@@ -1003,7 +1003,7 @@ static int update_file_flags(struct merge_options *opt,
1003
close(fd);
1004
} else if (S_ISLNK(contents->mode)) {
1005
char *lnk = xmemdupz(buf, size);
1006
- safe_create_leading_directories_const(path);
1006
+ safe_create_leading_directories_const(the_repository, path);
1007
unlink(path);
1008
if (symlink(lnk, path))
1009
ret = err(opt, _("failed to symlink '%s': %s"),
midx-write.c
+1
-1
@@ -1086,7 +1086,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
1086
object_dir);
1087
else
1088
get_midx_filename(r->hash_algo, &midx_name, object_dir);
1089
- if (safe_create_leading_directories(midx_name.buf))
1089
+ if (safe_create_leading_directories(r, midx_name.buf))
1090
die_errno(_("unable to create leading directories of %s"),
1091
midx_name.buf);
1092
notes-merge.c
+2
-2
@@ -296,7 +296,7 @@ static void check_notes_merge_worktree(struct notes_merge_options *o)
296
"(%s exists)."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*"));
297
}
298
299
- if (safe_create_leading_directories_const(repo_git_path_replace(the_repository, &buf,
299
+ if (safe_create_leading_directories_const(the_repository, repo_git_path_replace(the_repository, &buf,
300
NOTES_MERGE_WORKTREE "/.test")))
301
die_errno("unable to create directory %s",
302
repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE));
@@ -314,7 +314,7 @@ static void write_buf_to_worktree(const struct object_id *obj,
314
{
315
int fd;
316
char *path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj));
317
- if (safe_create_leading_directories_const(path))
317
+ if (safe_create_leading_directories_const(the_repository, path))
318
die_errno("unable to create directory for '%s'", path);
319
320
fd = xopen(path, O_WRONLY | O_EXCL | O_CREAT, 0666);
object-file.c
+2
-79
@@ -90,83 +90,6 @@ static int get_conv_flags(unsigned flags)
90
return 0;
91
}
92
93
-static enum scld_error safe_create_leading_directories_1(char *path, int share)
94
-{
95
- char *next_component = path + offset_1st_component(path);
96
- enum scld_error ret = SCLD_OK;
97
-
98
- while (ret == SCLD_OK && next_component) {
99
- struct stat st;
100
- char *slash = next_component, slash_character;
101
-
102
- while (*slash && !is_dir_sep(*slash))
103
- slash++;
104
-
105
- if (!*slash)
106
- break;
107
-
108
- next_component = slash + 1;
109
- while (is_dir_sep(*next_component))
110
- next_component++;
111
- if (!*next_component)
112
- break;
113
-
114
- slash_character = *slash;
115
- *slash = '\0';
116
- if (!stat(path, &st)) {
117
- /* path exists */
118
- if (!S_ISDIR(st.st_mode)) {
119
- errno = ENOTDIR;
120
- ret = SCLD_EXISTS;
121
- }
122
- } else if (mkdir(path, 0777)) {
123
- if (errno == EEXIST &&
124
- !stat(path, &st) && S_ISDIR(st.st_mode))
125
- ; /* somebody created it since we checked */
126
- else if (errno == ENOENT)
127
- /*
128
- * Either mkdir() failed because
129
- * somebody just pruned the containing
130
- * directory, or stat() failed because
131
- * the file that was in our way was
132
- * just removed. Either way, inform
133
- * the caller that it might be worth
134
- * trying again:
135
- */
136
- ret = SCLD_VANISHED;
137
- else
138
- ret = SCLD_FAILED;
139
- } else if (share && adjust_shared_perm(the_repository, path)) {
140
- ret = SCLD_PERMS;
141
- }
142
- *slash = slash_character;
143
- }
144
- return ret;
145
-}
146
-
147
-enum scld_error safe_create_leading_directories(char *path)
148
-{
149
- return safe_create_leading_directories_1(path, 1);
150
-}
151
-
152
-enum scld_error safe_create_leading_directories_no_share(char *path)
153
-{
154
- return safe_create_leading_directories_1(path, 0);
155
-}
156
-
157
-enum scld_error safe_create_leading_directories_const(const char *path)
158
-{
159
- int save_errno;
160
- /* path points to cache entries, so xstrdup before messing with it */
161
- char *buf = xstrdup(path);
162
- enum scld_error result = safe_create_leading_directories(buf);
163
-
164
- save_errno = errno;
165
- free(buf);
166
- errno = save_errno;
167
- return result;
168
-}
169
-
93
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
94
{
95
int fd;
@@ -183,7 +106,7 @@ int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
106
/* slow path */
107
/* some mkstemp implementations erase temp_filename on failure */
108
repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern);
186
- safe_create_leading_directories(temp_filename->buf);
109
+ safe_create_leading_directories(the_repository, temp_filename->buf);
110
return xmkstemp_mode(temp_filename->buf, mode);
111
}
112
@@ -196,7 +119,7 @@ int odb_pack_keep(const char *name)
119
return fd;
120
121
/* slow path */
199
- safe_create_leading_directories_const(name);
122
+ safe_create_leading_directories_const(the_repository, name);
123
return open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
124
}
125
object-file.h
-33
@@ -21,39 +21,6 @@ extern int fetch_if_missing;
21
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);
22
int index_path(struct index_state *istate, struct object_id *oid, const char *path, struct stat *st, unsigned flags);
23
24
-/*
25
- * Create the directory containing the named path, using care to be
26
- * somewhat safe against races. Return one of the scld_error values to
27
- * indicate success/failure. On error, set errno to describe the
28
- * problem.
29
- *
30
- * SCLD_VANISHED indicates that one of the ancestor directories of the
31
- * path existed at one point during the function call and then
32
- * suddenly vanished, probably because another process pruned the
33
- * directory while we were working. To be robust against this kind of
34
- * race, callers might want to try invoking the function again when it
35
- * returns SCLD_VANISHED.
36
- *
37
- * safe_create_leading_directories() temporarily changes path while it
38
- * is working but restores it before returning.
39
- * safe_create_leading_directories_const() doesn't modify path, even
40
- * temporarily. Both these variants adjust the permissions of the
41
- * created directories to honor core.sharedRepository, so they are best
42
- * suited for files inside the git dir. For working tree files, use
43
- * safe_create_leading_directories_no_share() instead, as it ignores
44
- * the core.sharedRepository setting.
45
- */
46
-enum scld_error {
47
- SCLD_OK = 0,
48
- SCLD_FAILED = -1,
49
- SCLD_PERMS = -2,
50
- SCLD_EXISTS = -3,
51
- SCLD_VANISHED = -4
52
-};
53
-enum scld_error safe_create_leading_directories(char *path);
54
-enum scld_error safe_create_leading_directories_const(const char *path);
55
-enum scld_error safe_create_leading_directories_no_share(char *path);
56
-
24
int git_open_cloexec(const char *name, int flags);
25
#define git_open(name) git_open_cloexec(name, O_RDONLY)
26
path.c
+80
@@ -931,6 +931,86 @@ int safe_create_dir_in_gitdir(struct repository *repo, const char *path)
931
return adjust_shared_perm(repo, path);
932
}
933
934
+static enum scld_error safe_create_leading_directories_1(struct repository *repo,
935
+ char *path)
936
+{
937
+ char *next_component = path + offset_1st_component(path);
938
+ enum scld_error ret = SCLD_OK;
939
+
940
+ while (ret == SCLD_OK && next_component) {
941
+ struct stat st;
942
+ char *slash = next_component, slash_character;
943
+
944
+ while (*slash && !is_dir_sep(*slash))
945
+ slash++;
946
+
947
+ if (!*slash)
948
+ break;
949
+
950
+ next_component = slash + 1;
951
+ while (is_dir_sep(*next_component))
952
+ next_component++;
953
+ if (!*next_component)
954
+ break;
955
+
956
+ slash_character = *slash;
957
+ *slash = '\0';
958
+ if (!stat(path, &st)) {
959
+ /* path exists */
960
+ if (!S_ISDIR(st.st_mode)) {
961
+ errno = ENOTDIR;
962
+ ret = SCLD_EXISTS;
963
+ }
964
+ } else if (mkdir(path, 0777)) {
965
+ if (errno == EEXIST &&
966
+ !stat(path, &st) && S_ISDIR(st.st_mode))
967
+ ; /* somebody created it since we checked */
968
+ else if (errno == ENOENT)
969
+ /*
970
+ * Either mkdir() failed because
971
+ * somebody just pruned the containing
972
+ * directory, or stat() failed because
973
+ * the file that was in our way was
974
+ * just removed. Either way, inform
975
+ * the caller that it might be worth
976
+ * trying again:
977
+ */
978
+ ret = SCLD_VANISHED;
979
+ else
980
+ ret = SCLD_FAILED;
981
+ } else if (repo && adjust_shared_perm(repo, path)) {
982
+ ret = SCLD_PERMS;
983
+ }
984
+ *slash = slash_character;
985
+ }
986
+ return ret;
987
+}
988
+
989
+enum scld_error safe_create_leading_directories(struct repository *repo,
990
+ char *path)
991
+{
992
+ return safe_create_leading_directories_1(repo, path);
993
+}
994
+
995
+enum scld_error safe_create_leading_directories_no_share(char *path)
996
+{
997
+ return safe_create_leading_directories_1(NULL, path);
998
+}
999
+
1000
+enum scld_error safe_create_leading_directories_const(struct repository *repo,
1001
+ const char *path)
1002
+{
1003
+ int save_errno;
1004
+ /* path points to cache entries, so xstrdup before messing with it */
1005
+ char *buf = xstrdup(path);
1006
+ enum scld_error result = safe_create_leading_directories(repo, buf);
1007
+
1008
+ save_errno = errno;
1009
+ free(buf);
1010
+ errno = save_errno;
1011
+ return result;
1012
+}
1013
+
1014
static int have_same_root(const char *path1, const char *path2)
1015
{
1016
int is_abs1, is_abs2;
path.h
+34
@@ -232,6 +232,40 @@ void safe_create_dir(struct repository *repo, const char *dir, int share);
232
*/
233
int safe_create_dir_in_gitdir(struct repository *repo, const char *path);
234
235
+/*
236
+ * Create the directory containing the named path, using care to be
237
+ * somewhat safe against races. Return one of the scld_error values to
238
+ * indicate success/failure. On error, set errno to describe the
239
+ * problem.
240
+ *
241
+ * SCLD_VANISHED indicates that one of the ancestor directories of the
242
+ * path existed at one point during the function call and then
243
+ * suddenly vanished, probably because another process pruned the
244
+ * directory while we were working. To be robust against this kind of
245
+ * race, callers might want to try invoking the function again when it
246
+ * returns SCLD_VANISHED.
247
+ *
248
+ * safe_create_leading_directories() temporarily changes path while it
249
+ * is working but restores it before returning.
250
+ * safe_create_leading_directories_const() doesn't modify path, even
251
+ * temporarily. Both these variants adjust the permissions of the
252
+ * created directories to honor core.sharedRepository, so they are best
253
+ * suited for files inside the git dir. For working tree files, use
254
+ * safe_create_leading_directories_no_share() instead, as it ignores
255
+ * the core.sharedRepository setting.
256
+ */
257
+enum scld_error {
258
+ SCLD_OK = 0,
259
+ SCLD_FAILED = -1,
260
+ SCLD_PERMS = -2,
261
+ SCLD_EXISTS = -3,
262
+ SCLD_VANISHED = -4
263
+};
264
+enum scld_error safe_create_leading_directories(struct repository *repo, char *path);
265
+enum scld_error safe_create_leading_directories_const(struct repository *repo,
266
+ const char *path);
267
+enum scld_error safe_create_leading_directories_no_share(char *path);
268
+
269
# ifdef USE_THE_REPOSITORY_VARIABLE
270
# include "strbuf.h"
271
# include "repository.h"
refs/files-backend.c
+2
-2
@@ -705,7 +705,7 @@ static int lock_raw_ref(struct files_ref_store *refs,
705
files_ref_path(refs, &ref_file, refname);
706
707
retry:
708
- switch (safe_create_leading_directories(ref_file.buf)) {
708
+ switch (safe_create_leading_directories(the_repository, ref_file.buf)) {
709
case SCLD_OK:
710
break; /* success */
711
case SCLD_EXISTS:
@@ -1109,7 +1109,7 @@ retry_fn:
1109
strbuf_addstr(&path_copy, path);
1110
1111
do {
1112
- scld_result = safe_create_leading_directories(path_copy.buf);
1112
+ scld_result = safe_create_leading_directories(the_repository, path_copy.buf);
1113
if (scld_result == SCLD_OK)
1114
goto retry_fn;
1115
} while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0);
sequencer.c
+2
-2
@@ -4411,7 +4411,7 @@ static int write_update_refs_state(struct string_list *refs_to_oids)
4411
goto cleanup;
4412
}
4413
4414
- if (safe_create_leading_directories(path)) {
4414
+ if (safe_create_leading_directories(the_repository, path)) {
4415
result = error(_("unable to create leading directories of %s"),
4416
path);
4417
goto cleanup;
@@ -4677,7 +4677,7 @@ static void create_autostash_internal(struct repository *r,
4677
strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV);
4678
4679
if (path) {
4680
- if (safe_create_leading_directories_const(path))
4680
+ if (safe_create_leading_directories_const(the_repository, path))
4681
die(_("Could not create directory for '%s'"),
4682
path);
4683
write_file(path, "%s", oid_to_hex(&oid));
server-info.c
+1
-1
@@ -88,7 +88,7 @@ static int update_info_file(struct repository *r, char *path,
88
.old_sb = STRBUF_INIT
89
};
90
91
- safe_create_leading_directories(path);
91
+ safe_create_leading_directories(r, path);
92
f = mks_tempfile_m(tmp, 0666);
93
if (!f)
94
goto out;
submodule.c
+1
-1
@@ -2384,7 +2384,7 @@ static void relocate_single_git_dir_into_superproject(const char *path,
2384
if (validate_submodule_git_dir(new_gitdir.buf, sub->name) < 0)
2385
die(_("refusing to move '%s' into an existing git dir"),
2386
real_old_git_dir);
2387
- if (safe_create_leading_directories_const(new_gitdir.buf) < 0)
2387
+ if (safe_create_leading_directories_const(the_repository, new_gitdir.buf) < 0)
2388
die(_("could not create directory '%s'"), new_gitdir.buf);
2389
real_new_git_dir = real_pathdup(new_gitdir.buf, 1);
2390