├── .gitignore
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature-request.yml
│ └── bug-report.yml
├── dependabot.yml
├── releaser.sh
└── workflows
│ ├── build-app.yml
│ ├── test-args.yml
│ └── release.yml
├── src
├── main.rs
├── commands
│ ├── mod.rs
│ ├── query.rs
│ ├── health.rs
│ ├── remove.rs
│ ├── list.rs
│ ├── install.rs
│ └── search.rs
├── lib.rs
└── engine
│ ├── msgx.rs
│ ├── init.rs
│ ├── mod.rs
│ ├── args.rs
│ ├── request.rs
│ ├── config.rs
│ └── helpers.rs
├── LICENSE
├── Cargo.toml
├── cliff.toml
├── CHANGELOG.md
├── README.md
└── Cargo.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | ko_fi: pwnwriter
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | #[tokio::main]
2 | async fn main() {
3 | hysp::engine::init::exec().await;
4 | }
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # version: 2
2 | # updates:
3 | # # Maintain dependencies for Cargo
4 | # - package-ecosystem: cargo
5 | # directory: "/"
6 | # schedule:
7 | # interval: daily
8 | # open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.github/releaser.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Trigger release action on new release
4 |
5 | if [ -z "$1" ]; then
6 | echo "Please provide a version number."
7 | echo "Usages: $0 v[X.Y.Z]"
8 | exit 1
9 | fi
10 |
11 | version=$1
12 |
13 | git tag "v$version"
14 | git push origin "v$version"
15 |
--------------------------------------------------------------------------------
/src/commands/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod health;
2 | pub mod install;
3 | pub mod list;
4 | pub mod query;
5 | pub mod remove;
6 | pub mod search;
7 |
8 | pub mod ui {
9 |
10 | pub const BAR: &str = r"────────────────────────────────────────────";
11 |
12 | pub const RESET: &str = "\x1B[0m"; // (resets the text color to the default)
13 |
14 | pub const ASCII: &str = "
15 |
16 | *ੈ✩‧₊˚ *ੈ✩‧₊˚
17 | __ _
18 | _( )_( )_
19 | (_ _ _)
20 | (_) (__)
21 |
22 | *ੈ✩‧₊˚ *ੈ✩‧₊˚
23 | ";
24 | }
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Describe a feature you want to see
3 | labels: [feature-request]
4 | body:
5 | - type: textarea
6 | attributes:
7 | label: "Description"
8 | description: "A clear and concise description of the feature you are requesting"
9 | validations:
10 | required: true
11 | - type: input
12 | attributes:
13 | label: "Related Documentation or Links"
14 | description: "Provide any supporting documents, links, or references that can help in understanding or implementing the feature."
15 | validations:
16 | required: false
17 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod commands;
2 | pub mod engine;
3 |
4 | //
5 | // ✮ ┓┏ ✮
6 | // ┣┫┓┏┏┏┓
7 | // ┛┗┗┫┛┣┛
8 | // ┛ ┛ @github.com/pwnwriter/hysp
9 | //
10 | // Copyright (c) 2023 Nabeen Tiwaree < pwnwriter.xyz >
11 | //
12 | // Permission is hereby granted, free of charge, to any person obtaining a copy
13 | // of this software and associated documentation files (the "Software"), to deal
14 | // in the Software without restriction, including without limitation the rights
15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | // copies of the Software, and to permit persons to whom the Software is
17 | // furnished to do so.
18 |
--------------------------------------------------------------------------------
/.github/workflows/build-app.yml:
--------------------------------------------------------------------------------
1 | # name: build hysp on matrix
2 | #
3 | # on:
4 | # push:
5 | # branches:
6 | # - main
7 | # pull_request:
8 | # branches:
9 | # - main
10 | #
11 | # env:
12 | # CARGO_TERM_COLOR: always
13 | #
14 | # jobs:
15 | # build:
16 | # runs-on: ubuntu-latest
17 | # strategy:
18 | # matrix:
19 | # toolchain:
20 | # - stable
21 | # - beta
22 | # - nightly
23 | #
24 | # steps:
25 | # - name: Checkout code
26 | # uses: actions/checkout@v2
27 | #
28 | # - name: Set up Rust
29 | # run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
30 | #
31 | # - name: Build
32 | # run: |
33 | # cargo build --verbose
34 | #
35 |
--------------------------------------------------------------------------------
/src/engine/msgx.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 |
3 | use colored::{Color, Colorize};
4 |
5 | /// Prints the given message to the console and aborts the process.
6 | pub fn abort(msg: &str) -> ! {
7 | eprintln!("Error: {}", msg);
8 | std::process::exit(1);
9 | }
10 |
11 | pub fn info(msg: &str, color: Color) {
12 | println!("{}: {}", "Info".bold().color(color), msg);
13 | }
14 |
15 | pub fn message(msg: &str, color: Color) {
16 | println!("Message: {}", msg.bold().color(color));
17 | }
18 |
19 | pub fn error(msg: &str) {
20 | println!("{}: {}", "Error".bold().color(Color::Red), msg);
21 | }
22 |
23 | pub fn success(msg: &str) {
24 | println!("{}: {}", "Success".bold().color(Color::Green), msg);
25 | }
26 |
27 | pub fn warn(msg: &str, color: Color) {
28 | println!("{}: {}", "Warning".bold().color(color), msg);
29 | }
30 |
--------------------------------------------------------------------------------
/src/engine/init.rs:
--------------------------------------------------------------------------------
1 | use crate::commands;
2 | use crate::engine::args::CommandChoice;
3 | use crate::engine::msgx::abort;
4 | use clap::Parser;
5 |
6 | pub async fn exec() {
7 | let cli = crate::engine::args::Cli::parse();
8 |
9 | let result = match cli.command {
10 | CommandChoice::Install(pkg_install_args) => {
11 | commands::install::install_packages(pkg_install_args).await
12 | }
13 |
14 | CommandChoice::Remove(pkg_uninstall_args) => {
15 | commands::remove::remove_pkgs(pkg_uninstall_args).await
16 | }
17 |
18 | CommandChoice::Search(pkg_search_args) => {
19 | commands::search::search_pkgs(pkg_search_args).await
20 | }
21 |
22 | CommandChoice::List(pkg_list_args) => commands::list::list_pkgs(pkg_list_args).await,
23 | CommandChoice::Query(pkg_query_args) => commands::query::query_info(pkg_query_args).await,
24 | CommandChoice::Health => commands::health::check_health().await,
25 | };
26 |
27 | if let Err(err) = result {
28 | abort(&format!("{}", err));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Nabeen Tiwaree < pwnwriter.xyz >
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/engine/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod args;
2 | pub mod config;
3 | pub mod helpers;
4 | pub mod init;
5 | pub mod msgx;
6 | pub mod request;
7 |
8 | pub mod hysp_ui {
9 | use colored::Colorize;
10 |
11 | pub static SPLASHES: &[&str] = &[
12 | "There are reasons to use rust. - PwnWriter",
13 | "whatsoever a man soweth, that shall he also reap. - Dylanaraps",
14 | "Harmonizing Your System",
15 | ];
16 |
17 | fn generate_random_number() -> usize {
18 | let current_time = std::time::SystemTime::now()
19 | .duration_since(std::time::SystemTime::UNIX_EPOCH)
20 | .expect("Time went backwards")
21 | .as_micros();
22 |
23 | (current_time % SPLASHES.len() as u128) as usize
24 | }
25 |
26 | pub fn show_splashes() -> String {
27 | let rng = generate_random_number();
28 |
29 | let app_version = env!("CARGO_PKG_VERSION");
30 |
31 | let logo = format!(
32 | r#"
33 | ✮ ┓┏ ✮
34 | ┣┫┓┏┏┏┓
35 | ┛┗┗┫┛┣┛
36 | ┛ ┛ v{}
37 |
38 | "#,
39 | app_version,
40 | )
41 | .bold()
42 | .purple();
43 | let splash = SPLASHES[rng].italic().white();
44 | format!("{logo} {splash}")
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/.github/workflows/test-args.yml:
--------------------------------------------------------------------------------
1 | # name: Test hysp commands // args
2 | #
3 | # on:
4 | # push:
5 | # branches:
6 | # - main
7 | # pull_request:
8 | # branches:
9 | # - main
10 | #
11 | # env:
12 | # CARGO_TERM_COLOR: always
13 | #
14 | # jobs:
15 | # build:
16 | # runs-on: ubuntu-latest
17 | # strategy:
18 | # matrix:
19 | # toolchain:
20 | # - stable
21 | # # - beta
22 | # # - nightly
23 | #
24 | # steps:
25 | # - name: Checkout code
26 | # uses: actions/checkout@v2
27 | #
28 | # - name: Set up Rust
29 | # run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
30 | #
31 | # - name: build and install hysp
32 | # run: |
33 | # cargo build --release --locked
34 | # mv $(find -type f -name hysp) /usr/local/bin && echo "Moved hysp"
35 | # if ! command -v hysp &> /dev/null; then
36 | # echo "hysp is not installed properly."
37 | # exit 1
38 | # fi
39 | #
40 | # - name: Check hysp install arg
41 | # run: |
42 | # hysp install -p nuclei
43 | # hysp health
44 | #
45 | #
46 | # - name: Check hysp uninstall arg
47 | # run: |
48 | # hysp remove -p nuclei --force
49 | # hysp health
50 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | description: Report a problem
3 | labels: [bug]
4 | body:
5 | - type: textarea
6 | attributes:
7 | label: "Description"
8 | description: "A brief summary of the issue"
9 | validations:
10 | required: true
11 | - type: input
12 | attributes:
13 | label: "Software Version"
14 | description: "Please provide the version number, e.g., `0.1.1`"
15 | validations:
16 | required: true
17 | - type: textarea
18 | attributes:
19 | label: "Steps to Reproduce"
20 | description: "Detailed steps to reproduce the issue. If possible, please provide a sample command or actions taken."
21 | validations:
22 | required: true
23 | - type: textarea
24 | attributes:
25 | label: "Expected Behavior"
26 | description: "A clear description of what you expected to happen"
27 | validations:
28 | required: true
29 | - type: textarea
30 | attributes:
31 | label: "Actual Behavior"
32 | description: "A description of the behavior you observed. Feel free to include images, gifs, or any other supporting materials."
33 | validations:
34 | required: true
35 | - type: textarea
36 | attributes:
37 | label: "Additional Information"
38 | description: "Any additional information that might be helpful in understanding the context or environment in which the issue occurred"
39 | validations:
40 | required: false
41 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "hysp"
3 | version = "0.1.2"
4 | edition = "2021"
5 | authors = [ "PwnWriter < hey@pwnwriter.xyz >" ]
6 | description = "📦 An independent package manager that every hacker deserves."
7 | readme = "README.md"
8 | repository = "https://github.com/pwnwriter/hysp"
9 | homepage = "https://github.com/pwnwriter/hysp.git"
10 | license = "MIT"
11 | keywords = ["package-manager", "ctf-tool-download", "pentesting", "pkgs"]
12 | categories = ["accessibility", "web-programming", "command-line" ]
13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
14 |
15 | [dependencies]
16 | reqwest = { version = "0.11.23", default-features = false, features = ["rustls-tls"] }
17 | spinoff = { version = "0.8.0", features = ["dots", "arc", "line"] }
18 | clap = { version = "4.4.11", features = ["string", "derive"] }
19 | serde = { version = "1.0.197", features = ["derive"] }
20 | tokio = { version = "1.35.1", features = ["full"] }
21 | async-recursion = "1.0.5"
22 | anyhow = "1.0.80"
23 | colored = "2.1.0"
24 | toml = "0.8.8"
25 | columns = "0.1.0"
26 | dirs = "5.0.1"
27 | sha2 = "0.10.8"
28 |
29 |
30 | [profile.dev]
31 | opt-level = 0
32 | debug = true
33 | panic = "abort"
34 |
35 | [profile.test]
36 | opt-level = 0
37 | debug = true
38 |
39 | [profile.release]
40 | opt-level = 3
41 | debug = false
42 | panic = "unwind"
43 | lto = true
44 | codegen-units = 1
45 |
46 | [profile.bench]
47 | opt-level = 3
48 | debug = false
49 |
50 |
--------------------------------------------------------------------------------
/cliff.toml:
--------------------------------------------------------------------------------
1 | [changelog]
2 | header = """
3 |
All changes of this release are documented here.
4 |
5 | 
6 |
7 | > *Note*: ***The 🚨emoji indicates significant changes in the commit.***
8 | """
9 |
10 | body = """
11 | {% for group, commits in commits | group_by(attribute="group") %}
12 | ## {{ group }}
13 | {% for commit in commits %}
14 | - [`{{ commit.id | truncate(length=7,end="") }}`](https://github.com/pwnwriter/hysp/commit/{{ commit.id }}): {% if commit.breaking %}🚨 {% endif %}{{ commit.message | upper_first }}.
15 | {% endfor %}
16 | {% endfor %}
17 | """
18 |
19 | footer = """
20 |
21 | 
22 | """
23 |
24 | [git]
25 | filter_commits = true
26 | commit_parsers = [
27 | { message = "^feat", group = "🦁Features" },
28 | { message = "^fix", group = "👨🏻🔧**Bug Fixes**" },
29 | { message = "^docx", group = "Documentation" },
30 | { message = "^perf", group = "🐶Performance" },
31 | { message = "^refactor", group = "✨Refactor" },
32 | { message = "^beautify", group = "🌈 Beautify" },
33 | { message = "^test", group = "🌝Testing" },
34 | { message = "^chore", group = "☃️ Miscellaneous Tasks"},
35 | { message = "^enhan", group = "🍂Enhancements" }
36 | ]
37 |
--------------------------------------------------------------------------------
/src/commands/query.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::{args::QueryArgs, msgx::abort};
2 | use anyhow::Result;
3 |
4 | pub async fn query_info(pkg_query_args: QueryArgs) -> Result<()> {
5 | match (
6 | pkg_query_args.print_default_config,
7 | pkg_query_args.print_example_package,
8 | ) {
9 | (true, false) => {
10 | print_default_config();
11 | }
12 | (false, true) => {
13 | print_example_pkg_toml();
14 | }
15 | _ => {
16 | abort("No such arg available");
17 | }
18 | }
19 |
20 | Ok(())
21 | }
22 |
23 | fn print_example_pkg_toml() {
24 | let example_toml = "
25 | [bin]
26 | name = \"$BIN\" # Name of the pkg to be installed as
27 |
28 | [package]
29 | architecture = \"x86_64\" # Your architecture
30 | name = \"$BIN\" # Your package name
31 | description = \"$DESCRIPTION\" # Description
32 | author = \"$AUTHOR\" # Author
33 | repo = \"$REPO_URL\"
34 | stars = \"${STARS}\"
35 | version = \"$PKG_VERSION\"
36 | updated = \"$PKG_RELEASED\"
37 | size = \"$SIZE\"
38 | sha = \"$SHA\"
39 | source = \"$SOURCE_URL\" # Source of the binary wherever it's hosted
40 | language = \"$LANGUAGE\"
41 | license = \"$LICENSE\"
42 |
43 | [package.conditions]
44 | conflicts = [\"$BIN\"] # Conflicts
45 | requires = [] # Dependencies
46 |
47 | [package.metadata]
48 | keywords = $TOPICS
49 | categories = [\"Utilities\"]
50 | ";
51 |
52 | println!("{}", example_toml);
53 | }
54 | fn print_default_config() {
55 | let def_toml = "
56 | [source]
57 | remote = \"https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/x86_64\"
58 | metadata =\"https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/metadata.toml\"
59 | aarch = \"Architecture\"
60 |
61 | [local]
62 | home=\"/home/user/.local/share/hysp\"
63 | bin=\"/home/user/.local/share/hysp/bin/\"
64 | data=\"/home/user/.local/share/hysp/data/\"
65 | ";
66 |
67 | println!("{}", def_toml);
68 | }
69 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # name: Continuous Deployment
2 | #
3 | # on:
4 | # push:
5 | # tags:
6 | # - "v*.*.*"
7 | #
8 | # jobs:
9 | # publish-github:
10 | # name: Publish on GitHub
11 | # runs-on: ${{ matrix.config.OS }}
12 | # strategy:
13 | # fail-fast: false
14 | # matrix:
15 | # config:
16 | # - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-gnu" }
17 | # - { OS: ubuntu-latest, TARGET: "x86_64-unknown-linux-musl" }
18 | # - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-gnu" }
19 | # - { OS: ubuntu-latest, TARGET: "i686-unknown-linux-musl" }
20 | # - { OS: ubuntu-latest, TARGET: "armv5te-unknown-linux-gnueabi" }
21 | # - { OS: ubuntu-latest, TARGET: "armv7-unknown-linux-gnueabihf" }
22 | # - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-gnu" }
23 | # - { OS: ubuntu-latest, TARGET: "aarch64-unknown-linux-musl" }
24 | # - { OS: macos-latest, TARGET: "x86_64-apple-darwin" }
25 | # - { OS: macos-latest, TARGET: "aarch64-apple-darwin" }
26 | # # - { OS: windows-latest, TARGET: "x86_64-pc-windows-msvc" }
27 | # # - { OS: windows-latest, TARGET: "i686-pc-windows-msvc" }
28 | #
29 | # steps:
30 | # - name: Checkout the repository
31 | # uses: actions/checkout@v3
32 | #
33 | # - name: Set the release version
34 | # shell: bash
35 | # run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV
36 | #
37 | # - name: Install Rust
38 | # uses: actions-rs/toolchain@v1
39 | # with:
40 | # toolchain: stable
41 | # target: ${{ matrix.config.TARGET }}
42 | # override: true
43 | #
44 | # - name: Build
45 | # uses: actions-rs/cargo@v1
46 | # with:
47 | # use-cross: true
48 | # command: build
49 | # args: --release --locked --target ${{ matrix.config.TARGET }}
50 | #
51 | # - name: Prepare release assets
52 | # shell: bash
53 | # run: |
54 | # mkdir release/
55 | # cp {LICENSE,README.md} release/
56 | # cp target/${{ matrix.config.TARGET }}/release/hysp release/
57 | # mv release/ hysp-${{ env.RELEASE_VERSION }}/
58 | #
59 | # - name: Create release artifacts
60 | # shell: bash
61 | # run: |
62 | # if [ "${{ matrix.config.OS }}" = "windows-latest" ]; then
63 | # 7z a -tzip "hysp-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.zip" \
64 | # hysp-${{ env.RELEASE_VERSION }}
65 | # else
66 | # tar -czvf hysp-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
67 | # hysp-${{ env.RELEASE_VERSION }}/
68 | # shasum -a 512 hysp-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz \
69 | # > hysp-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.tar.gz.sha512
70 | # fi
71 | #
72 | # - name: Upload the release
73 | # uses: svenstaro/upload-release-action@v2
74 | # with:
75 | # repo_token: ${{ secrets.GITHUB_TOKEN }}
76 | # file: hysp-${{ env.RELEASE_VERSION }}-${{ matrix.config.TARGET }}.*
77 | # file_glob: true
78 | # overwrite: true
79 | # tag: ${{ github.ref }}
80 | #
81 | # publish-crates-io:
82 | # name: Publish on crates.io
83 | # needs: publish-github
84 | # runs-on: ubuntu-latest
85 | # steps:
86 | # - name: Checkout the repository
87 | # uses: actions/checkout@v3
88 | #
89 | # - name: Publish
90 | # uses: actions-rs/cargo@v1
91 | # with:
92 | # command: publish
93 | # args: --locked --token ${{ secrets.CARGO_TOKEN }}
94 |
--------------------------------------------------------------------------------
/src/commands/health.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::{helpers::local_config, msgx::info};
2 | use anyhow::Result;
3 | use std::env;
4 | use std::fs;
5 | use std::os::unix::fs::PermissionsExt;
6 | use std::path::Path;
7 |
8 | enum Health {
9 | ExistsWithPermissions,
10 | ExistsWithoutPermissions,
11 | DoesNotExist,
12 | }
13 |
14 | pub async fn check_health() -> Result<()> {
15 | let (_hysp_remote, hysp_data_dir, hysp_bin_dir, _hysp_metadata, _architecture) =
16 | match local_config().await {
17 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
18 | (remote, data_dir, bin_dir, metadata, architecture)
19 | }
20 | Err(err) => {
21 | eprintln!("{}", err);
22 | std::process::exit(1);
23 | }
24 | };
25 |
26 | check_and_log_directory("Hysp data", &hysp_data_dir).await?;
27 | check_and_log_directory("Hysp bin", &hysp_bin_dir).await?;
28 |
29 | if is_directory_in_path(&hysp_bin_dir) {
30 | info(
31 | &format!("Hysp bin directory {}: is in PATH", hysp_bin_dir),
32 | colored::Color::BrightBlue,
33 | );
34 | } else {
35 | info(
36 | &format!("Hysp bin directory {}: isn't in PATH", hysp_bin_dir),
37 | colored::Color::Red,
38 | );
39 | }
40 |
41 | Ok(())
42 | }
43 |
44 | fn check_directory(path: &str) -> Result {
45 | match fs::metadata(path) {
46 | Ok(metadata) => {
47 | if metadata.is_dir() {
48 | let permissions = metadata.permissions();
49 | let mode = permissions.mode();
50 |
51 | if mode & 0o600 == 0o600 {
52 | Ok(Health::ExistsWithPermissions)
53 | } else {
54 | Ok(Health::ExistsWithoutPermissions)
55 | }
56 | } else {
57 | Err(anyhow::anyhow!(
58 | "Path exists but is not a directory: {}",
59 | path
60 | ))
61 | }
62 | }
63 | Err(e) => {
64 | if let std::io::ErrorKind::NotFound = e.kind() {
65 | info(
66 | &format!("Path doesn't exist: {}", path),
67 | colored::Color::Cyan,
68 | );
69 | Ok(Health::DoesNotExist)
70 | } else {
71 | Err(e.into())
72 | }
73 | }
74 | }
75 | }
76 | async fn check_and_log_directory(dir_name: &str, dir_path: &str) -> Result<()> {
77 | match check_directory(dir_path)? {
78 | Health::ExistsWithPermissions => info(
79 | &format!(
80 | "{} directory exists with required permissions at: {} ",
81 | dir_name, dir_path
82 | ),
83 | colored::Color::Cyan,
84 | ),
85 | Health::ExistsWithoutPermissions => info(
86 | &format!(
87 | "{} directory exists but doesn't have enough permissions at: {} ",
88 | dir_name, dir_path
89 | ),
90 | colored::Color::Red,
91 | ),
92 | Health::DoesNotExist => info(
93 | &format!("{} directory doesn't exist at: {} ", dir_name, dir_path),
94 | colored::Color::BrightRed,
95 | ),
96 | };
97 | Ok(())
98 | }
99 |
100 | fn is_directory_in_path(directory: &str) -> bool {
101 | if let Some(paths) = env::var_os("PATH") {
102 | if let Some(paths_str) = paths.to_str() {
103 | let path_list: Vec<&str> = paths_str.split(':').collect();
104 | let dir_path = Path::new(directory);
105 |
106 | for path in path_list {
107 | if Path::new(path) == dir_path {
108 | return true;
109 | }
110 | }
111 | }
112 | }
113 | false
114 | }
115 |
--------------------------------------------------------------------------------
/src/commands/remove.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::helpers::remove_and_print;
2 | use crate::engine::{
3 | args::RemoveArgs,
4 | config::pkg_config_structure::PackageInfo,
5 | helpers::{
6 | local_config, print_package_info, prompt_yn, read_file_content, remove_trailing_slash,
7 | },
8 | msgx::info,
9 | };
10 | use anyhow::Result;
11 |
12 | pub async fn remove_pkgs(pkg_remove_args: RemoveArgs) -> Result<()> {
13 | for package in pkg_remove_args.packages {
14 | remove_package(&package, pkg_remove_args.force, pkg_remove_args.quiet).await?;
15 | }
16 | Ok(())
17 | }
18 |
19 | pub async fn remove_package(package_name: &str, force: bool, quiet: bool) -> Result<()> {
20 | let (_hysp_remote, hysp_data_dir, hysp_bin_dir, _hysp_metadata, _architecture) =
21 | match local_config().await {
22 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
23 | (remote, data_dir, bin_dir, metadata, architecture)
24 | }
25 | Err(err) => {
26 | eprintln!("{}", err);
27 | std::process::exit(1);
28 | }
29 | };
30 |
31 | let package_toml_path = format!(
32 | "{}/{}.toml",
33 | remove_trailing_slash(hysp_data_dir.clone()),
34 | package_name
35 | );
36 |
37 | let package_toml = read_file_content(&package_toml_path).await;
38 | match package_toml {
39 | Ok(package_toml) => {
40 | let parsed_package_info: PackageInfo = toml::from_str(&package_toml)?;
41 |
42 | if !quiet {
43 | print_package_info(parsed_package_info.clone());
44 | }
45 |
46 | let package_binary_name = parsed_package_info.bin.name;
47 | let package_binary_path = format!(
48 | "{}/{}",
49 | remove_trailing_slash(hysp_bin_dir.clone()),
50 | package_binary_name
51 | );
52 |
53 | if !force {
54 | info(
55 | &format!("Removing package : {} ", package_binary_name),
56 | colored::Color::Cyan,
57 | );
58 | if !prompt_yn("Would you like to proceed with the transaction (y/n)? ".to_string())
59 | {
60 | return Ok(());
61 | }
62 | }
63 |
64 | let dependencies: Vec = parsed_package_info.package.conditions.requires;
65 | let dependencies_str: String = dependencies.join(", ");
66 |
67 | if !dependencies.is_empty() {
68 | info(
69 | &format!("Dependencies detected, removing : {} ", dependencies_str),
70 | colored::Color::Cyan,
71 | );
72 | }
73 |
74 | for dependency in dependencies {
75 | let dependent_toml_path = format!(
76 | "{}/{}.toml",
77 | remove_trailing_slash(hysp_data_dir.clone()),
78 | dependency
79 | );
80 |
81 | let dependent_package_toml = read_file_content(&dependent_toml_path).await?;
82 |
83 | let parsed_dependent_package_info: PackageInfo =
84 | toml::from_str(&dependent_package_toml)?;
85 |
86 | let dependent_binary_path = format!(
87 | "{}/{}",
88 | remove_trailing_slash(hysp_bin_dir.clone()),
89 | parsed_dependent_package_info.bin.name
90 | );
91 | remove_and_print(&dependent_binary_path);
92 | remove_and_print(&dependent_toml_path);
93 | }
94 |
95 | remove_and_print(&package_binary_path);
96 | remove_and_print(&package_toml_path);
97 |
98 | Ok(())
99 | }
100 | Err(_e) => {
101 | info(
102 | &format!("No such package found as : {} ", package_toml_path),
103 | colored::Color::Cyan,
104 | );
105 | Ok(())
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/engine/args.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::hysp_ui::show_splashes;
2 | use clap::{Args, Parser, Subcommand, ValueEnum};
3 |
4 | /// The HYSP CLI.
5 | #[derive(Parser)]
6 | #[command(author, version, about = show_splashes(), long_about = show_splashes())]
7 | #[command(propagate_version = true)]
8 | #[command(arg_required_else_help = true)]
9 | pub struct Cli {
10 | /// The command to execute.
11 | #[clap(subcommand)]
12 | pub command: CommandChoice,
13 | }
14 |
15 | #[derive(Subcommand)]
16 | pub enum CommandChoice {
17 | /// Install packages
18 | #[command(arg_required_else_help = true)]
19 | #[clap(name = "install", visible_alias = "i")]
20 | Install(InstallArgs),
21 |
22 | /// Uninstall packages
23 | #[command(arg_required_else_help = true)]
24 | #[clap(name = "remove", visible_alias = "r")]
25 | Remove(RemoveArgs),
26 |
27 | /// Search for a package
28 | #[command(arg_required_else_help = true)]
29 | #[clap(name = "search", visible_alias = "s")]
30 | Search(SearchArgs),
31 |
32 | /// List installed pkgs
33 | #[clap(name = "list", visible_alias = "l")]
34 | List(ListArgs),
35 |
36 | /// Check configuration health
37 | #[clap(name = "health", visible_alias = "h")]
38 | Health,
39 |
40 | /// Misc queries and helpers
41 | #[clap(name = "query", visible_alias = "q")]
42 | Query(QueryArgs),
43 | }
44 |
45 | #[derive(Args, Clone)]
46 | pub struct InstallArgs {
47 | /// Name of the package to install
48 | #[arg(short,long,num_args(0..=100))] // Max 100 pkgs can be installed at once
49 | #[arg(required = true)]
50 | pub packages: Vec,
51 |
52 | /// Force install a package
53 | #[arg(long)]
54 | #[arg(required = false)]
55 | pub force: bool,
56 |
57 | /// strip down console output
58 | #[arg(long, required = false)]
59 | pub quiet: bool,
60 | }
61 |
62 | #[derive(Args, Clone)]
63 | pub struct RemoveArgs {
64 | /// Name of the package to Uninstall
65 | #[arg(short,long,num_args(0..=100))]
66 | #[arg(required = true)]
67 | pub packages: Vec,
68 |
69 | /// Force remove a package
70 | #[arg(long, required = false)]
71 | pub force: bool,
72 |
73 | /// strip down console input/output
74 | #[arg(long, required = false)]
75 | pub quiet: bool,
76 | }
77 |
78 | #[derive(Args, Clone)]
79 | #[command(arg_required_else_help = true)]
80 | pub struct SearchArgs {
81 | /// Name of the package to search
82 | #[arg(short, long)]
83 | #[arg(required = true)]
84 | pub package: String,
85 |
86 | /// Search for similar packages
87 | #[arg(long, value_enum, default_value = "raw")]
88 | pub mode: Modes,
89 |
90 | /// Define no. of max packages to show for fuzzy search
91 | #[arg(long, default_value = "4")]
92 | pub limit: u16,
93 | }
94 |
95 | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
96 | #[allow(non_camel_case_types)]
97 | pub enum Modes {
98 | /// Uses raw method to get package info
99 | raw,
100 |
101 | /// Uses metadata to get package info
102 | database,
103 |
104 | /// Grabs package with pkgname in name & description
105 | fuzzy, // TODO: set limit arg only for fuzzy mode
106 | }
107 |
108 | #[derive(Args, Clone)]
109 | #[command(arg_required_else_help = true)]
110 | pub struct ListArgs {
111 | /// Print all available packages
112 | #[arg(long, required = false, conflicts_with = "installed")]
113 | pub available: bool,
114 |
115 | /// Print all installed packages
116 | #[arg(long, required = false)]
117 | pub installed: bool,
118 |
119 | /// Verbose print the package information
120 | #[arg(long, required = false)]
121 | pub verbose: bool,
122 | }
123 |
124 | #[derive(Args, Clone)]
125 | #[command(arg_required_else_help = true)]
126 | pub struct QueryArgs {
127 | /// Print default hysp config
128 | #[arg(long, required = false)]
129 | pub print_default_config: bool,
130 |
131 | /// Print example package toml
132 | #[arg(long, required = false)]
133 | pub print_example_package: bool,
134 | }
135 |
--------------------------------------------------------------------------------
/src/commands/list.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::args::ListArgs;
2 | use crate::engine::config::parse_metadata_info;
3 | use crate::engine::config::pkg_config_structure::PackageInfo;
4 | use crate::engine::helpers::{
5 | local_config, print_metadata_package_info, print_package_info, read_file_content,
6 | };
7 | use crate::engine::msgx::{abort, info};
8 | use anyhow::{Context, Result};
9 | use std::fs;
10 | use std::path::{Path, PathBuf};
11 |
12 | const TOML_EXTENSION: &str = ".toml";
13 |
14 | pub async fn list_pkgs(pkg_list_args: ListArgs) -> Result<()> {
15 | let (_hysp_remote, hysp_data_dir, _hysp_bin_dir, hysp_metadata, architecture) =
16 | match local_config().await {
17 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
18 | (remote, data_dir, bin_dir, metadata, architecture)
19 | }
20 | Err(err) => {
21 | eprintln!("{}", err);
22 | std::process::exit(1);
23 | }
24 | };
25 |
26 | match (pkg_list_args.available, pkg_list_args.installed) {
27 | (true, false) => {
28 | print_available_pkg(&hysp_metadata, pkg_list_args.verbose, architecture).await?;
29 | }
30 | (false, true) => {
31 | print_installed_pkgs(&hysp_data_dir, pkg_list_args.verbose).await?;
32 | }
33 | _ => {
34 | abort("No such arg available");
35 | }
36 | }
37 |
38 | Ok(())
39 | }
40 |
41 | async fn print_available_pkg(
42 | metadata_toml: &str,
43 | verbose: bool,
44 | architecture: String,
45 | ) -> Result<(), anyhow::Error> {
46 | let metadata_toml_info = parse_metadata_info(metadata_toml).await?;
47 | info("Available packages in metadata", colored::Color::Green);
48 | if verbose {
49 | for package in metadata_toml_info.packages.clone() {
50 | print_metadata_package_info(metadata_toml_info.clone(), &package.name);
51 | }
52 | } else {
53 | for package in metadata_toml_info.packages {
54 | let package_arch = package.architecture.clone();
55 | if package_arch == architecture {
56 | println!("{} ", package.name);
57 | }
58 | }
59 | }
60 |
61 | Ok(())
62 | }
63 |
64 | async fn print_installed_pkgs(hysp_data_dir: &str, verbose: bool) -> Result<()> {
65 | let packages: Vec<(String, String)> = iterate_over_package_files(hysp_data_dir).collect();
66 |
67 | if packages.is_empty() {
68 | info("No packages installed via hysp", colored::Color::Red);
69 | } else {
70 | info("Installed packages ", colored::Color::Blue);
71 | for (file_path, file_name) in packages {
72 | if verbose {
73 | get_package_info(&file_path).await?;
74 | } else {
75 | println!("{}", file_name);
76 | }
77 | }
78 | }
79 | Ok(())
80 | }
81 |
82 | fn iterate_over_package_files(file_path: &str) -> impl Iterator- + '_ {
83 | fs::read_dir(file_path)
84 | .expect("Failed to read directory")
85 | .filter_map(|entry| entry.ok().map(|e| e.path()))
86 | .filter_map(extract_file_info)
87 | }
88 |
89 | fn extract_file_info(entry: PathBuf) -> Option<(String, String)> {
90 | let file_name = entry.file_name()?.to_str()?;
91 | let stripped_name = Path::new(file_name).file_stem()?.to_str()?;
92 | let (file_path, file_name) = if stripped_name.ends_with(TOML_EXTENSION) {
93 | let file_path = entry.to_string_lossy().to_string();
94 | let file_name = stripped_name
95 | .strip_suffix(TOML_EXTENSION)
96 | .expect("Expected TOML extension")
97 | .to_string();
98 | (file_path, file_name)
99 | } else {
100 | let file_path = entry.to_string_lossy().to_string();
101 | let file_name = stripped_name.to_string();
102 | (file_path, file_name)
103 | };
104 | Some((file_path, file_name))
105 | }
106 |
107 | async fn get_package_info(pkg_file: &str) -> Result<()> {
108 | let package_toml = read_file_content(pkg_file)
109 | .await
110 | .context("Failed to read package file")?;
111 | let parsed_package_info: PackageInfo =
112 | toml::from_str(&package_toml).context("Failed to parse package TOML")?;
113 |
114 | print_package_info(parsed_package_info);
115 |
116 | Ok(())
117 | }
118 |
--------------------------------------------------------------------------------
/src/engine/request.rs:
--------------------------------------------------------------------------------
1 | use spinoff::{spinners, Color, Spinner, Streams};
2 | use std::path::Path;
3 | use std::{io::Write, os::unix::fs::PermissionsExt};
4 |
5 | use crate::engine::config::parse_pkg_info;
6 |
7 | use super::config::pkg_config_structure::PackageInfo;
8 | use crate::engine::msgx::info;
9 | use anyhow::Result;
10 | use std::fs::{self, File, Permissions};
11 | use std::io::copy;
12 |
13 | /// Downloads content from the provided `download_url` and saves it as a file at the specified `download_location`.
14 | ///
15 | /// # Arguments
16 | ///
17 | /// * `download_url` - A string slice representing the URL to download the content from.
18 | /// * `download_location` - A string slice representing the path to save the downloaded content.
19 | ///
20 | /// # Returns
21 | ///
22 | /// A Result indicating the success or failure of the download process.
23 | ///
24 | pub async fn download_as_byte(
25 | download_url: &str,
26 | download_location: &str,
27 | ) -> Result<(), anyhow::Error> {
28 | let response = reqwest::get(download_url).await?;
29 |
30 | match response.status().as_u16() {
31 | 200 => {
32 | let mut spinner_binary = Spinner::new_with_stream(
33 | spinners::Dots,
34 | "Fetching binary ... ",
35 | Color::Green,
36 | Streams::Stderr,
37 | );
38 | if Path::new(download_location).exists() {
39 | std::fs::remove_file(download_location)?; // Already asked to continue or not so, removing it anyway
40 | }
41 | let content = response.bytes().await?;
42 | let mut dest = File::create(download_location)?;
43 | copy(&mut content.as_ref(), &mut dest)?;
44 |
45 | let permissions = Permissions::from_mode(0o755);
46 | fs::set_permissions(download_location, permissions)?;
47 |
48 | spinner_binary.stop_and_persist("Downloading binary ", "Done");
49 |
50 | info(
51 | &format!("Package binary location : {} ", &download_location),
52 | colored::Color::Cyan,
53 | );
54 | }
55 | _ => {
56 | return Err(anyhow::anyhow!(
57 | "Unexpected status code: {}",
58 | response.status()
59 | ));
60 | }
61 | };
62 |
63 | Ok(())
64 | }
65 |
66 | /// Downloads package information from the provided `download_url`, parses it, and saves it as a TOML file at the specified `download_location`.
67 | ///
68 | /// # Arguments
69 | ///
70 | /// * `download_url` - A string slice representing the URL to download the package information from.
71 | /// * `download_location` - A string slice representing the path to save the downloaded package information.
72 | ///
73 | /// # Returns
74 | ///
75 | /// A Result containing the parsed `PackageInfo` struct or an error if the download or parsing fails.
76 | ///
77 | pub async fn download_and_parse_package(
78 | download_url: &str,
79 | download_location: &str,
80 | ) -> Result {
81 | let mut spinner_pkginfo = Spinner::new_with_stream(
82 | spinners::Dots,
83 | "Fetching package info ... ",
84 | Color::Green,
85 | Streams::Stderr,
86 | );
87 | let response = reqwest::get(download_url).await?;
88 |
89 | match response.status().as_u16() {
90 | 200 => {
91 | if Path::new(download_location).exists() {
92 | std::fs::remove_file(download_location)?;
93 | }
94 |
95 | let parsed_pkg_info = parse_pkg_info(download_url).await?;
96 | let toml_string = toml::to_string(&parsed_pkg_info)?;
97 |
98 | let mut dest = File::create(download_location)?;
99 | dest.write_all(toml_string.as_bytes())?;
100 |
101 | spinner_pkginfo.stop_and_persist("Fetching package info ", "Done ");
102 | info(
103 | &format!("Package data location : {} ", download_location),
104 | colored::Color::Cyan,
105 | );
106 | Ok(parsed_pkg_info)
107 | }
108 | 404 => {
109 | println!();
110 | info("No such package found", colored::Color::Red);
111 | std::process::exit(1);
112 | }
113 | _ => Err(anyhow::anyhow!(
114 | "Unexpected status code: {}",
115 | response.status()
116 | )),
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/commands/install.rs:
--------------------------------------------------------------------------------
1 | use crate::engine::{
2 | args::InstallArgs,
3 | helpers::{
4 | check_hash, create_directory_if_not_exists, is_pkg_installed, local_config,
5 | print_package_info, prompt_yn, remove_trailing_slash,
6 | },
7 | msgx::info,
8 | request::{download_and_parse_package, download_as_byte},
9 | };
10 | use anyhow::Result;
11 | use async_recursion::async_recursion;
12 | use spinoff::{spinners, Color, Spinner, Streams};
13 | use std::fs::remove_file;
14 | use std::path::Path;
15 | use tokio::task;
16 |
17 | pub async fn install_packages(install_pkgs: InstallArgs) -> Result<()> {
18 | let mut tasks = vec![];
19 |
20 | for package_name in install_pkgs.packages.clone() {
21 | let install_pkgs_clone = install_pkgs.clone();
22 | let task = task::spawn(async move {
23 | if let Err(e) = install_pkg(&install_pkgs_clone, &package_name, false).await {
24 | eprint!("{}", e);
25 | }
26 | });
27 | tasks.push(task);
28 | }
29 |
30 | for task in tasks {
31 | if let Err(e) = task.await {
32 | eprintln!("Task failed: {}", e);
33 | }
34 | }
35 |
36 | Ok(())
37 | }
38 |
39 | #[async_recursion]
40 | pub async fn install_pkg(
41 | install_pkgs: &InstallArgs,
42 | package_name: &str,
43 | is_dependency: bool,
44 | ) -> Result<()> {
45 | let (hysp_remote, hysp_data_dir, hysp_bin_dir, _hysp_metadata, _architecture) =
46 | match local_config().await {
47 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
48 | (remote, data_dir, bin_dir, metadata, architecture)
49 | }
50 | Err(err) => {
51 | eprintln!("{}", err);
52 | std::process::exit(1);
53 | }
54 | };
55 |
56 | create_directory_if_not_exists(&hysp_bin_dir);
57 | create_directory_if_not_exists(&hysp_data_dir);
58 |
59 | let package_data_location = format!(
60 | "{}/{}.toml",
61 | remove_trailing_slash(hysp_data_dir.clone()),
62 | package_name
63 | );
64 |
65 | if !install_pkgs.force && Path::new(&package_data_location).exists() {
66 | info(
67 | &format!(
68 | "There's already a package exist as: {} ",
69 | package_data_location
70 | ),
71 | colored::Color::Cyan,
72 | );
73 | prompt_yn("Would you like to overwrite ? (y/n)".to_string());
74 | }
75 |
76 | let package_download_url = format!(
77 | "{}/{}.toml",
78 | remove_trailing_slash(hysp_remote),
79 | package_name
80 | );
81 |
82 | match download_and_parse_package(&package_download_url, &package_data_location).await {
83 | Ok(parsed_info) => {
84 | let binary_path = format!(
85 | "{}/{}",
86 | remove_trailing_slash(hysp_bin_dir),
87 | parsed_info.bin.name
88 | );
89 |
90 | let dependency_names: Vec<_> = parsed_info.package.conditions.requires.to_vec();
91 |
92 | if !dependency_names.is_empty() {
93 | let dependencies_str = dependency_names.join(", ");
94 | info(
95 | &format!(
96 | "Dependency cycle detected installing dependencies: {}",
97 | dependencies_str
98 | ),
99 | colored::Color::Cyan,
100 | );
101 | }
102 |
103 | for dep in parsed_info.package.conditions.requires.clone() {
104 | if !is_pkg_installed(&dep) {
105 | install_pkg(install_pkgs, &dep, true).await?;
106 | }
107 | }
108 |
109 | if install_pkgs.packages.len() < 2 && !is_dependency && !install_pkgs.quiet {
110 | print_package_info(parsed_info.clone());
111 | }
112 |
113 | download_as_byte(&parsed_info.package.source, &binary_path).await?;
114 |
115 | let mut spinner_hash = Spinner::new_with_stream(
116 | spinners::Dots,
117 | "Validating hash ... ",
118 | Color::Green,
119 | Streams::Stderr,
120 | );
121 | let check_result =
122 | check_hash(binary_path.clone(), parsed_info.package.sha.clone()).await;
123 |
124 | if let Ok(result) = check_result {
125 | if !result {
126 | if let Err(e) = remove_file(&binary_path) {
127 | eprintln!("Failed to remove file: {}", e);
128 | }
129 | if let Err(e) = remove_file(&package_data_location) {
130 | eprintln!("Failed to remove package data: {}", e);
131 | }
132 | }
133 | } else {
134 | eprintln!("Error checking hash: {}", check_result.err().unwrap());
135 | }
136 | spinner_hash.stop_and_persist("Validating hash ", "Done");
137 | }
138 | Err(e) => {
139 | eprint!("{}", e);
140 | }
141 | };
142 |
143 | Ok(())
144 | }
145 |
--------------------------------------------------------------------------------
/src/commands/search.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | commands::ui::BAR,
3 | engine::{
4 | args::{Modes, SearchArgs},
5 | config::{parse_metadata_info, parse_pkg_info},
6 | helpers::{
7 | local_config, print_metadata_package_info, print_package_info, remove_trailing_slash,
8 | },
9 | msgx::info,
10 | },
11 | };
12 | use anyhow::Result;
13 | use colored::Colorize;
14 | use reqwest::StatusCode;
15 | use spinoff::{spinners, Color, Spinner, Streams};
16 |
17 | pub async fn search_pkgs(pkg_search_args: SearchArgs) -> Result<()> {
18 | let (hysp_remote, _hysp_data_dir, _hysp_bin_dir, hysp_metadata, _architecture) =
19 | match local_config().await {
20 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
21 | (remote, data_dir, bin_dir, metadata, architecture)
22 | }
23 | Err(err) => {
24 | eprintln!("{}", err);
25 | std::process::exit(1);
26 | }
27 | };
28 |
29 | let package_name = pkg_search_args.package;
30 | let limit = pkg_search_args.limit;
31 |
32 | match pkg_search_args.mode {
33 | Modes::database => {
34 | print_info_using_metadata(&package_name, &hysp_metadata).await?;
35 | }
36 | Modes::raw => {
37 | print_info_using_raw(&package_name, &hysp_remote).await?;
38 | }
39 | Modes::fuzzy => {
40 | search_similar_packages(&hysp_metadata, &package_name, limit).await?;
41 | }
42 | }
43 |
44 | Ok(())
45 | }
46 |
47 | async fn print_info_using_metadata(package_name: &str, hysp_metadata: &str) -> Result<()> {
48 | let mut spinner_search_pkgs = Spinner::new_with_stream(
49 | spinners::Dots,
50 | "Using metadata to check for packages .. ",
51 | Color::Cyan,
52 | Streams::Stderr,
53 | );
54 |
55 | let available_pkg_info = parse_metadata_info(hysp_metadata).await?;
56 | spinner_search_pkgs.stop_and_persist("Using metadata to check for packages ", "Done ");
57 | print_metadata_package_info(available_pkg_info, package_name);
58 |
59 | Ok(())
60 | }
61 |
62 | async fn print_info_using_raw(package_name: &str, hysp_remote: &str) -> Result<(), anyhow::Error> {
63 | info(
64 | "Using raw method to check for packages",
65 | colored::Color::BrightBlue,
66 | );
67 | let package_url = format!(
68 | "{}/{}.toml",
69 | remove_trailing_slash(hysp_remote.to_string()),
70 | package_name
71 | );
72 |
73 | let response = reqwest::get(&package_url).await?;
74 |
75 | match response.status() {
76 | StatusCode::OK => {
77 | info(
78 | &format!("Package found as: {}", package_name.bold()),
79 | colored::Color::Cyan,
80 | );
81 |
82 | let parsed_pkg_info = parse_pkg_info(&package_url).await?;
83 | print_package_info(parsed_pkg_info);
84 | Ok(())
85 | }
86 | StatusCode::NOT_FOUND => {
87 | info(
88 | &format!("No such package found as: {}", package_name),
89 | colored::Color::Cyan,
90 | );
91 | Ok(())
92 | }
93 | _ => Err(anyhow::anyhow!(
94 | "Unexpected status code: {}",
95 | response.status()
96 | )),
97 | }
98 | }
99 |
100 | async fn search_similar_packages(
101 | hysp_metadata: &str,
102 | package_name: &str,
103 | package_limit: u16,
104 | ) -> Result<(), anyhow::Error> {
105 | let mut spinner_search_similar_pkgs = Spinner::new_with_stream(
106 | spinners::Dots,
107 | "Searching for databases in metadata ... ",
108 | Color::Green,
109 | Streams::Stderr,
110 | );
111 | let available_pkg_info = parse_metadata_info(hysp_metadata).await?;
112 |
113 | spinner_search_similar_pkgs.stop_and_persist("Searching for package in metadata ", "Done ");
114 |
115 | let mut printed_packages = 0;
116 | let mut found_packages = false;
117 |
118 | for package in available_pkg_info.packages {
119 | if printed_packages >= package_limit {
120 | break;
121 | }
122 |
123 | let lowercase_package_name = package_name.to_lowercase();
124 | let lowercase_package = package.name.to_lowercase();
125 | let lowercase_description = package.description.to_lowercase();
126 |
127 | if lowercase_package.contains(&lowercase_package_name)
128 | || lowercase_description.contains(&lowercase_package_name)
129 | {
130 | found_packages = true; // At least one package found
131 |
132 | let highlighted_name = package
133 | .name
134 | .replacen(&lowercase_package_name, &package_name.cyan().to_string(), 1)
135 | .replacen(
136 | &lowercase_package_name.to_uppercase(),
137 | &package_name.cyan().to_uppercase().to_string(),
138 | 1,
139 | );
140 |
141 | let highlighted_desc = package
142 | .description
143 | .replacen(&lowercase_package_name, &package_name.cyan().to_string(), 1)
144 | .replacen(
145 | &lowercase_package_name.to_uppercase(),
146 | &package_name.cyan().to_uppercase().to_string(),
147 | 1,
148 | );
149 |
150 | println!("Package: {}", highlighted_name);
151 | println!("Description: {}", highlighted_desc);
152 | println!("{}", BAR);
153 |
154 | printed_packages += 1;
155 | }
156 | }
157 |
158 | if !found_packages {
159 | info("No such package exist in metadata", colored::Color::Red);
160 | }
161 | Ok(())
162 | }
163 |
--------------------------------------------------------------------------------
/src/engine/config.rs:
--------------------------------------------------------------------------------
1 | use crate::commands::ui::BAR;
2 | use crate::engine::config::metadata_config_structure::MetadataInfo;
3 | use crate::engine::config::pkg_config_structure::PackageInfo;
4 | use crate::engine::helpers::{get_arch, read_file_content};
5 | use crate::engine::msgx::info;
6 | use anyhow::{anyhow, Result};
7 | use colored::Colorize;
8 | use local_config_structure::LocalConfig;
9 | use reqwest;
10 |
11 | pub mod local_config_structure {
12 | use serde::{Deserialize, Serialize};
13 | use std::path::PathBuf;
14 |
15 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
16 | pub struct LocalConfig {
17 | pub source: Source,
18 | pub local: Local,
19 | }
20 |
21 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
22 | pub struct Source {
23 | pub remote: Option,
24 | pub metadata: Option,
25 | pub aarch: Option,
26 | }
27 |
28 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
29 | pub struct Local {
30 | pub home: Option,
31 | pub bin: Option,
32 | pub data: Option,
33 | }
34 | }
35 |
36 | pub mod pkg_config_structure {
37 | use serde::{Deserialize, Serialize};
38 |
39 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
40 | pub struct PackageInfo {
41 | pub bin: Bin,
42 | pub package: Package,
43 | }
44 |
45 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
46 | pub struct Bin {
47 | pub name: String,
48 | }
49 |
50 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
51 | pub struct Package {
52 | pub architecture: String,
53 | pub name: String,
54 | pub description: String,
55 | pub author: String,
56 | pub repo: String,
57 | pub stars: String,
58 | pub version: String,
59 | pub updated: String,
60 | pub size: String,
61 | pub sha: String,
62 | pub source: String,
63 | pub language: String,
64 | pub license: String,
65 | pub conditions: Conditions,
66 | pub metadata: Metadata,
67 | }
68 |
69 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
70 | pub struct Conditions {
71 | pub conflicts: Vec,
72 | pub requires: Vec,
73 | }
74 |
75 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
76 | pub struct Metadata {
77 | pub keywords: Vec,
78 | pub categories: Vec,
79 | }
80 | }
81 |
82 | pub mod metadata_config_structure {
83 |
84 | use serde::{Deserialize, Serialize};
85 |
86 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
87 | #[serde(rename_all = "camelCase")]
88 | pub struct MetadataInfo {
89 | pub packages: Vec,
90 | }
91 |
92 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
93 | #[serde(rename_all = "camelCase")]
94 | pub struct Package {
95 | pub architecture: String,
96 | pub name: String,
97 | pub description: String,
98 | pub author: String,
99 | pub repo: String,
100 | pub stars: String,
101 | pub version: String,
102 | pub updated: String,
103 | pub size: String,
104 | pub bsum: String,
105 | pub sha: String,
106 | pub source: String,
107 | pub language: String,
108 | pub license: String,
109 | }
110 | }
111 |
112 | /// Parse hysp user config
113 | #[inline]
114 | pub async fn parse_local_config() -> Result {
115 | let config_file_path = dirs::config_dir()
116 | .ok_or_else(|| anyhow!("Config directory not found"))?
117 | .join("hysp/config.toml");
118 |
119 | let arch = get_arch();
120 |
121 | let contents = match read_file_content(&config_file_path.to_string_lossy()).await {
122 | Ok(contents) => {
123 | println!("{}", BAR.bold().purple());
124 | info(
125 | &format!(
126 | "Using custom config from: {} ",
127 | config_file_path.to_string_lossy(),
128 | ),
129 | colored::Color::Cyan,
130 | );
131 | println!("{}", BAR.bold().purple());
132 | contents
133 | }
134 | Err(_) => {
135 | println!("{}", BAR.bold().purple());
136 | info("Using default configuration.", colored::Color::Green);
137 | println!("{}", BAR.bold().purple());
138 | let home = match std::env::var("HOME") {
139 | Ok(val) => val,
140 | Err(_) => {
141 | eprintln!("Error: HOME environment variable not found");
142 | std::process::exit(0);
143 | }
144 | };
145 | format!(
146 | r#"
147 | [source]
148 | remote = "https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/x86_64"
149 | metadata = "https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/metadata.toml"
150 | aarch = "{}"
151 | [local]
152 | home = "{}/.local/share/hysp"
153 | bin = "{}/.local/share/hysp/bin/"
154 | data = "{}/.local/share/hysp/data/"
155 | "#,
156 | arch, home, home, home
157 | )
158 | }
159 | };
160 |
161 | let parsed_local_config = toml::from_str::(&contents)?;
162 | Ok(parsed_local_config)
163 | }
164 |
165 | /// Parse hysp packages config
166 | #[inline]
167 | pub async fn parse_pkg_info(pkg_url: &str) -> Result {
168 | let client = reqwest::Client::builder()
169 | .redirect(reqwest::redirect::Policy::limited(10)) // Allow redirection limit = 10
170 | .danger_accept_invalid_certs(true) // allow http as well
171 | .build()?;
172 |
173 | let response = client.get(pkg_url).send().await?;
174 | let body = response.text().await?;
175 | let parsed_package_info: PackageInfo = toml::from_str(&body)?;
176 | Ok(parsed_package_info)
177 | }
178 |
179 | #[inline]
180 | pub async fn parse_metadata_info(metadata_url: &str) -> Result {
181 | let client = reqwest::Client::builder()
182 | .redirect(reqwest::redirect::Policy::limited(10)) // Allow redirection limit = 10
183 | .danger_accept_invalid_certs(true) // allow http as well
184 | .build()?;
185 |
186 | let response = client.get(metadata_url).send().await?;
187 | let body = response.text().await?;
188 | let parsed_metadata_info: MetadataInfo = toml::from_str(&body)?;
189 | Ok(parsed_metadata_info)
190 | }
191 |
192 | #[cfg(test)]
193 | mod tests {
194 | use crate::engine::helpers::{create_directory_if_not_exists, local_config};
195 |
196 | #[tokio::test]
197 | async fn test_directories_exist() {
198 | let (_hysp_remote, hysp_data_dir, hysp_bin_dir, _hysp_metadata, _architecture) =
199 | match local_config().await {
200 | Ok((remote, data_dir, bin_dir, metadata, architecture)) => {
201 | (remote, data_dir, bin_dir, metadata, architecture)
202 | }
203 | Err(err) => {
204 | eprintln!("{}", err);
205 | std::process::exit(1)
206 | }
207 | };
208 |
209 | create_directory_if_not_exists(&hysp_data_dir);
210 | create_directory_if_not_exists(&hysp_bin_dir);
211 |
212 | assert!(std::path::Path::new(&hysp_data_dir).exists());
213 | assert!(std::path::Path::new(&hysp_bin_dir).exists());
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
All changes of this release are documented here.
2 |
3 | 
4 |
5 | > *Note*: ***The 🚨emoji indicates significant changes in the commit.***
6 |
7 | ## ☃️ Miscellaneous Tasks
8 |
9 | - [`d5cdb53`](https://github.com/pwnwriter/hysp/commit/d5cdb5361d5609de879f1c5fbdf714cf02058860): Show helpful message on zero pkgs [closes #5].
10 |
11 | - [`4486045`](https://github.com/pwnwriter/hysp/commit/4486045545da49482c9c939f308dbcd4b18f4d3b): Showcase images (`help,remove,list`) for demos.
12 |
13 | - [`eb5c97d`](https://github.com/pwnwriter/hysp/commit/eb5c97d6c3b9e0dd78d9f910301468b3ddeadb04): One liner script for binary installation.
14 |
15 | - [`6b2c040`](https://github.com/pwnwriter/hysp/commit/6b2c0401d94b2021fc888da5226d2f8e8b90681c): Demo imgs for health // help.
16 |
17 | - [`1cb163f`](https://github.com/pwnwriter/hysp/commit/1cb163f856d5528c30e15f77583cfa4a659ce244): Use absolute path for $path ; link to repo.
18 |
19 | - [`6ffce0c`](https://github.com/pwnwriter/hysp/commit/6ffce0caaabf7f2e39da9eb05a909300cbe37b72): Fixed default data location [closes #11].
20 |
21 | - [`8b86568`](https://github.com/pwnwriter/hysp/commit/8b865680580edbd51386e1359e1b3efc102129de): Added key features lable ; links to upstream sources.
22 |
23 | - [`07de8ef`](https://github.com/pwnwriter/hysp/commit/07de8ef23fd9a4d512b0443685126d4e8a911395): Added features in tables; store links inside security stuffs.
24 |
25 | - [`1f7a006`](https://github.com/pwnwriter/hysp/commit/1f7a006dd97d9cb6d10a84423101ddae31cbef5d): Ask if the package already available/exist or not.
26 |
27 | - [`b22aae7`](https://github.com/pwnwriter/hysp/commit/b22aae778f9630ef7873cf7252cb371a2b06852b): Removed pkg-req temp (redirect to hysp-pkgs).
28 |
29 | - [`4821ddf`](https://github.com/pwnwriter/hysp/commit/4821ddf72868a48e987fe75f299db3a1a588c36a): Bump colored from 2.0.4 to 2.1.0.
30 |
31 | - [`6af2037`](https://github.com/pwnwriter/hysp/commit/6af20374bfa0f02a9fc347d42d2c88f3dcb7b707): Bump tokio from 1.34.0 to 1.35.0.
32 |
33 | - [`7836b9a`](https://github.com/pwnwriter/hysp/commit/7836b9ab7dd1049dcbec5a2416e7e43fa30f41a3): Bump clap from 4.4.8 to 4.4.11.
34 |
35 | - [`b42a889`](https://github.com/pwnwriter/hysp/commit/b42a889180a0045184832590bdf4cb334bd36126): Removed aarchitecure info for new version update.
36 |
37 | - [`e3e0b22`](https://github.com/pwnwriter/hysp/commit/e3e0b22951e008c4ab31ca09acfc2199a9f9dbcd): Removed unused dependencies.
38 |
39 | - [`a87df67`](https://github.com/pwnwriter/hysp/commit/a87df67d452a196956bea91355c4922a6ed73114): Test install, health commands via ci/cd.
40 |
41 | - [`45d79d1`](https://github.com/pwnwriter/hysp/commit/45d79d179b9e81b9ecd6d498a934096c32fdd465): Use different names for test ci workflows.
42 |
43 | - [`779e63c`](https://github.com/pwnwriter/hysp/commit/779e63c5033f29e16968bb63ed00a92f482de05b): Show pkgs only of current system aarch.
44 |
45 | - [`0d06726`](https://github.com/pwnwriter/hysp/commit/0d067269997b57875aa15cdd05db65e193082a70): Show log info if path doesn't exist.
46 |
47 | - [`1ae5b46`](https://github.com/pwnwriter/hysp/commit/1ae5b468eb448e23fa85e2e0943cc6691adb8c15): Install pkgs in force mode.
48 |
49 | - [`a4599e8`](https://github.com/pwnwriter/hysp/commit/a4599e8f66505ccb2081cdfdb281498f900a06e9): Remove pkgs in force mode.
50 |
51 | - [`cfc74b9`](https://github.com/pwnwriter/hysp/commit/cfc74b9ee456f94d003bf3db975fb58549ee6d90): Fixed local config args // removed unused docx.
52 |
53 |
54 | ## ✨Refactor
55 |
56 | - [`7616115`](https://github.com/pwnwriter/hysp/commit/76161152ef6c32d535ab6a92686fe7f65f0bee70): Use git-cliff to generate release docs.
57 |
58 |
59 | ## 🌈 Beautify
60 |
61 | - [`f68ba68`](https://github.com/pwnwriter/hysp/commit/f68ba68d0bcf6cc026bfff11ac35cdaeb258a03e): Show binary path before removing.
62 |
63 |
64 | ## 🐶Performance
65 |
66 | - [`3e245e1`](https://github.com/pwnwriter/hysp/commit/3e245e1dc9945e3279feb4fc03e639a6473a2319): Use tokio task for concurrent pkg install.
67 |
68 |
69 | ## 🦁Features
70 |
71 | - [`ea5fcda`](https://github.com/pwnwriter/hysp/commit/ea5fcda4c9960161f19d22e8b8a71268a8645ba9): Subcommand to check for local config health.
72 |
73 | - [`d0b2f3b`](https://github.com/pwnwriter/hysp/commit/d0b2f3b420ad0ef8a702e3c9818b2fef09ddce8b): Subcommand to check for local config health [closes #6].
74 |
75 | - [`dcc448b`](https://github.com/pwnwriter/hysp/commit/dcc448b0eabe3ba3ce16b6814161f0d0ca4089d2): Use issue templates // labels to track and submit new issues.
76 |
77 | - [`2daaa4a`](https://github.com/pwnwriter/hysp/commit/2daaa4abf7de2e1b12f6d852a5a78bd119d0ad69): Handle dependencies, seprated code structur via helper modules.
78 |
79 | - [`6bdbf5a`](https://github.com/pwnwriter/hysp/commit/6bdbf5ad7ffe0d3b6d1d5b2d54460e2320a2be57): Argument to list available,queries; check hysp health and cmd via ci/cd.
80 |
81 | - [`e82f64f`](https://github.com/pwnwriter/hysp/commit/e82f64f6e188dc812362433094370d72b7cb2040): Check for binary directory in path.
82 |
83 | - [`eae0d6f`](https://github.com/pwnwriter/hysp/commit/eae0d6f6ed013c3b864964f7ef81848d161e691f): New commands usages and fixes.
84 |
85 |
86 | ## ☃️ Miscellaneous Tasks
87 |
88 | - [`b316907`](https://github.com/pwnwriter/hysp/commit/b31690785914a9548d7ef562244998eb3ee763df): Fixed desc for the app.
89 |
90 | - [`79b9023`](https://github.com/pwnwriter/hysp/commit/79b90235c90e3daff23a6b2eadfa768f534b8b63): Bump serde from 1.0.192 to 1.0.193.
91 |
92 | - [`75b43a5`](https://github.com/pwnwriter/hysp/commit/75b43a5a5302b95da542e056a652bcec6e719f68): Fixed spells ; notes for hysp directory structure.
93 |
94 | - [`39d5867`](https://github.com/pwnwriter/hysp/commit/39d5867aab0b9ecab5373c43afecf665e1e4eb71): Show demo upon logo clicksss.
95 |
96 | - [`3c3cbfb`](https://github.com/pwnwriter/hysp/commit/3c3cbfbab65cb022f23961abde483f29429ab345): Bumping new version for releases.
97 |
98 | - [`d2955aa`](https://github.com/pwnwriter/hysp/commit/d2955aaf499bc8896a8619869ab4e948be217851): Fixed typos // broken links.
99 |
100 | - [`0c90794`](https://github.com/pwnwriter/hysp/commit/0c90794c93cae8041949b4e395eff1d092abfc1f): Demos and explanations of config file; donate links.
101 |
102 | - [`18d74cd`](https://github.com/pwnwriter/hysp/commit/18d74cd285616e9e7109a4fb9562b6add8d75d83): Show usages ; demo imgs.
103 |
104 | - [`b3ae712`](https://github.com/pwnwriter/hysp/commit/b3ae712a5a58d9559c26da4c2424949252d957da): Demo imgs for searching pkgs.
105 |
106 | - [`6352582`](https://github.com/pwnwriter/hysp/commit/6352582f07806555ab568f5a9b082801bce74993): Support links // msgs :P.
107 |
108 | - [`1270871`](https://github.com/pwnwriter/hysp/commit/12708713379d3b3b238723dd6599c2a69f80c83e): Removed redundant markdown docs.
109 |
110 |
111 | ## ✨Refactor
112 |
113 | - [`5b7b6ef`](https://github.com/pwnwriter/hysp/commit/5b7b6efd3b63185f9684bf7eeaced510fdf49e59): Made pkg-info except name optional.
114 |
115 | - [`74e3796`](https://github.com/pwnwriter/hysp/commit/74e3796eabee64ab8f2b168649cc2425cc2218a0): Use sha for integrity validation [closes #3]; rewritten core from scratch.
116 |
117 | - [`2019022`](https://github.com/pwnwriter/hysp/commit/201902235e2725ae9dd42a4590005630d851bf6d): Made pkg-info as optional to handle aborting.
118 |
119 |
120 | ## 🦁Features
121 |
122 | - [`d190690`](https://github.com/pwnwriter/hysp/commit/d19069089a7761db5ed47cbab1039a0cb3567456): Docx for the app // pkg demp.
123 |
124 | - [`24a9d3c`](https://github.com/pwnwriter/hysp/commit/24a9d3c04bad5e78edec4df60aa17e6b1353d143): Changelogs, preparing for new (v0.1.1) release.
125 |
126 | - [`6259ee1`](https://github.com/pwnwriter/hysp/commit/6259ee1ae4c9e0e8084d24a4c56a17c662e05fa2): Fixed spinner on conflict detect // subcommand to check for installed pkgs.
127 |
128 | - [`5a1e2d9`](https://github.com/pwnwriter/hysp/commit/5a1e2d9bc78fef144511e6ca501597d2a7a4aaae): Subcommand to search for available packages [closes #4].
129 |
130 | - [`2331bff`](https://github.com/pwnwriter/hysp/commit/2331bffda50335cd39ae396d955f79c95ffa7fc1): Preparing for new release.
131 |
132 |
133 | ## Documentation
134 |
135 | - [`b54cc3e`](https://github.com/pwnwriter/hysp/commit/b54cc3e0c43ab199b72f85a01c0722dd23c3f382): Update.
136 |
137 |
138 | ## ☃️ Miscellaneous Tasks
139 |
140 | - [`7c7dce2`](https://github.com/pwnwriter/hysp/commit/7c7dce2b43ddfffcc88523b727710d75ae4f008f): Working code / fetch toml from the repo.
141 |
142 | - [`4ba1e9b`](https://github.com/pwnwriter/hysp/commit/4ba1e9b23875e73ddd1ca27a821a58c6e569fbc4): Use multiple structs to handle pkg info.
143 |
144 | - [`1dbbdf0`](https://github.com/pwnwriter/hysp/commit/1dbbdf0b8f88bb166134b238889c38277bf91c86): Use distinct keywords based on usages.
145 |
146 | - [`209d9be`](https://github.com/pwnwriter/hysp/commit/209d9bec666b42661bce49803d99886cac78bbf7): Show example env variables.
147 |
148 | - [`e3e2868`](https://github.com/pwnwriter/hysp/commit/e3e28680f5a3e746056bf2ee079579f22a5a3dd9): Use strings instead of vector // testing infos.
149 |
150 | - [`6e6b5f4`](https://github.com/pwnwriter/hysp/commit/6e6b5f422fbff1afd231ef53bff50fbbdc8a5954): Start engine from init.
151 |
152 | - [`c551da4`](https://github.com/pwnwriter/hysp/commit/c551da41eae207ae1112e227662846bddadbe3be): Bump spinoff from 0.7.0 to 0.8.0.
153 |
154 | - [`58df65d`](https://github.com/pwnwriter/hysp/commit/58df65d8a054798941d9582d19eaeffdb3e02efe): Use mutable vars befor spinning.
155 |
156 | - [`72c6b3d`](https://github.com/pwnwriter/hysp/commit/72c6b3d6ba594992ab6ddd05e71d29642bd16c3f): Removed unused deps.
157 |
158 | - [`2011135`](https://github.com/pwnwriter/hysp/commit/2011135a4a3a089aef56862fd4334787c3ba3dac): Use new binary name for the releases.
159 |
160 | - [`d39f987`](https://github.com/pwnwriter/hysp/commit/d39f9870b2bd6ed1c56bcf8695618359f990c574): Use capitalized the readme file.
161 |
162 | - [`1e33cdc`](https://github.com/pwnwriter/hysp/commit/1e33cdcb2c5a883516b099e112ee09fc89a17b0a): Don't release for windows aarch.
163 |
164 |
165 | ## ✨Refactor
166 |
167 | - [`2821399`](https://github.com/pwnwriter/hysp/commit/282139977578a7a753729edda3ed8471badebcad): Store args inside single file.
168 |
169 | - [`4a6f0ee`](https://github.com/pwnwriter/hysp/commit/4a6f0eed4917cd3610188282e8dd309c90462e36): Fixed ascii // app name over the app.
170 |
171 |
172 | ## 🦁Features
173 |
174 | - [`100c963`](https://github.com/pwnwriter/hysp/commit/100c9639ed13e12510a5de2bc1c425031bebdde2): Dir;conf structure an ui.
175 |
176 | - [`61f5ba4`](https://github.com/pwnwriter/hysp/commit/61f5ba47709869e2967488bd876ce8fb97306609): Test app builds on push // release ci actions.
177 |
178 | - [`cfbde9c`](https://github.com/pwnwriter/hysp/commit/cfbde9ce6c447952e85f16a4dcf713cb3911cf7b): (dirs); home,bin,data structure for the pkg infos.
179 |
180 | - [`0780fe3`](https://github.com/pwnwriter/hysp/commit/0780fe3cbe5570461a8f7f5263137bbf5bfca122): The overall flow of the pkg.
181 |
182 | - [`14ac3c5`](https://github.com/pwnwriter/hysp/commit/14ac3c54ff42ee2b28e10a45a7432a6842696bef): Args skeleton for cli.
183 |
184 | - [`d5f5eb3`](https://github.com/pwnwriter/hysp/commit/d5f5eb3ca1d484e299a53db7daa18fe003b5e2be): Basic implementation to download and process pkg toml.
185 |
186 | - [`74d0d32`](https://github.com/pwnwriter/hysp/commit/74d0d3200b0549ee4fa560e7e8432cc5a7b33f4b): Load repo url from env else use @bytehunt/seren-pkgs.
187 |
188 | - [`5ada962`](https://github.com/pwnwriter/hysp/commit/5ada962c43dcc8fd763922641da8f788fd53710e): Install on tmp and move on seren-bin-dir.
189 |
190 | - [`00f9ad8`](https://github.com/pwnwriter/hysp/commit/00f9ad8dc3527ea8854947465c4b5471b19d2241): Basic installation poc, working code.
191 |
192 | - [`b3bbba8`](https://github.com/pwnwriter/hysp/commit/b3bbba8d4977736d3e4c43a8739799ae386bc3ea): Check for conflict/deps (stable).
193 |
194 | - [`76476b0`](https://github.com/pwnwriter/hysp/commit/76476b0694866ad918db88972f4131f34a836309): Pkg manager for *nix [working code].
195 |
196 | - [`89441a4`](https://github.com/pwnwriter/hysp/commit/89441a49262f041a07cb7c2e7bbf331f331f62be): Initialized docx.
197 |
198 |
199 | 
200 |
--------------------------------------------------------------------------------
/src/engine/helpers.rs:
--------------------------------------------------------------------------------
1 | use super::config::parse_local_config;
2 | use crate::commands::ui::{ASCII, BAR, RESET};
3 | use crate::engine::config::metadata_config_structure::MetadataInfo;
4 | use crate::engine::config::pkg_config_structure::PackageInfo;
5 | use crate::engine::msgx::info;
6 | use anyhow::anyhow;
7 | use anyhow::{Context, Result};
8 | use colored::Colorize;
9 | use columns::Columns;
10 | use sha2::{Digest, Sha256};
11 | use std::fs;
12 | use std::io::{self, Write};
13 | use std::process::Command;
14 | use tokio::{fs::File, io::AsyncReadExt};
15 |
16 | /// Formats a given field, returning "Not available" if empty.
17 | ///
18 | /// # Arguments
19 | ///
20 | /// * `field` - A string slice representing the field to be formatted.
21 | ///
22 | /// # Returns
23 | ///
24 | /// A formatted string with "Not available" for empty input or the original field.
25 | ///
26 | #[inline]
27 | fn format_field(field: &str) -> String {
28 | if field.is_empty() {
29 | "Not available".to_string()
30 | } else {
31 | field.to_string()
32 | }
33 | }
34 |
35 | /// Removes a trailing slash from a string path if it exists.
36 | ///
37 | /// # Arguments
38 | ///
39 | /// * `path` - A String representing the path to be modified.
40 | ///
41 | /// # Returns
42 | ///
43 | /// A string with the trailing slash removed (if present).
44 | ///
45 | #[inline]
46 | pub fn remove_trailing_slash(mut path: String) -> String {
47 | if path.ends_with('/') {
48 | path.pop();
49 | }
50 | path
51 | }
52 |
53 | /// Reads the contents of a file specified by `file_path` and returns them as a string.
54 | ///
55 | /// # Arguments
56 | ///
57 | /// * `file_path` - A string slice representing the path to the file.
58 | ///
59 | /// # Returns
60 | ///
61 | /// A Result containing either the file's contents as a string or an error.
62 | ///
63 | #[inline]
64 | pub async fn read_file_content(file_path: &str) -> Result {
65 | let mut file = File::open(file_path)
66 | .await
67 | .with_context(|| format!("Failed to open file '{}'", file_path))?;
68 |
69 | let mut contents = String::new();
70 | file.read_to_string(&mut contents)
71 | .await
72 | .with_context(|| format!("Failed to read file '{}'", file_path))?;
73 |
74 | Ok(contents)
75 | }
76 |
77 | /// Retrieves the system's architecture (either x86_64 or aarch64).
78 | ///
79 | /// # Returns
80 | ///
81 | /// A string representing the system architecture.
82 | ///
83 | #[inline]
84 | pub fn get_arch() -> String {
85 | let architecture = std::env::consts::ARCH.to_string();
86 |
87 | match architecture.as_str() {
88 | "x86_64" => "x86_64".to_string(),
89 | "aarch64" => "aarch64".to_string(),
90 | _ => {
91 | eprintln!("Error: Unsupported architecture");
92 | std::process::exit(1);
93 | }
94 | }
95 | }
96 |
97 | /// Prompts the user with a yes/no question and returns the user's response.
98 | ///
99 | /// # Arguments
100 | ///
101 | /// * `prompt` - A String containing the prompt message.
102 | ///
103 | /// # Returns
104 | ///
105 | /// A boolean value: `true` for yes, `false` for no.
106 | ///
107 | #[inline]
108 | pub fn prompt_yn(prompt: String) -> bool {
109 | loop {
110 | print!("{}", prompt);
111 | io::stdout().flush().unwrap();
112 |
113 | let mut input = String::new();
114 | io::stdin()
115 | .read_line(&mut input)
116 | .expect("Failed to read line");
117 |
118 | let trimmed = input.trim().to_lowercase();
119 | match trimmed.as_str() {
120 | "yes" | "y" => {
121 | info("Proceeding ...", colored::Color::Green);
122 | return true;
123 | }
124 | "no" | "n" => {
125 | info("Exitting .. ", colored::Color::Red);
126 | std::process::exit(1);
127 | }
128 | _ => {
129 | println!("Please enter 'y|es' or 'n|o'.");
130 | }
131 | }
132 | }
133 | }
134 |
135 | /// Prints package information based on PackageInfo struct.
136 | ///
137 | /// # Arguments
138 | ///
139 | /// * `pkginfo` - A PackageInfo struct containing package information.
140 | ///
141 | #[inline]
142 | pub fn print_package_info(pkginfo: PackageInfo) {
143 | // Needed
144 | let pkg_bin_name = &pkginfo.bin.name.bold().bright_red();
145 | let pkg_architecture = &pkginfo.package.architecture.green();
146 | let pkg_hash = &pkginfo.package.sha.bold().cyan();
147 |
148 | // Optional fields
149 | let pkg_desc = format_field(&pkginfo.package.description).bold().blue();
150 | let pkg_author = format_field(&pkginfo.package.author).cyan();
151 | let pkg_stars = format_field(&pkginfo.package.stars).yellow();
152 | let pkg_version = format_field(&pkginfo.package.version).green();
153 | let pkg_size = format_field(&pkginfo.package.size).bold().cyan();
154 | let pkg_license = format_field(&pkginfo.package.license).blue();
155 | let pkg_language = format_field(&pkginfo.package.language).cyan();
156 |
157 | let package_information = Columns::from(vec![
158 | ASCII.split('\n').collect::>(),
159 | vec![
160 | &format!("Package: {pkg_bin_name}"),
161 | &format!("Architecture: {pkg_architecture}"),
162 | &format!("Stars: {pkg_stars}"),
163 | &format!("Version: {pkg_version}"),
164 | &format!("Author: {pkg_author}"),
165 | &format!("Size: {pkg_size}"),
166 | &format!("Desc: {pkg_desc}"),
167 | &format!("Hash: {pkg_hash}"),
168 | &format!("Language: {pkg_language}"),
169 | &format!("License: {pkg_license}"),
170 | ],
171 | ])
172 | .set_tabsize(15)
173 | .make_columns();
174 | println!("{}", RESET); // RESET terminal colors
175 | println!("{}", BAR.purple());
176 | println!("{}", package_information);
177 | println!("{}", BAR.purple());
178 | }
179 |
180 | /// Prints metadata package information based on MetadataInfo struct and package name.
181 | ///
182 | /// # Arguments
183 | ///
184 | /// * `metadatainfo` - A MetadataInfo struct containing metadata information.
185 | /// * `package_name` - A string slice representing the package name.
186 | ///
187 | #[inline]
188 | pub fn print_metadata_package_info(metadatainfo: MetadataInfo, package_name: &str) {
189 | if let Some(package) = metadatainfo
190 | .packages
191 | .iter()
192 | .find(|p| p.name == package_name)
193 | {
194 | // Needed fields
195 | let pkg_bin_name = &package.name;
196 | let pkg_architecture = &package.architecture;
197 | let pkg_hash = &package.sha.bold().cyan();
198 |
199 | // Optional fields
200 | let pkg_desc = format_field(&package.description).bold().blue();
201 | let pkg_author = format_field(&package.author).cyan();
202 | let pkg_stars = format_field(&package.stars).yellow();
203 | let pkg_version = format_field(&package.version).green();
204 | let pkg_size = format_field(&package.size).bold().cyan();
205 | let pkg_license = format_field(&package.license).blue();
206 | let pkg_language = format_field(&package.language).cyan();
207 |
208 | let package_information = Columns::from(vec![
209 | ASCII.split('\n').collect::>(),
210 | vec![
211 | &format!("Package: {}", pkg_bin_name),
212 | &format!("Architecture: {}", pkg_architecture),
213 | &format!("Stars: {}", pkg_stars),
214 | &format!("Version: {}", pkg_version),
215 | &format!("Author: {}", pkg_author),
216 | &format!("Size: {}", pkg_size),
217 | &format!("Desc: {}", pkg_desc),
218 | &format!("Hash: {}", pkg_hash),
219 | &format!("Language: {}", pkg_language),
220 | &format!("License: {}", pkg_license),
221 | ],
222 | ])
223 | .set_tabsize(15)
224 | .make_columns();
225 | println!("{}", RESET);
226 | println!("{}", BAR.purple());
227 | println!("{}", package_information);
228 | println!("{}", BAR.purple());
229 | } else {
230 | info(
231 | &format!("No such package found as: {}", package_name),
232 | colored::Color::Cyan,
233 | );
234 | }
235 | }
236 |
237 | /// Fetches local configuration data.
238 | ///
239 | /// # Returns
240 | ///
241 | /// A Result containing a tuple of strings representing remote, data directory,
242 | /// binary directory, and metadata link, or an error.
243 | ///
244 | #[inline]
245 | pub async fn local_config() -> Result<(String, String, String, String, String)> {
246 | let hysp_config = parse_local_config().await?;
247 |
248 | let hysp_remote = remove_trailing_slash(
249 | hysp_config
250 | .source
251 | .remote
252 | .ok_or_else(|| anyhow!("Couldn't get data directory"))?
253 | .to_string(),
254 | );
255 |
256 | let hysp_data_dir = remove_trailing_slash(
257 | hysp_config
258 | .local
259 | .data
260 | .ok_or_else(|| anyhow!("Couldn't get data directory"))?
261 | .to_string_lossy()
262 | .to_string(),
263 | );
264 |
265 | let hysp_bin_dir = remove_trailing_slash(
266 | hysp_config
267 | .local
268 | .bin
269 | .ok_or_else(|| anyhow!("Couldn't get binary directory"))?
270 | .to_string_lossy()
271 | .to_string(),
272 | );
273 |
274 | let hysp_metadata = remove_trailing_slash(
275 | hysp_config
276 | .source
277 | .metadata
278 | .ok_or_else(|| anyhow!("Couldn't get metadata link"))?
279 | .to_string(),
280 | );
281 |
282 | let system_arch = hysp_config
283 | .source
284 | .aarch
285 | .ok_or_else(|| anyhow!("Couldn't get aarch"))?
286 | .to_string();
287 |
288 | Ok((
289 | hysp_remote,
290 | hysp_data_dir,
291 | hysp_bin_dir,
292 | hysp_metadata,
293 | system_arch,
294 | ))
295 | }
296 |
297 | /// Creates a directory at the specified path if it does not already exist.
298 | ///
299 | /// # Arguments
300 | ///
301 | /// * `path` - A string slice representing the path of the directory to create.
302 | ///
303 | #[inline]
304 | pub fn create_directory_if_not_exists(path: &str) {
305 | if let Err(err) = std::fs::create_dir_all(path) {
306 | eprintln!("Error creating directory '{}': {}", path, err);
307 | }
308 | }
309 |
310 | /// Checks the hash of a file against an expected hash.
311 | ///
312 | /// # Arguments
313 | ///
314 | /// * `pkgname` - A String containing the file name.
315 | /// * `expected_hash` - A String containing the expected hash.
316 | ///
317 | /// # Returns
318 | ///
319 | /// A Result containing a boolean value: `true` if the actual hash matches the expected hash,
320 | /// `false` otherwise, or an error.
321 | ///
322 | #[inline]
323 | pub async fn check_hash(filename: String, expected_hash: String) -> Result {
324 | let mut file = File::open(filename).await?;
325 |
326 | let mut hasher = Sha256::new();
327 |
328 | let mut buffer = [0; 4096];
329 | loop {
330 | let bytes_read = file.read(&mut buffer).await?;
331 | if bytes_read == 0 {
332 | break;
333 | }
334 | hasher.update(&buffer[..bytes_read]);
335 | }
336 |
337 | let actual_hash = format!("{:x}", hasher.finalize());
338 |
339 | Ok(actual_hash == expected_hash)
340 | }
341 |
342 | /// Checks if a package is installed.
343 | ///
344 | /// # Arguments
345 | ///
346 | /// * `pkg_name` - A string slice representing the name of the package.
347 | ///
348 | /// # Returns
349 | ///
350 | /// A boolean value indicating whether the package is installed.
351 | ///
352 | #[inline]
353 | pub fn is_pkg_installed(pkg_name: &str) -> bool {
354 | let output = Command::new("which")
355 | .arg(pkg_name)
356 | .output()
357 | .expect("Failed to execute 'which' command");
358 |
359 | output.status.success()
360 | }
361 |
362 | /// Removes a file and prints a message indicating success or failure.
363 | ///
364 | /// # Arguments
365 | ///
366 | /// * `file_path` - A string slice representing the path of the file to be removed.
367 | ///
368 | #[inline]
369 | pub fn remove_and_print(file_path: &str) {
370 | if let Err(err) = fs::remove_file(file_path) {
371 | eprintln!("Error removing {}: {}", file_path, err);
372 | } else {
373 | info(&format!("Removed : {}", file_path), colored::Color::Cyan);
374 | }
375 | }
376 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | _**This project has been archived and is no longer maintained.**_
2 |
3 | WHY?
4 |
5 | _I recently started university and am currently busy with my personal work.
6 | Additionally, I've begun using `nix`, and this project was initially a way for me to learn about package managers and their internals. Therefore, I am archiving this project and do not recommend anyone use it. However, feel free to borrow any parts of it for your own projects if you find them inspiring._
7 |
8 |
9 |
10 |
11 |
12 |
13 | An independent package manager for unix and linux🌷
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | ## Table of contents 📔
31 |
32 | * [`Why`](#why)
33 | * [`Features`](#features)
34 | * [`Installation`](#installation)
35 | * [`Hysp usages`](#usages)
36 | * [`Hosting custom repo`](#repo)
37 | * [`Packages`](#pkgs)
38 | * [`Support`](#support)
39 | * [`License`](#license)
40 |
41 |
42 | ## Why?? 🚩
43 |
44 | I am a **CTF player** [***(Capture the flag)*** ](https://en.wikipedia.org/wiki/Capture_the_flag_(cybersecurity)) who often finds myself without my main laptop in places that lack the tools I need. Some distros don't carry the packages I require and some doesn't keep them updated. That's why I created my own package manager :). It fetches tool binaries easily, ensuring I always have what I need to compete.
45 |
46 | Dont touch my shrug
47 |
48 |
49 | ## Features ⚾
50 | 1. **Versatile** : Hysp operates on (*nix) systems and various architectures (x86, aarch64_arm), providing flexibility for your needs.
51 | 2. **Simple** : No prerequisites is needed for `Hysp` or `hysp-pkgs`. Install Hysp as a single binary, no need for Go, Rust, or any other dependencies. Saves space, storage, and time.
52 | 3. **Customizable** : Pkg-Source can be self-hosted by anyone, allowing hysp to use your ***very own*** instead of the default source and local configuration as well. See [#Self hosting](https://github.com/pwnwriter/hysp#repo)
53 | 4. **Statically compiled** : The default source [`metis-os/hysp-pkgs`](https://github.com/metis-os/hysp-pkgs)) has all statically compiled binaries, _only statically linked binaries that will run anywhere_. You can always host dynamic or whatever you want.
54 | 5. **No Special Privileges** : [Hysp](https://github.com/pwnwriter/hysp) requires no special perms or privileges. It can run completely in userspace with all of its features.
55 | 6. **Everything is open source** : Hysp uses github actions to build and ship the packages. On top of that it uses `sha` for varifying the binary.
56 |
57 | 7. Security Considerations
58 |
59 |
60 | It is never a good idea to install random binaries from random sources.
61 |
62 | Check these `HackerNews Discussions`
63 | > - [A cautionary tale from the decline of SourceForge](https://news.ycombinator.com/item?id=31110206)
64 | > - [Downloading PuTTY Safely Is Nearly Impossible (2014)](https://news.ycombinator.com/item?id=9577861)
65 |
66 |
67 | > ```bash
68 | > !# PKG Metadata
69 | > # Everything is automated via Github Actions & Scripts
70 | > Repo --> https://github.com/metis-os/hysp-pkgs
71 | > WorkFlows --> https://github.com/metis-os/hysp-pkgs/tree/main/.github/workflows
72 | > Scripts --> https://github.com/metis-os/hysp-pkgs/tree/main/.github/scripts
73 | >
74 | > !# Upstream Source
75 | > # Everything is automated via Github Actions & Build Scripts
76 | > Repo --> https://github.com/Azathothas/Toolpacks
77 | > WorkFlows --> https://github.com/Azathothas/Toolpacks/tree/main/.github/workflows
78 | > Build Scripts --> https://github.com/Azathothas/Toolpacks/tree/main/.github/scripts
79 | > ```
80 |
81 |
82 |
83 |
84 |
85 | ## Installation 📩
86 |
87 | ###### 🐤 From source
88 |
89 | ```bash
90 | git clone --depth=1 https://github.com/pwnwriter/hysp --branch=main
91 | cd hysp
92 | cargo build --release
93 | ```
94 | Then go to `release` dir and `./hysp` or move the `binary` to your any `$PATH` for instant access from anywhere.
95 |
96 |
97 | 🪄 Binary
98 |
99 |
100 | - *Manual* : You can directly download the [**binary**](https://github.com/pwnwriter/hysp/releases) of your arch and run it.
101 | - *One liner* : Run this script, requires `jq`,`curl`, `tar` & `wget`
102 | ```bash
103 | wget -qO- "$(curl -qfsSL "https://api.github.com/repos/pwnwriter/hysp/releases/latest" | jq -r '.assets[].browser_download_url' | grep -Ei "$(uname -m).*$(uname -s).*musl" | grep -v "\.sha")" | tar -xzf - --strip-components=1
104 | ./hysp -h
105 | ```
106 |
107 |
108 |
109 | 💮 using Cargo
110 |
111 |
112 | - Using [crates.io](https://crates.io/crates/hysp)
113 | ```bash
114 | cargo install hysp
115 | ```
116 | - Using [binstall](https://github.com/cargo-bins/cargo-binstall)
117 | ```bash
118 | cargo binstall hysp
119 | ```
120 |
121 | > **NOTE:**
122 | > This requires a working setup of rust/cargo & binstall.
123 |
124 |
125 |
126 | 🚩 METIS Linux
127 |
128 |
129 | ```bash
130 | sudo/doas pacman -Sy hysp
131 | ```
132 |
133 |
134 |
135 | 💢 Arch user repository
136 |
137 |
138 | ```bash
139 | paru/yay -S hysp-git
140 | ```
141 |
142 |
143 |
144 |
145 |
146 | ## Hysp usages 🎠
147 |
148 | ***Firstly, if you intend to access the binaries installed via `hysp` over the system, you may want to...***
149 |
150 | ##### Setup path for hysp bin
151 |
152 | - Add the following line to your shellrc. [ `zshrc`, `bashrc` ***etc***. ]
153 |
154 | ```bash
155 | export PATH="$HOME/.local/share/hysp/bin/:$PATH" # While using default config, else use your own path to bin
156 | ```
157 |
158 | Help menu
159 |
160 |
161 |
162 | ```bash
163 | hysp |install|uninstall|search| -h # check for help menu
164 | ```
165 |
166 | 
167 |
168 |
169 |
170 | Installing packages
171 |
172 |
173 | ```bash
174 | hysp install -p # use --force to overwrite already installed binary, --quiet to supress console io
175 | ```
176 | 
177 |
178 |
179 |
180 |
181 | Removing packages
182 |
183 |
184 | ```bash
185 | hysp remove -p
186 | ```
187 |
188 | 
189 |
190 |
191 |
192 | Search for available pkgs
193 |
194 |
195 | ```bash
196 | hysp search -p
197 | ```
198 |
199 | - Raw mode (default)
200 |
201 | 
202 |
203 | - Database mode
204 |
205 | 
206 |
207 | - Fuzzy mode
208 |
209 | 
210 |
211 |
212 |
213 | Checking configuration health
214 |
215 |
216 | ```bash
217 | hysp health
218 | ```
219 |
220 | 
221 |
222 |
223 |
224 | ##### Numerous other options exist. Consider installing Hysp and checking it out, wouldn't you?
225 |
226 |
227 | ## Hosting custom repo 💾
228 |
229 | - Hysp provies the following configuration, which can be overwritten by defining a `config file` in `~/.config/hysp/config.toml`
230 |
231 | ```toml
232 | [source]
233 | remote = "https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/x86_64"
234 | metadata ="https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/metadata.toml"
235 | aarch = "Architecture"
236 |
237 | [local]
238 | home="/home/user/.local/share/hysp"
239 | bin="/home/user/.local/share/hysp/bin/"
240 | data="/home/user/.local/share/hysp/data/"
241 |
242 | ```
243 | - Explanation
244 |
245 | | Name | Description | Default |
246 | |-------------|------------------------------------|----------------------------------------------------|
247 | | `remote` | Package repository | [***`metis-os/hysp-pkgs`***](https://github.com/metis-os/hysp-pkgs) |
248 | | `metadata` | Available pkg info | [***`metis-os/hysp-pkgs/metadata.toml`***](https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/metadata.toml)|
249 | | `home` | Home for `hysp` | ***`hysp`*** |
250 | | `bin` | Directory to save the binaries | ***`~/.local/share/hysp/bin`*** |
251 | | `data` | Directory to save pkg data | ***`~/.local/share/hysp/data`*** |
252 | | `aarch` | Your system Architecture | Only supported ***`X86_64,aarch64`*** |
253 |
254 | 🎄 Tree view of the repo
255 |
256 |
257 | ```bash
258 | .
259 | ├── available.toml # Storing available pkgs info (Optional)
260 | ├── data
261 | │ └── foo.toml # where the package data are stored (needed)
262 | ```
263 |
264 |
265 |
266 |
267 | 📂 Sample pkg
268 |
269 |
270 | ```bash
271 | [bin]
272 | name = "$BIN" # Name of the pkg to be installed as
273 |
274 | [package]
275 | architecture = "x86_64" # Your aarchitecture
276 | name = "$BIN" # Your package name
277 | description = "$DESCRIPTION" # Description
278 | author = "$AUTHOR" # Author
279 | repo = "$REPO_URL"
280 | stars = "${STARS}"
281 | version = "$PKG_VERSION"
282 | updated = "$PKG_RELEASED"
283 | size = "$SIZE"
284 | sha = "$SHA"
285 | source = "$SOURCE_URL" # Source of the binary wherever it's hosted
286 | language = "$LANGUAGE"
287 | license = "$LICENSE"
288 |
289 | [package.conditions]
290 | conflicts = ["$BIN"] # Conflictions
291 | requires = [] # Dependencies
292 |
293 | [package.metadata]
294 | keywords = $TOPICS
295 | categories = ["Utilities"]
296 | ```
297 |
298 |
299 |
300 |
301 | ## Packages whuat?? 📦
302 | There is a list of packages available in [*`metis-os/hysp-pkgs`*](https://github.com/metis-os/hysp-pkgs) . You can confidently utilize the default configuration without any hesitation. However, if you prefer to host your own packages, you have the option to do so by creating your own custom configuration file under ***`~/.config/hysp/config.toml`***. See [`#repo`](https://github.com/pwnwriter/hysp#repo)
303 |
304 |
305 |
306 | ## Support 💌
307 |
308 | I am a student currently attending university. I like working for *Open Source* in my free time. If you find my tool or work beneficial, please consider supporting me via [*KO-FI*](https://ko-fi.com/pwnwriter) or [*ESEWA*](https://metislinux.org/docs/donate)* (***Nepal only***), Or by leaving a star ⭐ ; I'll appreciate your action :)
309 |
310 |
311 | ## License ㊙️
312 |
313 | Everything is license under the [`MIT`](https://raw.githubusercontent.com/pwnwriter/hysp/main/LICENSE) except for the packages...
314 | They hold their own livess :oOO
315 |
316 | 
317 | Copyright © 2023 pwnwriter xyz ☘️
318 |
319 |
320 |
321 |
322 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "addr2line"
7 | version = "0.21.0"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
10 | dependencies = [
11 | "gimli",
12 | ]
13 |
14 | [[package]]
15 | name = "adler"
16 | version = "1.0.2"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19 |
20 | [[package]]
21 | name = "anstream"
22 | version = "0.6.4"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
25 | dependencies = [
26 | "anstyle",
27 | "anstyle-parse",
28 | "anstyle-query",
29 | "anstyle-wincon",
30 | "colorchoice",
31 | "utf8parse",
32 | ]
33 |
34 | [[package]]
35 | name = "anstyle"
36 | version = "1.0.4"
37 | source = "registry+https://github.com/rust-lang/crates.io-index"
38 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
39 |
40 | [[package]]
41 | name = "anstyle-parse"
42 | version = "0.2.2"
43 | source = "registry+https://github.com/rust-lang/crates.io-index"
44 | checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
45 | dependencies = [
46 | "utf8parse",
47 | ]
48 |
49 | [[package]]
50 | name = "anstyle-query"
51 | version = "1.0.0"
52 | source = "registry+https://github.com/rust-lang/crates.io-index"
53 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
54 | dependencies = [
55 | "windows-sys",
56 | ]
57 |
58 | [[package]]
59 | name = "anstyle-wincon"
60 | version = "3.0.1"
61 | source = "registry+https://github.com/rust-lang/crates.io-index"
62 | checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
63 | dependencies = [
64 | "anstyle",
65 | "windows-sys",
66 | ]
67 |
68 | [[package]]
69 | name = "anyhow"
70 | version = "1.0.80"
71 | source = "registry+https://github.com/rust-lang/crates.io-index"
72 | checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
73 |
74 | [[package]]
75 | name = "async-recursion"
76 | version = "1.0.5"
77 | source = "registry+https://github.com/rust-lang/crates.io-index"
78 | checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
79 | dependencies = [
80 | "proc-macro2",
81 | "quote",
82 | "syn",
83 | ]
84 |
85 | [[package]]
86 | name = "autocfg"
87 | version = "1.1.0"
88 | source = "registry+https://github.com/rust-lang/crates.io-index"
89 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
90 |
91 | [[package]]
92 | name = "backtrace"
93 | version = "0.3.69"
94 | source = "registry+https://github.com/rust-lang/crates.io-index"
95 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
96 | dependencies = [
97 | "addr2line",
98 | "cc",
99 | "cfg-if",
100 | "libc",
101 | "miniz_oxide",
102 | "object",
103 | "rustc-demangle",
104 | ]
105 |
106 | [[package]]
107 | name = "base64"
108 | version = "0.21.5"
109 | source = "registry+https://github.com/rust-lang/crates.io-index"
110 | checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
111 |
112 | [[package]]
113 | name = "bitflags"
114 | version = "1.3.2"
115 | source = "registry+https://github.com/rust-lang/crates.io-index"
116 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
117 |
118 | [[package]]
119 | name = "bitflags"
120 | version = "2.4.1"
121 | source = "registry+https://github.com/rust-lang/crates.io-index"
122 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
123 |
124 | [[package]]
125 | name = "block-buffer"
126 | version = "0.10.4"
127 | source = "registry+https://github.com/rust-lang/crates.io-index"
128 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
129 | dependencies = [
130 | "generic-array",
131 | ]
132 |
133 | [[package]]
134 | name = "bumpalo"
135 | version = "3.14.0"
136 | source = "registry+https://github.com/rust-lang/crates.io-index"
137 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
138 |
139 | [[package]]
140 | name = "bytes"
141 | version = "1.5.0"
142 | source = "registry+https://github.com/rust-lang/crates.io-index"
143 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
144 |
145 | [[package]]
146 | name = "cc"
147 | version = "1.0.83"
148 | source = "registry+https://github.com/rust-lang/crates.io-index"
149 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
150 | dependencies = [
151 | "libc",
152 | ]
153 |
154 | [[package]]
155 | name = "cfg-if"
156 | version = "1.0.0"
157 | source = "registry+https://github.com/rust-lang/crates.io-index"
158 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
159 |
160 | [[package]]
161 | name = "clap"
162 | version = "4.4.11"
163 | source = "registry+https://github.com/rust-lang/crates.io-index"
164 | checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
165 | dependencies = [
166 | "clap_builder",
167 | "clap_derive",
168 | ]
169 |
170 | [[package]]
171 | name = "clap_builder"
172 | version = "4.4.11"
173 | source = "registry+https://github.com/rust-lang/crates.io-index"
174 | checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
175 | dependencies = [
176 | "anstream",
177 | "anstyle",
178 | "clap_lex",
179 | "strsim",
180 | ]
181 |
182 | [[package]]
183 | name = "clap_derive"
184 | version = "4.4.7"
185 | source = "registry+https://github.com/rust-lang/crates.io-index"
186 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
187 | dependencies = [
188 | "heck",
189 | "proc-macro2",
190 | "quote",
191 | "syn",
192 | ]
193 |
194 | [[package]]
195 | name = "clap_lex"
196 | version = "0.6.0"
197 | source = "registry+https://github.com/rust-lang/crates.io-index"
198 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
199 |
200 | [[package]]
201 | name = "colorchoice"
202 | version = "1.0.0"
203 | source = "registry+https://github.com/rust-lang/crates.io-index"
204 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
205 |
206 | [[package]]
207 | name = "colored"
208 | version = "2.1.0"
209 | source = "registry+https://github.com/rust-lang/crates.io-index"
210 | checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
211 | dependencies = [
212 | "lazy_static",
213 | "windows-sys",
214 | ]
215 |
216 | [[package]]
217 | name = "columns"
218 | version = "0.1.0"
219 | source = "registry+https://github.com/rust-lang/crates.io-index"
220 | checksum = "42118f8f83dd1c93860502e6acfffc2283201a1ad51bad7cdf2157ef6faeab80"
221 |
222 | [[package]]
223 | name = "core-foundation"
224 | version = "0.9.3"
225 | source = "registry+https://github.com/rust-lang/crates.io-index"
226 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
227 | dependencies = [
228 | "core-foundation-sys",
229 | "libc",
230 | ]
231 |
232 | [[package]]
233 | name = "core-foundation-sys"
234 | version = "0.8.4"
235 | source = "registry+https://github.com/rust-lang/crates.io-index"
236 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
237 |
238 | [[package]]
239 | name = "cpufeatures"
240 | version = "0.2.11"
241 | source = "registry+https://github.com/rust-lang/crates.io-index"
242 | checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
243 | dependencies = [
244 | "libc",
245 | ]
246 |
247 | [[package]]
248 | name = "crypto-common"
249 | version = "0.1.6"
250 | source = "registry+https://github.com/rust-lang/crates.io-index"
251 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
252 | dependencies = [
253 | "generic-array",
254 | "typenum",
255 | ]
256 |
257 | [[package]]
258 | name = "digest"
259 | version = "0.10.7"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
262 | dependencies = [
263 | "block-buffer",
264 | "crypto-common",
265 | ]
266 |
267 | [[package]]
268 | name = "dirs"
269 | version = "5.0.1"
270 | source = "registry+https://github.com/rust-lang/crates.io-index"
271 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
272 | dependencies = [
273 | "dirs-sys",
274 | ]
275 |
276 | [[package]]
277 | name = "dirs-sys"
278 | version = "0.4.1"
279 | source = "registry+https://github.com/rust-lang/crates.io-index"
280 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
281 | dependencies = [
282 | "libc",
283 | "option-ext",
284 | "redox_users",
285 | "windows-sys",
286 | ]
287 |
288 | [[package]]
289 | name = "encoding_rs"
290 | version = "0.8.33"
291 | source = "registry+https://github.com/rust-lang/crates.io-index"
292 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
293 | dependencies = [
294 | "cfg-if",
295 | ]
296 |
297 | [[package]]
298 | name = "equivalent"
299 | version = "1.0.1"
300 | source = "registry+https://github.com/rust-lang/crates.io-index"
301 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
302 |
303 | [[package]]
304 | name = "fnv"
305 | version = "1.0.7"
306 | source = "registry+https://github.com/rust-lang/crates.io-index"
307 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
308 |
309 | [[package]]
310 | name = "form_urlencoded"
311 | version = "1.2.1"
312 | source = "registry+https://github.com/rust-lang/crates.io-index"
313 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
314 | dependencies = [
315 | "percent-encoding",
316 | ]
317 |
318 | [[package]]
319 | name = "futures-channel"
320 | version = "0.3.29"
321 | source = "registry+https://github.com/rust-lang/crates.io-index"
322 | checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
323 | dependencies = [
324 | "futures-core",
325 | ]
326 |
327 | [[package]]
328 | name = "futures-core"
329 | version = "0.3.29"
330 | source = "registry+https://github.com/rust-lang/crates.io-index"
331 | checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
332 |
333 | [[package]]
334 | name = "futures-sink"
335 | version = "0.3.29"
336 | source = "registry+https://github.com/rust-lang/crates.io-index"
337 | checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
338 |
339 | [[package]]
340 | name = "futures-task"
341 | version = "0.3.29"
342 | source = "registry+https://github.com/rust-lang/crates.io-index"
343 | checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
344 |
345 | [[package]]
346 | name = "futures-util"
347 | version = "0.3.29"
348 | source = "registry+https://github.com/rust-lang/crates.io-index"
349 | checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
350 | dependencies = [
351 | "futures-core",
352 | "futures-task",
353 | "pin-project-lite",
354 | "pin-utils",
355 | ]
356 |
357 | [[package]]
358 | name = "generic-array"
359 | version = "0.14.7"
360 | source = "registry+https://github.com/rust-lang/crates.io-index"
361 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
362 | dependencies = [
363 | "typenum",
364 | "version_check",
365 | ]
366 |
367 | [[package]]
368 | name = "getrandom"
369 | version = "0.2.11"
370 | source = "registry+https://github.com/rust-lang/crates.io-index"
371 | checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
372 | dependencies = [
373 | "cfg-if",
374 | "libc",
375 | "wasi",
376 | ]
377 |
378 | [[package]]
379 | name = "gimli"
380 | version = "0.28.1"
381 | source = "registry+https://github.com/rust-lang/crates.io-index"
382 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
383 |
384 | [[package]]
385 | name = "h2"
386 | version = "0.3.22"
387 | source = "registry+https://github.com/rust-lang/crates.io-index"
388 | checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
389 | dependencies = [
390 | "bytes",
391 | "fnv",
392 | "futures-core",
393 | "futures-sink",
394 | "futures-util",
395 | "http",
396 | "indexmap",
397 | "slab",
398 | "tokio",
399 | "tokio-util",
400 | "tracing",
401 | ]
402 |
403 | [[package]]
404 | name = "hashbrown"
405 | version = "0.14.2"
406 | source = "registry+https://github.com/rust-lang/crates.io-index"
407 | checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
408 |
409 | [[package]]
410 | name = "heck"
411 | version = "0.4.1"
412 | source = "registry+https://github.com/rust-lang/crates.io-index"
413 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
414 |
415 | [[package]]
416 | name = "hermit-abi"
417 | version = "0.3.3"
418 | source = "registry+https://github.com/rust-lang/crates.io-index"
419 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
420 |
421 | [[package]]
422 | name = "http"
423 | version = "0.2.11"
424 | source = "registry+https://github.com/rust-lang/crates.io-index"
425 | checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
426 | dependencies = [
427 | "bytes",
428 | "fnv",
429 | "itoa",
430 | ]
431 |
432 | [[package]]
433 | name = "http-body"
434 | version = "0.4.5"
435 | source = "registry+https://github.com/rust-lang/crates.io-index"
436 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
437 | dependencies = [
438 | "bytes",
439 | "http",
440 | "pin-project-lite",
441 | ]
442 |
443 | [[package]]
444 | name = "httparse"
445 | version = "1.8.0"
446 | source = "registry+https://github.com/rust-lang/crates.io-index"
447 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
448 |
449 | [[package]]
450 | name = "httpdate"
451 | version = "1.0.3"
452 | source = "registry+https://github.com/rust-lang/crates.io-index"
453 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
454 |
455 | [[package]]
456 | name = "hyper"
457 | version = "0.14.27"
458 | source = "registry+https://github.com/rust-lang/crates.io-index"
459 | checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
460 | dependencies = [
461 | "bytes",
462 | "futures-channel",
463 | "futures-core",
464 | "futures-util",
465 | "h2",
466 | "http",
467 | "http-body",
468 | "httparse",
469 | "httpdate",
470 | "itoa",
471 | "pin-project-lite",
472 | "socket2 0.4.10",
473 | "tokio",
474 | "tower-service",
475 | "tracing",
476 | "want",
477 | ]
478 |
479 | [[package]]
480 | name = "hyper-rustls"
481 | version = "0.24.2"
482 | source = "registry+https://github.com/rust-lang/crates.io-index"
483 | checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
484 | dependencies = [
485 | "futures-util",
486 | "http",
487 | "hyper",
488 | "rustls",
489 | "tokio",
490 | "tokio-rustls",
491 | ]
492 |
493 | [[package]]
494 | name = "hysp"
495 | version = "0.1.2"
496 | dependencies = [
497 | "anyhow",
498 | "async-recursion",
499 | "clap",
500 | "colored",
501 | "columns",
502 | "dirs",
503 | "reqwest",
504 | "serde",
505 | "sha2",
506 | "spinoff",
507 | "tokio",
508 | "toml",
509 | ]
510 |
511 | [[package]]
512 | name = "idna"
513 | version = "0.5.0"
514 | source = "registry+https://github.com/rust-lang/crates.io-index"
515 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
516 | dependencies = [
517 | "unicode-bidi",
518 | "unicode-normalization",
519 | ]
520 |
521 | [[package]]
522 | name = "indexmap"
523 | version = "2.1.0"
524 | source = "registry+https://github.com/rust-lang/crates.io-index"
525 | checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
526 | dependencies = [
527 | "equivalent",
528 | "hashbrown",
529 | ]
530 |
531 | [[package]]
532 | name = "ipnet"
533 | version = "2.9.0"
534 | source = "registry+https://github.com/rust-lang/crates.io-index"
535 | checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
536 |
537 | [[package]]
538 | name = "itoa"
539 | version = "1.0.9"
540 | source = "registry+https://github.com/rust-lang/crates.io-index"
541 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
542 |
543 | [[package]]
544 | name = "js-sys"
545 | version = "0.3.65"
546 | source = "registry+https://github.com/rust-lang/crates.io-index"
547 | checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
548 | dependencies = [
549 | "wasm-bindgen",
550 | ]
551 |
552 | [[package]]
553 | name = "lazy_static"
554 | version = "1.4.0"
555 | source = "registry+https://github.com/rust-lang/crates.io-index"
556 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
557 |
558 | [[package]]
559 | name = "libc"
560 | version = "0.2.150"
561 | source = "registry+https://github.com/rust-lang/crates.io-index"
562 | checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
563 |
564 | [[package]]
565 | name = "libredox"
566 | version = "0.0.1"
567 | source = "registry+https://github.com/rust-lang/crates.io-index"
568 | checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
569 | dependencies = [
570 | "bitflags 2.4.1",
571 | "libc",
572 | "redox_syscall",
573 | ]
574 |
575 | [[package]]
576 | name = "lock_api"
577 | version = "0.4.11"
578 | source = "registry+https://github.com/rust-lang/crates.io-index"
579 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
580 | dependencies = [
581 | "autocfg",
582 | "scopeguard",
583 | ]
584 |
585 | [[package]]
586 | name = "log"
587 | version = "0.4.20"
588 | source = "registry+https://github.com/rust-lang/crates.io-index"
589 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
590 |
591 | [[package]]
592 | name = "memchr"
593 | version = "2.6.4"
594 | source = "registry+https://github.com/rust-lang/crates.io-index"
595 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
596 |
597 | [[package]]
598 | name = "mime"
599 | version = "0.3.17"
600 | source = "registry+https://github.com/rust-lang/crates.io-index"
601 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
602 |
603 | [[package]]
604 | name = "miniz_oxide"
605 | version = "0.7.1"
606 | source = "registry+https://github.com/rust-lang/crates.io-index"
607 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
608 | dependencies = [
609 | "adler",
610 | ]
611 |
612 | [[package]]
613 | name = "mio"
614 | version = "0.8.9"
615 | source = "registry+https://github.com/rust-lang/crates.io-index"
616 | checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
617 | dependencies = [
618 | "libc",
619 | "wasi",
620 | "windows-sys",
621 | ]
622 |
623 | [[package]]
624 | name = "num_cpus"
625 | version = "1.16.0"
626 | source = "registry+https://github.com/rust-lang/crates.io-index"
627 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
628 | dependencies = [
629 | "hermit-abi",
630 | "libc",
631 | ]
632 |
633 | [[package]]
634 | name = "object"
635 | version = "0.32.1"
636 | source = "registry+https://github.com/rust-lang/crates.io-index"
637 | checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
638 | dependencies = [
639 | "memchr",
640 | ]
641 |
642 | [[package]]
643 | name = "once_cell"
644 | version = "1.18.0"
645 | source = "registry+https://github.com/rust-lang/crates.io-index"
646 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
647 |
648 | [[package]]
649 | name = "option-ext"
650 | version = "0.2.0"
651 | source = "registry+https://github.com/rust-lang/crates.io-index"
652 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
653 |
654 | [[package]]
655 | name = "parking_lot"
656 | version = "0.12.1"
657 | source = "registry+https://github.com/rust-lang/crates.io-index"
658 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
659 | dependencies = [
660 | "lock_api",
661 | "parking_lot_core",
662 | ]
663 |
664 | [[package]]
665 | name = "parking_lot_core"
666 | version = "0.9.9"
667 | source = "registry+https://github.com/rust-lang/crates.io-index"
668 | checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
669 | dependencies = [
670 | "cfg-if",
671 | "libc",
672 | "redox_syscall",
673 | "smallvec",
674 | "windows-targets",
675 | ]
676 |
677 | [[package]]
678 | name = "paste"
679 | version = "1.0.14"
680 | source = "registry+https://github.com/rust-lang/crates.io-index"
681 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
682 |
683 | [[package]]
684 | name = "percent-encoding"
685 | version = "2.3.1"
686 | source = "registry+https://github.com/rust-lang/crates.io-index"
687 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
688 |
689 | [[package]]
690 | name = "pin-project-lite"
691 | version = "0.2.13"
692 | source = "registry+https://github.com/rust-lang/crates.io-index"
693 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
694 |
695 | [[package]]
696 | name = "pin-utils"
697 | version = "0.1.0"
698 | source = "registry+https://github.com/rust-lang/crates.io-index"
699 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
700 |
701 | [[package]]
702 | name = "proc-macro2"
703 | version = "1.0.78"
704 | source = "registry+https://github.com/rust-lang/crates.io-index"
705 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
706 | dependencies = [
707 | "unicode-ident",
708 | ]
709 |
710 | [[package]]
711 | name = "quote"
712 | version = "1.0.35"
713 | source = "registry+https://github.com/rust-lang/crates.io-index"
714 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
715 | dependencies = [
716 | "proc-macro2",
717 | ]
718 |
719 | [[package]]
720 | name = "redox_syscall"
721 | version = "0.4.1"
722 | source = "registry+https://github.com/rust-lang/crates.io-index"
723 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
724 | dependencies = [
725 | "bitflags 1.3.2",
726 | ]
727 |
728 | [[package]]
729 | name = "redox_users"
730 | version = "0.4.4"
731 | source = "registry+https://github.com/rust-lang/crates.io-index"
732 | checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
733 | dependencies = [
734 | "getrandom",
735 | "libredox",
736 | "thiserror",
737 | ]
738 |
739 | [[package]]
740 | name = "reqwest"
741 | version = "0.11.23"
742 | source = "registry+https://github.com/rust-lang/crates.io-index"
743 | checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41"
744 | dependencies = [
745 | "base64",
746 | "bytes",
747 | "encoding_rs",
748 | "futures-core",
749 | "futures-util",
750 | "h2",
751 | "http",
752 | "http-body",
753 | "hyper",
754 | "hyper-rustls",
755 | "ipnet",
756 | "js-sys",
757 | "log",
758 | "mime",
759 | "once_cell",
760 | "percent-encoding",
761 | "pin-project-lite",
762 | "rustls",
763 | "rustls-pemfile",
764 | "serde",
765 | "serde_json",
766 | "serde_urlencoded",
767 | "system-configuration",
768 | "tokio",
769 | "tokio-rustls",
770 | "tower-service",
771 | "url",
772 | "wasm-bindgen",
773 | "wasm-bindgen-futures",
774 | "web-sys",
775 | "webpki-roots",
776 | "winreg",
777 | ]
778 |
779 | [[package]]
780 | name = "ring"
781 | version = "0.17.5"
782 | source = "registry+https://github.com/rust-lang/crates.io-index"
783 | checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b"
784 | dependencies = [
785 | "cc",
786 | "getrandom",
787 | "libc",
788 | "spin",
789 | "untrusted",
790 | "windows-sys",
791 | ]
792 |
793 | [[package]]
794 | name = "rustc-demangle"
795 | version = "0.1.23"
796 | source = "registry+https://github.com/rust-lang/crates.io-index"
797 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
798 |
799 | [[package]]
800 | name = "rustls"
801 | version = "0.21.9"
802 | source = "registry+https://github.com/rust-lang/crates.io-index"
803 | checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
804 | dependencies = [
805 | "log",
806 | "ring",
807 | "rustls-webpki",
808 | "sct",
809 | ]
810 |
811 | [[package]]
812 | name = "rustls-pemfile"
813 | version = "1.0.4"
814 | source = "registry+https://github.com/rust-lang/crates.io-index"
815 | checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
816 | dependencies = [
817 | "base64",
818 | ]
819 |
820 | [[package]]
821 | name = "rustls-webpki"
822 | version = "0.101.7"
823 | source = "registry+https://github.com/rust-lang/crates.io-index"
824 | checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
825 | dependencies = [
826 | "ring",
827 | "untrusted",
828 | ]
829 |
830 | [[package]]
831 | name = "ryu"
832 | version = "1.0.15"
833 | source = "registry+https://github.com/rust-lang/crates.io-index"
834 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
835 |
836 | [[package]]
837 | name = "scopeguard"
838 | version = "1.2.0"
839 | source = "registry+https://github.com/rust-lang/crates.io-index"
840 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
841 |
842 | [[package]]
843 | name = "sct"
844 | version = "0.7.1"
845 | source = "registry+https://github.com/rust-lang/crates.io-index"
846 | checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
847 | dependencies = [
848 | "ring",
849 | "untrusted",
850 | ]
851 |
852 | [[package]]
853 | name = "serde"
854 | version = "1.0.197"
855 | source = "registry+https://github.com/rust-lang/crates.io-index"
856 | checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
857 | dependencies = [
858 | "serde_derive",
859 | ]
860 |
861 | [[package]]
862 | name = "serde_derive"
863 | version = "1.0.197"
864 | source = "registry+https://github.com/rust-lang/crates.io-index"
865 | checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
866 | dependencies = [
867 | "proc-macro2",
868 | "quote",
869 | "syn",
870 | ]
871 |
872 | [[package]]
873 | name = "serde_json"
874 | version = "1.0.108"
875 | source = "registry+https://github.com/rust-lang/crates.io-index"
876 | checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
877 | dependencies = [
878 | "itoa",
879 | "ryu",
880 | "serde",
881 | ]
882 |
883 | [[package]]
884 | name = "serde_spanned"
885 | version = "0.6.4"
886 | source = "registry+https://github.com/rust-lang/crates.io-index"
887 | checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
888 | dependencies = [
889 | "serde",
890 | ]
891 |
892 | [[package]]
893 | name = "serde_urlencoded"
894 | version = "0.7.1"
895 | source = "registry+https://github.com/rust-lang/crates.io-index"
896 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
897 | dependencies = [
898 | "form_urlencoded",
899 | "itoa",
900 | "ryu",
901 | "serde",
902 | ]
903 |
904 | [[package]]
905 | name = "sha2"
906 | version = "0.10.8"
907 | source = "registry+https://github.com/rust-lang/crates.io-index"
908 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
909 | dependencies = [
910 | "cfg-if",
911 | "cpufeatures",
912 | "digest",
913 | ]
914 |
915 | [[package]]
916 | name = "signal-hook-registry"
917 | version = "1.4.1"
918 | source = "registry+https://github.com/rust-lang/crates.io-index"
919 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
920 | dependencies = [
921 | "libc",
922 | ]
923 |
924 | [[package]]
925 | name = "slab"
926 | version = "0.4.9"
927 | source = "registry+https://github.com/rust-lang/crates.io-index"
928 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
929 | dependencies = [
930 | "autocfg",
931 | ]
932 |
933 | [[package]]
934 | name = "smallvec"
935 | version = "1.11.2"
936 | source = "registry+https://github.com/rust-lang/crates.io-index"
937 | checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
938 |
939 | [[package]]
940 | name = "socket2"
941 | version = "0.4.10"
942 | source = "registry+https://github.com/rust-lang/crates.io-index"
943 | checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
944 | dependencies = [
945 | "libc",
946 | "winapi",
947 | ]
948 |
949 | [[package]]
950 | name = "socket2"
951 | version = "0.5.5"
952 | source = "registry+https://github.com/rust-lang/crates.io-index"
953 | checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
954 | dependencies = [
955 | "libc",
956 | "windows-sys",
957 | ]
958 |
959 | [[package]]
960 | name = "spin"
961 | version = "0.9.8"
962 | source = "registry+https://github.com/rust-lang/crates.io-index"
963 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
964 |
965 | [[package]]
966 | name = "spinoff"
967 | version = "0.8.0"
968 | source = "registry+https://github.com/rust-lang/crates.io-index"
969 | checksum = "20aa2ed67fbb202e7b716ff8bfc6571dd9301617767380197d701c31124e88f6"
970 | dependencies = [
971 | "colored",
972 | "once_cell",
973 | "paste",
974 | ]
975 |
976 | [[package]]
977 | name = "strsim"
978 | version = "0.10.0"
979 | source = "registry+https://github.com/rust-lang/crates.io-index"
980 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
981 |
982 | [[package]]
983 | name = "syn"
984 | version = "2.0.50"
985 | source = "registry+https://github.com/rust-lang/crates.io-index"
986 | checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
987 | dependencies = [
988 | "proc-macro2",
989 | "quote",
990 | "unicode-ident",
991 | ]
992 |
993 | [[package]]
994 | name = "system-configuration"
995 | version = "0.5.1"
996 | source = "registry+https://github.com/rust-lang/crates.io-index"
997 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
998 | dependencies = [
999 | "bitflags 1.3.2",
1000 | "core-foundation",
1001 | "system-configuration-sys",
1002 | ]
1003 |
1004 | [[package]]
1005 | name = "system-configuration-sys"
1006 | version = "0.5.0"
1007 | source = "registry+https://github.com/rust-lang/crates.io-index"
1008 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
1009 | dependencies = [
1010 | "core-foundation-sys",
1011 | "libc",
1012 | ]
1013 |
1014 | [[package]]
1015 | name = "thiserror"
1016 | version = "1.0.50"
1017 | source = "registry+https://github.com/rust-lang/crates.io-index"
1018 | checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
1019 | dependencies = [
1020 | "thiserror-impl",
1021 | ]
1022 |
1023 | [[package]]
1024 | name = "thiserror-impl"
1025 | version = "1.0.50"
1026 | source = "registry+https://github.com/rust-lang/crates.io-index"
1027 | checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
1028 | dependencies = [
1029 | "proc-macro2",
1030 | "quote",
1031 | "syn",
1032 | ]
1033 |
1034 | [[package]]
1035 | name = "tinyvec"
1036 | version = "1.6.0"
1037 | source = "registry+https://github.com/rust-lang/crates.io-index"
1038 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
1039 | dependencies = [
1040 | "tinyvec_macros",
1041 | ]
1042 |
1043 | [[package]]
1044 | name = "tinyvec_macros"
1045 | version = "0.1.1"
1046 | source = "registry+https://github.com/rust-lang/crates.io-index"
1047 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
1048 |
1049 | [[package]]
1050 | name = "tokio"
1051 | version = "1.35.1"
1052 | source = "registry+https://github.com/rust-lang/crates.io-index"
1053 | checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
1054 | dependencies = [
1055 | "backtrace",
1056 | "bytes",
1057 | "libc",
1058 | "mio",
1059 | "num_cpus",
1060 | "parking_lot",
1061 | "pin-project-lite",
1062 | "signal-hook-registry",
1063 | "socket2 0.5.5",
1064 | "tokio-macros",
1065 | "windows-sys",
1066 | ]
1067 |
1068 | [[package]]
1069 | name = "tokio-macros"
1070 | version = "2.2.0"
1071 | source = "registry+https://github.com/rust-lang/crates.io-index"
1072 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
1073 | dependencies = [
1074 | "proc-macro2",
1075 | "quote",
1076 | "syn",
1077 | ]
1078 |
1079 | [[package]]
1080 | name = "tokio-rustls"
1081 | version = "0.24.1"
1082 | source = "registry+https://github.com/rust-lang/crates.io-index"
1083 | checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
1084 | dependencies = [
1085 | "rustls",
1086 | "tokio",
1087 | ]
1088 |
1089 | [[package]]
1090 | name = "tokio-util"
1091 | version = "0.7.10"
1092 | source = "registry+https://github.com/rust-lang/crates.io-index"
1093 | checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
1094 | dependencies = [
1095 | "bytes",
1096 | "futures-core",
1097 | "futures-sink",
1098 | "pin-project-lite",
1099 | "tokio",
1100 | "tracing",
1101 | ]
1102 |
1103 | [[package]]
1104 | name = "toml"
1105 | version = "0.8.8"
1106 | source = "registry+https://github.com/rust-lang/crates.io-index"
1107 | checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
1108 | dependencies = [
1109 | "serde",
1110 | "serde_spanned",
1111 | "toml_datetime",
1112 | "toml_edit",
1113 | ]
1114 |
1115 | [[package]]
1116 | name = "toml_datetime"
1117 | version = "0.6.5"
1118 | source = "registry+https://github.com/rust-lang/crates.io-index"
1119 | checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
1120 | dependencies = [
1121 | "serde",
1122 | ]
1123 |
1124 | [[package]]
1125 | name = "toml_edit"
1126 | version = "0.21.0"
1127 | source = "registry+https://github.com/rust-lang/crates.io-index"
1128 | checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
1129 | dependencies = [
1130 | "indexmap",
1131 | "serde",
1132 | "serde_spanned",
1133 | "toml_datetime",
1134 | "winnow",
1135 | ]
1136 |
1137 | [[package]]
1138 | name = "tower-service"
1139 | version = "0.3.2"
1140 | source = "registry+https://github.com/rust-lang/crates.io-index"
1141 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
1142 |
1143 | [[package]]
1144 | name = "tracing"
1145 | version = "0.1.40"
1146 | source = "registry+https://github.com/rust-lang/crates.io-index"
1147 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
1148 | dependencies = [
1149 | "pin-project-lite",
1150 | "tracing-core",
1151 | ]
1152 |
1153 | [[package]]
1154 | name = "tracing-core"
1155 | version = "0.1.32"
1156 | source = "registry+https://github.com/rust-lang/crates.io-index"
1157 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
1158 | dependencies = [
1159 | "once_cell",
1160 | ]
1161 |
1162 | [[package]]
1163 | name = "try-lock"
1164 | version = "0.2.4"
1165 | source = "registry+https://github.com/rust-lang/crates.io-index"
1166 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
1167 |
1168 | [[package]]
1169 | name = "typenum"
1170 | version = "1.17.0"
1171 | source = "registry+https://github.com/rust-lang/crates.io-index"
1172 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
1173 |
1174 | [[package]]
1175 | name = "unicode-bidi"
1176 | version = "0.3.13"
1177 | source = "registry+https://github.com/rust-lang/crates.io-index"
1178 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
1179 |
1180 | [[package]]
1181 | name = "unicode-ident"
1182 | version = "1.0.12"
1183 | source = "registry+https://github.com/rust-lang/crates.io-index"
1184 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
1185 |
1186 | [[package]]
1187 | name = "unicode-normalization"
1188 | version = "0.1.22"
1189 | source = "registry+https://github.com/rust-lang/crates.io-index"
1190 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
1191 | dependencies = [
1192 | "tinyvec",
1193 | ]
1194 |
1195 | [[package]]
1196 | name = "untrusted"
1197 | version = "0.9.0"
1198 | source = "registry+https://github.com/rust-lang/crates.io-index"
1199 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
1200 |
1201 | [[package]]
1202 | name = "url"
1203 | version = "2.5.0"
1204 | source = "registry+https://github.com/rust-lang/crates.io-index"
1205 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
1206 | dependencies = [
1207 | "form_urlencoded",
1208 | "idna",
1209 | "percent-encoding",
1210 | ]
1211 |
1212 | [[package]]
1213 | name = "utf8parse"
1214 | version = "0.2.1"
1215 | source = "registry+https://github.com/rust-lang/crates.io-index"
1216 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
1217 |
1218 | [[package]]
1219 | name = "version_check"
1220 | version = "0.9.4"
1221 | source = "registry+https://github.com/rust-lang/crates.io-index"
1222 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
1223 |
1224 | [[package]]
1225 | name = "want"
1226 | version = "0.3.1"
1227 | source = "registry+https://github.com/rust-lang/crates.io-index"
1228 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
1229 | dependencies = [
1230 | "try-lock",
1231 | ]
1232 |
1233 | [[package]]
1234 | name = "wasi"
1235 | version = "0.11.0+wasi-snapshot-preview1"
1236 | source = "registry+https://github.com/rust-lang/crates.io-index"
1237 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1238 |
1239 | [[package]]
1240 | name = "wasm-bindgen"
1241 | version = "0.2.88"
1242 | source = "registry+https://github.com/rust-lang/crates.io-index"
1243 | checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
1244 | dependencies = [
1245 | "cfg-if",
1246 | "wasm-bindgen-macro",
1247 | ]
1248 |
1249 | [[package]]
1250 | name = "wasm-bindgen-backend"
1251 | version = "0.2.88"
1252 | source = "registry+https://github.com/rust-lang/crates.io-index"
1253 | checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
1254 | dependencies = [
1255 | "bumpalo",
1256 | "log",
1257 | "once_cell",
1258 | "proc-macro2",
1259 | "quote",
1260 | "syn",
1261 | "wasm-bindgen-shared",
1262 | ]
1263 |
1264 | [[package]]
1265 | name = "wasm-bindgen-futures"
1266 | version = "0.4.38"
1267 | source = "registry+https://github.com/rust-lang/crates.io-index"
1268 | checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
1269 | dependencies = [
1270 | "cfg-if",
1271 | "js-sys",
1272 | "wasm-bindgen",
1273 | "web-sys",
1274 | ]
1275 |
1276 | [[package]]
1277 | name = "wasm-bindgen-macro"
1278 | version = "0.2.88"
1279 | source = "registry+https://github.com/rust-lang/crates.io-index"
1280 | checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
1281 | dependencies = [
1282 | "quote",
1283 | "wasm-bindgen-macro-support",
1284 | ]
1285 |
1286 | [[package]]
1287 | name = "wasm-bindgen-macro-support"
1288 | version = "0.2.88"
1289 | source = "registry+https://github.com/rust-lang/crates.io-index"
1290 | checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
1291 | dependencies = [
1292 | "proc-macro2",
1293 | "quote",
1294 | "syn",
1295 | "wasm-bindgen-backend",
1296 | "wasm-bindgen-shared",
1297 | ]
1298 |
1299 | [[package]]
1300 | name = "wasm-bindgen-shared"
1301 | version = "0.2.88"
1302 | source = "registry+https://github.com/rust-lang/crates.io-index"
1303 | checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
1304 |
1305 | [[package]]
1306 | name = "web-sys"
1307 | version = "0.3.65"
1308 | source = "registry+https://github.com/rust-lang/crates.io-index"
1309 | checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
1310 | dependencies = [
1311 | "js-sys",
1312 | "wasm-bindgen",
1313 | ]
1314 |
1315 | [[package]]
1316 | name = "webpki-roots"
1317 | version = "0.25.3"
1318 | source = "registry+https://github.com/rust-lang/crates.io-index"
1319 | checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
1320 |
1321 | [[package]]
1322 | name = "winapi"
1323 | version = "0.3.9"
1324 | source = "registry+https://github.com/rust-lang/crates.io-index"
1325 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1326 | dependencies = [
1327 | "winapi-i686-pc-windows-gnu",
1328 | "winapi-x86_64-pc-windows-gnu",
1329 | ]
1330 |
1331 | [[package]]
1332 | name = "winapi-i686-pc-windows-gnu"
1333 | version = "0.4.0"
1334 | source = "registry+https://github.com/rust-lang/crates.io-index"
1335 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1336 |
1337 | [[package]]
1338 | name = "winapi-x86_64-pc-windows-gnu"
1339 | version = "0.4.0"
1340 | source = "registry+https://github.com/rust-lang/crates.io-index"
1341 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1342 |
1343 | [[package]]
1344 | name = "windows-sys"
1345 | version = "0.48.0"
1346 | source = "registry+https://github.com/rust-lang/crates.io-index"
1347 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
1348 | dependencies = [
1349 | "windows-targets",
1350 | ]
1351 |
1352 | [[package]]
1353 | name = "windows-targets"
1354 | version = "0.48.5"
1355 | source = "registry+https://github.com/rust-lang/crates.io-index"
1356 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
1357 | dependencies = [
1358 | "windows_aarch64_gnullvm",
1359 | "windows_aarch64_msvc",
1360 | "windows_i686_gnu",
1361 | "windows_i686_msvc",
1362 | "windows_x86_64_gnu",
1363 | "windows_x86_64_gnullvm",
1364 | "windows_x86_64_msvc",
1365 | ]
1366 |
1367 | [[package]]
1368 | name = "windows_aarch64_gnullvm"
1369 | version = "0.48.5"
1370 | source = "registry+https://github.com/rust-lang/crates.io-index"
1371 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
1372 |
1373 | [[package]]
1374 | name = "windows_aarch64_msvc"
1375 | version = "0.48.5"
1376 | source = "registry+https://github.com/rust-lang/crates.io-index"
1377 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
1378 |
1379 | [[package]]
1380 | name = "windows_i686_gnu"
1381 | version = "0.48.5"
1382 | source = "registry+https://github.com/rust-lang/crates.io-index"
1383 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
1384 |
1385 | [[package]]
1386 | name = "windows_i686_msvc"
1387 | version = "0.48.5"
1388 | source = "registry+https://github.com/rust-lang/crates.io-index"
1389 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
1390 |
1391 | [[package]]
1392 | name = "windows_x86_64_gnu"
1393 | version = "0.48.5"
1394 | source = "registry+https://github.com/rust-lang/crates.io-index"
1395 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
1396 |
1397 | [[package]]
1398 | name = "windows_x86_64_gnullvm"
1399 | version = "0.48.5"
1400 | source = "registry+https://github.com/rust-lang/crates.io-index"
1401 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
1402 |
1403 | [[package]]
1404 | name = "windows_x86_64_msvc"
1405 | version = "0.48.5"
1406 | source = "registry+https://github.com/rust-lang/crates.io-index"
1407 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
1408 |
1409 | [[package]]
1410 | name = "winnow"
1411 | version = "0.5.19"
1412 | source = "registry+https://github.com/rust-lang/crates.io-index"
1413 | checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
1414 | dependencies = [
1415 | "memchr",
1416 | ]
1417 |
1418 | [[package]]
1419 | name = "winreg"
1420 | version = "0.50.0"
1421 | source = "registry+https://github.com/rust-lang/crates.io-index"
1422 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
1423 | dependencies = [
1424 | "cfg-if",
1425 | "windows-sys",
1426 | ]
1427 |
--------------------------------------------------------------------------------