@@ -885,12 +885,20 @@ impl PublishPlan {
885885
886886 if neighbors. peek ( ) . is_none ( ) {
887887 // tracing::debug!("{dep} has no dependents");
888- println ! ( "{dep} has no dependents" ) ;
888+ println ! ( "[{dep} has no dependents]" ) ;
889+ } else {
890+ println ! ( "[{dep}]" ) ;
889891 }
890892
891893 while let Some ( id) = neighbors. next ( ) {
892894 let pkg = & self . dependents [ id] ;
893- println ! ( "{dep} -(DependencyOF)-> {pkg}" ) ;
895+ let separator = if neighbors. peek ( ) . is_some ( ) {
896+ "├─"
897+ } else {
898+ "╰─"
899+ } ;
900+
901+ println ! ( "{separator}(DependencyOf)─▶ {pkg}" ) ;
894902 }
895903
896904 dep
@@ -912,12 +920,13 @@ impl PublishPlan {
912920 self . dependents
913921 . nodes_iter ( )
914922 // there are no dependents on `self.dendents[id]`
915- . filter ( |id| self . dependents . neighbors ( * id ) . count ( ) == 0 )
916- . map ( |id| {
917- let pkg = & self . dependents [ id ] ;
918- self . indices . remove ( & pkg . package ) ;
919- pkg . clone ( )
923+ . filter ( |id| {
924+ self . dependents
925+ . neighbors_directed ( * id , Direction :: Incoming )
926+ . count ( )
927+ == 0
920928 } )
929+ . map ( |id| self . dependents [ id] . clone ( ) )
921930 . collect ( )
922931 }
923932
@@ -928,15 +937,37 @@ impl PublishPlan {
928937
929938 /// Packages confirmed to be available in the registry, potentially allowing additional
930939 /// packages to be "ready".
931- pub fn mark_confirmed ( & mut self , published : impl IntoIterator < Item = PackageRef > ) {
932- for pkg in published {
940+ pub fn mark_confirmed ( & mut self , published : impl IntoIterator < Item = PackageSpec > ) {
941+ for spec in published {
933942 let ( id, _) = self
934943 . indices
935- . remove ( & pkg )
944+ . remove ( & spec . package )
936945 . expect ( "PackageSpec has no associated index" ) ;
937- self . dependents
938- . remove_node ( id)
939- . expect ( "index has no associated PackageSpec" ) ;
946+ // NOTE: nodes without edges will return None here
947+ self . dependents . remove_node ( id) ;
948+ }
949+ }
950+ }
951+
952+ /// Format a collection of packages as a list
953+ ///
954+ /// e.g. "foo:a@0.1.0, bar:b@0.2.0, and baz:c@0.3.0".
955+ ///
956+ /// Note: the final separator (e.g. "and" in the previous example) can be chosen.
957+ pub fn package_list < ' a > (
958+ pkgs : impl IntoIterator < Item = & ' a PackageSpec > ,
959+ final_sep : Option < & str > ,
960+ ) -> String {
961+ let final_sep = final_sep. unwrap_or ( "and" ) ;
962+ let mut names: Vec < _ > = pkgs. into_iter ( ) . map ( |pkg| pkg. to_string ( ) ) . collect ( ) ;
963+ names. sort ( ) ;
964+
965+ match & names[ ..] {
966+ [ ] => String :: new ( ) ,
967+ [ a] => a. clone ( ) ,
968+ [ a, b] => format ! ( "{a} {final_sep} {b}" ) ,
969+ [ names @ .., last] => {
970+ format ! ( "{}, {final_sep} {last}" , names. join( ", " ) )
940971 }
941972 }
942973}
@@ -946,69 +977,57 @@ mod tests {
946977 use std:: collections:: HashSet ;
947978 use std:: path:: PathBuf ;
948979
949- use super :: PublishPlan ;
980+ use super :: * ;
981+ use glob:: glob;
950982 use wasm_pkg_client:: PackageRef ;
951983
952984 fn transitive_local_paths ( ) -> Vec < PathBuf > {
953- let fixtures =
954- PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "tests/fixtures/transitive-local" ) ;
955- [ "example-a" , "example-b" , "example-c" ]
985+ let fixtures = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) )
986+ . join ( "tests/fixtures/transitive-local/*/wit/" ) ;
987+ glob ( fixtures. to_str ( ) . unwrap ( ) )
988+ . unwrap ( )
956989 . into_iter ( )
957- . map ( |name| fixtures . join ( name ) . join ( "wit ") )
990+ . map ( |p| p . expect ( "glob path error ") )
958991 . collect ( )
959992 }
960993
961994 #[ test]
962- fn publish_plan_from_paths_collects_all_packages ( ) {
995+ fn publish_plan_iter ( ) {
963996 let paths = transitive_local_paths ( ) ;
964- let plan = PublishPlan :: from_paths ( & paths) . expect ( "plan should build" ) ;
965-
966- assert ! ( !plan. is_empty( ) ) ;
967- assert_eq ! ( plan. len( ) , 3 ) ;
968-
969- for name in [ "example-a:foo" , "example-b:bar" , "example-c:baz" ] {
970- let pkg: PackageRef = name. parse ( ) . expect ( "valid package ref" ) ;
971- assert ! (
972- plan. get_path( & pkg) . is_some( ) ,
973- "expected `{name}` to have an associated path in the plan" ,
974- ) ;
975- }
997+ let plan = PublishPlan :: from_paths ( & paths) . unwrap ( ) ;
998+ assert_eq ! (
999+ plan. iter( ) . count( ) ,
1000+ 4 ,
1001+ "unexpected package count\n packages found: {}" ,
1002+ package_list( plan. iter( ) , None )
1003+ ) ;
9761004 }
9771005
9781006 #[ test]
979- fn publish_plan_iter_yields_each_package_once ( ) {
1007+ fn publish_plan_chunks ( ) {
9801008 let paths = transitive_local_paths ( ) ;
981- let plan = PublishPlan :: from_paths ( & paths) . expect ( "plan should build" ) ;
982-
983- let seen: Vec < PackageRef > = plan. iter ( ) . map ( |spec| spec. package . clone ( ) ) . collect ( ) ;
984- assert_eq ! ( seen. len( ) , 3 , "iter should yield one entry per package" ) ;
985-
986- let unique: HashSet < _ > = seen. iter ( ) . cloned ( ) . collect ( ) ;
987- assert_eq ! ( unique. len( ) , seen. len( ) , "iter must not yield duplicates" ) ;
988-
989- let expected: HashSet < PackageRef > = [ "example-a:foo" , "example-b:bar" , "example-c:baz" ]
990- . into_iter ( )
991- . map ( |s| s. parse ( ) . unwrap ( ) )
992- . collect ( ) ;
993- assert_eq ! ( unique, expected) ;
994- }
995- }
996-
997- /// Format a collection of packages as a list
998- ///
999- /// e.g. "foo:a@0.1.0, bar:b@0.2.0, and baz:c@0.3.0".
1000- ///
1001- /// Note: the final separator (e.g. "and" in the previous example) can be chosen.
1002- pub fn package_list ( pkgs : impl IntoIterator < Item = PackageSpec > , final_sep : & str ) -> String {
1003- let mut names: Vec < _ > = pkgs. into_iter ( ) . map ( |pkg| pkg. to_string ( ) ) . collect ( ) ;
1004- names. sort ( ) ;
1005-
1006- match & names[ ..] {
1007- [ ] => String :: new ( ) ,
1008- [ a] => a. clone ( ) ,
1009- [ a, b] => format ! ( "{a} {final_sep} {b}" ) ,
1010- [ names @ .., last] => {
1011- format ! ( "{}, {final_sep} {last}" , names. join( ", " ) )
1012- }
1009+ let mut plan = PublishPlan :: from_paths ( & paths) . unwrap ( ) ;
1010+ let mut ready_for_publish = plan. take_ready ( ) ;
1011+ assert_eq ! (
1012+ ready_for_publish. iter( ) . collect:: <Vec <_>>( ) ,
1013+ [ "example-c:baz@0.1.0" , "example-d:foo@0.1.0" ] ,
1014+ ) ;
1015+ plan. mark_confirmed ( ready_for_publish. into_iter ( ) ) ;
1016+
1017+ ready_for_publish = plan. take_ready ( ) ;
1018+ assert_eq ! (
1019+ ready_for_publish. iter( ) . collect:: <Vec <_>>( ) ,
1020+ [ "example-b:bar@0.1.0" ] ,
1021+ ) ;
1022+ plan. mark_confirmed ( ready_for_publish. into_iter ( ) ) ;
1023+
1024+ ready_for_publish = plan. take_ready ( ) ;
1025+ assert_eq ! (
1026+ ready_for_publish. iter( ) . collect:: <Vec <_>>( ) ,
1027+ [ "example-a:foo@0.1.0" ] ,
1028+ ) ;
1029+ plan. mark_confirmed ( ready_for_publish. into_iter ( ) ) ;
1030+
1031+ assert ! ( plan. is_empty( ) ) ;
10131032 }
10141033}
0 commit comments