diff --git a/Cargo.lock b/Cargo.lock index 0f6e72f..9ecc83e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,46 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342258dd14006105c2b75ab1bd7543a03bdf0cfc94383303ac212a04939dff6f" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-wincon", + "concolor-override", + "concolor-query", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ea9e81bd02e310c216d080f6223c179012256e5151c41db88d12c88a1684d2" + +[[package]] +name = "anstyle-parse" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7d1bb534e9efed14f3e5f44e7dd1a4f709384023a4165199a4241e18dff0116" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-wincon" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3127af6145b149f3287bb9a0d10ad9c5692dba8c53ad48285e5bec4063834fa" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "argon2" version = "0.5.0" @@ -55,12 +95,75 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046ae530c528f252094e4a77886ee1374437744b2bff1497aa898bbddbbb29b3" +dependencies = [ + "clap_builder", + "clap_derive", + "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" + +[[package]] +name = "concolor-override" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" + +[[package]] +name = "concolor-query" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d11d52c3d7ca2e6d0040212be9e4dbbcd78b6447f535b6b561f449427944cf" +dependencies = [ + "windows-sys", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -102,10 +205,32 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "errno" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "forge-client" version = "0.1.0" dependencies = [ + "clap", "paris", "serde", "serde_json", @@ -166,6 +291,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.2.6" @@ -175,6 +306,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "idna" version = "0.3.0" @@ -195,6 +332,29 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys", +] + [[package]] name = "itoa" version = "1.0.6" @@ -207,6 +367,12 @@ version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + [[package]] name = "lock_api" version = "0.4.9" @@ -250,10 +416,16 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + [[package]] name = "outref" version = "0.5.1" @@ -386,6 +558,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rustix" +version = "0.37.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d097081ed288dfe45699b72f5b5d648e5f15d64d900c7080273baa20c16a6849" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.13" @@ -463,6 +649,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.4.1" @@ -618,6 +810,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "1.3.0" diff --git a/README.md b/README.md index 55d4d67..26ca0c8 100644 --- a/README.md +++ b/README.md @@ -10,31 +10,6 @@ Authentication will use *Argon2id* to hash and verify passwords. Actually building stuff is a **WIP**. ## Client -Fully **WIP**. Right now it just sends test data. +Fully **WIP**. -Eventually, everything will be specified via command arguments, using [clap](https://lib.rs/crates/clap) for parsing. - -``` -Usage: forge-client [OPTIONS] [COMMAND] - -Options: - -V, --version Print version info and exit - -H, --host Host IP to connect to (default 127.0.0.1) - -p, --port Host port to connect to (default 9134) - --json Recieve information in JSON format (or read build command from JSON file) - - --auth Password for authentication - --profile Whether to profile the build - --prexec Command(s) to run before building - --repo Remote git repository to clone from - --base Basename of the git repo (used to cd into) - --build [cargo|make] Build system to use - --subcommand [run|build|install] Cargo/Make subcommand to use - --features Comma-separated cargo features - --tag [release|debug] Optional cargo flag (default debug) - -Command: - send Send a new build request - status Get status of a build request - fetch Fetch the binary result of a build request -``` +Sends data to the server specified via commandline options. diff --git a/forge-client/Cargo.toml b/forge-client/Cargo.toml index 4cce7df..4adf9ad 100644 --- a/forge-client/Cargo.toml +++ b/forge-client/Cargo.toml @@ -10,3 +10,4 @@ serde.workspace = true url.workspace = true uuid.workspace = true paris.workspace = true +clap = { version = "4.2.1", features = ["derive"]} diff --git a/forge-client/src/main.rs b/forge-client/src/main.rs index 48b0072..c52f864 100644 --- a/forge-client/src/main.rs +++ b/forge-client/src/main.rs @@ -1,3 +1,4 @@ +use clap::{Args, Parser, Subcommand, ValueEnum}; use paris::{error, info, success}; use serde::{Deserialize, Serialize}; use std::error::Error; @@ -7,61 +8,103 @@ use tokio::net::TcpStream; use url::Url; use uuid::Uuid; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Debug, Parser)] +#[command(name = "forge-server")] +#[command(about = "A simple remote build system", long_about = None)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Debug, Subcommand)] +enum Commands { + /// Send a new build request + #[command(arg_required_else_help = true)] + Send { + /// Password for authentication + #[arg(long, value_name = "PASSWD")] + auth: Option, + + /// Whether to profile the build + #[arg(long, default_value_t = false)] + profile: bool, + + /// Command(s) to run before building + #[arg(long, value_name = "CMD")] + prexec: Option, + + /// Remote git repository to clone from + #[arg(long, value_name = "URL")] + repo: String, + + /// Build system to use + #[arg(long,require_equals = true, num_args = 0..=1, default_value_t = BuildSystem::Cargo,default_missing_value = "cargo")] + build: BuildSystem, + + /// Cargo/Make subcommand to use + #[arg(long, require_equals = true, num_args = 0..=1, default_value_t = BuildSubcommand::Build, default_missing_value = "build")] + subcommand: BuildSubcommand, + + /// Comma-separated cargo features + #[arg(long, value_name = "FEATURES")] + features: Option>, + + /// Optional cargo flag + #[arg(long, require_equals = true, num_args = 0..=1, default_value_t = Tag::Debug, default_missing_value = "debug")] + tag: Tag, + }, +} + +#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, ValueEnum)] enum BuildSystem { Cargo, Make, - Custom(String), } -impl fmt::Display for BuildSystem { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - BuildSystem::Cargo => write!(f, "cargo"), - BuildSystem::Make => write!(f, "make"), - BuildSystem::Custom(s) => write!(f, "{}", s), - } +impl std::fmt::Display for BuildSystem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value() + .expect("no values are skipped") + .get_name() + .fmt(f) } } -#[derive(Serialize, Deserialize, Debug)] -enum Subcommand { +#[derive(Serialize, Deserialize, ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] +enum BuildSubcommand { Run, Build, Install, - Custom(String), } -impl fmt::Display for Subcommand { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Subcommand::Run => write!(f, "run"), - Subcommand::Build => write!(f, "build"), - Subcommand::Install => write!(f, "install"), - Subcommand::Custom(s) => write!(f, "{}", s), - } +impl std::fmt::Display for BuildSubcommand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value() + .expect("no values are skipped") + .get_name() + .fmt(f) } } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, ValueEnum, Copy, Clone, Debug, PartialEq, Eq)] enum Tag { Release, Debug, } -impl fmt::Display for Tag { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Tag::Release => write!(f, "--release"), - Tag::Debug => write!(f, "--debug"), - } +impl std::fmt::Display for Tag { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value() + .expect("no values are skipped") + .get_name() + .fmt(f) } } #[derive(Serialize, Deserialize)] struct Command { build_system: BuildSystem, - subcommand: Subcommand, + subcommand: BuildSubcommand, features: Option>, tag: Tag, } @@ -79,32 +122,46 @@ struct Message { #[tokio::main] async fn main() -> Result<(), Box> { - // Connect to a peer - let mut stream = TcpStream::connect("127.0.0.1:9134").await?; - success!("Connected to: 127.0.0.1:9134"); + let args = Cli::parse(); + match args.command { + Commands::Send { + auth, + repo, + profile, + prexec, + build, + subcommand, + features, + tag, + } => { + // Connect to a peer + let mut stream = TcpStream::connect("127.0.0.1:9134").await?; + success!("Connected to: 127.0.0.1:9134"); - let test_command = Command { - build_system: BuildSystem::Cargo, - subcommand: Subcommand::Build, - features: Some(vec!["one".to_string(), "two".to_string()]), - tag: Tag::Debug, - }; - let test_message = Message { - authentication: Some("test123".to_string()), - uuid: Uuid::new_v4(), - pre_exec: None, - profile: false, - command: test_command, - repository: Url::parse("https://lib.rs/crates/serde_json").unwrap(), - basename: "serde_json".to_string(), - }; + let test_command = Command { + build_system: build, + subcommand, + features, + tag, + }; + let test_message = Message { + authentication: auth, + uuid: Uuid::new_v4(), + pre_exec: prexec, + profile, + command: test_command, + repository: Url::parse(&repo).unwrap(), + basename: "serde_json".to_string(), + }; - let j = serde_json::to_string(&test_message)?; - stream.write_all(&j.as_bytes()).await?; - info!( - "Sent JSON:\n{}", - serde_json::to_string_pretty(&test_message)? - ); + let j = serde_json::to_string(&test_message)?; + stream.write_all(&j.as_bytes()).await?; + info!( + "Sent JSON:\n{}", + serde_json::to_string_pretty(&test_message)? + ); + } + } Ok(()) }