@@ -6,19 +6,35 @@ const MAX_PACKAGE_FILES: usize = 1000;
66const MAX_PACKAGE_FILE_BYTES : u64 = 16 * 1024 * 1024 ;
77const MAX_PACKAGE_TOTAL_BYTES : u64 = 64 * 1024 * 1024 ;
88
9+ include ! ( "package_release.rs" ) ;
10+
911fn prepare_package_entrypoint_from_arg (
1012 runtime_root : & Path ,
1113 source : & Path ,
1214) -> Result < PathBuf , String > {
1315 let source_text = source. to_string_lossy ( ) ;
14- let package_path = if is_package_url ( & source_text) {
15- download_package_url ( runtime_root, & source_text) ?
16+ let source_url = if is_package_url ( & source_text) {
17+ Some ( source_text. to_string ( ) )
18+ } else {
19+ None
20+ } ;
21+ let package_path = if let Some ( url) = & source_url {
22+ download_package_url ( runtime_root, url) ?
1623 } else {
1724 source. to_path_buf ( )
1825 } ;
1926 if is_package_zip_path ( & package_path) {
2027 let imported = import_package_zip ( runtime_root, & package_path, None ) ?;
2128 Ok ( imported. entrypoint )
29+ } else if is_package_release_path ( & package_path) {
30+ match package_zip_from_release_manifest ( runtime_root, & package_path, source_url. as_deref ( ) ) ?
31+ {
32+ Some ( zip_path) => {
33+ let imported = import_package_zip ( runtime_root, & zip_path, None ) ?;
34+ Ok ( imported. entrypoint )
35+ }
36+ None => Ok ( package_path) ,
37+ }
2238 } else {
2339 Ok ( package_path)
2440 }
@@ -47,11 +63,19 @@ fn run_import_package(args: Vec<String>) -> Result<(), String> {
4763 . map_or_else ( env:: current_dir, Ok )
4864 . map_err ( |err| format ! ( "failed to get current directory: {err}" ) ) ?;
4965 let source_text = source. to_string_lossy ( ) ;
50- let package_path = if is_package_url ( & source_text) {
51- download_package_url ( & runtime_root, & source_text) ?
66+ let source_url = if is_package_url ( & source_text) {
67+ Some ( source_text. to_string ( ) )
68+ } else {
69+ None
70+ } ;
71+ let package_path = if let Some ( url) = & source_url {
72+ download_package_url ( & runtime_root, url) ?
5273 } else {
5374 absolutize ( & runtime_root, & source)
5475 } ;
76+ let package_path =
77+ package_zip_from_release_manifest ( & runtime_root, & package_path, source_url. as_deref ( ) ) ?
78+ . unwrap_or ( package_path) ;
5579 let imported = import_package_zip ( & runtime_root, & package_path, output_dir. as_deref ( ) ) ?;
5680 println ! ( "root\t {}" , imported. root. display( ) ) ;
5781 println ! ( "entrypoint\t {}" , imported. entrypoint. display( ) ) ;
@@ -170,6 +194,23 @@ fn load_package_descriptor(root: &Path) -> Result<PackageDescriptor, String> {
170194 . ok_or_else ( || {
171195 format ! ( "package descriptor {} is missing schema" , path. display( ) )
172196 } ) ?;
197+ if matches ! (
198+ schema,
199+ "bioscript:panel:1.0"
200+ | "bioscript:assay:1.0"
201+ | "bioscript:variant:1.0"
202+ | "bioscript:variant"
203+ ) {
204+ let package_name = value
205+ . as_mapping ( )
206+ . and_then ( |mapping| mapping. get ( serde_yaml:: Value :: String ( "name" . to_owned ( ) ) ) )
207+ . and_then ( serde_yaml:: Value :: as_str)
208+ . map ( ToOwned :: to_owned) ;
209+ return Ok ( PackageDescriptor {
210+ entrypoint : PathBuf :: from ( PACKAGE_DESCRIPTOR ) ,
211+ name : package_name,
212+ } ) ;
213+ }
173214 if schema != "bioscript:package:1.0" {
174215 return Err ( format ! (
175216 "package descriptor {} has unsupported schema '{schema}'" ,
@@ -352,11 +393,13 @@ fn download_package_url(runtime_root: &Path, url: &str) -> Result<PathBuf, Strin
352393 return Err ( "package URLs must use https://" . to_owned ( ) ) ;
353394 }
354395 let url_path = url. split ( '?' ) . next ( ) . unwrap_or ( url) ;
355- if ! Path :: new ( url_path)
396+ let extension = Path :: new ( url_path)
356397 . extension ( )
357- . is_some_and ( |ext| ext. eq_ignore_ascii_case ( "zip" ) )
358- {
359- return Err ( "package URL must point to a .zip file" . to_owned ( ) ) ;
398+ . and_then ( |ext| ext. to_str ( ) )
399+ . unwrap_or_default ( )
400+ . to_ascii_lowercase ( ) ;
401+ if !matches ! ( extension. as_str( ) , "zip" | "yaml" | "yml" ) {
402+ return Err ( "package URL must point to a .zip, .yaml, or .yml file" . to_owned ( ) ) ;
360403 }
361404 let downloads = runtime_root. join ( PACKAGE_DOWNLOAD_DIR ) ;
362405 fs:: create_dir_all ( & downloads) . map_err ( |err| {
@@ -408,3 +451,9 @@ fn is_package_zip_path(path: &Path) -> bool {
408451 . and_then ( |ext| ext. to_str ( ) )
409452 . is_some_and ( |ext| ext. eq_ignore_ascii_case ( "zip" ) )
410453}
454+
455+ fn is_package_release_path ( path : & Path ) -> bool {
456+ path. extension ( )
457+ . and_then ( |ext| ext. to_str ( ) )
458+ . is_some_and ( |ext| matches ! ( ext. to_ascii_lowercase( ) . as_str( ) , "yaml" | "yml" ) )
459+ }
0 commit comments