Loading lcov.info +394 −367 Original line number Diff line number Diff line Loading @@ -108,144 +108,165 @@ LH:0 end_of_record TN: SF:/root/dev/command/pipe-cli/src/commands/run/mod.rs FN:19,run FNF:1 FNDA:0,run DA:19,0 DA:29,0 FNF:0 DA:23,0 DA:24,0 DA:30,0 DA:31,0 DA:32,0 DA:33,0 DA:34,0 DA:35,0 DA:36,0 DA:38,0 DA:39,0 DA:40,0 DA:42,0 DA:43,0 DA:45,0 DA:46,0 DA:47,0 DA:50,0 DA:51,0 DA:53,0 DA:54,0 DA:55,0 DA:56,0 DA:57,0 DA:58,0 DA:62,0 DA:60,0 DA:61,0 DA:63,0 DA:65,0 DA:66,0 DA:67,0 DA:69,0 DA:70,0 DA:72,0 DA:73,0 DA:74,0 DA:77,0 DA:78,0 DA:79,0 DA:80,0 DA:82,0 DA:84,0 DA:85,0 DA:86,0 DA:88,0 DA:91,0 DA:92,0 DA:93,0 DA:94,0 DA:95,0 DA:96,0 DA:98,0 DA:97,0 DA:99,0 DA:100,0 DA:101,0 DA:102,0 DA:103,0 DA:107,0 DA:109,0 DA:111,0 DA:113,0 DA:114,0 DA:115,0 DA:118,0 DA:119,0 DA:120,0 DA:123,0 DA:125,0 DA:126,0 DA:128,0 DA:131,0 DA:132,0 DA:134,0 DA:130,0 DA:133,0 DA:135,0 DA:137,0 DA:138,0 DA:139,0 DA:140,0 DA:141,0 DA:142,0 DA:144,0 DA:143,0 DA:146,0 DA:147,0 DA:148,0 DA:151,0 DA:153,0 DA:154,0 DA:155,0 DA:156,0 DA:157,0 DA:159,0 DA:163,0 DA:165,0 DA:167,0 DA:162,0 DA:164,0 DA:166,0 DA:168,0 DA:172,0 DA:182,0 DA:169,0 DA:173,0 DA:174,0 DA:175,0 DA:178,0 DA:180,0 DA:181,0 DA:183,0 DA:184,0 DA:185,0 DA:186,0 DA:187,0 DA:189,0 DA:190,0 DA:192,0 DA:193,0 DA:194,0 DA:195,0 DA:196,0 DA:197,0 DA:200,0 DA:203,0 DA:205,0 DA:207,0 DA:199,0 DA:209,0 DA:210,0 DA:211,0 DA:212,0 DA:213,0 DA:214,0 DA:215,0 DA:216,0 DA:217,0 DA:218,0 DA:219,0 DA:221,0 DA:224,0 DA:220,0 DA:222,0 DA:223,0 DA:227,0 DA:230,0 DA:232,0 DA:233,0 DA:234,0 DA:235,0 DA:236,0 DA:237,0 DA:238,0 DA:239,0 DA:240,0 DA:243,0 DA:246,0 DA:250,0 DA:251,0 DA:242,0 DA:247,0 DA:248,0 DA:252,0 DA:253,0 DA:255,0 DA:256,0 DA:258,0 DA:259,0 DA:260,0 DA:261,0 DA:262,0 DA:263,0 DA:264,0 DA:265,0 DA:266,0 DA:267,0 DA:268,0 DA:269,0 DA:270,0 DA:271,0 DA:272,0 DA:273,0 DA:274,0 DA:276,0 DA:278,0 DA:281,0 DA:283,0 LF:134 DA:279,0 DA:282,0 DA:285,0 DA:287,0 DA:288,0 DA:289,0 DA:290,0 DA:291,0 DA:292,0 DA:293,0 DA:295,0 DA:298,0 DA:301,0 DA:305,0 DA:306,0 DA:307,0 DA:308,0 DA:310,0 DA:311,0 DA:313,0 DA:314,0 DA:315,0 DA:316,0 DA:317,0 DA:318,0 DA:319,0 DA:320,0 DA:322,0 DA:325,0 DA:328,0 DA:331,0 DA:333,0 DA:336,0 DA:338,0 LF:157 LH:0 end_of_record TN: Loading Loading @@ -391,45 +412,46 @@ FN:641,Label::fail FN:645,Label::found FN:649,Label::not_found FN:653,Label::output FN:657,Label::read FN:661,Label::rejected FN:665,Label::run FN:669,Label::using FN:675,ModuleUri<'_>::from FN:685,ModuleUri<'_>::hash FN:709,ModuleUri<'_>::get_whitelist FN:712,ModuleUri<'_>::is_allowed FN:715,ModuleUri<'_>::test FN:716,ModuleUri<'_>::test::check FN:733,ModuleUri<'_>::working_directory FN:745,SemanticVersion::from_string FN:768,Script::expand_arguments FN:803,Script::expand_arguments_from FN:838,Script::from_module FN:896,Script::from_path FN:911,Script::from_template FN:931,Script::get_command FN:941,Script::get_arguments FN:981,Script::maybe_create_virtual_environment FN:1026,Script::maybe_git_clone FN:1033,Script::python_default FN:1047,Script::run FN:1114,Script::with_container FN:1121,Script::with_current_dir FN:1126,Script::with_envs FN:1168,Script::with_virtual_environment FN:1174,ScriptTemplate::from_path FN:1186,ScriptTemplate::resolve_python_virtual_environment FN:1214,StringTemplate::new FN:1223,StringTemplate::expand FN:1230,StringTemplate::get_variable FN:1260,StringTemplate::is_handlebars FN:1295,StringTemplate::remove_spaces FN:1305,add_dot_slash FN:1313,add_forward_slash FN:1320,download_binary FN:1321,download_binary::download FNF:61 FN:657,Label::pass FN:661,Label::read FN:665,Label::rejected FN:669,Label::run FN:673,Label::using FN:679,ModuleUri<'_>::from FN:689,ModuleUri<'_>::hash FN:713,ModuleUri<'_>::get_whitelist FN:716,ModuleUri<'_>::is_allowed FN:719,ModuleUri<'_>::test FN:720,ModuleUri<'_>::test::check FN:737,ModuleUri<'_>::working_directory FN:749,SemanticVersion::from_string FN:772,Script::expand_arguments FN:807,Script::expand_arguments_from FN:842,Script::from_module FN:900,Script::from_path FN:915,Script::from_template FN:935,Script::get_command FN:945,Script::get_arguments FN:985,Script::maybe_create_virtual_environment FN:1030,Script::maybe_git_clone FN:1037,Script::python_default FN:1051,Script::run FN:1118,Script::with_container FN:1125,Script::with_current_dir FN:1130,Script::with_envs FN:1172,Script::with_virtual_environment FN:1178,ScriptTemplate::from_path FN:1190,ScriptTemplate::resolve_python_virtual_environment FN:1218,StringTemplate::new FN:1227,StringTemplate::expand FN:1234,StringTemplate::get_variable FN:1264,StringTemplate::is_handlebars FN:1299,StringTemplate::remove_spaces FN:1309,add_dot_slash FN:1317,add_forward_slash FN:1324,download_binary FN:1325,download_binary::download FNF:62 FNDA:1,Command::test FNDA:1,Config::read FNDA:1,Config::read_json Loading @@ -453,6 +475,7 @@ FNDA:0,Label::fail FNDA:0,Label::found FNDA:0,Label::not_found FNDA:1,Label::output FNDA:0,Label::pass FNDA:0,Label::read FNDA:0,Label::rejected FNDA:0,Label::run Loading Loading @@ -494,10 +517,10 @@ FNDA:0,download_binary::download DA:446,1 DA:447,2 DA:448,1 DA:449,3 DA:450,2 DA:452,3 DA:453,1 DA:449,4 DA:450,4 DA:452,6 DA:453,2 DA:456,0 DA:457,0 DA:462,3 Loading @@ -519,7 +542,7 @@ DA:494,2 DA:495,2 DA:497,0 DA:498,0 DA:501,2 DA:501,3 DA:502,2 DA:503,4 DA:504,0 Loading Loading @@ -630,292 +653,291 @@ DA:667,0 DA:669,0 DA:670,0 DA:671,0 DA:675,2 DA:676,2 DA:677,5 DA:678,2 DA:673,0 DA:674,0 DA:675,0 DA:679,2 DA:680,0 DA:682,1 DA:685,1 DA:680,2 DA:681,5 DA:682,2 DA:683,2 DA:684,0 DA:686,1 DA:687,1 DA:688,1 DA:689,2 DA:690,0 DA:692,4 DA:689,1 DA:690,1 DA:691,1 DA:692,1 DA:693,2 DA:694,0 DA:696,4 DA:697,4 DA:699,4 DA:700,2 DA:702,2 DA:705,0 DA:700,4 DA:701,4 DA:703,4 DA:704,2 DA:706,2 DA:709,0 DA:710,0 DA:712,0 DA:713,0 DA:715,0 DA:714,0 DA:716,0 DA:717,0 DA:719,0 DA:720,0 DA:721,0 DA:722,0 DA:723,0 DA:724,0 DA:725,0 DA:726,0 DA:727,0 DA:728,0 DA:729,0 DA:731,0 DA:733,0 DA:734,0 DA:735,0 DA:736,0 DA:737,0 DA:738,0 DA:739,0 DA:740,0 DA:745,1 DA:746,1 DA:747,3 DA:748,3 DA:749,3 DA:768,1 DA:769,2 DA:772,2 DA:773,1 DA:774,2 DA:775,1 DA:776,1 DA:741,0 DA:743,0 DA:744,0 DA:749,1 DA:750,1 DA:751,3 DA:752,3 DA:753,3 DA:772,1 DA:773,2 DA:776,2 DA:777,1 DA:778,2 DA:782,1 DA:783,1 DA:803,1 DA:804,2 DA:807,2 DA:808,1 DA:809,2 DA:810,2 DA:779,1 DA:780,1 DA:782,2 DA:786,1 DA:787,1 DA:807,1 DA:808,2 DA:811,2 DA:812,1 DA:813,2 DA:815,1 DA:814,2 DA:817,2 DA:821,1 DA:822,1 DA:838,0 DA:840,0 DA:841,0 DA:819,1 DA:821,2 DA:825,1 DA:826,1 DA:842,0 DA:844,0 DA:845,0 DA:846,0 DA:847,0 DA:848,0 DA:849,0 DA:850,0 DA:851,0 DA:852,0 DA:853,0 DA:855,0 DA:856,0 DA:857,0 DA:858,0 DA:859,0 DA:860,0 DA:861,0 DA:862,0 DA:863,0 DA:864,0 DA:866,0 DA:867,0 DA:869,0 DA:870,0 DA:868,0 DA:871,0 DA:873,0 DA:879,0 DA:880,0 DA:896,1 DA:897,1 DA:898,1 DA:911,1 DA:912,1 DA:913,3 DA:917,2 DA:919,2 DA:874,0 DA:877,0 DA:883,0 DA:884,0 DA:900,1 DA:901,1 DA:902,1 DA:915,1 DA:916,1 DA:917,3 DA:921,2 DA:925,1 DA:926,1 DA:927,1 DA:929,2 DA:923,2 DA:925,2 DA:929,1 DA:930,1 DA:931,1 DA:932,1 DA:933,1 DA:934,1 DA:933,2 DA:935,1 DA:936,1 DA:937,2 DA:937,1 DA:938,1 DA:941,1 DA:940,1 DA:941,2 DA:942,1 DA:943,1 DA:944,1 DA:945,1 DA:946,1 DA:947,0 DA:949,0 DA:950,0 DA:953,2 DA:954,1 DA:956,1 DA:947,1 DA:948,1 DA:949,1 DA:950,1 DA:951,0 DA:953,0 DA:954,0 DA:957,2 DA:958,1 DA:959,1 DA:960,1 DA:961,2 DA:962,2 DA:962,1 DA:963,1 DA:964,1 DA:965,2 DA:966,2 DA:967,2 DA:969,0 DA:970,0 DA:973,1 DA:974,1 DA:976,1 DA:981,0 DA:986,0 DA:987,0 DA:988,0 DA:968,1 DA:970,2 DA:971,2 DA:973,0 DA:974,0 DA:977,1 DA:978,1 DA:980,1 DA:985,0 DA:990,0 DA:991,0 DA:992,0 DA:993,0 DA:994,0 DA:995,0 DA:996,0 DA:997,0 DA:998,0 DA:999,0 DA:1000,0 DA:1001,0 DA:1002,0 DA:1003,0 DA:1004,0 DA:1005,0 DA:1006,0 DA:1007,0 DA:1009,0 DA:1010,0 DA:1013,0 DA:1014,0 DA:1017,0 DA:1022,0 DA:1026,1 DA:1027,2 DA:1028,2 DA:1029,2 DA:1030,3 DA:1031,1 DA:1033,0 DA:1034,0 DA:1035,0 DA:1043,0 DA:1047,1 DA:1048,1 DA:1049,1 DA:1050,2 DA:1051,2 DA:1052,3 DA:1018,0 DA:1021,0 DA:1026,0 DA:1030,1 DA:1031,2 DA:1032,2 DA:1033,2 DA:1034,3 DA:1035,1 DA:1037,0 DA:1038,0 DA:1039,0 DA:1047,0 DA:1051,1 DA:1052,1 DA:1053,1 DA:1054,7 DA:1054,2 DA:1055,2 DA:1056,1 DA:1056,3 DA:1057,1 DA:1058,1 DA:1059,1 DA:1064,2 DA:1065,1 DA:1067,0 DA:1068,0 DA:1071,1 DA:1072,1 DA:1073,2 DA:1074,2 DA:1058,7 DA:1059,2 DA:1060,1 DA:1061,1 DA:1062,1 DA:1063,1 DA:1068,2 DA:1069,1 DA:1071,0 DA:1072,0 DA:1075,1 DA:1076,1 DA:1077,2 DA:1078,1 DA:1080,0 DA:1081,0 DA:1084,1 DA:1085,1 DA:1086,2 DA:1087,0 DA:1088,0 DA:1091,2 DA:1092,1 DA:1093,3 DA:1094,1 DA:1095,3 DA:1096,3 DA:1097,1 DA:1099,0 DA:1100,0 DA:1101,0 DA:1078,2 DA:1081,2 DA:1082,1 DA:1084,0 DA:1085,0 DA:1088,1 DA:1089,1 DA:1090,2 DA:1091,0 DA:1092,0 DA:1095,2 DA:1096,1 DA:1097,3 DA:1098,1 DA:1099,3 DA:1100,3 DA:1101,1 DA:1103,0 DA:1104,0 DA:1105,0 DA:1106,0 DA:1108,0 DA:1109,0 DA:1110,0 DA:1111,0 DA:1114,1 DA:1115,1 DA:1116,1 DA:1121,1 DA:1122,2 DA:1123,1 DA:1126,0 DA:1127,0 DA:1128,0 DA:1168,1 DA:1169,1 DA:1170,1 DA:1114,0 DA:1115,0 DA:1118,1 DA:1119,1 DA:1120,1 DA:1125,1 DA:1126,2 DA:1127,1 DA:1130,0 DA:1131,0 DA:1132,0 DA:1172,1 DA:1173,1 DA:1174,1 DA:1175,2 DA:1176,1 DA:1178,0 DA:1179,0 DA:1182,2 DA:1184,1 DA:1186,0 DA:1187,0 DA:1188,0 DA:1189,0 DA:1178,1 DA:1179,2 DA:1180,1 DA:1182,0 DA:1183,0 DA:1186,2 DA:1188,1 DA:1190,0 DA:1191,0 DA:1192,0 DA:1193,0 DA:1194,0 DA:1195,0 DA:1196,0 DA:1197,0 DA:1202,0 DA:1203,0 DA:1204,0 DA:1214,1 DA:1216,1 DA:1223,1 DA:1224,4 DA:1225,3 DA:1230,1 DA:1231,2 DA:1232,2 DA:1233,1 DA:1234,2 DA:1236,0 DA:1260,1 DA:1261,2 DA:1262,2 DA:1263,1 DA:1264,0 DA:1266,0 DA:1295,1 DA:1296,2 DA:1297,1 DA:1298,0 DA:1300,3 DA:1199,0 DA:1200,0 DA:1201,0 DA:1206,0 DA:1207,0 DA:1208,0 DA:1218,1 DA:1220,1 DA:1227,1 DA:1228,4 DA:1229,3 DA:1234,1 DA:1235,2 DA:1236,2 DA:1237,1 DA:1238,2 DA:1240,0 DA:1264,1 DA:1265,2 DA:1266,2 DA:1267,1 DA:1268,0 DA:1270,0 DA:1299,1 DA:1300,2 DA:1301,1 DA:1302,0 DA:1304,3 DA:1305,1 DA:1306,2 DA:1307,2 DA:1309,3 DA:1313,1 DA:1314,2 DA:1315,0 DA:1317,2 DA:1320,0 DA:1321,0 DA:1322,0 DA:1323,0 DA:1309,1 DA:1310,2 DA:1311,2 DA:1313,3 DA:1317,1 DA:1318,2 DA:1319,0 DA:1321,2 DA:1324,0 DA:1325,0 DA:1326,0 Loading @@ -924,55 +946,60 @@ DA:1328,0 DA:1329,0 DA:1330,0 DA:1331,0 DA:1332,0 DA:1333,0 DA:1334,0 DA:1335,0 DA:1338,0 DA:1337,0 DA:1339,0 DA:1340,0 DA:1352,1 DA:1353,2 DA:1354,2 DA:1355,2 DA:1356,2 DA:1357,5 DA:1360,1 DA:1362,2 DA:1364,4 DA:1367,0 DA:1394,1 DA:1395,2 DA:1396,2 DA:1397,1 DA:1398,6 DA:1410,1 DA:1412,0 DA:1414,1 DA:1429,1 DA:1430,1 DA:1433,1 DA:1434,3 DA:1446,1 DA:1447,1 DA:1450,0 DA:1451,0 DA:1452,0 DA:1454,0 DA:1458,0 DA:1342,0 DA:1343,0 DA:1344,0 DA:1345,0 DA:1357,1 DA:1358,2 DA:1359,2 DA:1360,2 DA:1361,2 DA:1362,5 DA:1365,1 DA:1367,2 DA:1369,4 DA:1372,0 DA:1399,1 DA:1400,2 DA:1401,2 DA:1402,1 DA:1403,6 DA:1415,1 DA:1417,0 DA:1419,1 DA:1434,1 DA:1435,1 DA:1438,1 DA:1439,3 DA:1451,1 DA:1452,1 DA:1455,0 DA:1456,0 DA:1457,0 DA:1459,0 DA:1460,0 DA:1462,0 DA:1476,2 DA:1477,2 DA:1478,4 DA:1479,4 DA:1480,12 DA:1481,8 DA:1483,1 DA:1484,3 DA:1485,1 DA:1463,0 DA:1464,0 DA:1465,0 DA:1467,0 DA:1481,2 DA:1482,2 DA:1483,4 DA:1484,4 DA:1485,12 DA:1486,8 DA:1488,1 DA:1489,3 DA:1490,1 DA:1491,4 LF:482 DA:1493,1 DA:1495,1 DA:1496,4 LF:486 LH:246 end_of_record notebooks/sandbox.ipynb +15 −14 Original line number Diff line number Diff line %% Cell type:code id: tags: ``` rust :dep pipe-lib = { path = "../pipe-lib" } ``` %% Cell type:code id: tags: ``` rust :dep reqwest :dep tokio = { version = "1.39.2", features = ["rt", "time", "rt-multi-thread"] } :dep bytes ``` %% Cell type:code id: tags: ``` rust use std::io::copy; use std::io::Cursor; use std::fs::File; use std::path::PathBuf; use tokio; pub fn download_binary(url: String) -> Result<bytes::Bytes, String> { async fn download(url: String) -> Result<bytes::Bytes, String> { pub fn download_binary(url: String, destination: PathBuf) -> Result<PathBuf, String> { async fn download(url: String, destination: PathBuf) -> Result<(), String> { let client = reqwest::Client::new(); let response = client.get(url.clone()).send(); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); match response.await { | Ok(data) => { match data.bytes().await { | Ok(content) => { let mut output = File::create(filename.clone()).unwrap(); copy(&mut Cursor::new(content.clone()), &mut output); println!("Downloaded {filename}"); Ok(content) }, | Err(_) => Err(format!("No content downloaded from {url}")) | Ok(data) => match data.bytes().await { | Ok(content) => { let mut output = File::create(destination.join(filename.clone())).unwrap(); let _ = copy(&mut Cursor::new(content.clone()), &mut output); debug!(filename = filename, "=> {} Downloaded", Label::output()); Ok(()) } | Err(_) => Err(format!("No content downloaded from {url}")), }, | Err(_) => Err(format!("Failed to download {url}")) | Err(_) => Err(format!("Failed to download {url}")), } } let runtime = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); runtime.block_on(download(url.clone())) let _ = runtime.block_on(download(url.clone(), destination.clone())); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); Ok(destination.join(filename)) } ``` %% Cell type:code id: tags: ``` rust let url = "https://code.ornl.gov/api/v4/projects/15383/packages/generic/x86_64-unknown-linux-gnu/v0.0.3/pipe".to_string(); let content = download_binary(url); let content = download_binary(url, PathBuf::from("/root/dev/notebooks")); println!("{:?}", content); ``` %% Output Downloaded pipe %% Cell type:code id: tags: ``` rust let path = "/tmp/pipe/iopbgzaGbV/pipe"; ``` pipe-cli/src/commands/run/mod.rs +76 −21 Original line number Diff line number Diff line Loading @@ -3,11 +3,15 @@ use color_eyre::eyre::Report; use exitcode; use nanoid::nanoid; use pipe_lib::{ get_parent, Command, Config, EnvironmentValue, Label, ModuleLanguage, ModuleType, ModuleUri, Script, ScriptTemplate, TemplateAttribute, download_binary, get_checksum, get_parent, Command, Config, EnvironmentValue, Label, ModuleLanguage, ModuleType, ModuleUri, Script, ScriptTemplate, TemplateAttribute, }; use rayon::prelude::*; use std::convert::TryFrom; use std::env; use std::fs; #[cfg(any(unix, target_os = "wasi", target_os = "redox"))] use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use tracing::{debug, error, info, warn}; use uriparse::Scheme; Loading @@ -15,6 +19,29 @@ use uriparse::URI; const DEFAULT_CONFIG_NAME: &str = "config.json"; #[cfg(any(unix, target_os = "wasi", target_os = "redox"))] fn make_executable(path: &PathBuf) { fs::set_permissions(path, fs::Permissions::from_mode(0o755)).unwrap(); } #[cfg(windows)] fn make_executable(path: &PathBuf) { // TODO: Add windows support...pass through? } fn check_requirements(config: &Config, skip: bool) { if !skip { config.requirements.iter().for_each(|name| { let command = Command::init().name(name.clone()).build(); if !command.test() { error!(name, "=> {} Requirement not met", Label::not_found()); std::process::exit(exitcode::UNAVAILABLE); } }); } else { warn!("Skipping requirements verification"); } } fn check_resources(_config: &Config, _skip: bool) {} #[allow(clippy::too_many_arguments)] pub fn run( config: &Option<PathBuf>, Loading @@ -31,7 +58,7 @@ pub fn run( match std::fs::create_dir_all(root.clone()) { | Ok(_) => { let path = root.clone().into_os_string().into_string().unwrap(); debug!(path, "Created temporary directory"); debug!(path, "=> {} Root directory", Label::using()); } | Err(err) => error!("{}", err), } Loading @@ -49,34 +76,62 @@ pub fn run( }; match Config::read(config_path) { | Some(cfg) => { // Check requirements if !skip_verify_requirements { cfg.requirements.iter().for_each(|name| { let command = Command::init().name(name.clone()).build(); if !command.test() { error!(name, "=> {} Requirement not met", Label::not_found()); std::process::exit(exitcode::UNAVAILABLE); } }); } else { warn!("Skipping requirements verification"); } check_requirements(&cfg, skip_verify_requirements); check_resources(&cfg, false); // // Prepare modules // cfg.modules.par_iter().for_each(|module| match &module.module_type { | ModuleType::Binary { uri, .. } => match ModuleUri::from(uri) { | ModuleType::Binary { uri, checksum } => match ModuleUri::from(uri) { | ModuleUri::Url(value) if !offline => match value.scheme() { | Scheme::HTTP | Scheme::HTTPS | Scheme::SSH => { let url = value.to_string(); debug!(module = module.name, url, "=> {} Remote binary", Label::found()); // TODO: Filter URL using whitelist // TODO: Check that URL exists // TODO: Download binary to temp directory debug!(module = module.name, url, "=> {} Remote binary", Label::found()); if !dry_run { let output = download_binary(url.clone(), root.clone()); if !skip_verify_checksum { // TODO: Verify binary checksum let calculated_checksum = match output.clone() { | Ok(path) => get_checksum(path), | _ => "".to_string(), }; match checksum { | Some(value) if value == &calculated_checksum => { info!(module = module.name, url, "=> {} Checksum verified", Label::pass()); if let Ok(path) = output { make_executable(&path); } } | Some(_) => { error!( module = module.name, url, checksum, calculated = calculated_checksum, "=> {} Remote binary checksum does not match", Label::fail() ); std::process::exit(exitcode::USAGE); } | None => { error!( module = module.name, url, checksum, "=> {} Remote binary checksum does not match", Label::fail() ); std::process::exit(exitcode::UNAVAILABLE); } } // TODO: Verify binary is executable (https://docs.rs/is_executable/latest/is_executable/) } else { warn!("Skipping checksum verification"); } } else { info!(module = module.name, url, "=> {} Download remote binary", Label::dry_run()); } unimplemented!("Remote binary modules are not supported yet"); } | _ => unimplemented!("Only HTTP, HTTPS, and SSH are currently supported for remote binary modules"), Loading pipe-lib/src/lib.rs +11 −6 Original line number Diff line number Diff line Loading @@ -640,7 +640,7 @@ impl Label { } pub fn fail() -> Styled<&'static &'static str> { let style = Style::new().white().on_red(); " FAIL ".style(style) " ✗ FAIL ".style(style) } pub fn found() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); Loading @@ -654,6 +654,10 @@ impl Label { let style = Style::new().cyan().dimmed().on_default_color(); "OUTPUT".style(style) } pub fn pass() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); "☑ PASS".style(style) } pub fn read() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); "READ".style(style) Loading Loading @@ -1317,15 +1321,15 @@ pub fn add_forward_slash(path: PathBuf) -> PathBuf { path.to_path_buf() } } pub fn download_binary(url: String) -> Result<(), String> { async fn download(url: String) -> Result<(), String> { pub fn download_binary(url: String, destination: PathBuf) -> Result<PathBuf, String> { async fn download(url: String, destination: PathBuf) -> Result<(), String> { let client = reqwest::Client::new(); let response = client.get(url.clone()).send(); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); match response.await { | Ok(data) => match data.bytes().await { | Ok(content) => { let mut output = File::create(filename.clone()).unwrap(); let mut output = File::create(destination.join(filename.clone())).unwrap(); let _ = copy(&mut Cursor::new(content.clone()), &mut output); debug!(filename = filename, "=> {} Downloaded", Label::output()); Ok(()) Loading @@ -1336,8 +1340,9 @@ pub fn download_binary(url: String) -> Result<(), String> { } } let runtime = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); let _ = runtime.block_on(download(url.clone())); Ok(()) let _ = runtime.block_on(download(url.clone(), destination.clone())); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); Ok(destination.join(filename)) } /// Get SHA256 hash of a file pub fn get_checksum(path: PathBuf) -> String { Loading Loading
lcov.info +394 −367 Original line number Diff line number Diff line Loading @@ -108,144 +108,165 @@ LH:0 end_of_record TN: SF:/root/dev/command/pipe-cli/src/commands/run/mod.rs FN:19,run FNF:1 FNDA:0,run DA:19,0 DA:29,0 FNF:0 DA:23,0 DA:24,0 DA:30,0 DA:31,0 DA:32,0 DA:33,0 DA:34,0 DA:35,0 DA:36,0 DA:38,0 DA:39,0 DA:40,0 DA:42,0 DA:43,0 DA:45,0 DA:46,0 DA:47,0 DA:50,0 DA:51,0 DA:53,0 DA:54,0 DA:55,0 DA:56,0 DA:57,0 DA:58,0 DA:62,0 DA:60,0 DA:61,0 DA:63,0 DA:65,0 DA:66,0 DA:67,0 DA:69,0 DA:70,0 DA:72,0 DA:73,0 DA:74,0 DA:77,0 DA:78,0 DA:79,0 DA:80,0 DA:82,0 DA:84,0 DA:85,0 DA:86,0 DA:88,0 DA:91,0 DA:92,0 DA:93,0 DA:94,0 DA:95,0 DA:96,0 DA:98,0 DA:97,0 DA:99,0 DA:100,0 DA:101,0 DA:102,0 DA:103,0 DA:107,0 DA:109,0 DA:111,0 DA:113,0 DA:114,0 DA:115,0 DA:118,0 DA:119,0 DA:120,0 DA:123,0 DA:125,0 DA:126,0 DA:128,0 DA:131,0 DA:132,0 DA:134,0 DA:130,0 DA:133,0 DA:135,0 DA:137,0 DA:138,0 DA:139,0 DA:140,0 DA:141,0 DA:142,0 DA:144,0 DA:143,0 DA:146,0 DA:147,0 DA:148,0 DA:151,0 DA:153,0 DA:154,0 DA:155,0 DA:156,0 DA:157,0 DA:159,0 DA:163,0 DA:165,0 DA:167,0 DA:162,0 DA:164,0 DA:166,0 DA:168,0 DA:172,0 DA:182,0 DA:169,0 DA:173,0 DA:174,0 DA:175,0 DA:178,0 DA:180,0 DA:181,0 DA:183,0 DA:184,0 DA:185,0 DA:186,0 DA:187,0 DA:189,0 DA:190,0 DA:192,0 DA:193,0 DA:194,0 DA:195,0 DA:196,0 DA:197,0 DA:200,0 DA:203,0 DA:205,0 DA:207,0 DA:199,0 DA:209,0 DA:210,0 DA:211,0 DA:212,0 DA:213,0 DA:214,0 DA:215,0 DA:216,0 DA:217,0 DA:218,0 DA:219,0 DA:221,0 DA:224,0 DA:220,0 DA:222,0 DA:223,0 DA:227,0 DA:230,0 DA:232,0 DA:233,0 DA:234,0 DA:235,0 DA:236,0 DA:237,0 DA:238,0 DA:239,0 DA:240,0 DA:243,0 DA:246,0 DA:250,0 DA:251,0 DA:242,0 DA:247,0 DA:248,0 DA:252,0 DA:253,0 DA:255,0 DA:256,0 DA:258,0 DA:259,0 DA:260,0 DA:261,0 DA:262,0 DA:263,0 DA:264,0 DA:265,0 DA:266,0 DA:267,0 DA:268,0 DA:269,0 DA:270,0 DA:271,0 DA:272,0 DA:273,0 DA:274,0 DA:276,0 DA:278,0 DA:281,0 DA:283,0 LF:134 DA:279,0 DA:282,0 DA:285,0 DA:287,0 DA:288,0 DA:289,0 DA:290,0 DA:291,0 DA:292,0 DA:293,0 DA:295,0 DA:298,0 DA:301,0 DA:305,0 DA:306,0 DA:307,0 DA:308,0 DA:310,0 DA:311,0 DA:313,0 DA:314,0 DA:315,0 DA:316,0 DA:317,0 DA:318,0 DA:319,0 DA:320,0 DA:322,0 DA:325,0 DA:328,0 DA:331,0 DA:333,0 DA:336,0 DA:338,0 LF:157 LH:0 end_of_record TN: Loading Loading @@ -391,45 +412,46 @@ FN:641,Label::fail FN:645,Label::found FN:649,Label::not_found FN:653,Label::output FN:657,Label::read FN:661,Label::rejected FN:665,Label::run FN:669,Label::using FN:675,ModuleUri<'_>::from FN:685,ModuleUri<'_>::hash FN:709,ModuleUri<'_>::get_whitelist FN:712,ModuleUri<'_>::is_allowed FN:715,ModuleUri<'_>::test FN:716,ModuleUri<'_>::test::check FN:733,ModuleUri<'_>::working_directory FN:745,SemanticVersion::from_string FN:768,Script::expand_arguments FN:803,Script::expand_arguments_from FN:838,Script::from_module FN:896,Script::from_path FN:911,Script::from_template FN:931,Script::get_command FN:941,Script::get_arguments FN:981,Script::maybe_create_virtual_environment FN:1026,Script::maybe_git_clone FN:1033,Script::python_default FN:1047,Script::run FN:1114,Script::with_container FN:1121,Script::with_current_dir FN:1126,Script::with_envs FN:1168,Script::with_virtual_environment FN:1174,ScriptTemplate::from_path FN:1186,ScriptTemplate::resolve_python_virtual_environment FN:1214,StringTemplate::new FN:1223,StringTemplate::expand FN:1230,StringTemplate::get_variable FN:1260,StringTemplate::is_handlebars FN:1295,StringTemplate::remove_spaces FN:1305,add_dot_slash FN:1313,add_forward_slash FN:1320,download_binary FN:1321,download_binary::download FNF:61 FN:657,Label::pass FN:661,Label::read FN:665,Label::rejected FN:669,Label::run FN:673,Label::using FN:679,ModuleUri<'_>::from FN:689,ModuleUri<'_>::hash FN:713,ModuleUri<'_>::get_whitelist FN:716,ModuleUri<'_>::is_allowed FN:719,ModuleUri<'_>::test FN:720,ModuleUri<'_>::test::check FN:737,ModuleUri<'_>::working_directory FN:749,SemanticVersion::from_string FN:772,Script::expand_arguments FN:807,Script::expand_arguments_from FN:842,Script::from_module FN:900,Script::from_path FN:915,Script::from_template FN:935,Script::get_command FN:945,Script::get_arguments FN:985,Script::maybe_create_virtual_environment FN:1030,Script::maybe_git_clone FN:1037,Script::python_default FN:1051,Script::run FN:1118,Script::with_container FN:1125,Script::with_current_dir FN:1130,Script::with_envs FN:1172,Script::with_virtual_environment FN:1178,ScriptTemplate::from_path FN:1190,ScriptTemplate::resolve_python_virtual_environment FN:1218,StringTemplate::new FN:1227,StringTemplate::expand FN:1234,StringTemplate::get_variable FN:1264,StringTemplate::is_handlebars FN:1299,StringTemplate::remove_spaces FN:1309,add_dot_slash FN:1317,add_forward_slash FN:1324,download_binary FN:1325,download_binary::download FNF:62 FNDA:1,Command::test FNDA:1,Config::read FNDA:1,Config::read_json Loading @@ -453,6 +475,7 @@ FNDA:0,Label::fail FNDA:0,Label::found FNDA:0,Label::not_found FNDA:1,Label::output FNDA:0,Label::pass FNDA:0,Label::read FNDA:0,Label::rejected FNDA:0,Label::run Loading Loading @@ -494,10 +517,10 @@ FNDA:0,download_binary::download DA:446,1 DA:447,2 DA:448,1 DA:449,3 DA:450,2 DA:452,3 DA:453,1 DA:449,4 DA:450,4 DA:452,6 DA:453,2 DA:456,0 DA:457,0 DA:462,3 Loading @@ -519,7 +542,7 @@ DA:494,2 DA:495,2 DA:497,0 DA:498,0 DA:501,2 DA:501,3 DA:502,2 DA:503,4 DA:504,0 Loading Loading @@ -630,292 +653,291 @@ DA:667,0 DA:669,0 DA:670,0 DA:671,0 DA:675,2 DA:676,2 DA:677,5 DA:678,2 DA:673,0 DA:674,0 DA:675,0 DA:679,2 DA:680,0 DA:682,1 DA:685,1 DA:680,2 DA:681,5 DA:682,2 DA:683,2 DA:684,0 DA:686,1 DA:687,1 DA:688,1 DA:689,2 DA:690,0 DA:692,4 DA:689,1 DA:690,1 DA:691,1 DA:692,1 DA:693,2 DA:694,0 DA:696,4 DA:697,4 DA:699,4 DA:700,2 DA:702,2 DA:705,0 DA:700,4 DA:701,4 DA:703,4 DA:704,2 DA:706,2 DA:709,0 DA:710,0 DA:712,0 DA:713,0 DA:715,0 DA:714,0 DA:716,0 DA:717,0 DA:719,0 DA:720,0 DA:721,0 DA:722,0 DA:723,0 DA:724,0 DA:725,0 DA:726,0 DA:727,0 DA:728,0 DA:729,0 DA:731,0 DA:733,0 DA:734,0 DA:735,0 DA:736,0 DA:737,0 DA:738,0 DA:739,0 DA:740,0 DA:745,1 DA:746,1 DA:747,3 DA:748,3 DA:749,3 DA:768,1 DA:769,2 DA:772,2 DA:773,1 DA:774,2 DA:775,1 DA:776,1 DA:741,0 DA:743,0 DA:744,0 DA:749,1 DA:750,1 DA:751,3 DA:752,3 DA:753,3 DA:772,1 DA:773,2 DA:776,2 DA:777,1 DA:778,2 DA:782,1 DA:783,1 DA:803,1 DA:804,2 DA:807,2 DA:808,1 DA:809,2 DA:810,2 DA:779,1 DA:780,1 DA:782,2 DA:786,1 DA:787,1 DA:807,1 DA:808,2 DA:811,2 DA:812,1 DA:813,2 DA:815,1 DA:814,2 DA:817,2 DA:821,1 DA:822,1 DA:838,0 DA:840,0 DA:841,0 DA:819,1 DA:821,2 DA:825,1 DA:826,1 DA:842,0 DA:844,0 DA:845,0 DA:846,0 DA:847,0 DA:848,0 DA:849,0 DA:850,0 DA:851,0 DA:852,0 DA:853,0 DA:855,0 DA:856,0 DA:857,0 DA:858,0 DA:859,0 DA:860,0 DA:861,0 DA:862,0 DA:863,0 DA:864,0 DA:866,0 DA:867,0 DA:869,0 DA:870,0 DA:868,0 DA:871,0 DA:873,0 DA:879,0 DA:880,0 DA:896,1 DA:897,1 DA:898,1 DA:911,1 DA:912,1 DA:913,3 DA:917,2 DA:919,2 DA:874,0 DA:877,0 DA:883,0 DA:884,0 DA:900,1 DA:901,1 DA:902,1 DA:915,1 DA:916,1 DA:917,3 DA:921,2 DA:925,1 DA:926,1 DA:927,1 DA:929,2 DA:923,2 DA:925,2 DA:929,1 DA:930,1 DA:931,1 DA:932,1 DA:933,1 DA:934,1 DA:933,2 DA:935,1 DA:936,1 DA:937,2 DA:937,1 DA:938,1 DA:941,1 DA:940,1 DA:941,2 DA:942,1 DA:943,1 DA:944,1 DA:945,1 DA:946,1 DA:947,0 DA:949,0 DA:950,0 DA:953,2 DA:954,1 DA:956,1 DA:947,1 DA:948,1 DA:949,1 DA:950,1 DA:951,0 DA:953,0 DA:954,0 DA:957,2 DA:958,1 DA:959,1 DA:960,1 DA:961,2 DA:962,2 DA:962,1 DA:963,1 DA:964,1 DA:965,2 DA:966,2 DA:967,2 DA:969,0 DA:970,0 DA:973,1 DA:974,1 DA:976,1 DA:981,0 DA:986,0 DA:987,0 DA:988,0 DA:968,1 DA:970,2 DA:971,2 DA:973,0 DA:974,0 DA:977,1 DA:978,1 DA:980,1 DA:985,0 DA:990,0 DA:991,0 DA:992,0 DA:993,0 DA:994,0 DA:995,0 DA:996,0 DA:997,0 DA:998,0 DA:999,0 DA:1000,0 DA:1001,0 DA:1002,0 DA:1003,0 DA:1004,0 DA:1005,0 DA:1006,0 DA:1007,0 DA:1009,0 DA:1010,0 DA:1013,0 DA:1014,0 DA:1017,0 DA:1022,0 DA:1026,1 DA:1027,2 DA:1028,2 DA:1029,2 DA:1030,3 DA:1031,1 DA:1033,0 DA:1034,0 DA:1035,0 DA:1043,0 DA:1047,1 DA:1048,1 DA:1049,1 DA:1050,2 DA:1051,2 DA:1052,3 DA:1018,0 DA:1021,0 DA:1026,0 DA:1030,1 DA:1031,2 DA:1032,2 DA:1033,2 DA:1034,3 DA:1035,1 DA:1037,0 DA:1038,0 DA:1039,0 DA:1047,0 DA:1051,1 DA:1052,1 DA:1053,1 DA:1054,7 DA:1054,2 DA:1055,2 DA:1056,1 DA:1056,3 DA:1057,1 DA:1058,1 DA:1059,1 DA:1064,2 DA:1065,1 DA:1067,0 DA:1068,0 DA:1071,1 DA:1072,1 DA:1073,2 DA:1074,2 DA:1058,7 DA:1059,2 DA:1060,1 DA:1061,1 DA:1062,1 DA:1063,1 DA:1068,2 DA:1069,1 DA:1071,0 DA:1072,0 DA:1075,1 DA:1076,1 DA:1077,2 DA:1078,1 DA:1080,0 DA:1081,0 DA:1084,1 DA:1085,1 DA:1086,2 DA:1087,0 DA:1088,0 DA:1091,2 DA:1092,1 DA:1093,3 DA:1094,1 DA:1095,3 DA:1096,3 DA:1097,1 DA:1099,0 DA:1100,0 DA:1101,0 DA:1078,2 DA:1081,2 DA:1082,1 DA:1084,0 DA:1085,0 DA:1088,1 DA:1089,1 DA:1090,2 DA:1091,0 DA:1092,0 DA:1095,2 DA:1096,1 DA:1097,3 DA:1098,1 DA:1099,3 DA:1100,3 DA:1101,1 DA:1103,0 DA:1104,0 DA:1105,0 DA:1106,0 DA:1108,0 DA:1109,0 DA:1110,0 DA:1111,0 DA:1114,1 DA:1115,1 DA:1116,1 DA:1121,1 DA:1122,2 DA:1123,1 DA:1126,0 DA:1127,0 DA:1128,0 DA:1168,1 DA:1169,1 DA:1170,1 DA:1114,0 DA:1115,0 DA:1118,1 DA:1119,1 DA:1120,1 DA:1125,1 DA:1126,2 DA:1127,1 DA:1130,0 DA:1131,0 DA:1132,0 DA:1172,1 DA:1173,1 DA:1174,1 DA:1175,2 DA:1176,1 DA:1178,0 DA:1179,0 DA:1182,2 DA:1184,1 DA:1186,0 DA:1187,0 DA:1188,0 DA:1189,0 DA:1178,1 DA:1179,2 DA:1180,1 DA:1182,0 DA:1183,0 DA:1186,2 DA:1188,1 DA:1190,0 DA:1191,0 DA:1192,0 DA:1193,0 DA:1194,0 DA:1195,0 DA:1196,0 DA:1197,0 DA:1202,0 DA:1203,0 DA:1204,0 DA:1214,1 DA:1216,1 DA:1223,1 DA:1224,4 DA:1225,3 DA:1230,1 DA:1231,2 DA:1232,2 DA:1233,1 DA:1234,2 DA:1236,0 DA:1260,1 DA:1261,2 DA:1262,2 DA:1263,1 DA:1264,0 DA:1266,0 DA:1295,1 DA:1296,2 DA:1297,1 DA:1298,0 DA:1300,3 DA:1199,0 DA:1200,0 DA:1201,0 DA:1206,0 DA:1207,0 DA:1208,0 DA:1218,1 DA:1220,1 DA:1227,1 DA:1228,4 DA:1229,3 DA:1234,1 DA:1235,2 DA:1236,2 DA:1237,1 DA:1238,2 DA:1240,0 DA:1264,1 DA:1265,2 DA:1266,2 DA:1267,1 DA:1268,0 DA:1270,0 DA:1299,1 DA:1300,2 DA:1301,1 DA:1302,0 DA:1304,3 DA:1305,1 DA:1306,2 DA:1307,2 DA:1309,3 DA:1313,1 DA:1314,2 DA:1315,0 DA:1317,2 DA:1320,0 DA:1321,0 DA:1322,0 DA:1323,0 DA:1309,1 DA:1310,2 DA:1311,2 DA:1313,3 DA:1317,1 DA:1318,2 DA:1319,0 DA:1321,2 DA:1324,0 DA:1325,0 DA:1326,0 Loading @@ -924,55 +946,60 @@ DA:1328,0 DA:1329,0 DA:1330,0 DA:1331,0 DA:1332,0 DA:1333,0 DA:1334,0 DA:1335,0 DA:1338,0 DA:1337,0 DA:1339,0 DA:1340,0 DA:1352,1 DA:1353,2 DA:1354,2 DA:1355,2 DA:1356,2 DA:1357,5 DA:1360,1 DA:1362,2 DA:1364,4 DA:1367,0 DA:1394,1 DA:1395,2 DA:1396,2 DA:1397,1 DA:1398,6 DA:1410,1 DA:1412,0 DA:1414,1 DA:1429,1 DA:1430,1 DA:1433,1 DA:1434,3 DA:1446,1 DA:1447,1 DA:1450,0 DA:1451,0 DA:1452,0 DA:1454,0 DA:1458,0 DA:1342,0 DA:1343,0 DA:1344,0 DA:1345,0 DA:1357,1 DA:1358,2 DA:1359,2 DA:1360,2 DA:1361,2 DA:1362,5 DA:1365,1 DA:1367,2 DA:1369,4 DA:1372,0 DA:1399,1 DA:1400,2 DA:1401,2 DA:1402,1 DA:1403,6 DA:1415,1 DA:1417,0 DA:1419,1 DA:1434,1 DA:1435,1 DA:1438,1 DA:1439,3 DA:1451,1 DA:1452,1 DA:1455,0 DA:1456,0 DA:1457,0 DA:1459,0 DA:1460,0 DA:1462,0 DA:1476,2 DA:1477,2 DA:1478,4 DA:1479,4 DA:1480,12 DA:1481,8 DA:1483,1 DA:1484,3 DA:1485,1 DA:1463,0 DA:1464,0 DA:1465,0 DA:1467,0 DA:1481,2 DA:1482,2 DA:1483,4 DA:1484,4 DA:1485,12 DA:1486,8 DA:1488,1 DA:1489,3 DA:1490,1 DA:1491,4 LF:482 DA:1493,1 DA:1495,1 DA:1496,4 LF:486 LH:246 end_of_record
notebooks/sandbox.ipynb +15 −14 Original line number Diff line number Diff line %% Cell type:code id: tags: ``` rust :dep pipe-lib = { path = "../pipe-lib" } ``` %% Cell type:code id: tags: ``` rust :dep reqwest :dep tokio = { version = "1.39.2", features = ["rt", "time", "rt-multi-thread"] } :dep bytes ``` %% Cell type:code id: tags: ``` rust use std::io::copy; use std::io::Cursor; use std::fs::File; use std::path::PathBuf; use tokio; pub fn download_binary(url: String) -> Result<bytes::Bytes, String> { async fn download(url: String) -> Result<bytes::Bytes, String> { pub fn download_binary(url: String, destination: PathBuf) -> Result<PathBuf, String> { async fn download(url: String, destination: PathBuf) -> Result<(), String> { let client = reqwest::Client::new(); let response = client.get(url.clone()).send(); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); match response.await { | Ok(data) => { match data.bytes().await { | Ok(content) => { let mut output = File::create(filename.clone()).unwrap(); copy(&mut Cursor::new(content.clone()), &mut output); println!("Downloaded {filename}"); Ok(content) }, | Err(_) => Err(format!("No content downloaded from {url}")) | Ok(data) => match data.bytes().await { | Ok(content) => { let mut output = File::create(destination.join(filename.clone())).unwrap(); let _ = copy(&mut Cursor::new(content.clone()), &mut output); debug!(filename = filename, "=> {} Downloaded", Label::output()); Ok(()) } | Err(_) => Err(format!("No content downloaded from {url}")), }, | Err(_) => Err(format!("Failed to download {url}")) | Err(_) => Err(format!("Failed to download {url}")), } } let runtime = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); runtime.block_on(download(url.clone())) let _ = runtime.block_on(download(url.clone(), destination.clone())); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); Ok(destination.join(filename)) } ``` %% Cell type:code id: tags: ``` rust let url = "https://code.ornl.gov/api/v4/projects/15383/packages/generic/x86_64-unknown-linux-gnu/v0.0.3/pipe".to_string(); let content = download_binary(url); let content = download_binary(url, PathBuf::from("/root/dev/notebooks")); println!("{:?}", content); ``` %% Output Downloaded pipe %% Cell type:code id: tags: ``` rust let path = "/tmp/pipe/iopbgzaGbV/pipe"; ```
pipe-cli/src/commands/run/mod.rs +76 −21 Original line number Diff line number Diff line Loading @@ -3,11 +3,15 @@ use color_eyre::eyre::Report; use exitcode; use nanoid::nanoid; use pipe_lib::{ get_parent, Command, Config, EnvironmentValue, Label, ModuleLanguage, ModuleType, ModuleUri, Script, ScriptTemplate, TemplateAttribute, download_binary, get_checksum, get_parent, Command, Config, EnvironmentValue, Label, ModuleLanguage, ModuleType, ModuleUri, Script, ScriptTemplate, TemplateAttribute, }; use rayon::prelude::*; use std::convert::TryFrom; use std::env; use std::fs; #[cfg(any(unix, target_os = "wasi", target_os = "redox"))] use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use tracing::{debug, error, info, warn}; use uriparse::Scheme; Loading @@ -15,6 +19,29 @@ use uriparse::URI; const DEFAULT_CONFIG_NAME: &str = "config.json"; #[cfg(any(unix, target_os = "wasi", target_os = "redox"))] fn make_executable(path: &PathBuf) { fs::set_permissions(path, fs::Permissions::from_mode(0o755)).unwrap(); } #[cfg(windows)] fn make_executable(path: &PathBuf) { // TODO: Add windows support...pass through? } fn check_requirements(config: &Config, skip: bool) { if !skip { config.requirements.iter().for_each(|name| { let command = Command::init().name(name.clone()).build(); if !command.test() { error!(name, "=> {} Requirement not met", Label::not_found()); std::process::exit(exitcode::UNAVAILABLE); } }); } else { warn!("Skipping requirements verification"); } } fn check_resources(_config: &Config, _skip: bool) {} #[allow(clippy::too_many_arguments)] pub fn run( config: &Option<PathBuf>, Loading @@ -31,7 +58,7 @@ pub fn run( match std::fs::create_dir_all(root.clone()) { | Ok(_) => { let path = root.clone().into_os_string().into_string().unwrap(); debug!(path, "Created temporary directory"); debug!(path, "=> {} Root directory", Label::using()); } | Err(err) => error!("{}", err), } Loading @@ -49,34 +76,62 @@ pub fn run( }; match Config::read(config_path) { | Some(cfg) => { // Check requirements if !skip_verify_requirements { cfg.requirements.iter().for_each(|name| { let command = Command::init().name(name.clone()).build(); if !command.test() { error!(name, "=> {} Requirement not met", Label::not_found()); std::process::exit(exitcode::UNAVAILABLE); } }); } else { warn!("Skipping requirements verification"); } check_requirements(&cfg, skip_verify_requirements); check_resources(&cfg, false); // // Prepare modules // cfg.modules.par_iter().for_each(|module| match &module.module_type { | ModuleType::Binary { uri, .. } => match ModuleUri::from(uri) { | ModuleType::Binary { uri, checksum } => match ModuleUri::from(uri) { | ModuleUri::Url(value) if !offline => match value.scheme() { | Scheme::HTTP | Scheme::HTTPS | Scheme::SSH => { let url = value.to_string(); debug!(module = module.name, url, "=> {} Remote binary", Label::found()); // TODO: Filter URL using whitelist // TODO: Check that URL exists // TODO: Download binary to temp directory debug!(module = module.name, url, "=> {} Remote binary", Label::found()); if !dry_run { let output = download_binary(url.clone(), root.clone()); if !skip_verify_checksum { // TODO: Verify binary checksum let calculated_checksum = match output.clone() { | Ok(path) => get_checksum(path), | _ => "".to_string(), }; match checksum { | Some(value) if value == &calculated_checksum => { info!(module = module.name, url, "=> {} Checksum verified", Label::pass()); if let Ok(path) = output { make_executable(&path); } } | Some(_) => { error!( module = module.name, url, checksum, calculated = calculated_checksum, "=> {} Remote binary checksum does not match", Label::fail() ); std::process::exit(exitcode::USAGE); } | None => { error!( module = module.name, url, checksum, "=> {} Remote binary checksum does not match", Label::fail() ); std::process::exit(exitcode::UNAVAILABLE); } } // TODO: Verify binary is executable (https://docs.rs/is_executable/latest/is_executable/) } else { warn!("Skipping checksum verification"); } } else { info!(module = module.name, url, "=> {} Download remote binary", Label::dry_run()); } unimplemented!("Remote binary modules are not supported yet"); } | _ => unimplemented!("Only HTTP, HTTPS, and SSH are currently supported for remote binary modules"), Loading
pipe-lib/src/lib.rs +11 −6 Original line number Diff line number Diff line Loading @@ -640,7 +640,7 @@ impl Label { } pub fn fail() -> Styled<&'static &'static str> { let style = Style::new().white().on_red(); " FAIL ".style(style) " ✗ FAIL ".style(style) } pub fn found() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); Loading @@ -654,6 +654,10 @@ impl Label { let style = Style::new().cyan().dimmed().on_default_color(); "OUTPUT".style(style) } pub fn pass() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); "☑ PASS".style(style) } pub fn read() -> Styled<&'static &'static str> { let style = Style::new().green().on_default_color(); "READ".style(style) Loading Loading @@ -1317,15 +1321,15 @@ pub fn add_forward_slash(path: PathBuf) -> PathBuf { path.to_path_buf() } } pub fn download_binary(url: String) -> Result<(), String> { async fn download(url: String) -> Result<(), String> { pub fn download_binary(url: String, destination: PathBuf) -> Result<PathBuf, String> { async fn download(url: String, destination: PathBuf) -> Result<(), String> { let client = reqwest::Client::new(); let response = client.get(url.clone()).send(); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); match response.await { | Ok(data) => match data.bytes().await { | Ok(content) => { let mut output = File::create(filename.clone()).unwrap(); let mut output = File::create(destination.join(filename.clone())).unwrap(); let _ = copy(&mut Cursor::new(content.clone()), &mut output); debug!(filename = filename, "=> {} Downloaded", Label::output()); Ok(()) Loading @@ -1336,8 +1340,9 @@ pub fn download_binary(url: String) -> Result<(), String> { } } let runtime = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); let _ = runtime.block_on(download(url.clone())); Ok(()) let _ = runtime.block_on(download(url.clone(), destination.clone())); let filename = PathBuf::from(url.clone()).file_name().unwrap().to_str().unwrap().to_string(); Ok(destination.join(filename)) } /// Get SHA256 hash of a file pub fn get_checksum(path: PathBuf) -> String { Loading