Skip to content

Commit

Permalink
Merge branch 'mh/ref-remove-empty-directory'
Browse files Browse the repository at this point in the history
Deletion of a branch "foo/bar" could remove .git/refs/heads/foo
once there no longer is any other branch whose name begins with
"foo/", but we didn't do so so far.  Now we do.

* mh/ref-remove-empty-directory: (23 commits)
  files_transaction_commit(): clean up empty directories
  try_remove_empty_parents(): teach to remove parents of reflogs, too
  try_remove_empty_parents(): don't trash argument contents
  try_remove_empty_parents(): rename parameter "name" -> "refname"
  delete_ref_loose(): inline function
  delete_ref_loose(): derive loose reference path from lock
  log_ref_write_1(): inline function
  log_ref_setup(): manage the name of the reflog file internally
  log_ref_write_1(): don't depend on logfile argument
  log_ref_setup(): pass the open file descriptor back to the caller
  log_ref_setup(): improve robustness against races
  log_ref_setup(): separate code for create vs non-create
  log_ref_write(): inline function
  rename_tmp_log(): improve error reporting
  rename_tmp_log(): use raceproof_create_file()
  lock_ref_sha1_basic(): use raceproof_create_file()
  lock_ref_sha1_basic(): inline constant
  raceproof_create_file(): new function
  safe_create_leading_directories(): set errno on SCLD_EXISTS
  safe_create_leading_directories_const(): preserve errno
  ...
  • Loading branch information
gitster committed Feb 27, 2017
2 parents 538569b + 4463977 commit 3ad8b5b
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 195 deletions.
48 changes: 46 additions & 2 deletions cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,8 +1072,9 @@ int adjust_shared_perm(const char *path);

/*
* 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.
* 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
Expand All @@ -1097,6 +1098,49 @@ enum scld_error {
enum scld_error safe_create_leading_directories(char *path);
enum scld_error safe_create_leading_directories_const(const char *path);

/*
* Callback function for raceproof_create_file(). This function is
* expected to do something that makes dirname(path) permanent despite
* the fact that other processes might be cleaning up empty
* directories at the same time. Usually it will create a file named
* path, but alternatively it could create another file in that
* directory, or even chdir() into that directory. The function should
* return 0 if the action was completed successfully. On error, it
* should return a nonzero result and set errno.
* raceproof_create_file() treats two errno values specially:
*
* - ENOENT -- dirname(path) does not exist. In this case,
* raceproof_create_file() tries creating dirname(path)
* (and any parent directories, if necessary) and calls
* the function again.
*
* - EISDIR -- the file already exists and is a directory. In this
* case, raceproof_create_file() removes the directory if
* it is empty (and recursively any empty directories that
* it contains) and calls the function again.
*
* Any other errno causes raceproof_create_file() to fail with the
* callback's return value and errno.
*
* Obviously, this function should be OK with being called again if it
* fails with ENOENT or EISDIR. In other scenarios it will not be
* called again.
*/
typedef int create_file_fn(const char *path, void *cb);

/*
* Create a file in dirname(path) by calling fn, creating leading
* directories if necessary. Retry a few times in case we are racing
* with another process that is trying to clean up the directory that
* contains path. See the documentation for create_file_fn for more
* details.
*
* Return the value and set the errno that resulted from the most
* recent call of fn. fn is always called at least once, and will be
* called more than once if it returns ENOENT or EISDIR.
*/
int raceproof_create_file(const char *path, create_file_fn fn, void *cb);

int mkdir_in_gitdir(const char *path);
extern char *expand_user_path(const char *path);
const char *enter_repo(const char *path, int strict);
Expand Down
Loading

0 comments on commit 3ad8b5b

Please sign in to comment.