|
63 | 63 | Ok(packages) |
64 | 64 | } |
65 | 65 |
|
| 66 | +/** |
| 67 | +* This is a preliminary implementation to get to first implementation. |
| 68 | +* It is unoptimal as it makes a request for each hex package. |
| 69 | +* Alternative is to create a package config with all direct dependencies |
| 70 | +* with "*" but I'm not sure if we will get correct resolution that way as |
| 71 | +* dependencies might cause the package to not return the latest major version. |
| 72 | +*/ |
| 73 | +fn resolve_major_versions( |
| 74 | + package_fetcher: Box<dyn PackageFetcher>, |
| 75 | + versions: PackageVersions, |
| 76 | +) -> Result<PackageVersions> { |
| 77 | + versions |
| 78 | + .iter() |
| 79 | + .map(|(package, version)| { |
| 80 | + // TODO: find out best error type for this operation |
| 81 | + let Ok(hexpackage) = package_fetcher.get_dependencies(package) else { |
| 82 | + return Err(Error::Hex( |
| 83 | + "Unable to retrieve package information".to_string(), |
| 84 | + )); |
| 85 | + }; |
| 86 | + |
| 87 | + let Some(latest) = &hexpackage |
| 88 | + .releases |
| 89 | + .last() |
| 90 | + .map(|release| release.version.clone()) |
| 91 | + else { |
| 92 | + return Err(Error::Hex("No releases available for package".to_string())); |
| 93 | + }; |
| 94 | + |
| 95 | + if latest.major > version.major { |
| 96 | + Ok((package.to_string(), latest.clone())) |
| 97 | + } else { |
| 98 | + Ok((package.to_string(), version.clone())) |
| 99 | + } |
| 100 | + }) |
| 101 | + .collect() |
| 102 | +} |
| 103 | + |
66 | 104 | // If the string would parse to an exact version then return the version |
67 | 105 | fn parse_exact_version(ver: &str) -> Option<Version> { |
68 | 106 | let version = ver.trim(); |
@@ -471,6 +509,88 @@ mod tests { |
471 | 509 | }, |
472 | 510 | ); |
473 | 511 |
|
| 512 | + let _ = deps.insert( |
| 513 | + "core_package".into(), |
| 514 | + hexpm::Package { |
| 515 | + name: "core_package".into(), |
| 516 | + repository: "hexpm".into(), |
| 517 | + releases: vec![ |
| 518 | + Release { |
| 519 | + version: Version::try_from("0.1.0").unwrap(), |
| 520 | + requirements: [( |
| 521 | + "gleam_stdlib".into(), |
| 522 | + Dependency { |
| 523 | + app: None, |
| 524 | + optional: true, |
| 525 | + repository: None, |
| 526 | + requirement: Range::new(">= 0.1.0 and < 0.3.0".into()), |
| 527 | + }, |
| 528 | + )] |
| 529 | + .into(), |
| 530 | + retirement_status: None, |
| 531 | + outer_checksum: vec![1, 2, 3], |
| 532 | + meta: (), |
| 533 | + }, |
| 534 | + Release { |
| 535 | + version: Version::try_from("1.0.0").unwrap(), |
| 536 | + requirements: [( |
| 537 | + "gleam_stdlib".into(), |
| 538 | + Dependency { |
| 539 | + app: None, |
| 540 | + optional: true, |
| 541 | + repository: None, |
| 542 | + requirement: Range::new(">= 0.1.0 and < 0.3.0".into()), |
| 543 | + }, |
| 544 | + )] |
| 545 | + .into(), |
| 546 | + retirement_status: None, |
| 547 | + outer_checksum: vec![1, 2, 3], |
| 548 | + meta: (), |
| 549 | + }, |
| 550 | + Release { |
| 551 | + version: Version::try_from("1.1.0").unwrap(), |
| 552 | + requirements: [( |
| 553 | + "gleam_stdlib".into(), |
| 554 | + Dependency { |
| 555 | + app: None, |
| 556 | + optional: true, |
| 557 | + repository: None, |
| 558 | + requirement: Range::new(">= 0.1.0 and < 0.3.0".into()), |
| 559 | + }, |
| 560 | + )] |
| 561 | + .into(), |
| 562 | + retirement_status: None, |
| 563 | + outer_checksum: vec![1, 2, 3], |
| 564 | + meta: (), |
| 565 | + }, |
| 566 | + ], |
| 567 | + }, |
| 568 | + ); |
| 569 | + |
| 570 | + let _ = deps.insert( |
| 571 | + "package_depends_on_core".into(), |
| 572 | + hexpm::Package { |
| 573 | + name: "package_depends_on_core".into(), |
| 574 | + repository: "hexpm".into(), |
| 575 | + releases: vec![Release { |
| 576 | + version: Version::try_from("0.1.0").unwrap(), |
| 577 | + requirements: [( |
| 578 | + "core_package".into(), |
| 579 | + Dependency { |
| 580 | + app: None, |
| 581 | + optional: true, |
| 582 | + repository: None, |
| 583 | + requirement: Range::new(">= 0.1.0 and < 1.0.0".into()), |
| 584 | + }, |
| 585 | + )] |
| 586 | + .into(), |
| 587 | + retirement_status: None, |
| 588 | + outer_checksum: vec![1, 2, 3], |
| 589 | + meta: (), |
| 590 | + }], |
| 591 | + }, |
| 592 | + ); |
| 593 | + |
474 | 594 | Box::new(Remote { deps }) |
475 | 595 | } |
476 | 596 |
|
@@ -832,4 +952,34 @@ mod tests { |
832 | 952 | assert_eq!(parse_exact_version("~> 1.0.0"), None); |
833 | 953 | assert_eq!(parse_exact_version(">= 1.0.0"), None); |
834 | 954 | } |
| 955 | + |
| 956 | + #[test] |
| 957 | + fn resolve_major_version_upgrades() { |
| 958 | + let result = resolve_major_versions( |
| 959 | + make_remote(), |
| 960 | + vec![ |
| 961 | + ("core_package".into(), Version::try_from("0.1.0").unwrap()), |
| 962 | + ( |
| 963 | + "package_depends_on_core".into(), |
| 964 | + Version::try_from("0.1.0").unwrap(), |
| 965 | + ), |
| 966 | + ] |
| 967 | + .into_iter() |
| 968 | + .collect(), |
| 969 | + ) |
| 970 | + .unwrap(); |
| 971 | + |
| 972 | + assert_eq!( |
| 973 | + result, |
| 974 | + vec![ |
| 975 | + ("core_package".into(), Version::try_from("1.1.0").unwrap()), |
| 976 | + ( |
| 977 | + "package_depends_on_core".into(), |
| 978 | + Version::try_from("0.1.0").unwrap() |
| 979 | + ) |
| 980 | + ] |
| 981 | + .into_iter() |
| 982 | + .collect() |
| 983 | + ); |
| 984 | + } |
835 | 985 | } |
0 commit comments