1+ mod dependency_manager;
2+
13use std:: {
24 cell:: RefCell ,
35 collections:: { HashMap , HashSet } ,
@@ -9,7 +11,6 @@ use std::{
911use camino:: { Utf8Path , Utf8PathBuf } ;
1012use ecow:: { EcoString , eco_format} ;
1113use flate2:: read:: GzDecoder ;
12- use futures:: future;
1314use gleam_core:: {
1415 Error , Result ,
1516 build:: { Mode , Target , Telemetry } ,
@@ -27,6 +28,8 @@ use itertools::Itertools;
2728use same_file:: is_same_file;
2829use strum:: IntoEnumIterator ;
2930
31+ pub use dependency_manager:: DependencyManagerConfig ;
32+
3033#[ cfg( test) ]
3134mod tests;
3235
@@ -648,237 +651,6 @@ fn same_requirements(
648651 Ok ( left == right)
649652}
650653
651- pub struct DependencyManagerConfig {
652- // If `Yes` we read the manifest from disc. If not set then we ignore any
653- // manifest which will result in the latest versions of the dependency
654- // packages being resolved (not the locked ones).
655- pub use_manifest : UseManifest ,
656- /// When set to `Yes`, the cli will check for major version updates of direct dependencies and
657- /// print them to the console if the major versions are not upgradeable due to constraints.
658- pub check_major_versions : CheckMajorVersions ,
659- }
660-
661- impl DependencyManagerConfig {
662- fn into_dependency_manager < Telem : Telemetry , P : dependency:: PackageFetcher > (
663- self ,
664- runtime : tokio:: runtime:: Handle ,
665- package_fetcher : P ,
666- telemetry : Telem ,
667- mode : Mode ,
668- ) -> DependencyManager < Telem , P > {
669- DependencyManager {
670- runtime,
671- package_fetcher,
672- telemetry,
673-
674- mode,
675- use_manifest : self . use_manifest ,
676- check_major_versions : self . check_major_versions ,
677- }
678- }
679- }
680-
681- struct DependencyManager < Telem , P > {
682- runtime : tokio:: runtime:: Handle ,
683- package_fetcher : P ,
684- mode : Mode ,
685- use_manifest : UseManifest ,
686- telemetry : Telem ,
687- check_major_versions : CheckMajorVersions ,
688- }
689-
690- impl < Telem , P > DependencyManager < Telem , P >
691- where
692- P : dependency:: PackageFetcher ,
693- Telem : Telemetry ,
694- {
695- fn get_manifest (
696- & self ,
697- paths : & ProjectPaths ,
698- config : & PackageConfig ,
699- packages_to_update : Vec < EcoString > ,
700- ) -> Result < ( bool , Manifest ) > {
701- // If there's no manifest (or we have been asked not to use it) then resolve
702- // the versions anew
703- let should_resolve = match self . use_manifest {
704- _ if !paths. manifest ( ) . exists ( ) => {
705- tracing:: debug!( "manifest_not_present" ) ;
706- true
707- }
708- UseManifest :: No => {
709- tracing:: debug!( "ignoring_manifest" ) ;
710- true
711- }
712- UseManifest :: Yes => false ,
713- } ;
714-
715- if should_resolve {
716- let manifest = self . resolve_versions ( paths, config, None , Vec :: new ( ) ) ?;
717- return Ok ( ( true , manifest) ) ;
718- }
719-
720- let manifest = read_manifest_from_disc ( paths) ?;
721-
722- // If there are no requested updates, and the config is unchanged
723- // since the manifest was written then it is up to date so we can return it unmodified.
724- if packages_to_update. is_empty ( )
725- && is_same_requirements (
726- & manifest. requirements ,
727- & config. all_direct_dependencies ( ) ?,
728- paths. root ( ) ,
729- ) ?
730- {
731- tracing:: debug!( "manifest_up_to_date" ) ;
732- Ok ( ( false , manifest) )
733- } else {
734- tracing:: debug!( "manifest_outdated" ) ;
735- let manifest =
736- self . resolve_versions ( paths, config, Some ( & manifest) , packages_to_update) ?;
737- Ok ( ( true , manifest) )
738- }
739- }
740-
741- fn download (
742- & self ,
743- paths : & ProjectPaths ,
744- new_package : Option < ( Vec < ( EcoString , Requirement ) > , bool ) > ,
745- packages_to_update : Vec < EcoString > ,
746- ) -> Result < Manifest > {
747- let span = tracing:: info_span!( "download_deps" ) ;
748- let _enter = span. enter ( ) ;
749-
750- // We do this before acquiring the build lock so that we don't create the
751- // build directory if there is no gleam.toml
752- crate :: config:: ensure_config_exists ( paths) ?;
753-
754- let lock = BuildLock :: new_packages ( paths) ?;
755- let _guard = lock. lock ( & self . telemetry ) ;
756-
757- let fs = ProjectIO :: boxed ( ) ;
758-
759- // Read the project config
760- let mut config = crate :: config:: read ( paths. root_config ( ) ) ?;
761- let project_name = config. name . clone ( ) ;
762-
763- // Insert the new packages to add, if it exists
764- if let Some ( ( packages, dev) ) = new_package {
765- for ( package, requirement) in packages {
766- if dev {
767- _ = config. dev_dependencies . insert ( package, requirement) ;
768- } else {
769- _ = config. dependencies . insert ( package, requirement) ;
770- } ;
771- }
772- }
773-
774- // Determine what versions we need
775- let ( manifest_updated, manifest) = self . get_manifest ( paths, & config, packages_to_update) ?;
776- let local = LocalPackages :: read_from_disc ( paths) ?;
777-
778- // Remove any packages that are no longer required due to gleam.toml changes
779- remove_extra_packages ( paths, & local, & manifest, & self . telemetry ) ?;
780-
781- // Download them from Hex to the local cache
782- self . runtime . block_on ( add_missing_packages (
783- paths,
784- fs,
785- & manifest,
786- & local,
787- project_name,
788- & self . telemetry ,
789- ) ) ?;
790-
791- if manifest_updated {
792- // Record new state of the packages directory
793- // TODO: test
794- tracing:: debug!( "writing_manifest_toml" ) ;
795- write_manifest_to_disc ( paths, & manifest) ?;
796- }
797- LocalPackages :: from_manifest ( & manifest) . write_to_disc ( paths) ?;
798-
799- if let CheckMajorVersions :: Yes = self . check_major_versions {
800- let major_versions_available =
801- dependency:: check_for_major_version_updates ( & manifest, & self . package_fetcher ) ;
802- if !major_versions_available. is_empty ( ) {
803- eprintln ! (
804- "{}" ,
805- pretty_print_major_versions_available( major_versions_available)
806- ) ;
807- }
808- }
809-
810- Ok ( manifest)
811- }
812-
813- fn resolve_versions (
814- & self ,
815- project_paths : & ProjectPaths ,
816- config : & PackageConfig ,
817- manifest : Option < & Manifest > ,
818- packages_to_update : Vec < EcoString > ,
819- ) -> Result < Manifest , Error > {
820- self . telemetry . resolving_package_versions ( ) ;
821- let dependencies = config. dependencies_for ( self . mode ) ?;
822- let mut locked = config. locked ( manifest) ?;
823-
824- if !packages_to_update. is_empty ( ) {
825- unlock_packages ( & mut locked, & packages_to_update, manifest) ?;
826- }
827-
828- // Packages which are provided directly instead of downloaded from hex
829- let mut provided_packages = HashMap :: new ( ) ;
830- // The version requires of the current project
831- let mut root_requirements = HashMap :: new ( ) ;
832-
833- // Populate the provided_packages and root_requirements maps
834- for ( name, requirement) in dependencies. into_iter ( ) {
835- let version = match requirement {
836- Requirement :: Hex { version } => version,
837- Requirement :: Path { path } => provide_local_package (
838- name. clone ( ) ,
839- & path,
840- project_paths. root ( ) ,
841- project_paths,
842- & mut provided_packages,
843- & mut vec ! [ ] ,
844- ) ?,
845- Requirement :: Git { git } => {
846- provide_git_package ( name. clone ( ) , & git, project_paths, & mut provided_packages) ?
847- }
848- } ;
849- let _ = root_requirements. insert ( name, version) ;
850- }
851-
852- // Convert provided packages into hex packages for pub-grub resolve
853- let provided_hex_packages = provided_packages
854- . iter ( )
855- . map ( |( name, package) | ( name. clone ( ) , package. to_hex_package ( name) ) )
856- . collect ( ) ;
857-
858- let resolved = dependency:: resolve_versions (
859- & self . package_fetcher ,
860- provided_hex_packages,
861- config. name . clone ( ) ,
862- root_requirements. into_iter ( ) ,
863- & locked,
864- ) ?;
865-
866- // Convert the hex packages and local packages into manifest packages
867- let manifest_packages = self . runtime . block_on ( future:: try_join_all (
868- resolved
869- . into_iter ( )
870- . map ( |( name, version) | lookup_package ( name, version, & provided_packages) ) ,
871- ) ) ?;
872-
873- let manifest = Manifest {
874- packages : manifest_packages,
875- requirements : config. all_direct_dependencies ( ) ?,
876- } ;
877-
878- Ok ( manifest)
879- }
880- }
881-
882654#[ derive( Clone , Eq , PartialEq , Debug ) ]
883655struct ProvidedPackage {
884656 version : Version ,
0 commit comments