├── .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 | ![-----------------------------------------------------](https://github.com/pwnwriter/haylxon/blob/readme-assets/colored.png) 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 | ![-----------------------------------------------------](https://github.com/pwnwriter/haylxon/blob/readme-assets/colored.png) 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 | MIT LICENSE 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 | ![screenshot_2023-12-13_19-51-00](https://github.com/pwnwriter/hysp/assets/90331517/01f15c0b-6b73-4e7c-ae74-5d010bef10f9) 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 | ![screenshot_2023-12-13_19-55-36](https://github.com/pwnwriter/hysp/assets/90331517/79ce202a-23a4-4086-bd47-66edd0718345) 177 | 178 |
179 | 180 | 181 |
Removing packages 182 |   183 | 184 | ```bash 185 | hysp remove -p 186 | ``` 187 | 188 | ![screenshot_2023-12-13_19-57-26](https://github.com/pwnwriter/hysp/assets/90331517/84841cf4-0693-4cbf-a2cc-b46869596b94) 189 | 190 |
191 | 192 |
Search for available pkgs 193 |   194 | 195 | ```bash 196 | hysp search -p 197 | ``` 198 | 199 | - Raw mode (default) 200 | 201 | ![screenshot_2023-12-13_19-58-22](https://github.com/pwnwriter/hysp/assets/90331517/c72bfd75-b246-4b9d-82b9-0c11e399c947) 202 | 203 | - Database mode 204 | 205 | ![screenshot_2023-12-13_19-59-55](https://github.com/pwnwriter/hysp/assets/90331517/66e1a7f2-9815-41c2-8da5-8e0144789d38) 206 | 207 | - Fuzzy mode 208 | 209 | ![screenshot_2023-12-13_20-00-34](https://github.com/pwnwriter/hysp/assets/90331517/0404c9d9-2049-459e-b09d-253dfbe30a4d) 210 | 211 |
212 | 213 |
Checking configuration health 214 |   215 | 216 | ```bash 217 | hysp health 218 | ``` 219 | 220 | ![screenshot_2023-12-13_20-01-34](https://github.com/pwnwriter/hysp/assets/90331517/2375116f-bda1-4dd9-96f9-48f04fa8bc47) 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 | --------------------------------------------------------------------------------