aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJae-Heon Ji <32578710+jaeheonji@users.noreply.github.com>2023-11-02 21:09:18 +0900
committerGitHub <noreply@github.com>2023-11-02 13:09:18 +0100
commitc87ff8cb2e6667648fc773dd2a811c25579c4ca0 (patch)
tree8757e0a0e69390e9ec6fea67b4eedcce44ff9c8b
parentdocs(changelog): plugin ui components (diff)
downloadsl0ppij-c87ff8cb2e6667648fc773dd2a811c25579c4ca0.tar.gz
sl0ppij-c87ff8cb2e6667648fc773dd2a811c25579c4ca0.tar.xz
sl0ppij-c87ff8cb2e6667648fc773dd2a811c25579c4ca0.zip
feat: load plugins from the web (#2863)
* feat: add basic downloader * feat: add download progress bar * feat: move crate location and some fix * feat: add downloader in layout * chore: remove comment * Revert "feat: add downloader in layout" This reverts commit ac4efb937e88cdb31fe7f18919f9fbe3857054b0. * feat: change http request module to surf * feat: add some function * feat: add plugin download in wasm * feat: add error handling * test: update unittest * feat: change hash library from ring to highway * fix: openssl-sys issue for surf-client * minor adjustments * style(fmt): rustfmt * move openssl-sys back to dependencies --------- Co-authored-by: Aram Drevekenin <aram@poor.dev>
-rw-r--r--Cargo.lock397
-rw-r--r--src/main.rs22
-rw-r--r--zellij-server/src/plugins/wasm_bridge.rs33
-rw-r--r--zellij-utils/Cargo.toml6
-rw-r--r--zellij-utils/src/cli.rs26
-rw-r--r--zellij-utils/src/downloader/download.rs49
-rw-r--r--zellij-utils/src/downloader/mod.rs147
-rw-r--r--zellij-utils/src/input/layout.rs6
-rw-r--r--zellij-utils/src/input/plugins.rs9
-rw-r--r--zellij-utils/src/lib.rs2
10 files changed, 465 insertions, 232 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0f02d18b..f471a020 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -77,7 +77,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
"once_cell",
"version_check",
]
@@ -148,16 +148,6 @@ dependencies = [
]
[[package]]
-name = "async-dup"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c"
-dependencies = [
- "futures-io",
- "simple-mutex",
-]
-
-[[package]]
name = "async-executor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -187,23 +177,6 @@ dependencies = [
]
[[package]]
-name = "async-h1"
-version = "2.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d1d1dae8cb2c4258a79d6ed088b7fb9b4763bf4e9b22d040779761e046a2971"
-dependencies = [
- "async-channel",
- "async-dup",
- "async-global-executor",
- "async-io",
- "futures-lite",
- "http-types",
- "httparse",
- "log",
- "pin-project",
-]
-
-[[package]]
name = "async-io"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -284,19 +257,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
[[package]]
-name = "async-tls"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d85a97c4a0ecce878efd3f945f119c78a646d8975340bca0398f9bb05c30cc52"
-dependencies = [
- "futures-core",
- "futures-io",
- "rustls",
- "webpki",
- "webpki-roots",
-]
-
-[[package]]
name = "async-trait"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -362,12 +322,6 @@ checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
[[package]]
name = "base64"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
-
-[[package]]
-name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
@@ -485,6 +439,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+
+[[package]]
+name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
@@ -503,9 +463,12 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
[[package]]
name = "cfg-if"
@@ -652,17 +615,6 @@ dependencies = [
]
[[package]]
-name = "config"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
-dependencies = [
- "lazy_static",
- "nom 5.1.2",
- "serde",
-]
-
-[[package]]
name = "console"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -908,6 +860,37 @@ dependencies = [
]
[[package]]
+name = "curl"
+version = "0.4.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22"
+dependencies = [
+ "curl-sys",
+ "libc",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "socket2",
+ "winapi",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.4.68+curl-8.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f"
+dependencies = [
+ "cc",
+ "libc",
+ "libnghttp2-sys",
+ "libz-sys",
+ "openssl-sys",
+ "pkg-config",
+ "vcpkg",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "daemonize"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -952,33 +935,6 @@ dependencies = [
]
[[package]]
-name = "dashmap"
-version = "5.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
-dependencies = [
- "cfg-if 1.0.0",
- "hashbrown 0.14.1",
- "lock_api",
- "once_cell",
- "parking_lot_core 0.9.9",
-]
-
-[[package]]
-name = "deadpool"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d126179d86aee4556e54f5f3c6bf6d9884e7cc52cef82f77ee6f90a7747616d"
-dependencies = [
- "async-trait",
- "config",
- "crossbeam-queue",
- "num_cpus",
- "serde",
- "tokio",
-]
-
-[[package]]
name = "deltae"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1294,6 +1250,17 @@ dependencies = [
]
[[package]]
+name = "flume"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bebadab126f8120d410b677ed95eee4ba6eb7c6dd8e34a5ec88a08050e26132"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "spinning_top",
+]
+
+[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1490,9 +1457,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if 1.0.0",
"libc",
@@ -1572,12 +1539,6 @@ dependencies = [
]
[[package]]
-name = "hashbrown"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
-
-[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1640,22 +1601,28 @@ dependencies = [
]
[[package]]
+name = "http"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+dependencies = [
+ "bytes 1.4.0",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
name = "http-client"
version = "6.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1947510dc91e2bf586ea5ffb412caad7673264e14bb39fb9078da114a94ce1a5"
dependencies = [
- "async-h1",
"async-std",
- "async-tls",
"async-trait",
"cfg-if 1.0.0",
- "dashmap",
- "deadpool",
- "futures",
"http-types",
+ "isahc",
"log",
- "rustls",
]
[[package]]
@@ -1681,12 +1648,6 @@ dependencies = [
]
[[package]]
-name = "httparse"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
-
-[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1876,6 +1837,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
[[package]]
+name = "isahc"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2948a0ce43e2c2ef11d7edf6816508998d99e13badd1150be0914205df9388a"
+dependencies = [
+ "bytes 0.5.6",
+ "crossbeam-utils",
+ "curl",
+ "curl-sys",
+ "flume",
+ "futures-lite",
+ "http",
+ "log",
+ "once_cell",
+ "slab",
+ "sluice",
+ "tracing",
+ "tracing-futures",
+ "url",
+ "waker-fn",
+]
+
+[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1964,23 +1948,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72d9d1bd215936bc8647ad92986bb56f3f216550b53c44ab785e3217ae33625e"
[[package]]
-name = "lexical-core"
-version = "0.7.6"
+name = "libc"
+version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
-dependencies = [
- "arrayvec 0.5.2",
- "bitflags",
- "cfg-if 1.0.0",
- "ryu",
- "static_assertions",
-]
+checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
-name = "libc"
-version = "0.2.140"
+name = "libnghttp2-sys"
+version = "0.1.8+1.55.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+checksum = "4fae956c192dadcdb5dace96db71fa0b827333cce7c7b38dc71446f024d8a340"
+dependencies = [
+ "cc",
+ "libc",
+]
[[package]]
name = "libssh2-sys"
@@ -2273,7 +2254,6 @@ version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
- "lexical-core",
"memchr",
"version_check",
]
@@ -2396,6 +2376,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-src"
+version = "300.1.6+3.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "openssl-sys"
version = "0.9.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2403,6 +2398,7 @@ checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
dependencies = [
"cc",
"libc",
+ "openssl-src",
"pkg-config",
"vcpkg",
]
@@ -2793,7 +2789,7 @@ version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"prost-derive",
]
@@ -2803,7 +2799,7 @@ version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"heck 0.4.0",
"itertools",
"lazy_static",
@@ -2941,7 +2937,7 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
]
[[package]]
@@ -3010,7 +3006,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
"redox_syscall 0.2.13",
"thiserror",
]
@@ -3075,21 +3071,6 @@ dependencies = [
]
[[package]]
-name = "ring"
-version = "0.16.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
-dependencies = [
- "cc",
- "libc",
- "once_cell",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
-]
-
-[[package]]
name = "rkyv"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3176,19 +3157,6 @@ dependencies = [
]
[[package]]
-name = "rustls"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81"
-dependencies = [
- "base64 0.12.3",
- "log",
- "ring",
- "sct",
- "webpki",
-]
-
-[[package]]
name = "ryu"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3204,20 +3172,19 @@ dependencies = [
]
[[package]]
-name = "scopeguard"
-version = "1.1.0"
+name = "schannel"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
+dependencies = [
+ "windows-sys 0.48.0",
+]
[[package]]
-name = "sct"
-version = "0.6.1"
+name = "scopeguard"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
-dependencies = [
- "ring",
- "untrusted",
-]
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "seahash"
@@ -3453,15 +3420,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
[[package]]
-name = "simple-mutex"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6"
-dependencies = [
- "event-listener",
-]
-
-[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3499,6 +3457,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
[[package]]
+name = "sluice"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5"
+dependencies = [
+ "async-channel",
+ "futures-core",
+ "futures-io",
+]
+
+[[package]]
name = "smallvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3521,12 +3490,6 @@ dependencies = [
]
[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
name = "spinning"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3536,6 +3499,15 @@ dependencies = [
]
[[package]]
+name = "spinning_top"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
name = "ssh2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3563,12 +3535,6 @@ dependencies = [
]
[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
name = "status-bar"
version = "0.1.0"
dependencies = [
@@ -3736,14 +3702,13 @@ dependencies = [
"async-trait",
"cfg-if 1.0.0",
"futures-util",
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
"http-client",
"http-types",
"log",
"mime_guess",
"once_cell",
"pin-project-lite",
- "rustls",
"serde",
"serde_json",
]
@@ -4021,17 +3986,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
[[package]]
-name = "tokio"
-version = "1.29.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
-dependencies = [
- "autocfg",
- "backtrace",
- "pin-project-lite",
-]
-
-[[package]]
name = "toml"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4074,6 +4028,16 @@ dependencies = [
]
[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
name = "typemap-ors"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4195,12 +4159,6 @@ dependencies = [
]
[[package]]
-name = "untrusted"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
-
-[[package]]
name = "url"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4225,7 +4183,7 @@ version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
"serde",
]
@@ -4429,7 +4387,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "840af6d21701220cb805dc7201af301cb99e9b4f646f48a41befbc1d949f0f90"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"cfg-if 1.0.0",
"indexmap",
"js-sys",
@@ -4590,7 +4548,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bc4fe3b48ccc620901bdcdfac98d8a76ef3487412c221752814750c2e7db4c1"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"thiserror",
"wasmer-vfs",
]
@@ -4601,11 +4559,11 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e893ecd57c63db83b17dacfaee90f660e1d7f5b26d2f9d88ea6aa2e8c4bc301d"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"cfg-if 1.0.0",
"derivative",
"generational-arena",
- "getrandom 0.2.7",
+ "getrandom 0.2.10",
"libc",
"thiserror",
"tracing",
@@ -4625,7 +4583,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd65882d8cee793848776f26e979b7ff3e139d927947d87304c940c89527a730"
dependencies = [
- "bytes",
+ "bytes 1.4.0",
"tracing",
"wasmer-vfs",
"wasmer-vnet",
@@ -4753,25 +4711,6 @@ dependencies = [
]
[[package]]
-name = "webpki"
-version = "0.21.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
-dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f"
-dependencies = [
- "webpki",
-]
-
-[[package]]
name = "wepoll-ffi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5193,6 +5132,7 @@ dependencies = [
"crossbeam",
"directories",
"expect-test",
+ "futures",
"humantime",
"include_dir",
"insta",
@@ -5206,6 +5146,7 @@ dependencies = [
"nix 0.23.1",
"notify-debouncer-full",
"once_cell",
+ "openssl-sys",
"percent-encoding",
"prost",
"prost-build",
diff --git a/src/main.rs b/src/main.rs
index 3d1f37f3..72dce0d2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -46,6 +46,28 @@ fn main() {
commands::send_action_to_session(command_cli_action, opts.session, config);
std::process::exit(0);
}
+ if let Some(Command::Sessions(Sessions::Plugin {
+ url,
+ floating,
+ in_place,
+ configuration,
+ })) = opts.command
+ {
+ let command_cli_action = CliAction::NewPane {
+ command: vec![],
+ plugin: Some(url),
+ direction: None,
+ cwd: None,
+ floating,
+ in_place,
+ name: None,
+ close_on_exit: false,
+ start_suspended: false,
+ configuration,
+ };
+ commands::send_action_to_session(command_cli_action, opts.session, config);
+ std::process::exit(0);
+ }
if let Some(Command::Sessions(Sessions::Edit {
file,
direction,
diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs
index b2ddb992..260740f9 100644
--- a/zellij-server/src/plugins/wasm_bridge.rs
+++ b/zellij-server/src/plugins/wasm_bridge.rs
@@ -4,6 +4,7 @@ use crate::plugins::plugin_map::{AtomicEvent, PluginEnv, PluginMap, RunningPlugi
use crate::plugins::plugin_worker::MessageToWorker;
use crate::plugins::watch_filesystem::watch_filesystem;
use crate::plugins::zellij_exports::{wasi_read_string, wasi_write_object};
+use highway::{HighwayHash, PortableHash};
use log::info;
use std::{
collections::{HashMap, HashSet},
@@ -14,7 +15,10 @@ use std::{
use wasmer::{Module, Store, Value};
use zellij_utils::async_channel::Sender;
use zellij_utils::async_std::task::{self, JoinHandle};
+use zellij_utils::consts::ZELLIJ_CACHE_DIR;
use zellij_utils::data::{PermissionStatus, PermissionType};
+use zellij_utils::downloader::download::Download;
+use zellij_utils::downloader::Downloader;
use zellij_utils::input::permission::PermissionCache;
use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
use zellij_utils::plugin_api::event::ProtobufEvent;
@@ -129,7 +133,7 @@ impl WasmBridge {
let plugin_id = self.next_plugin_id;
- let plugin = self
+ let mut plugin = self
.plugins
.get(run)
.with_context(|| format!("failed to resolve plugin {run:?}"))
@@ -158,6 +162,33 @@ impl WasmBridge {
let _ =
senders.send_to_background_jobs(BackgroundJob::AnimatePluginLoading(plugin_id));
let mut loading_indication = LoadingIndication::new(plugin_name.clone());
+
+ if let RunPluginLocation::Remote(url) = &plugin.location {
+ let download = Download::from(url);
+
+ let hash: String = PortableHash::default()
+ .hash128(download.url.as_bytes())
+ .iter()
+ .map(ToString::to_string)
+ .collect();
+
+ let plugin_directory = ZELLIJ_CACHE_DIR.join(hash);
+
+ // The plugin path is determined by the hash of the plugin URL in the cache directory.
+ plugin.path = plugin_directory.join(&download.file_name);
+
+ let downloader = Downloader::new(plugin_directory);
+ match downloader.fetch(&download).await {
+ Ok(_) => {},
+ Err(e) => handle_plugin_loading_failure(
+ &senders,
+ plugin_id,
+ &mut loading_indication,
+ e,
+ ),
+ }
+ }
+
match PluginLoader::start_plugin(
plugin_id,
client_id,
diff --git a/zellij-utils/Cargo.toml b/zellij-utils/Cargo.toml
index 8845b64f..bb7d0308 100644
--- a/zellij-utils/Cargo.toml
+++ b/zellij-utils/Cargo.toml
@@ -54,7 +54,11 @@ interprocess = "1.2.1"
async-std = { version = "1.3.0", features = ["unstable"] }
notify-debouncer-full = "0.1.0"
humantime = "2.1.0"
-surf = { version = "2.3.2", default-features = false, features = ["h1-client-rustls"] }
+futures = "0.3.28"
+surf = { version = "2.3.2", default-features = false, features = [
+ "curl-client",
+] }
+openssl-sys = { version = "0.9.93", features = ["vendored"] }
[dev-dependencies]
insta = { version = "1.6.0", features = ["backtrace"] }
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index 79aad994..c196c17d 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -217,6 +217,32 @@ pub enum Sessions {
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
start_suspended: bool,
},
+ /// Load a plugin
+ #[clap(visible_alias = "r")]
+ Plugin {
+ /// Plugin URL, can either start with http(s), file: or zellij:
+ #[clap(last(true), required(true))]
+ url: String,
+
+ /// Plugin configuration
+ #[clap(short, long, value_parser)]
+ configuration: Option<PluginUserConfiguration>,
+
+ /// Open the new pane in floating mode
+ #[clap(short, long, value_parser, default_value("false"), takes_value(false))]
+ floating: bool,
+
+ /// Open the new pane in place of the current pane, temporarily suspending it
+ #[clap(
+ short,
+ long,
+ value_parser,
+ default_value("false"),
+ takes_value(false),
+ conflicts_with("floating")
+ )]
+ in_place: bool,
+ },
/// Edit file with default $EDITOR / $VISUAL
#[clap(visible_alias = "e")]
Edit {
diff --git a/zellij-utils/src/downloader/download.rs b/zellij-utils/src/downloader/download.rs
new file mode 100644
index 00000000..d665f7e5
--- /dev/null
+++ b/zellij-utils/src/downloader/download.rs
@@ -0,0 +1,49 @@
+use serde::{Deserialize, Serialize};
+use surf::Url;
+
+#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
+pub struct Download {
+ pub url: String,
+ pub file_name: String,
+}
+
+impl Download {
+ pub fn from(url: &str) -> Self {
+ match Url::parse(url) {
+ Ok(u) => u
+ .path_segments()
+ .map_or_else(Download::default, |segments| {
+ let file_name = segments.last().unwrap_or("").to_string();
+
+ Download {
+ url: url.to_string(),
+ file_name,
+ }
+ }),
+ Err(_) => Download::default(),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_from_download() {
+ let download = Download::from("https://github.com/example/plugin.wasm");
+ assert_eq!(download.url, "https://github.com/example/plugin.wasm");
+ assert_eq!(download.file_name, "plugin.wasm");
+ }
+
+ #[test]
+ fn test_empty_download() {
+ let d1 = Download::from("https://example.com");
+ assert_eq!(d1.url, "https://example.com");
+ assert_eq!(d1.file_name, "");
+
+ let d2 = Download::from("github.com");
+ assert_eq!(d2.url, "");
+ assert_eq!(d2.file_name, "");
+ }
+}
diff --git a/zellij-utils/src/downloader/mod.rs b/zellij-utils/src/downloader/mod.rs
new file mode 100644
index 00000000..b0b2771d
--- /dev/null
+++ b/zellij-utils/src/downloader/mod.rs
@@ -0,0 +1,147 @@
+pub mod download;
+
+use async_std::{
+ fs::{create_dir_all, File},
+ io::{ReadExt, WriteExt},
+ stream, task,
+};
+use futures::{StreamExt, TryStreamExt};
+use std::path::PathBuf;
+use surf::Client;
+use thiserror::Error;
+
+use self::download::Download;
+
+#[derive(Error, Debug)]
+pub enum DownloaderError {
+ #[error("RequestError: {0}")]
+ Request(surf::Error),
+ #[error("StatusError: {0}, StatusCode: {1}")]
+ Status(String, surf::StatusCode),
+ #[error("IoError: {0}")]
+ Io(#[source] std::io::Error),
+ #[error("IoPathError: {0}, File: {1}")]
+ IoPath(std::io::Error, PathBuf),
+}
+
+#[derive(Default, Debug)]
+pub struct Downloader {
+ client: Client,
+ directory: PathBuf,
+}
+
+impl Downloader {
+ pub fn new(directory: PathBuf) -> Self {
+ Self {
+ client: surf::client().with(surf::middleware::Redirect::default()),
+ directory,
+ }
+ }
+
+ pub fn set_directory(&mut self, directory: PathBuf) {
+ self.directory = directory;
+ }
+
+ pub fn download(&self, downloads: &[Download]) -> Vec<Result<(), DownloaderError>> {
+ task::block_on(async {
+ stream::from_iter(downloads)
+ .map(|download| self.fetch(download))
+ .buffer_unordered(4)
+ .collect::<Vec<_>>()
+ .await
+ })
+ }
+
+ pub async fn fetch(&self, download: &Download) -> Result<(), DownloaderError> {
+ let mut file_size: usize = 0;
+
+ let file_path = self.directory.join(&download.file_name);
+
+ if file_path.exists() {
+ file_size = match file_path.metadata() {
+ Ok(metadata) => metadata.len() as usize,
+ Err(e) => return Err(DownloaderError::IoPath(e, file_path)),
+ }
+ }
+
+ let response = self
+ .client
+ .get(&download.url)
+ .await
+ .map_err(|e| DownloaderError::Request(e))?;
+ let status = response.status();
+
+ if status.is_client_error() || status.is_server_error() {
+ return Err(DownloaderError::Status(
+ status.canonical_reason().to_string(),
+ status,
+ ));
+ }
+
+ let length = response.len().unwrap_or(0);
+ if length > 0 && length == file_size {
+ return Ok(());
+ }
+
+ let mut dest = {
+ create_dir_all(&self.directory)
+ .await
+ .map_err(|e| DownloaderError::IoPath(e, self.directory.clone()))?;
+ File::create(&file_path)
+ .await
+ .map_err(|e| DownloaderError::IoPath(e, file_path))?
+ };
+
+ let mut bytes = response.bytes();
+ while let Some(byte) = bytes.try_next().await.map_err(DownloaderError::Io)? {
+ dest.write_all(&[byte]).await.map_err(DownloaderError::Io)?;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ use tempfile::tempdir;
+
+ #[test]
+ #[ignore]
+ fn test_fetch_plugin() {
+ let dir = tempdir().expect("could not get temp dir");
+ let dir_path = dir.path();
+
+ let downloader = Downloader::new(dir_path.to_path_buf());
+ let dl = Download::from(
+ "https://github.com/imsnif/monocle/releases/download/0.37.2/monocle.wasm",
+ );
+
+ let result = task::block_on(downloader.fetch(&dl));
+
+ assert!(result.is_ok());
+ }
+
+ #[test]
+ #[ignore]
+ fn test_download_plugins() {
+ let dir = tempdir().expect("could not get temp dir");
+ let dir_path = dir.path();
+
+ let downloader = Downloader::new(dir_path.to_path_buf());
+ let downloads = vec![
+ Download::from(
+ "https://github.com/imsnif/monocle/releases/download/0.37.2/monocle.wasm",
+ ),
+ Download::from(
+ "https://github.com/imsnif/multitask/releases/download/0.38.2/multitask.wasm",
+ ),
+ ];
+
+ let results = downloader.download(&downloads);
+ for result in results {
+ assert!(result.is_ok())
+ }
+ }
+}
diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs
index ace471f8..312286ec 100644
--- a/zellij-utils/src/input/layout.rs
+++ b/zellij-utils/src/input/layout.rs
@@ -287,6 +287,7 @@ impl FromStr for PluginUserConfiguration {
pub enum RunPluginLocation {
File(PathBuf),
Zellij(PluginTag),
+ Remote(String),
}
impl Default for RunPluginLocation {
@@ -332,6 +333,7 @@ impl RunPluginLocation {
};
Ok(Self::File(path))
},
+ "https" | "http" => Ok(Self::Remote(url.as_str().to_owned())),
_ => Err(PluginsConfigError::InvalidUrlScheme(url)),
}
}
@@ -339,6 +341,7 @@ impl RunPluginLocation {
match self {
RunPluginLocation::File(pathbuf) => format!("file:{}", pathbuf.display()),
RunPluginLocation::Zellij(plugin_tag) => format!("zellij:{}", plugin_tag),
+ RunPluginLocation::Remote(url) => format!("remote:{}", url),
}
}
}
@@ -351,6 +354,7 @@ impl From<&RunPluginLocation> for Url {
path.clone().into_os_string().into_string().unwrap()
),
RunPluginLocation::Zellij(tag) => format!("zellij:{}", tag),
+ RunPluginLocation::Remote(url) => format!("remote:{}", url),
};
Self::parse(&url).unwrap()
}
@@ -364,8 +368,8 @@ impl fmt::Display for RunPluginLocation {
"{}",
path.clone().into_os_string().into_string().unwrap()
),
-
Self::Zellij(tag) => write!(f, "{}", tag),
+ Self::Remote(url) => write!(f, "{}", url),
}
}
}
diff --git a/zellij-utils/src/input/plugins.rs b/zellij-utils/src/input/plugins.rs
index f12aba2a..2a262222 100644
--- a/zellij-utils/src/input/plugins.rs
+++ b/zellij-utils/src/input/plugins.rs
@@ -55,6 +55,13 @@ impl PluginsConfig {
userspace_configuration: run.configuration.clone(),
..plugin
}),
+ RunPluginLocation::Remote(_) => Some(PluginConfig {
+ path: PathBuf::new(),
+ run: PluginType::Pane(None),
+ _allow_exec_host_cmd: run._allow_exec_host_cmd,
+ location: run.location.clone(),
+ userspace_configuration: run.configuration.clone(),
+ }),
}
}
@@ -231,7 +238,7 @@ pub enum PluginsConfigError {
DuplicatePlugins(PluginTag),
#[error("Failed to parse url: {0:?}")]
InvalidUrl(#[from] url::ParseError),
- #[error("Only 'file:' and 'zellij:' url schemes are supported for plugin lookup. '{0}' does not match either.")]
+ #[error("Only 'file:', 'http(s):' and 'zellij:' url schemes are supported for plugin lookup. '{0}' does not match either.")]
InvalidUrlScheme(Url),
#[error("Could not find plugin at the path: '{0:?}'")]
InvalidPluginLocation(PathBuf),
diff --git a/zellij-utils/src/lib.rs b/zellij-utils/src/lib.rs
index 5438f323..05752e21 100644
--- a/zellij-utils/src/lib.rs
+++ b/zellij-utils/src/lib.rs
@@ -17,6 +17,8 @@ pub mod shared;
#[cfg(not(target_family = "wasm"))]
pub mod channels; // Requires async_std
#[cfg(not(target_family = "wasm"))]
+pub mod downloader; // Requires async_std
+#[cfg(not(target_family = "wasm"))]
pub mod ipc; // Requires interprocess
#[cfg(not(target_family = "wasm"))]
pub mod logging; // Requires log4rs