Skip to content

More Better Worktree Support #603

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

Merged
merged 27 commits into from
Nov 18, 2020
Merged

More Better Worktree Support #603

merged 27 commits into from
Nov 18, 2020

Conversation

foriequal0
Copy link
Contributor

#404 has been draft for a while. Since @mkeeler said 'Feel free to take it over'(comment), I've appended some commits after it.
I've intentionally not cleaned commits to preserve history and intensions. I'll clean up the history as it get reviewed.

Copy link

@Aetf Aetf left a comment

Choose a reason for hiding this comment

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

Only noticed this after me spending two days writing my worktree bindings...

@kamalmarhubi
Copy link
Contributor

@foriequal0 could you add a rough todo list of what needs to happen for this to be done? I might have some time to put in, and as a heavy worktree user I'd love this to make its way into git2-rs based tools. :-)

The systest changes were necessary due to the actual field name used in the C library being “ref” and not being able to name the field the same in the Rust struct because “ref” is a reserved keyword.
The type it aliases, git_indexer_progress, is still checked but this prevents spurious warnings about using deprecated fields.
@foriequal0
Copy link
Contributor Author

foriequal0 commented Oct 27, 2020

I rebased it to resolve merge conflict.

@kamalmarhubi I forgot this while waiting for a review. I think the feature is done. After finishing the review, I have to squash some commits before merging.
Can someone review this?

@kamalmarhubi
Copy link
Contributor

ping @joshtriplett or @alexcrichton as you've both recently merged prs

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Looking good, thanks for picking this up!

src/repo.rs Outdated
@@ -162,6 +163,19 @@ impl Repository {
}
}

/// Attempt to open an already-existing repository from a worktree.
pub fn open_from_worktree(worktree: &Worktree) -> Result<Repository, Error> {
crate::init();
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 can be skipped since the presence of Worktree implies it's already been called.

systest/build.rs Outdated
@@ -41,5 +43,6 @@ fn main() {
cfg.skip_roundtrip(|t| t == "git_clone_options" || t == "git_submodule_update_options");

cfg.skip_type(|t| t == "__enum_ty");
cfg.skip_type(|t| t == "git_transfer_progress");
Copy link
Member

Choose a reason for hiding this comment

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

How come this is skipped?

Copy link
Contributor Author

@foriequal0 foriequal0 Oct 31, 2020

Choose a reason for hiding this comment

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

I didn't write this commit. I think @mkeeler wanted to turn off deprecation warning according to the commit message, but it doesn't complaint on my computer, and I think it is not reponsibility of this PR. I'll remove it.

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 may still want to get removed?

src/test.rs Outdated
@@ -17,6 +18,118 @@ macro_rules! t {
};
}

// `repo_test! will
macro_rules! repo_test {
Copy link
Member

Choose a reason for hiding this comment

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

I may be missing something, but how come a macro for this was added? Could the tests be written just against the right function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I asume that @mjkeeler wanted to make sure that same code should have same functionalities even if underlying repositories are different (normal repo, normal repo's worktree, bare repo, bare repo's worktree). I've finished his implementation, but I still think it is the libgit2's responsibility since git2-rs is just a binding. Should I remove this?

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 it's good to keep some tests in this repository, but whether or not it's done with a macro is up to you. I personally prefer to avoid macros where possible.

src/test.rs Outdated
(tds, worktree_repo)
}

pub fn repo_init_typical_worktree() -> (TempDirs, Repository) {
Copy link
Member

Choose a reason for hiding this comment

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

Since these functions seem related to worktree-testing, perhaps they could be scoped to the worktree tests submodule?

src/worktree.rs Outdated
/// filesystem and that the metadata is correct
pub fn validate(&self) -> Result<(), Error> {
unsafe {
call::c_try(raw::git_worktree_validate(call::convert(&self.raw)))?;
Copy link
Member

Choose a reason for hiding this comment

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

Could this use the try_call! macro instead of the call module directly?

Copy link
Member

Choose a reason for hiding this comment

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

(same below)

src/worktree.rs Outdated
let v = buf.to_vec();
Ok(WorktreeLockStatus::Locked(match v.len() {
0 => None,
_ => String::from_utf8(v).ok(),
Copy link
Member

Choose a reason for hiding this comment

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

Could this use .unwrap() since it's expected to always be utf-8?

src/worktree.rs Outdated

/// Opens the repository from the worktree
pub fn to_repository(&self) -> Result<Repository, Error> {
Repository::open_from_worktree(self)
Copy link
Member

Choose a reason for hiding this comment

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

I personally prefer to stick close to the original git2 API where possible, so could this and the other convenience alias be removed?

src/worktree.rs Outdated
);

opts.lock = self.lock as c_int;
opts.reference = crate::call::convert(&self.reference.as_ref().map(|o| o.raw()));
Copy link
Member

Choose a reason for hiding this comment

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

Instead of the convert function could this do the conversion manually?

Also I think it might be good to store the git_worktree_add_options directly in this structure.

src/worktree.rs Outdated
/// This method is unsafe as the returned value may have pointers to the
/// interior of this structure
pub unsafe fn raw(&self) -> raw::git_worktree_prune_options {
let mut opts = mem::zeroed();
Copy link
Member

Choose a reason for hiding this comment

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

Could this opts be stored directly in the structure?

src/branch.rs Outdated
@@ -153,8 +153,7 @@ impl<'repo> Drop for Branches<'repo> {
mod tests {
use crate::BranchType;

#[test]
fn smoke() {
repo_test!(smoke, (Typical, TypicalWorktree, BareWorktree), |_| {
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 probably don't need to update old tests like this

Copy link
Contributor Author

@foriequal0 foriequal0 Nov 5, 2020

Choose a reason for hiding this comment

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

I'll revert old tests, but keep worktree tests. I'll move repo_test macro to worktree.rs and worktree tests. Let smoke tests be simple smoke tests.

src/test.rs Outdated
@@ -17,6 +18,118 @@ macro_rules! t {
};
}

// `repo_test! will
macro_rules! repo_test {
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 it's good to keep some tests in this repository, but whether or not it's done with a macro is up to you. I personally prefer to avoid macros where possible.

@kamalmarhubi
Copy link
Contributor

Looks like review comments were all addressed, is that right @foriequal0?

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Just a few more small comments!

src/worktree.rs Outdated

// It is the current belief that a `Worktree` can be sent among threads, or
// even shared among threads in a mutex
unsafe impl Send for Worktree {}
Copy link
Member

Choose a reason for hiding this comment

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

Oh sorry I think I missed this earlier, but are you sure of this? Is this documented in libgit2?

Copy link
Contributor

@kamalmarhubi kamalmarhubi Nov 16, 2020

Choose a reason for hiding this comment

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

This is the best I could find:

Unless otherwise specified, libgit2 objects cannot be safely accessed by multiple threads simultaneously.
[...]
Use an object from a single thread at a time. Most data structures do not guard against concurrent access themselves. This is because they are rarely used in isolation and it makes more sense to synchronize access via a larger lock or similar mechanism.

https://github.com/libgit2/libgit2/blob/master/docs/threading.md

I think this can be read as they are Send but not Sync?

Looks like Repository has been Send for a while: 51f1376

And the comment this was modeled after was added around the same time: 2b0f5cb#diff-8a44ff48a251d03d58e6d3c73e8664553e2aa7b2a925641dd6c3d2f81c0d2e11

(Both changes by you, almost six years ago!)

Copy link
Contributor

Choose a reason for hiding this comment

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

The original version of that file was clearer on this point:

You may safely use any libgit2 object from any thread, though there may be issues depending on the cryptographic libraries libgit2 or its dependencies link to (more on this later).

libgit2/libgit2@15bea02#diff-bb59cfb2bcd0e444b33e25dc3f1e127e095d72379150cc82d408afa63b9903bf

Copy link
Member

Choose a reason for hiding this comment

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

Yeah as @joshtriplett pointed out below libgit2's policy isn't enough to dictate whether things are Send or Sync in Rust. You'll need to devle into the internals and audit what's happening to see if it's safe. I think I did that for git_repository a long time ago, but if this wants to stay then it should happen for git_worktree as well. It's always ok to drop this unsafe impl for now though and add it back later if it works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. I didn't notice that. I'll remove it.

systest/build.rs Outdated
@@ -41,5 +43,6 @@ fn main() {
cfg.skip_roundtrip(|t| t == "git_clone_options" || t == "git_submodule_update_options");

cfg.skip_type(|t| t == "__enum_ty");
cfg.skip_type(|t| t == "git_transfer_progress");
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 may still want to get removed?

@joshtriplett
Copy link
Member

joshtriplett commented Nov 16, 2020 via email

@foriequal0
Copy link
Contributor Author

Thanks for the review! I think you can squash merge if it is okay or I should rebase commits before merging them.

@alexcrichton
Copy link
Member

OK everything looks great to me, thanks again! And no worries, I use the squash-and-merge button so that happens automatically.

@alexcrichton alexcrichton merged commit 2ba1852 into rust-lang:master Nov 18, 2020
@joshtriplett
Copy link
Member

@foriequal0 To the best of your knowledge, does this fully supersede #404 , or is there additional work in that PR that needs updating and merging?

@foriequal0 foriequal0 deleted the worktrees branch January 26, 2021 04:05
@foriequal0
Copy link
Contributor Author

@joshtriplett I think there is no additional work for this :)

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.

6 participants