Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/cmd/audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ pub fn run(sess: &Session, args: &AuditArgs) -> Result<()> {
.map(|&pkg| async move {
futures::join!(
async { *pkg },
io_ref.dependency_versions(*pkg, args.fetch, None)
io_ref.dependency_versions(
*pkg,
if args.fetch { Some(true) } else { None },
None
)
)
})
.collect::<Vec<_>>();
Expand Down
52 changes: 39 additions & 13 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,17 +290,30 @@ impl<'ctx> DependencyResolver<'ctx> {
tmp
})
.collect();
let ids: IndexSet<DependencyRef> = names.iter().map(|(_, &id)| id).collect();
// debugln!("resolve: dep names {:?}", names);
// debugln!("resolve: dep ids {:?}", ids);

// Determine the available versions for the dependencies.
let versions: Vec<_> = ids
// Skip fetching for dependencies that are locked.
let locked_names: IndexSet<&str> = self
.locked
.iter()
.map(|&id| async move {
io.dependency_versions(id, false, None)
.await
.map(move |v| (id, v))
.filter(|(_, (_, _, _, is_locked))| *is_locked)
.map(|(&name, _)| name)
.collect();
let fetched_names: IndexSet<&str> = names
.keys()
.filter(|name| !locked_names.contains(*name))
.copied()
.collect();
let versions: Vec<_> = names
.iter()
.map(|(&name, &id)| {
let skip = locked_names.contains(name);
async move {
io.dependency_versions(id, if skip { Some(false) } else { None }, None)
.await
.map(move |v| (id, v))
}
})
.collect();
let versions: IndexMap<_, _> = rt
Expand All @@ -309,6 +322,13 @@ impl<'ctx> DependencyResolver<'ctx> {
.collect::<Result<Vec<_>>>()?
.into_iter()
.collect::<IndexMap<_, _>>();

// Record fetched deps so refetch attempts in mark/pick can skip them.
for (&name, &id) in &names {
if fetched_names.contains(name) {
self.refetched.insert((id, None));
}
}
// debugln!("resolve: versions {:#?}", versions);

// Register the versions.
Expand Down Expand Up @@ -456,7 +476,11 @@ impl<'ctx> DependencyResolver<'ctx> {
async move {
Ok::<(_, _), Error>((
dep.to_string(),
(hash, io.dependency_versions(src, false, None).await?, src),
(
hash,
io.dependency_versions(src, Some(false), None).await?,
src,
),
))
}
})))
Expand Down Expand Up @@ -658,7 +682,7 @@ impl<'ctx> DependencyResolver<'ctx> {
// attempt plain refetch
self.refetched.insert((*id, None));
if let Ok(new_versions) =
rt.block_on(io.dependency_versions(*id, true, None))
rt.block_on(io.dependency_versions(*id, Some(true), None))
{
src.versions = new_versions;
}
Expand Down Expand Up @@ -688,9 +712,11 @@ impl<'ctx> DependencyResolver<'ctx> {
if !self.refetched.contains(&(*id, Some(rev.clone()))) {
// attempt refetch with rev
self.refetched.insert((*id, Some(rev.clone())));
if let Ok(new_versions) =
rt.block_on(io.dependency_versions(*id, true, Some(rev.as_str())))
{
if let Ok(new_versions) = rt.block_on(io.dependency_versions(
*id,
Some(true),
Some(rev.as_str()),
)) {
src.versions = new_versions;
}
}
Expand Down Expand Up @@ -945,7 +971,7 @@ impl<'ctx> DependencyResolver<'ctx> {
);
let refetched_versions = rt.block_on(io.dependency_versions(
decision.1,
true,
Some(true),
fetch_ref.as_deref(),
));
if let Ok(new_versions) = refetched_versions {
Expand Down
23 changes: 17 additions & 6 deletions src/sess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,10 +491,14 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
/// If `fetch_ref` is provided, a specific ref (e.g. a commit hash not on
/// any branch) is fetched and a temporary tag is created so that
/// `rev-list --all` can discover it.
/// `force_fetch` controls fetching behavior:
/// - `None`: use manifest modification time check (default)
/// - `Some(true)`: force a fetch regardless of modification time
/// - `Some(false)`: skip fetching regardless of modification time
pub async fn dependency_versions(
&'io self,
dep_id: DependencyRef,
force_fetch: bool,
force_fetch: Option<bool>,
fetch_ref: Option<&str>,
) -> Result<DependencyVersions<'ctx>> {
self.sess.stats.num_calls_dependency_versions.increment();
Expand Down Expand Up @@ -548,7 +552,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
&'io self,
name: &str,
url: &str,
force_fetch: bool,
force_fetch: Option<bool>,
fetch_ref: Option<&str>,
) -> Result<Git<'ctx>> {
// TODO: Make the assembled future shared and keep it in a lookup table.
Expand Down Expand Up @@ -631,7 +635,12 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
} else {
// Update if the manifest has been modified since the last fetch.
let db_mtime = try_modification_time(db_dir.join("FETCH_HEAD"));
if (self.sess.manifest_mtime < db_mtime && !force_fetch) || self.sess.local_only {
let skip_fetch = match force_fetch {
Some(true) => false,
Some(false) => true,
None => self.sess.manifest_mtime < db_mtime,
};
if skip_fetch || self.sess.local_only {
debugln!("sess: skipping fetch of {:?}", db_dir);
return Ok(git);
}
Expand Down Expand Up @@ -900,7 +909,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
);
if current == revision {
CheckoutState::Clean
} else if let Ok(db) = self.git_database(name, url, false, None).await {
} else if let Ok(db) = self.git_database(name, url, Some(false), None).await {
if let Ok(remote) = local_git.clone().remote_url("origin").await {
if remote == db.path.to_str().unwrap() {
CheckoutState::ToCheckout
Expand Down Expand Up @@ -968,7 +977,9 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
let tag_name_0 = format!("bender-tmp-{}", revision).clone();
let tag_name_1 = tag_name_0.clone();
let tag_name_2 = tag_name_0.clone();
let git = self.git_database(name, url, false, Some(revision)).await?;
let git = self
.git_database(name, url, Some(false), Some(revision))
.await?;
match git
.clone()
.spawn_with(
Expand Down Expand Up @@ -1386,7 +1397,7 @@ impl<'io, 'sess: 'io, 'ctx: 'sess> SessionIo<'sess, 'ctx> {
}
(DepSrc::Git(url), DepVer::Git(rev)) => {
let dep_name = self.sess.intern_string(dep.name.as_str());
let db = self.git_database(&dep.name, url, false, None).await?;
let db = self.git_database(&dep.name, url, Some(false), None).await?;
let entries = db.clone().list_files(rev, Some("Bender.yml")).await?;
let data = match entries.into_iter().next() {
None => Ok(None),
Expand Down