refs file backend: move raceproof_create_file() here

Move the raceproof_create_file() API added to cache.h and object-file.c in 177978f56ad (raceproof_create_file(): new function, 2017-01-06) to its only user, refs/files-backend.c. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Aug 23, 2021 at 13:52 UTC 3fa2e91d173b260c19f19af8edd3907e65bf85f7
3 files changed +109 -111
cache.h
-43
@@ -1202,49 +1202,6 @@ enum scld_error safe_create_leading_directories(char *path);
1202 enum scld_error safe_create_leading_directories_const(const char *path);
1203 enum scld_error safe_create_leading_directories_no_share(char *path);
1204
1205 -/*
1206 - * Callback function for raceproof_create_file(). This function is
1207 - * expected to do something that makes dirname(path) permanent despite
1208 - * the fact that other processes might be cleaning up empty
1209 - * directories at the same time. Usually it will create a file named
1210 - * path, but alternatively it could create another file in that
1211 - * directory, or even chdir() into that directory. The function should
1212 - * return 0 if the action was completed successfully. On error, it
1213 - * should return a nonzero result and set errno.
1214 - * raceproof_create_file() treats two errno values specially:
1215 - *
1216 - * - ENOENT -- dirname(path) does not exist. In this case,
1217 - * raceproof_create_file() tries creating dirname(path)
1218 - * (and any parent directories, if necessary) and calls
1219 - * the function again.
1220 - *
1221 - * - EISDIR -- the file already exists and is a directory. In this
1222 - * case, raceproof_create_file() removes the directory if
1223 - * it is empty (and recursively any empty directories that
1224 - * it contains) and calls the function again.
1225 - *
1226 - * Any other errno causes raceproof_create_file() to fail with the
1227 - * callback's return value and errno.
1228 - *
1229 - * Obviously, this function should be OK with being called again if it
1230 - * fails with ENOENT or EISDIR. In other scenarios it will not be
1231 - * called again.
1232 - */
1233 -typedef int create_file_fn(const char *path, void *cb);
1234 -
1235 -/*
1236 - * Create a file in dirname(path) by calling fn, creating leading
1237 - * directories if necessary. Retry a few times in case we are racing
1238 - * with another process that is trying to clean up the directory that
1239 - * contains path. See the documentation for create_file_fn for more
1240 - * details.
1241 - *
1242 - * Return the value and set the errno that resulted from the most
1243 - * recent call of fn. fn is always called at least once, and will be
1244 - * called more than once if it returns ENOENT or EISDIR.
1245 - */
1246 -int raceproof_create_file(const char *path, create_file_fn fn, void *cb);
1247 -
1205 int mkdir_in_gitdir(const char *path);
1206 char *expand_user_path(const char *path, int real_home);
1207 const char *enter_repo(const char *path, int strict);
object-file.c
-68
@@ -414,74 +414,6 @@ enum scld_error safe_create_leading_directories_const(const char *path)
414 return result;
415 }
416
417 -int raceproof_create_file(const char *path, create_file_fn fn, void *cb)
418 -{
419 - /*
420 - * The number of times we will try to remove empty directories
421 - * in the way of path. This is only 1 because if another
422 - * process is racily creating directories that conflict with
423 - * us, we don't want to fight against them.
424 - */
425 - int remove_directories_remaining = 1;
426 -
427 - /*
428 - * The number of times that we will try to create the
429 - * directories containing path. We are willing to attempt this
430 - * more than once, because another process could be trying to
431 - * clean up empty directories at the same time as we are
432 - * trying to create them.
433 - */
434 - int create_directories_remaining = 3;
435 -
436 - /* A scratch copy of path, filled lazily if we need it: */
437 - struct strbuf path_copy = STRBUF_INIT;
438 -
439 - int ret, save_errno;
440 -
441 - /* Sanity check: */
442 - assert(*path);
443 -
444 -retry_fn:
445 - ret = fn(path, cb);
446 - save_errno = errno;
447 - if (!ret)
448 - goto out;
449 -
450 - if (errno == EISDIR && remove_directories_remaining-- > 0) {
451 - /*
452 - * A directory is in the way. Maybe it is empty; try
453 - * to remove it:
454 - */
455 - if (!path_copy.len)
456 - strbuf_addstr(&path_copy, path);
457 -
458 - if (!remove_dir_recursively(&path_copy, REMOVE_DIR_EMPTY_ONLY))
459 - goto retry_fn;
460 - } else if (errno == ENOENT && create_directories_remaining-- > 0) {
461 - /*
462 - * Maybe the containing directory didn't exist, or
463 - * maybe it was just deleted by a process that is
464 - * racing with us to clean up empty directories. Try
465 - * to create it:
466 - */
467 - enum scld_error scld_result;
468 -
469 - if (!path_copy.len)
470 - strbuf_addstr(&path_copy, path);
471 -
472 - do {
473 - scld_result = safe_create_leading_directories(path_copy.buf);
474 - if (scld_result == SCLD_OK)
475 - goto retry_fn;
476 - } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0);
477 - }
478 -
479 -out:
480 - strbuf_release(&path_copy);
481 - errno = save_errno;
482 - return ret;
483 -}
484 -
417 static void fill_loose_path(struct strbuf *buf, const struct object_id *oid)
418 {
419 int i;
refs/files-backend.c
+109
@@ -852,6 +852,115 @@ static struct ref_iterator *files_ref_iterator_begin(
852 return ref_iterator;
853 }
854
855 +/*
856 + * Callback function for raceproof_create_file(). This function is
857 + * expected to do something that makes dirname(path) permanent despite
858 + * the fact that other processes might be cleaning up empty
859 + * directories at the same time. Usually it will create a file named
860 + * path, but alternatively it could create another file in that
861 + * directory, or even chdir() into that directory. The function should
862 + * return 0 if the action was completed successfully. On error, it
863 + * should return a nonzero result and set errno.
864 + * raceproof_create_file() treats two errno values specially:
865 + *
866 + * - ENOENT -- dirname(path) does not exist. In this case,
867 + * raceproof_create_file() tries creating dirname(path)
868 + * (and any parent directories, if necessary) and calls
869 + * the function again.
870 + *
871 + * - EISDIR -- the file already exists and is a directory. In this
872 + * case, raceproof_create_file() removes the directory if
873 + * it is empty (and recursively any empty directories that
874 + * it contains) and calls the function again.
875 + *
876 + * Any other errno causes raceproof_create_file() to fail with the
877 + * callback's return value and errno.
878 + *
879 + * Obviously, this function should be OK with being called again if it
880 + * fails with ENOENT or EISDIR. In other scenarios it will not be
881 + * called again.
882 + */
883 +typedef int create_file_fn(const char *path, void *cb);
884 +
885 +/*
886 + * Create a file in dirname(path) by calling fn, creating leading
887 + * directories if necessary. Retry a few times in case we are racing
888 + * with another process that is trying to clean up the directory that
889 + * contains path. See the documentation for create_file_fn for more
890 + * details.
891 + *
892 + * Return the value and set the errno that resulted from the most
893 + * recent call of fn. fn is always called at least once, and will be
894 + * called more than once if it returns ENOENT or EISDIR.
895 + */
896 +static int raceproof_create_file(const char *path, create_file_fn fn, void *cb)
897 +{
898 + /*
899 + * The number of times we will try to remove empty directories
900 + * in the way of path. This is only 1 because if another
901 + * process is racily creating directories that conflict with
902 + * us, we don't want to fight against them.
903 + */
904 + int remove_directories_remaining = 1;
905 +
906 + /*
907 + * The number of times that we will try to create the
908 + * directories containing path. We are willing to attempt this
909 + * more than once, because another process could be trying to
910 + * clean up empty directories at the same time as we are
911 + * trying to create them.
912 + */
913 + int create_directories_remaining = 3;
914 +
915 + /* A scratch copy of path, filled lazily if we need it: */
916 + struct strbuf path_copy = STRBUF_INIT;
917 +
918 + int ret, save_errno;
919 +
920 + /* Sanity check: */
921 + assert(*path);
922 +
923 +retry_fn:
924 + ret = fn(path, cb);
925 + save_errno = errno;
926 + if (!ret)
927 + goto out;
928 +
929 + if (errno == EISDIR && remove_directories_remaining-- > 0) {
930 + /*
931 + * A directory is in the way. Maybe it is empty; try
932 + * to remove it:
933 + */
934 + if (!path_copy.len)
935 + strbuf_addstr(&path_copy, path);
936 +
937 + if (!remove_dir_recursively(&path_copy, REMOVE_DIR_EMPTY_ONLY))
938 + goto retry_fn;
939 + } else if (errno == ENOENT && create_directories_remaining-- > 0) {
940 + /*
941 + * Maybe the containing directory didn't exist, or
942 + * maybe it was just deleted by a process that is
943 + * racing with us to clean up empty directories. Try
944 + * to create it:
945 + */
946 + enum scld_error scld_result;
947 +
948 + if (!path_copy.len)
949 + strbuf_addstr(&path_copy, path);
950 +
951 + do {
952 + scld_result = safe_create_leading_directories(path_copy.buf);
953 + if (scld_result == SCLD_OK)
954 + goto retry_fn;
955 + } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0);
956 + }
957 +
958 +out:
959 + strbuf_release(&path_copy);
960 + errno = save_errno;
961 + return ret;
962 +}
963 +
964 static int remove_empty_directories(struct strbuf *path)
965 {
966 /*