Skip to content

Commit

Permalink
Merge pull request #4833 from csware/drop-empty-dirs
Browse files Browse the repository at this point in the history
Remove empty (sub-)directories when deleting refs
  • Loading branch information
pks-t committed Dec 19, 2018
2 parents 8b2670b + 9f48dc3 commit bc21965
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 2 deletions.
44 changes: 42 additions & 2 deletions src/refdb_fs.c
Expand Up @@ -1313,6 +1313,43 @@ static int refdb_fs_backend__write_tail(
return error;
}

static void refdb_fs_backend__try_delete_empty_ref_hierarchie(
refdb_fs_backend *backend,
const char *ref_name,
bool reflog)
{
git_buf relative_path = GIT_BUF_INIT;
git_buf base_path = GIT_BUF_INIT;
size_t commonlen;

assert(backend && ref_name);

if (git_buf_sets(&relative_path, ref_name) < 0)
goto cleanup;

git_path_squash_slashes(&relative_path);
if ((commonlen = git_path_common_dirlen("refs/heads/", git_buf_cstr(&relative_path))) == strlen("refs/heads/") ||
(commonlen = git_path_common_dirlen("refs/tags/", git_buf_cstr(&relative_path))) == strlen("refs/tags/") ||
(commonlen = git_path_common_dirlen("refs/remotes/", git_buf_cstr(&relative_path))) == strlen("refs/remotes/")) {

git_buf_truncate(&relative_path, commonlen);

if (reflog) {
if (git_buf_join3(&base_path, '/', backend->commonpath, GIT_REFLOG_DIR, git_buf_cstr(&relative_path)) < 0)
goto cleanup;
} else {
if (git_buf_joinpath(&base_path, backend->commonpath, git_buf_cstr(&relative_path)) < 0)
goto cleanup;
}

git_futils_rmdir_r(ref_name + commonlen, git_buf_cstr(&base_path), GIT_RMDIR_EMPTY_PARENTS | GIT_RMDIR_SKIP_ROOT);
}

cleanup:
git_buf_dispose(&relative_path);
git_buf_dispose(&base_path);
}

static int refdb_fs_backend__delete(
git_refdb_backend *_backend,
const char *ref_name,
Expand Down Expand Up @@ -1393,7 +1430,8 @@ static int refdb_fs_backend__delete_tail(
cleanup:
git_buf_dispose(&loose_path);
git_filebuf_cleanup(file);

if (loose_deleted)
refdb_fs_backend__try_delete_empty_ref_hierarchie(backend, ref_name, false);
return error;
}

Expand Down Expand Up @@ -2021,8 +2059,10 @@ static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name

error = retrieve_reflog_path(&path, repo, name);

if (!error && git_path_exists(path.ptr))
if (!error && git_path_exists(path.ptr)) {
error = p_unlink(path.ptr);
refdb_fs_backend__try_delete_empty_ref_hierarchie(backend, name, true);
}

git_buf_dispose(&path);

Expand Down
46 changes: 46 additions & 0 deletions tests/refs/branches/delete.c
Expand Up @@ -2,6 +2,8 @@
#include "refs.h"
#include "repo/repo_helpers.h"
#include "config/config_helpers.h"
#include "fileops.h"
#include "reflog.h"

static git_repository *repo;
static git_reference *fake_remote;
Expand Down Expand Up @@ -140,3 +142,47 @@ void test_refs_branches_delete__removes_reflog(void)
git_reflog_free(log);
}

void test_refs_branches_delete__removes_empty_folders(void)
{
const char *commondir = git_repository_commondir(repo);
git_oid commit_id;
git_commit *commit;
git_reference *branch;

git_reflog *log;
git_oid oidzero = {{0}};
git_signature *sig;

git_buf ref_folder = GIT_BUF_INIT;
git_buf reflog_folder = GIT_BUF_INIT;

/* Create a new branch with a nested name */
cl_git_pass(git_oid_fromstr(&commit_id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"));
cl_git_pass(git_commit_lookup(&commit, repo, &commit_id));
cl_git_pass(git_branch_create(&branch, repo, "some/deep/ref", commit, 0));
git_commit_free(commit);

/* Ensure the reflog has at least one entry */
cl_git_pass(git_signature_now(&sig, "Me", "user@example.com"));
cl_git_pass(git_reflog_read(&log, repo, "refs/heads/some/deep/ref"));
cl_git_pass(git_reflog_append(log, &oidzero, sig, "message"));
cl_assert(git_reflog_entrycount(log) > 0);
git_signature_free(sig);
git_reflog_free(log);

cl_git_pass(git_buf_joinpath(&ref_folder, commondir, "refs/heads/some/deep"));
cl_git_pass(git_buf_join3(&reflog_folder, '/', commondir, GIT_REFLOG_DIR, "refs/heads/some/deep"));

cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == true);
cl_assert(git_path_exists(git_buf_cstr(&reflog_folder)) == true);

cl_git_pass(git_branch_delete(branch));

cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == false);
cl_assert(git_path_exists(git_buf_cstr(&reflog_folder)) == false);

git_reference_free(branch);
git_buf_dispose(&ref_folder);
git_buf_dispose(&reflog_folder);
}

0 comments on commit bc21965

Please sign in to comment.