diff --git a/Cargo.lock b/Cargo.lock index c26d6601..26b68c2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -322,6 +322,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concolor" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90f9dcd9490a97db91a85ccd79e38a87e14323f0bb824659ee3274e9143ba37" +dependencies = [ + "atty", + "bitflags", + "concolor-query", +] + +[[package]] +name = "concolor-query" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317" + [[package]] name = "console" version = "0.15.2" @@ -376,6 +403,30 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.12" @@ -830,6 +881,12 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "group" version = "0.12.1" @@ -930,6 +987,22 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" +dependencies = [ + "humantime", + "serde", +] + [[package]] name = "hyper" version = "0.14.22" @@ -1174,6 +1247,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -1261,6 +1343,12 @@ dependencies = [ "serde", ] +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1367,6 +1455,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "os_pipe" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dceb7e43f59c35ee1548045b2c72945a5a3bb6ce6d6f07cdc13dc8f6bc4930a" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "overload" version = "0.1.1" @@ -1620,8 +1718,10 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "tempfile", "thiserror", "timeago", + "trycmd", "zeroize", ] @@ -1837,6 +1937,30 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1926,6 +2050,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "scratch" version = "1.0.2" @@ -2035,6 +2165,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + [[package]] name = "signature" version = "1.6.4" @@ -2075,6 +2211,28 @@ dependencies = [ "serde", ] +[[package]] +name = "snapbox" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "827c00e91b15e2674d8a5270bae91f898693cbf9561cbb58d8eaa31974597293" +dependencies = [ + "concolor", + "libc", + "normalize-line-endings", + "os_pipe", + "snapbox-macros", + "wait-timeout", + "winapi", + "yansi", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "485e65c1203eb37244465e857d15a26d3a85a5410648ccb53b18bd44cb3a7336" + [[package]] name = "socket2" version = "0.4.7" @@ -2375,6 +2533,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml_datetime" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646" +dependencies = [ + "combine", + "indexmap", + "itertools", + "serde", + "toml_datetime", +] + [[package]] name = "tower" version = "0.4.13" @@ -2504,6 +2684,22 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "trycmd" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e44a0ef010323b99f3b8fc13c6cac2e25df2e3bf5daacea5abef7bf5bd841bb8" +dependencies = [ + "glob", + "humantime", + "humantime-serde", + "rayon", + "serde", + "shlex", + "snapbox", + "toml_edit", +] + [[package]] name = "typenum" version = "1.15.0" @@ -2593,6 +2789,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "want" version = "0.3.0" @@ -2772,6 +2977,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zeroize" version = "1.5.7" diff --git a/radicle-cli/Cargo.toml b/radicle-cli/Cargo.toml index 757135c9..f5382495 100644 --- a/radicle-cli/Cargo.toml +++ b/radicle-cli/Cargo.toml @@ -36,3 +36,8 @@ path = "../radicle-cob" [dependencies.radicle-crypto] version = "0" path = "../radicle-crypto" + +[dev-dependencies] +trycmd = { version = "0.14.4", default-features = false, features = ["color-auto"] } +tempfile = { version = "3.3.0" } +radicle = { path = "../radicle", features = ["test"] } diff --git a/radicle-cli/examples/rad-auth.md b/radicle-cli/examples/rad-auth.md new file mode 100644 index 00000000..19661b6c --- /dev/null +++ b/radicle-cli/examples/rad-auth.md @@ -0,0 +1,30 @@ + +Initializing a new identity with `rad-auth`. +The example below is run with `RAD_PASSPHRASE` set. + +``` +$ rad auth + +Initializing your 🌱 profile and identity + +ok Creating your 🌱 Ed25519 keypair... +ok Profile z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi created. + +Your radicle Node ID is z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi. This identifies your device. + +=> To create a radicle project, run `rad init` from a git repository. + +``` + +You can get the above information at all times using the `self` command: + +``` +$ rad self +ID z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi +Key (hash) SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA +Key (full) AAAAC3NzaC1lZDI1NTE5AAAAIHahWSBEpuT1ESZbynOmBNkLBSnR32Ar4woZqSV2YNH1 +Storage (git) [..]/storage +Storage (keys) [..]/keys +Node (socket) [..]/node/radicle.sock + +``` diff --git a/radicle-cli/examples/rad-init.md b/radicle-cli/examples/rad-init.md new file mode 100644 index 00000000..c7be1d38 --- /dev/null +++ b/radicle-cli/examples/rad-init.md @@ -0,0 +1,33 @@ + +To create your first radicle project, navigate to a git repository, and run +the `init` command: + +``` +$ rad init --name acme --description "Acme's repository" --no-confirm + +Initializing local 🌱 project in . + +ok Project acme created +{ + "name": "acme", + "description": "Acme's repository", + "default-branch": "master" +} + + +Your project id is [..]. You can show it any time by running: + rad . + +To publish your project to the network, run: + rad push + + +``` + +Projects can be listed with the `ls` command: + +``` +$ rad ls +acme [..] [..] Acme's repository + +``` diff --git a/radicle-cli/src/lib.rs b/radicle-cli/src/lib.rs index 2b151c21..d27d6565 100644 --- a/radicle-cli/src/lib.rs +++ b/radicle-cli/src/lib.rs @@ -5,3 +5,5 @@ pub mod commands; pub mod git; pub mod project; pub mod terminal; +#[cfg(test)] +mod tests; diff --git a/radicle-cli/src/terminal/textbox.rs b/radicle-cli/src/terminal/textbox.rs index 002ecf33..0746b4f1 100644 --- a/radicle-cli/src/terminal/textbox.rs +++ b/radicle-cli/src/terminal/textbox.rs @@ -40,7 +40,7 @@ impl fmt::Display for TextBox { .unwrap_or(0) + 2; if let Some(max) = term::width() { - if max < width + 2 { + if width + 2 > max { width = max - 2 } } diff --git a/radicle-cli/src/tests.rs b/radicle-cli/src/tests.rs new file mode 100644 index 00000000..26710c10 --- /dev/null +++ b/radicle-cli/src/tests.rs @@ -0,0 +1 @@ +mod cli; diff --git a/radicle-cli/src/tests/cli.rs b/radicle-cli/src/tests/cli.rs new file mode 100644 index 00000000..4b938993 --- /dev/null +++ b/radicle-cli/src/tests/cli.rs @@ -0,0 +1,41 @@ +use std::path::Path; +use std::{env, time}; + +use radicle::profile::Profile; +use radicle::test::fixtures; + +#[test] +fn rad_auth() { + let base = Path::new(env!("CARGO_MANIFEST_DIR")); + let home = tempfile::tempdir().unwrap(); + + trycmd::TestCases::new() + .env("RAD_DEBUG", "1") + .env("RAD_PASSPHRASE", "radicle") + .env("RAD_HOME", home.path().to_string_lossy()) + .timeout(time::Duration::from_secs(6)) + .case(base.join("examples/rad-auth.md")) + .run(); +} + +#[test] +fn rad_init() { + let base = Path::new(env!("CARGO_MANIFEST_DIR")); + let home = tempfile::tempdir().unwrap(); + let cwd = tempfile::tempdir().unwrap(); + + // Setup a test repository. + fixtures::repository(cwd.path()); + // Navigate to repository. + env::set_current_dir(cwd.path()).unwrap(); + // Setup a new user. + Profile::init(home.path(), "radicle").unwrap(); + + trycmd::TestCases::new() + .env("RAD_DEBUG", "1") + .env("RAD_PASSPHRASE", "radicle") + .env("RAD_HOME", home.path().to_string_lossy()) + .timeout(time::Duration::from_secs(6)) + .case(base.join("examples/rad-init.md")) + .run(); +}