Re: [PATCH 1/9] object-file: move `safe_create_leading_directories()` into "dir.c"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 8, 2025 at 3:37 AM Patrick Steinhardt <ps@xxxxxx> wrote:
>
> The `safe_create_leading_directories()` function and its relatives

How is mkdir_in_gitdir() a relative of safe_create_leading_directories()?

I assumed the relation was "called by", but there is no such
relationship.  The rest of the patch looked fine, but I was puzzled
for a while trying to figure out what this relationship is.

> 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".

Makes sense.


>
> Signed-off-by: Patrick Steinhardt <ps@xxxxxx>
> ---
>  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
>
>





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux