Hi,
I'm having trouble understanding the error for the following code example (using the dependency git2 = "0.14.2"
):
use git2::{Object, Reference, Repository};
use std::path::Path;
fn branch_object_and_reference<'a>(
repository: &'a Repository,
branch: &str,
) -> Result<(Object<'a>, Reference<'a>), git2::Error> {
let branch_name = format!("origin/{}", branch);
let branch_reference = repository
.find_branch(&branch_name, git2::BranchType::Remote)?
.into_reference();
let branch_object = branch_reference.peel(git2::ObjectType::Any)?;
Ok((branch_object, branch_reference))
}
pub fn clone_checkout_git_revision(
url: &str,
checkout_folder_path: &Path,
revision: &str,
) -> Result<Repository, git2::Error> {
let repository = Repository::clone(url, checkout_folder_path)?;
let (revision_object, revision_reference) = if let Ok((branch_object, branch_reference)) =
branch_object_and_reference(&repository, revision)
{
// Checkout the branch the revision points to.
(branch_object, Some(branch_reference))
} else {
// Checkout the revision hash.
repository.revparse_ext(revision)?
};
repository.checkout_tree(&revision_object, None)?;
match revision_reference {
Some(ref reference) => {
if let Some(reference_name) = reference.name() {
repository.set_head(reference_name)?
} else {
repository.set_head_detached(revision_object.id())?
}
}
None => repository.set_head_detached(revision_object.id())?,
}
Ok(repository)
}
This gives the error:
error[E0505]: cannot move out of `repository` because it is borrowed
--> src/lib.rs:49:8
|
26 | branch_object_and_reference(&repository, revision)
| ----------- borrow of `repository` occurs here
...
49 | Ok(repository)
| ^^^^^^^^^^ move out of `repository` occurs here
50 | }
| - borrow might be used here, when `revision_object` is dropped and runs the `Drop` code for type `git2::Object`
Looking around on the internet the suggested fixes for this are to either use a local scope or manual drops. Sure enough adding manual drops at the end fixes this:
drop(revision_object);
drop(revision_reference);
Ok(repository)
But I don't understand why this fixes the error. So I basically have 2 questions:
- What exactly is the reason for the error in the first place?
My current working theory is that it's a lifetime issue based on the error message.
Thebranch_object_and_reference()
function declares that the returning Object and Reference have the same lifetime as the passed&Repository
. So when the variables inside theclone_checkout_git_revision()
function are no longer used, they get dropped. And since they need to have the same lifetime as therepository
variable, that needs to get dropped as well before I can return it.
Is this somewhat close to what's happening or am I already way off here? - Why do the manual drops fix this error?
Assuming the above assumption is somewhat correct: Shouldn't manual drops have the same issue? The variables get dropped and since their lifetime needs to be same as therepository
variable, the same error should occur?
Obviously the error doesn't appear so I'm getting something wrong here.
I would really like to understand this issue as it's confusing me quite a bit.
Thanks in advance to everyone helping me understand this!