Skip to content

Commit 8e35fd7

Browse files
committed
Auto merge of #4051 - alexcrichton:fix-flaky-test, r=alexcrichton
Fix a flaky concurrent test with correct locking The recent refactoring to clone the bare registry left in an accidental path where index checkouts could clobber one another. This commit updates the logic with proper locking and attempt ordering, attempting a full retry of the open operation after the index locked.
2 parents 3def3bf + 7b44acc commit 8e35fd7

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

src/cargo/sources/registry/remote.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,18 @@ impl<'cfg> RemoteRegistry<'cfg> {
5555
self.repo.get_or_try_init(|| {
5656
let path = self.index_path.clone().into_path_unlocked();
5757

58+
// Fast path without a lock
59+
if let Ok(repo) = git2::Repository::open(&path) {
60+
return Ok(repo)
61+
}
62+
63+
// Ok, now we need to lock and try the whole thing over again.
64+
let lock = self.index_path.open_rw(Path::new(INDEX_LOCK),
65+
self.config,
66+
"the registry index")?;
5867
match git2::Repository::open(&path) {
5968
Ok(repo) => Ok(repo),
6069
Err(_) => {
61-
self.index_path.create_dir()?;
62-
let lock = self.index_path.open_rw(Path::new(INDEX_LOCK),
63-
self.config,
64-
"the registry index")?;
6570
let _ = lock.remove_siblings();
6671
Ok(git2::Repository::init_bare(&path)?)
6772
}
@@ -153,25 +158,29 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
153158
"the registry index")?;
154159
self.config.shell().status("Updating",
155160
format!("registry `{}`", self.source_id.url()))?;
161+
let mut needs_fetch = true;
156162

157163
if self.source_id.url().host_str() == Some("github.com") {
158164
if let Ok(oid) = self.head() {
159165
let mut handle = self.easy()?.borrow_mut();
160166
debug!("attempting github fast path for {}",
161167
self.source_id.url());
162168
if github_up_to_date(&mut handle, self.source_id.url(), &oid) {
163-
return Ok(())
169+
needs_fetch = false;
170+
} else {
171+
debug!("fast path failed, falling back to a git fetch");
164172
}
165-
debug!("fast path failed, falling back to a git fetch");
166173
}
167174
}
168175

169-
// git fetch origin master
170-
let url = self.source_id.url().to_string();
171-
let refspec = "refs/heads/master:refs/remotes/origin/master";
172-
git::fetch(&repo, &url, refspec, self.config).chain_error(|| {
173-
human(format!("failed to fetch `{}`", url))
174-
})?;
176+
if needs_fetch {
177+
// git fetch origin master
178+
let url = self.source_id.url().to_string();
179+
let refspec = "refs/heads/master:refs/remotes/origin/master";
180+
git::fetch(&repo, &url, refspec, self.config).chain_error(|| {
181+
human(format!("failed to fetch `{}`", url))
182+
})?;
183+
}
175184
self.head.set(None);
176185
*self.tree.borrow_mut() = None;
177186
Ok(())

0 commit comments

Comments
 (0)