Skip to content

Commit

Permalink
Write .cargo_ok after submodule checkout completes successfully
Browse files Browse the repository at this point in the history
  • Loading branch information
osiewicz committed Oct 1, 2024
1 parent 14a646e commit f847c14
Showing 1 changed file with 30 additions and 10 deletions.
40 changes: 30 additions & 10 deletions src/cargo/sources/git/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,25 @@ pub struct GitCheckout<'a> {
repo: git2::Repository,
}

/// See [`GitCheckout::reset`] for rationale on this type.
struct CheckoutGuard {
ok_file: PathBuf,
}

impl CheckoutGuard {
#[must_use]
fn guard(path: &Path) -> Self {
let ok_file = path.join(CHECKOUT_READY_LOCK);
let _ = paths::remove_file(&ok_file);
Self { ok_file }
}

fn mark_ok(self) -> CargoResult<()> {
let _ = paths::create(self.ok_file)?;
Ok(())
}
}

impl GitRemote {
/// Creates an instance for a remote repository URL.
pub fn new(url: &Url) -> GitRemote {
Expand Down Expand Up @@ -182,8 +201,9 @@ impl GitDatabase {
{
Some(co) => co,
None => {
let checkout = GitCheckout::clone_into(dest, self, rev, gctx)?;
let (checkout, guard) = GitCheckout::clone_into(dest, self, rev, gctx)?;
checkout.update_submodules(gctx)?;
guard.mark_ok()?;
checkout
}
};
Expand Down Expand Up @@ -284,7 +304,7 @@ impl<'a> GitCheckout<'a> {
database: &'a GitDatabase,
revision: git2::Oid,
gctx: &GlobalContext,
) -> CargoResult<GitCheckout<'a>> {
) -> CargoResult<(GitCheckout<'a>, CheckoutGuard)> {
let dirname = into.parent().unwrap();
paths::create_dir_all(&dirname)?;
if into.exists() {
Expand Down Expand Up @@ -333,8 +353,8 @@ impl<'a> GitCheckout<'a> {
let repo = repo.unwrap();

let checkout = GitCheckout::new(database, revision, repo);
checkout.reset(gctx)?;
Ok(checkout)
let guard = checkout.reset(gctx)?;
Ok((checkout, guard))
}

/// Checks if the `HEAD` of this checkout points to the expected revision.
Expand All @@ -359,12 +379,12 @@ impl<'a> GitCheckout<'a> {
/// To enable this we have a dummy file in our checkout, [`.cargo-ok`],
/// which if present means that the repo has been successfully reset and is
/// ready to go. Hence if we start to do a reset, we make sure this file
/// *doesn't* exist, and then once we're done we create the file.
/// *doesn't* exist. The caller of [`reset`] has an option to perform additional operations
/// (e.g. submodule update) before marking the check-out as ready.
///
/// [`.cargo-ok`]: CHECKOUT_READY_LOCK
fn reset(&self, gctx: &GlobalContext) -> CargoResult<()> {
let ok_file = self.path.join(CHECKOUT_READY_LOCK);
let _ = paths::remove_file(&ok_file);
fn reset(&self, gctx: &GlobalContext) -> CargoResult<CheckoutGuard> {
let guard = CheckoutGuard::guard(&self.path);
info!("reset {} to {}", self.repo.path().display(), self.revision);

// Ensure libgit2 won't mess with newlines when we vendor.
Expand All @@ -374,8 +394,8 @@ impl<'a> GitCheckout<'a> {

let object = self.repo.find_object(self.revision, None)?;
reset(&self.repo, &object, gctx)?;
paths::create(ok_file)?;
Ok(())

Ok(guard)
}

/// Like `git submodule update --recursive` but for this git checkout.
Expand Down

0 comments on commit f847c14

Please sign in to comment.