Skip to content

Commit 64b6149

Browse files
andholpil
authored andcommitted
refactor(dependencies): use the same PackageFetcher during dependency resolution and major version resolution to reduce network calls to hexpm ♻️
1 parent 75e67e8 commit 64b6149

File tree

2 files changed

+48
-32
lines changed

2 files changed

+48
-32
lines changed

compiler-cli/src/dependencies.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,12 @@ pub fn tree(paths: &ProjectPaths, options: TreeOptions) -> Result<()> {
8181
fn get_manifest_details(paths: &ProjectPaths) -> Result<(PackageConfig, Manifest)> {
8282
let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
8383
let config = crate::config::root_config(paths)?;
84+
let package_fetcher: Box<dyn dependency::PackageFetcher> =
85+
PackageFetcher::boxed(runtime.handle().clone());
8486
let (_, manifest) = get_manifest(
8587
paths,
8688
runtime.handle().clone(),
89+
&*package_fetcher,
8790
Mode::Dev,
8891
&config,
8992
&cli::Reporter::new(),
@@ -385,11 +388,14 @@ pub fn download<Telem: Telemetry>(
385388

386389
// Start event loop so we can run async functions to call the Hex API
387390
let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
391+
let package_fetcher: Box<dyn dependency::PackageFetcher> =
392+
PackageFetcher::boxed(runtime.handle().clone());
388393

389394
// Determine what versions we need
390395
let (manifest_updated, manifest) = get_manifest(
391396
paths,
392397
runtime.handle().clone(),
398+
&*package_fetcher,
393399
mode,
394400
&config,
395401
&telemetry,
@@ -419,9 +425,8 @@ pub fn download<Telem: Telemetry>(
419425
}
420426
LocalPackages::from_manifest(&manifest).write_to_disc(paths)?;
421427

422-
let package_fetcher = PackageFetcher::boxed(runtime.handle().clone());
423428
let major_versions_available =
424-
dependency::check_for_major_version_updates(&manifest, package_fetcher);
429+
dependency::check_for_major_version_updates(&manifest, &*package_fetcher);
425430
if !major_versions_available.is_empty() {
426431
eprintln!(
427432
"{}",
@@ -665,9 +670,10 @@ impl LocalPackages {
665670
}
666671
}
667672

668-
fn get_manifest<Telem: Telemetry>(
673+
fn get_manifest<'a, Telem: Telemetry>(
669674
paths: &ProjectPaths,
670675
runtime: tokio::runtime::Handle,
676+
package_fetcher: &'a dyn dependency::PackageFetcher,
671677
mode: Mode,
672678
config: &PackageConfig,
673679
telemetry: &Telem,
@@ -689,7 +695,16 @@ fn get_manifest<Telem: Telemetry>(
689695
};
690696

691697
if should_resolve {
692-
let manifest = resolve_versions(runtime, mode, paths, config, None, telemetry, Vec::new())?;
698+
let manifest = resolve_versions(
699+
runtime,
700+
package_fetcher,
701+
mode,
702+
paths,
703+
config,
704+
None,
705+
telemetry,
706+
Vec::new(),
707+
)?;
693708
return Ok((true, manifest));
694709
}
695710

@@ -710,6 +725,7 @@ fn get_manifest<Telem: Telemetry>(
710725
tracing::debug!("manifest_outdated");
711726
let manifest = resolve_versions(
712727
runtime,
728+
package_fetcher,
713729
mode,
714730
paths,
715731
config,
@@ -865,6 +881,7 @@ impl PartialEq for ProvidedPackageSource {
865881

866882
fn resolve_versions<Telem: Telemetry>(
867883
runtime: tokio::runtime::Handle,
884+
package_fetcher: &dyn dependency::PackageFetcher,
868885
mode: Mode,
869886
project_paths: &ProjectPaths,
870887
config: &PackageConfig,
@@ -916,7 +933,7 @@ fn resolve_versions<Telem: Telemetry>(
916933
.collect();
917934

918935
let resolved = dependency::resolve_versions(
919-
PackageFetcher::boxed(runtime.clone()),
936+
package_fetcher,
920937
provided_hex_packages,
921938
config.name.clone(),
922939
root_requirements.into_iter(),

compiler-core/src/dependency.rs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use hexpm::{
77
Dependency, Release,
88
version::{Range, ResolutionError, Version},
99
};
10-
use itertools::Itertools;
1110
use pubgrub::{
1211
solver::{Dependencies, choose_package_with_fewest_versions},
1312
type_aliases::Map,
@@ -18,7 +17,7 @@ pub type PackageVersions = HashMap<String, Version>;
1817
type PubgrubRange = pubgrub::range::Range<Version>;
1918

2019
pub fn resolve_versions<Requirements>(
21-
package_fetcher: Box<dyn PackageFetcher>,
20+
package_fetcher: &dyn PackageFetcher,
2221
provided_packages: HashMap<EcoString, hexpm::Package>,
2322
root_name: EcoString,
2423
dependencies: Requirements,
@@ -70,7 +69,7 @@ where
7069
pub type PackageVersionDiffs = HashMap<String, (Version, Version)>;
7170

7271
fn resolve_major_versions(
73-
package_fetcher: Box<dyn PackageFetcher>,
72+
package_fetcher: &dyn PackageFetcher,
7473
versions: PackageVersions,
7574
) -> PackageVersionDiffs {
7675
versions
@@ -100,20 +99,20 @@ fn resolve_major_versions(
10099
/// constraints.
101100
pub fn check_for_major_version_updates(
102101
manifest: &manifest::Manifest,
103-
package_fetcher: Box<dyn PackageFetcher>,
102+
package_fetcher: &dyn PackageFetcher,
104103
) -> HashMap<String, (Version, Version)> {
105104
// get the resolved versions of the direct dependencies to check for major
106105
// version updates.
107106
let versions = manifest
108107
.packages
109108
.iter()
110-
.map(|manifest_pkg| (manifest_pkg.name.to_string(), manifest_pkg.version.clone()))
111-
.filter(|(name, _)| {
109+
.filter(|manifest_package| {
112110
manifest
113111
.requirements
114112
.iter()
115-
.any(|(required_pkg, _)| name == required_pkg)
113+
.any(|(required_pkg, _)| manifest_package.name == *required_pkg)
116114
})
115+
.map(|manifest_pkg| (manifest_pkg.name.to_string(), manifest_pkg.version.clone()))
117116
.collect();
118117

119118
resolve_major_versions(package_fetcher, versions)
@@ -203,7 +202,7 @@ pub trait PackageFetcher {
203202

204203
struct DependencyProvider<'a> {
205204
packages: RefCell<HashMap<EcoString, hexpm::Package>>,
206-
remote: Box<dyn PackageFetcher>,
205+
remote: &'a dyn PackageFetcher,
207206
locked: &'a HashMap<EcoString, Version>,
208207
// Map of packages where an exact version was requested
209208
// We need this because by default pubgrub checks exact version by checking if a version is between the exact
@@ -214,7 +213,7 @@ struct DependencyProvider<'a> {
214213

215214
impl<'a> DependencyProvider<'a> {
216215
fn new(
217-
remote: Box<dyn PackageFetcher>,
216+
remote: &'a dyn PackageFetcher,
218217
mut packages: HashMap<EcoString, hexpm::Package>,
219218
root: hexpm::Package,
220219
locked: &'a HashMap<EcoString, Version>,
@@ -612,7 +611,7 @@ mod tests {
612611
fn resolution_with_locked() {
613612
let locked_stdlib = ("gleam_stdlib".into(), Version::parse("0.1.0").unwrap());
614613
let result = resolve_versions(
615-
make_remote(),
614+
&*make_remote(),
616615
HashMap::new(),
617616
"app".into(),
618617
vec![("gleam_stdlib".into(), Range::new("~> 0.1".into()))].into_iter(),
@@ -630,7 +629,7 @@ mod tests {
630629
#[test]
631630
fn resolution_without_deps() {
632631
let result = resolve_versions(
633-
make_remote(),
632+
&*make_remote(),
634633
HashMap::new(),
635634
"app".into(),
636635
vec![].into_iter(),
@@ -643,7 +642,7 @@ mod tests {
643642
#[test]
644643
fn resolution_1_dep() {
645644
let result = resolve_versions(
646-
make_remote(),
645+
&*make_remote(),
647646
HashMap::new(),
648647
"app".into(),
649648
vec![("gleam_stdlib".into(), Range::new("~> 0.1".into()))].into_iter(),
@@ -661,7 +660,7 @@ mod tests {
661660
#[test]
662661
fn resolution_with_nested_deps() {
663662
let result = resolve_versions(
664-
make_remote(),
663+
&*make_remote(),
665664
HashMap::new(),
666665
"app".into(),
667666
vec![("gleam_otp".into(), Range::new("~> 0.1".into()))].into_iter(),
@@ -682,7 +681,7 @@ mod tests {
682681
#[test]
683682
fn resolution_with_optional_deps() {
684683
let result = resolve_versions(
685-
make_remote(),
684+
&*make_remote(),
686685
HashMap::new(),
687686
"app".into(),
688687
vec![("package_with_optional".into(), Range::new("~> 0.1".into()))].into_iter(),
@@ -703,7 +702,7 @@ mod tests {
703702
#[test]
704703
fn resolution_with_optional_deps_explicitly_provided() {
705704
let result = resolve_versions(
706-
make_remote(),
705+
&*make_remote(),
707706
HashMap::new(),
708707
"app".into(),
709708
vec![
@@ -731,7 +730,7 @@ mod tests {
731730
#[test]
732731
fn resolution_with_optional_deps_incompatible() {
733732
let result = resolve_versions(
734-
make_remote(),
733+
&*make_remote(),
735734
HashMap::new(),
736735
"app".into(),
737736
vec![
@@ -747,7 +746,7 @@ mod tests {
747746
#[test]
748747
fn resolution_with_optional_deps_required_by_nested_deps() {
749748
let result = resolve_versions(
750-
make_remote(),
749+
&*make_remote(),
751750
HashMap::new(),
752751
"app".into(),
753752
vec![
@@ -779,7 +778,7 @@ mod tests {
779778
#[test]
780779
fn resolution_locked_to_older_version() {
781780
let result = resolve_versions(
782-
make_remote(),
781+
&*make_remote(),
783782
HashMap::new(),
784783
"app".into(),
785784
vec![("gleam_otp".into(), Range::new("~> 0.1.0".into()))].into_iter(),
@@ -800,7 +799,7 @@ mod tests {
800799
#[test]
801800
fn resolution_retired_versions_not_used_by_default() {
802801
let result = resolve_versions(
803-
make_remote(),
802+
&*make_remote(),
804803
HashMap::new(),
805804
"app".into(),
806805
vec![("package_with_retired".into(), Range::new("> 0.0.0".into()))].into_iter(),
@@ -822,7 +821,7 @@ mod tests {
822821
#[test]
823822
fn resolution_retired_versions_can_be_used_if_locked() {
824823
let result = resolve_versions(
825-
make_remote(),
824+
&*make_remote(),
826825
HashMap::new(),
827826
"app".into(),
828827
vec![("package_with_retired".into(), Range::new("> 0.0.0".into()))].into_iter(),
@@ -846,7 +845,7 @@ mod tests {
846845
#[test]
847846
fn resolution_prerelease_can_be_selected() {
848847
let result = resolve_versions(
849-
make_remote(),
848+
&*make_remote(),
850849
HashMap::new(),
851850
"app".into(),
852851
vec![("gleam_otp".into(), Range::new("~> 0.3.0-rc1".into()))].into_iter(),
@@ -867,7 +866,7 @@ mod tests {
867866
#[test]
868867
fn resolution_exact_prerelease_can_be_selected() {
869868
let result = resolve_versions(
870-
make_remote(),
869+
&*make_remote(),
871870
HashMap::new(),
872871
"app".into(),
873872
vec![("gleam_otp".into(), Range::new("0.3.0-rc1".into()))].into_iter(),
@@ -888,7 +887,7 @@ mod tests {
888887
#[test]
889888
fn resolution_not_found_dep() {
890889
let _ = resolve_versions(
891-
make_remote(),
890+
&*make_remote(),
892891
HashMap::new(),
893892
"app".into(),
894893
vec![("unknown".into(), Range::new("~> 0.1".into()))].into_iter(),
@@ -900,7 +899,7 @@ mod tests {
900899
#[test]
901900
fn resolution_no_matching_version() {
902901
let _ = resolve_versions(
903-
make_remote(),
902+
&*make_remote(),
904903
HashMap::new(),
905904
"app".into(),
906905
vec![("gleam_stdlib".into(), Range::new("~> 99.0".into()))].into_iter(),
@@ -912,7 +911,7 @@ mod tests {
912911
#[test]
913912
fn resolution_locked_version_doesnt_satisfy_requirements() {
914913
let err = resolve_versions(
915-
make_remote(),
914+
&*make_remote(),
916915
HashMap::new(),
917916
"app".into(),
918917
vec![("gleam_stdlib".into(), Range::new("~> 0.1.0".into()))].into_iter(),
@@ -934,7 +933,7 @@ mod tests {
934933
#[test]
935934
fn resolution_with_exact_dep() {
936935
let result = resolve_versions(
937-
make_remote(),
936+
&*make_remote(),
938937
HashMap::new(),
939938
"app".into(),
940939
vec![("gleam_stdlib".into(), Range::new("0.1.0".into()))].into_iter(),
@@ -1035,7 +1034,7 @@ mod tests {
10351034
},
10361035
],
10371036
};
1038-
let result = check_for_major_version_updates(&manifest, make_remote());
1037+
let result = check_for_major_version_updates(&manifest, &*make_remote());
10391038

10401039
// indirect package with major version will not be in the result even though a major
10411040
// version of it is available

0 commit comments

Comments
 (0)