Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove empty (sub-)directories when deleting refs #4833

Merged
merged 1 commit into from Dec 19, 2018
Merged

Remove empty (sub-)directories when deleting refs #4833

merged 1 commit into from Dec 19, 2018

Conversation

csware
Copy link
Contributor

@csware csware commented Oct 5, 2018

Fixes issue #4806.

@csware csware changed the title WIP: Remove empty directories when deleting refs Remove empty directories when deleting refs Oct 5, 2018
@csware csware changed the title Remove empty directories when deleting refs Remove empty (sub-)directories when deleting refs Oct 5, 2018
Copy link
Member

@pks-t pks-t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this! I've accidentally also implemented a fix yesterday, but didn't yet upload it. I think essentially, both fixes boiled down to the same thing: using the rmdir_r function that's already available. I already got enough PRs open right now that I have to handle, so I'm going to favour yours :)

src/refdb_fs.c Outdated
git_buf base_path = GIT_BUF_INIT;
git_buf relative_path = GIT_BUF_INIT;
int just_delete = 1;
int error = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to initialize error = 0, as you immediately set it in the first statement

src/refdb_fs.c Outdated
const char *ref_name,
const char *ref_path,
bool reflog
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The opening bracket belongs on the last line

src/refdb_fs.c Outdated

while (*start_ptr == '/') /* drop multiple path separators */
++start_ptr;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a bit too lenient. E.g. if I'm creating a thing "foo/bar/x", it will just skip "foo/bar". I think we should instead explicitly special-case precious directories:

git_buf_sets(&buf, ref_name);
git_path_squash_slashes(&buf);
if ((commonlen = git_path_common_dirlen("refs/heads/", buf.ptr)) ||
    (commonlen = git_path_common_dirlen("refs/tags/", buf.ptr)) ||
    ...) {
        git_buf base = GIT_BUF_INIT;
        git_buf_printf(&base, "%s/%.*s", backend->commonpath, commonlen, buf.ptr);
        git_futils_rmdir_r(ref_path + commonlen, base.ptr, GIT_RMDIR_EMPTY_PARENTS|GIT_RMDIR_REMOVE_FILES|GIT_RMDIR_SKIP_ROOT);
} else {
       p_unlink(ref_path);
}

Something like the above. It's completely untested and out of my head, but I guess it's sufficient to demonstrate what I imagine.

src/refdb_fs.c Outdated
goto cleanup;
}

error = packed_write(backend);
/* unlock here, so that we can delete the all empty parents */
git_filebuf_cleanup(file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're cleaning up file twice now, aren't we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to close the lock file before we can remove the possibly empty parents, otherwise it won't work. And we still need it in the cleanup path. As cleanup disposes the internal buffer, calling it twice doesn't cause problems.

src/refdb_fs.c Outdated
/* unlock here, so that we can delete the all empty parents */
git_filebuf_cleanup(file);

error = refdb_fs_backend__delete_empty_parents(backend, ref_name, git_buf_cstr(&loose_path), false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rename this function. It doesn't only remove parents, but also the reference itself.

@csware
Copy link
Contributor Author

csware commented Oct 5, 2018

@pks-t Updated...

@tiennou
Copy link
Contributor

tiennou commented Oct 8, 2018

/rebuild

@libgit2-azure-pipelines
Copy link

Okay, @tiennou, I started to rebuild this pull request.

@csware
Copy link
Contributor Author

csware commented Oct 9, 2018

/rebuild

@libgit2-azure-pipelines
Copy link

Sorry @csware, you're not allowed to do that.

@pks-t
Copy link
Member

pks-t commented Oct 11, 2018

@ethomson: shouldn't PR owners be allowed to rebuild their own PRs?

@ethomson
Copy link
Member

ethomson commented Oct 11, 2018 via email

@csware
Copy link
Contributor Author

csware commented Oct 11, 2018

@pks-t Any new comments?

@pks-t
Copy link
Member

pks-t commented Oct 12, 2018

Huh, CI is still failing. Let's try it again

@pks-t
Copy link
Member

pks-t commented Oct 12, 2018

/rebuild

@libgit2-azure-pipelines
Copy link

Okay, @pks-t, I started to rebuild this pull request.

@pks-t
Copy link
Member

pks-t commented Oct 12, 2018

@ethomson: seems like CI is currently having problems?

@ethomson
Copy link
Member

The CI is not having problems, the code simply doesn't compile.

@csware
Copy link
Contributor Author

csware commented Oct 12, 2018

The CI is not having problems, the code simply doesn't compile.

I see Docker issues:

Unable to find image 'libgit2/trusty-mbedtls:latest' locally
latest: Pulling from libgit2/trusty-mbedtls
28bfaceaff9b: Pulling fs layer
Pulling fs layer
2965585ef8b8: Pulling fs layer
2416bb9f3ad2: Pulling fs layer
93b55a6a6807: Pulling fs layer
b1f4f03bf07c: Pulling fs layer
dfd74b70ab8f: Pulling fs layer
e7a3b540949e: Pulling fs layer
Pulling fs layer

@ethomson
Copy link
Member

2018-10-12T10:33:54.5086580Z /Users/vsts/agent/2.140.2/work/1/s/tests/refs/branches/delete.c:154:12: error: implicit declaration of function 'git_path_exists' [-Werror,-Wimplicit-function-declaration]
2018-10-12T10:33:54.5086830Z         cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == true);
2018-10-12T10:33:54.5086960Z                   ^
2018-10-12T10:33:54.5107770Z /Users/vsts/agent/2.140.2/work/1/s/tests/refs/branches/delete.c:154:12: note: did you mean 'git_odb_exists'?
2018-10-12T10:33:54.5109090Z /Users/vsts/agent/2.140.2/work/1/s/include/git2/odb.h:160:17: note: 'git_odb_exists' declared here
2018-10-12T10:33:54.5109230Z GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
2018-10-12T10:33:54.5109280Z                 ^
2018-10-12T10:33:54.5110210Z /Users/vsts/agent/2.140.2/work/1/s/tests/refs/branches/delete.c:154:12: error: this function declaration is not a prototype [-Werror,-Wstrict-prototypes]
2018-10-12T10:33:54.5110330Z         cl_assert(git_path_exists(git_buf_cstr(&ref_folder)) == true);
2018-10-12T10:33:54.5110690Z                   ^
2018-10-12T10:33:54.5122930Z 2 errors generated.

@ethomson
Copy link
Member

I see Docker issues:

It's reporting the first things that hit stderr. Expand the section.

@pks-t
Copy link
Member

pks-t commented Oct 12, 2018

Ooh, that's why. I've also only spotted the Docker issues, didn't even think it might hide the relevant information.

@ethomson
Copy link
Member

Yeah, unfortunately since we're running inside docker we can't just push all its noisy stderr to stdout, since we'd also be doing that for the things being executed in the container. :/ But I'm going to investigate this a big more since having the relevant problems up-front (and not "behind the fold") would be a big improvement.

@csware csware changed the title Remove empty (sub-)directories when deleting refs WIP: Remove empty (sub-)directories when deleting refs Oct 12, 2018
@csware csware changed the title WIP: Remove empty (sub-)directories when deleting refs Remove empty (sub-)directories when deleting refs Oct 12, 2018
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ci says:

/src/tests/refs/branches/delete.c: In function 'test_refs_branches_delete__removes_empty_folders':
/src/tests/refs/branches/delete.c:163:2: warning: passing argument 1 of 'git_commit_free' from incompatible pointer type [enabled by default]
  git_commit_free(&commit);
  ^
In file included from /src/include/git2.h:20:0,
                 from /src/tests/clar_libgit2.h:5,
                 from /src/tests/refs/branches/delete.c:1:
/src/include/git2/commit.h:70:18: note: expected 'struct git_commit *' but argument is of type 'struct git_commit **'
 GIT_EXTERN(void) git_commit_free(git_commit *commit);
                  ^

So you probably want to pass commit rather than &commit.

I wonder why this doesn't result in a compilation failure...

Signed-off-by: Sven Strickroth <email@cs-ware.de>
@csware
Copy link
Contributor Author

csware commented Oct 16, 2018

@pks-t
All issues fixed.

@pks-t
Copy link
Member

pks-t commented Dec 19, 2018

Indeed they are. Thanks for being patient and for your work!

@pks-t pks-t merged commit bc21965 into libgit2:master Dec 19, 2018
@csware csware deleted the drop-empty-dirs branch December 20, 2018 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants