@@ -3,24 +3,69 @@ use std::{
33 path:: PathBuf ,
44} ;
55
6- use anyhow:: { bail, Context as _, Result } ;
6+ use anyhow:: { anyhow , bail, Context as _, Error , Result } ;
77use clap:: Args ;
8+ use std:: borrow:: Cow ;
9+ use std:: str:: FromStr ;
810use wac_graph:: { CompositionGraph , EncodeOptions , NodeId , PackageId } ;
911use wac_types:: { Package , SubtypeChecker } ;
1012
13+ #[ cfg( feature = "registry" ) ]
14+ use warg_client:: FileSystemClient ;
15+
16+ #[ cfg( feature = "registry" ) ]
17+ use warg_protocol:: registry:: PackageName ;
18+
19+ /// The package path or registry package name.
20+ #[ derive( Clone , Debug ) ]
21+ pub enum PackageRef {
22+ /// The local file path to the component.
23+ LocalPath ( PathBuf ) ,
24+ /// The registry package name.
25+ #[ cfg( feature = "registry" ) ]
26+ RegistryPackage ( PackageName ) , // TODO handle package versions
27+ }
28+
29+ impl FromStr for PackageRef {
30+ type Err = Error ;
31+
32+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
33+ if cfg ! ( not( feature = "registry" ) ) {
34+ return Ok ( Self :: LocalPath ( PathBuf :: from ( s) ) ) ;
35+ }
36+
37+ #[ cfg( feature = "registry" ) ]
38+ if let Ok ( package_name) = PackageName :: new ( s) {
39+ // only `namespace:package-name` without file extensions is valid
40+ Ok ( Self :: RegistryPackage ( package_name) )
41+ } else {
42+ Ok ( Self :: LocalPath ( PathBuf :: from ( s) ) )
43+ }
44+ }
45+ }
46+
47+ impl std:: fmt:: Display for PackageRef {
48+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
49+ match self {
50+ Self :: LocalPath ( path) => write ! ( f, "{}" , path. display( ) ) ,
51+ Self :: RegistryPackage ( name) => write ! ( f, "{}" , name) ,
52+ }
53+ }
54+ }
55+
1156/// Plugs the exports of any number of 'plug' components into the imports of a 'socket' component.
1257#[ derive( Args ) ]
1358#[ clap( disable_version_flag = true ) ]
1459pub struct PlugCommand {
15- /// The path to the plug component.
60+ /// The local path to the plug component or the registry package name .
1661 ///
1762 /// More than one plug can be supplied.
1863 #[ clap( long = "plug" , value_name = "PLUG_PATH" , required = true ) ]
19- pub plugs : Vec < PathBuf > ,
64+ pub plugs : Vec < PackageRef > ,
2065
21- /// The path to the socket component
66+ /// The local path to the socket component or the registry package name.
2267 #[ clap( value_name = "SOCKET_PATH" , required = true ) ]
23- pub socket : PathBuf ,
68+ pub socket : PackageRef ,
2469
2570 /// Whether to emit the WebAssembly text format.
2671 #[ clap( long, short = 't' ) ]
@@ -31,6 +76,11 @@ pub struct PlugCommand {
3176 /// If not specified, the output will be written to stdout.
3277 #[ clap( long, short = 'o' ) ]
3378 pub output : Option < PathBuf > ,
79+
80+ /// The URL of the registry to use.
81+ #[ cfg( feature = "registry" ) ]
82+ #[ clap( long, value_name = "URL" ) ]
83+ pub registry : Option < String > ,
3484}
3585
3686impl PlugCommand {
@@ -39,10 +89,28 @@ impl PlugCommand {
3989 log:: debug!( "executing plug command" ) ;
4090 let mut graph = CompositionGraph :: new ( ) ;
4191
42- let socket = std:: fs:: read ( & self . socket ) . with_context ( || {
92+ #[ cfg( feature = "registry" ) ]
93+ let client = FileSystemClient :: new_with_default_config ( self . registry . as_deref ( ) ) . ok ( ) ;
94+
95+ let socket_path = match & self . socket {
96+ #[ cfg( feature = "registry" ) ]
97+ PackageRef :: RegistryPackage ( name) => {
98+ client
99+ . as_ref ( )
100+ . ok_or_else ( || {
101+ anyhow ! ( "Warg registry is not configured. Package `{name}` was not found." )
102+ } ) ?
103+ . download ( name, & semver:: VersionReq :: STAR )
104+ . await ?
105+ . ok_or_else ( || anyhow ! ( "package `{name}` was not found" ) ) ?
106+ . path
107+ }
108+ PackageRef :: LocalPath ( path) => path. clone ( ) ,
109+ } ;
110+ let socket = std:: fs:: read ( & socket_path) . with_context ( || {
43111 format ! (
44- "failed to read socket component `{path }`" ,
45- path = self . socket. display ( )
112+ "failed to read socket component `{socket }`" ,
113+ socket = self . socket
46114 )
47115 } ) ?;
48116
@@ -53,24 +121,40 @@ impl PlugCommand {
53121 // Collect the plugs by their names
54122 let mut plugs_by_name = std:: collections:: HashMap :: < _ , Vec < _ > > :: new ( ) ;
55123 for plug in self . plugs . iter ( ) {
56- let name = plug
57- . file_stem ( )
58- . map ( |fs| fs. to_string_lossy ( ) )
59- . with_context ( || format ! ( "path to plug '{}' was not a file" , plug. display( ) ) ) ?;
124+ let name = match plug {
125+ PackageRef :: RegistryPackage ( name) => Cow :: Borrowed ( name. as_ref ( ) ) ,
126+ PackageRef :: LocalPath ( path) => path
127+ . file_stem ( )
128+ . map ( |fs| fs. to_string_lossy ( ) )
129+ . with_context ( || format ! ( "path to plug '{}' was not a file" , plug) ) ?,
130+ } ;
131+
60132 // TODO(rylev): sanitize the name to ensure it's a valid package identifier.
61133 plugs_by_name. entry ( name) . or_default ( ) . push ( plug) ;
62134 }
63135
64136 // Plug each plug into the socket.
65- for ( name, plug_paths) in plugs_by_name {
66- for ( i, plug_path) in plug_paths. iter ( ) . enumerate ( ) {
67- let mut name = format ! ( "plug:{name}" ) ;
137+ for ( name, plug_refs) in plugs_by_name {
138+ for ( i, plug_ref) in plug_refs. iter ( ) . enumerate ( ) {
139+ let ( mut name, path) = match plug_ref {
140+ PackageRef :: RegistryPackage ( name) => (
141+ name. as_ref ( ) . to_string ( ) ,
142+ client
143+ . as_ref ( )
144+ . ok_or_else ( || anyhow ! ( "Warg registry is not configured. Package `{name}` was not found." ) ) ?
145+ . download ( name, & semver:: VersionReq :: STAR )
146+ . await ?
147+ . ok_or_else ( || anyhow ! ( "package `{name}` was not found" ) ) ?
148+ . path ,
149+ ) ,
150+ PackageRef :: LocalPath ( path) => ( format ! ( "plug:{name}" ) , path. clone ( ) ) ,
151+ } ;
68152 // If there's more than one plug with the same name, append an index to the name.
69- if plug_paths . len ( ) > 1 {
153+ if plug_refs . len ( ) > 1 {
70154 use core:: fmt:: Write ;
71155 write ! ( & mut name, "{i}" ) . unwrap ( ) ;
72156 }
73- plug_into_socket ( & name, plug_path , socket, socket_instantiation, & mut graph) ?;
157+ plug_into_socket ( & name, & path , socket, socket_instantiation, & mut graph) ?;
74158 }
75159 }
76160
0 commit comments