Skip to content

Commit 955e00e

Browse files
pks-tgitster
authored andcommitted
object-file: move safe_create_leading_directories() into "dir.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 "dir.c". Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0dfca98 commit 955e00e

File tree

13 files changed

+150
-148
lines changed

13 files changed

+150
-148
lines changed

builtin/bugreport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#define USE_THE_REPOSITORY_VARIABLE
22
#include "builtin.h"
33
#include "abspath.h"
4+
#include "dir.h"
45
#include "editor.h"
56
#include "gettext.h"
67
#include "parse-options.h"
@@ -10,7 +11,6 @@
1011
#include "hook.h"
1112
#include "hook-list.h"
1213
#include "diagnose.h"
13-
#include "object-file.h"
1414
#include "setup.h"
1515
#include "version.h"
1616

builtin/credential-cache--daemon.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#define USE_THE_REPOSITORY_VARIABLE
22
#include "builtin.h"
33
#include "abspath.h"
4+
#include "dir.h"
45
#include "gettext.h"
5-
#include "object-file.h"
66
#include "parse-options.h"
77

88
#ifndef NO_UNIX_SOCKETS

builtin/diagnose.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
#include "builtin.h"
44
#include "abspath.h"
5+
#include "dir.h"
56
#include "gettext.h"
6-
#include "object-file.h"
77
#include "parse-options.h"
88
#include "diagnose.h"
99

builtin/fsck.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#define USE_THE_REPOSITORY_VARIABLE
22
#include "builtin.h"
3+
#include "dir.h"
34
#include "gettext.h"
45
#include "hex.h"
56
#include "config.h"

builtin/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "builtin.h"
1717
#include "abspath.h"
1818
#include "date.h"
19+
#include "dir.h"
1920
#include "environment.h"
2021
#include "hex.h"
2122
#include "config.h"
@@ -28,7 +29,6 @@
2829
#include "commit.h"
2930
#include "commit-graph.h"
3031
#include "packfile.h"
31-
#include "object-file.h"
3232
#include "object-store-ll.h"
3333
#include "pack.h"
3434
#include "pack-objects.h"

builtin/init-db.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
#define USE_THE_REPOSITORY_VARIABLE
77
#include "builtin.h"
88
#include "abspath.h"
9+
#include "dir.h"
910
#include "environment.h"
1011
#include "gettext.h"
11-
#include "object-file.h"
1212
#include "parse-options.h"
1313
#include "path.h"
1414
#include "refs.h"

builtin/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
#include "builtin.h"
1111
#include "abspath.h"
1212
#include "config.h"
13+
#include "dir.h"
1314
#include "environment.h"
1415
#include "gettext.h"
1516
#include "hex.h"
1617
#include "refs.h"
17-
#include "object-file.h"
1818
#include "object-name.h"
1919
#include "object-store-ll.h"
2020
#include "pager.h"

commit-graph.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "git-compat-util.h"
55
#include "config.h"
66
#include "csum-file.h"
7+
#include "dir.h"
78
#include "gettext.h"
89
#include "hex.h"
910
#include "lockfile.h"

dir.c

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "environment.h"
1818
#include "gettext.h"
1919
#include "name-hash.h"
20-
#include "object-file.h"
2120
#include "object-store-ll.h"
2221
#include "path.h"
2322
#include "refs.h"
@@ -4132,3 +4131,109 @@ int path_match_flags(const char *const str, const enum path_match_flags flags)
41324131
return is_xplatform_dir_sep(*p);
41334132
BUG("unreachable");
41344133
}
4134+
4135+
int mkdir_in_gitdir(const char *path)
4136+
{
4137+
if (mkdir(path, 0777)) {
4138+
int saved_errno = errno;
4139+
struct stat st;
4140+
struct strbuf sb = STRBUF_INIT;
4141+
4142+
if (errno != EEXIST)
4143+
return -1;
4144+
/*
4145+
* Are we looking at a path in a symlinked worktree
4146+
* whose original repository does not yet have it?
4147+
* e.g. .git/rr-cache pointing at its original
4148+
* repository in which the user hasn't performed any
4149+
* conflict resolution yet?
4150+
*/
4151+
if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
4152+
strbuf_readlink(&sb, path, st.st_size) ||
4153+
!is_absolute_path(sb.buf) ||
4154+
mkdir(sb.buf, 0777)) {
4155+
strbuf_release(&sb);
4156+
errno = saved_errno;
4157+
return -1;
4158+
}
4159+
strbuf_release(&sb);
4160+
}
4161+
return adjust_shared_perm(the_repository, path);
4162+
}
4163+
4164+
static enum scld_error safe_create_leading_directories_1(char *path, int share)
4165+
{
4166+
char *next_component = path + offset_1st_component(path);
4167+
enum scld_error ret = SCLD_OK;
4168+
4169+
while (ret == SCLD_OK && next_component) {
4170+
struct stat st;
4171+
char *slash = next_component, slash_character;
4172+
4173+
while (*slash && !is_dir_sep(*slash))
4174+
slash++;
4175+
4176+
if (!*slash)
4177+
break;
4178+
4179+
next_component = slash + 1;
4180+
while (is_dir_sep(*next_component))
4181+
next_component++;
4182+
if (!*next_component)
4183+
break;
4184+
4185+
slash_character = *slash;
4186+
*slash = '\0';
4187+
if (!stat(path, &st)) {
4188+
/* path exists */
4189+
if (!S_ISDIR(st.st_mode)) {
4190+
errno = ENOTDIR;
4191+
ret = SCLD_EXISTS;
4192+
}
4193+
} else if (mkdir(path, 0777)) {
4194+
if (errno == EEXIST &&
4195+
!stat(path, &st) && S_ISDIR(st.st_mode))
4196+
; /* somebody created it since we checked */
4197+
else if (errno == ENOENT)
4198+
/*
4199+
* Either mkdir() failed because
4200+
* somebody just pruned the containing
4201+
* directory, or stat() failed because
4202+
* the file that was in our way was
4203+
* just removed. Either way, inform
4204+
* the caller that it might be worth
4205+
* trying again:
4206+
*/
4207+
ret = SCLD_VANISHED;
4208+
else
4209+
ret = SCLD_FAILED;
4210+
} else if (share && adjust_shared_perm(the_repository, path)) {
4211+
ret = SCLD_PERMS;
4212+
}
4213+
*slash = slash_character;
4214+
}
4215+
return ret;
4216+
}
4217+
4218+
enum scld_error safe_create_leading_directories(char *path)
4219+
{
4220+
return safe_create_leading_directories_1(path, 1);
4221+
}
4222+
4223+
enum scld_error safe_create_leading_directories_no_share(char *path)
4224+
{
4225+
return safe_create_leading_directories_1(path, 0);
4226+
}
4227+
4228+
enum scld_error safe_create_leading_directories_const(const char *path)
4229+
{
4230+
int save_errno;
4231+
/* path points to cache entries, so xstrdup before messing with it */
4232+
char *buf = xstrdup(path);
4233+
enum scld_error result = safe_create_leading_directories(buf);
4234+
4235+
save_errno = errno;
4236+
free(buf);
4237+
errno = save_errno;
4238+
return result;
4239+
}

dir.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,4 +676,39 @@ static inline int starts_with_dot_dot_slash_native(const char *const path)
676676
return path_match_flags(path, what | PATH_MATCH_NATIVE);
677677
}
678678

679+
/*
680+
* Create the directory containing the named path, using care to be
681+
* somewhat safe against races. Return one of the scld_error values to
682+
* indicate success/failure. On error, set errno to describe the
683+
* problem.
684+
*
685+
* SCLD_VANISHED indicates that one of the ancestor directories of the
686+
* path existed at one point during the function call and then
687+
* suddenly vanished, probably because another process pruned the
688+
* directory while we were working. To be robust against this kind of
689+
* race, callers might want to try invoking the function again when it
690+
* returns SCLD_VANISHED.
691+
*
692+
* safe_create_leading_directories() temporarily changes path while it
693+
* is working but restores it before returning.
694+
* safe_create_leading_directories_const() doesn't modify path, even
695+
* temporarily. Both these variants adjust the permissions of the
696+
* created directories to honor core.sharedRepository, so they are best
697+
* suited for files inside the git dir. For working tree files, use
698+
* safe_create_leading_directories_no_share() instead, as it ignores
699+
* the core.sharedRepository setting.
700+
*/
701+
enum scld_error {
702+
SCLD_OK = 0,
703+
SCLD_FAILED = -1,
704+
SCLD_PERMS = -2,
705+
SCLD_EXISTS = -3,
706+
SCLD_VANISHED = -4
707+
};
708+
enum scld_error safe_create_leading_directories(char *path);
709+
enum scld_error safe_create_leading_directories_const(const char *path);
710+
enum scld_error safe_create_leading_directories_no_share(char *path);
711+
712+
int mkdir_in_gitdir(const char *path);
713+
679714
#endif

0 commit comments

Comments
 (0)