diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f3e0da..c068679 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,20 +10,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: sudo apt update && sudo apt install -y libssh2-1-dev libssl-dev && mkdir -p $HOME/.ssh && touch $HOME/.ssh/config - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: Swatinem/rust-cache@v2 with: - toolchain: stable - override: true - components: rustfmt, clippy + cache-on-failure: true + - uses: dtolnay/rust-toolchain@stable + - name: Set up environment for tests + run: mkdir -p $HOME/.ssh && touch $HOME/.ssh/config + - name: Style check + run: cargo fmt --all --check - name: Run tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --no-fail-fast - - name: Format - run: cargo fmt --all -- --check + run: cargo test - name: Clippy run: cargo clippy -- -Dwarnings diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7b34151..1d50e61 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -10,28 +10,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Install dependencies - run: sudo apt update && sudo apt install -y libssh2-1-dev libssl-dev && mkdir -p $HOME/.ssh && touch $HOME/.ssh/config - - name: Setup nightly toolchain - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: taiki-e/install-action@cargo-llvm-cov + - name: Set up environment for tests + run: mkdir -p $HOME/.ssh && touch $HOME/.ssh/config + - name: Generate code coverage + run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 with: - toolchain: nightly - override: true - - name: Run tests (nightly) - uses: actions-rs/cargo@v1 - with: - command: test - args: --lib --no-fail-fast - env: - CARGO_INCREMENTAL: "0" - RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - RUSTDOCFLAGS: "-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests" - - name: Coverage with grcov - id: coverage - uses: actions-rs/grcov@v0.1 + path: lcov.info - name: Coveralls - uses: coverallsapp/github-action@v1.1.1 + uses: coverallsapp/github-action@v2.3.4 with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ${{ steps.coverage.outputs.report }} diff --git a/examples/client.rs b/examples/client.rs index a651b6b..a8b0e37 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -60,10 +60,7 @@ fn connect(host: &str, params: &HostParams) { Some(h) => h, None => host, }; - let port = match params.port { - None => 22, - Some(p) => p, - }; + let port = params.port.unwrap_or(22); let host = match host.contains(':') { true => host.to_string(), false => format!("{}:{}", host, port), diff --git a/src/lib.rs b/src/lib.rs index af6eee9..3e61749 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,20 +158,26 @@ mod test { fn should_query_ssh_config() { let mut config = SshConfig::default(); // add config - let mut params1 = HostParams::default(); - params1.bind_address = Some(String::from("0.0.0.0")); + let mut params1 = HostParams { + bind_address: Some(String::from("0.0.0.0")), + ..Default::default() + }; config.hosts.push(Host::new( vec![HostClause::new(String::from("192.168.*.*"), false)], params1.clone(), )); - let mut params2 = HostParams::default(); - params2.bind_interface = Some(String::from("tun0")); + let params2 = HostParams { + bind_interface: Some(String::from("tun0")), + ..Default::default() + }; config.hosts.push(Host::new( vec![HostClause::new(String::from("192.168.10.*"), false)], params2.clone(), )); - let mut params3 = HostParams::default(); - params3.host_name = Some(String::from("172.26.104.4")); + let params3 = HostParams { + host_name: Some(String::from("172.26.104.4")), + ..Default::default() + }; config.hosts.push(Host::new( vec![ HostClause::new(String::from("172.26.*.*"), false), diff --git a/src/params.rs b/src/params.rs index 2d5e455..7c80a04 100644 --- a/src/params.rs +++ b/src/params.rs @@ -246,31 +246,31 @@ mod test { #[test] fn should_merge_params() { let mut params = HostParams::default(); - let mut b = HostParams::default(); - b.bind_address = Some(String::from("pippo")); - b.bind_interface = Some(String::from("tun0")); - b.ca_signature_algorithms = Some(vec![]); - b.certificate_file = Some(PathBuf::default()); - b.ciphers = Some(vec![]); - b.compression = Some(true); - b.connect_timeout = Some(Duration::from_secs(1)); - b.connection_attempts = Some(3); - b.host_key_algorithms = Some(vec![]); - b.host_name = Some(String::from("192.168.1.2")); - b.identity_file = Some(vec![PathBuf::default()]); - b.ignore_unknown = Some(vec![]); - b.kex_algorithms = Some(vec![]); - b.mac = Some(vec![]); - b.port = Some(22); - b.pubkey_accepted_algorithms = Some(vec![]); - b.pubkey_authentication = Some(true); - b.remote_forward = Some(32); - b.server_alive_interval = Some(Duration::from_secs(10)); - #[cfg(target_os = "macos")] - { - b.use_keychain = Some(true); - } - b.tcp_keep_alive = Some(true); + let mut b = HostParams { + bind_address: Some(String::from("pippo")), + bind_interface: Some(String::from("tun0")), + ca_signature_algorithms: Some(vec![]), + certificate_file: Some(PathBuf::default()), + ciphers: Some(vec![]), + compression: Some(true), + connect_timeout: Some(Duration::from_secs(1)), + connection_attempts: Some(3), + host_key_algorithms: Some(vec![]), + host_name: Some(String::from("192.168.1.2")), + identity_file: Some(vec![PathBuf::default()]), + ignore_unknown: Some(vec![]), + kex_algorithms: Some(vec![]), + mac: Some(vec![]), + port: Some(22), + pubkey_accepted_algorithms: Some(vec![]), + pubkey_authentication: Some(true), + remote_forward: Some(32), + server_alive_interval: Some(Duration::from_secs(10)), + #[cfg(target_os = "macos")] + use_keychain: Some(true), + tcp_keep_alive: Some(true), + ..Default::default() + }; params.merge(&b); assert!(params.bind_address.is_some()); assert!(params.bind_interface.is_some()); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d866cbb..6b7ed2b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -304,7 +304,7 @@ impl SshConfigParser { /// parse boolean value fn parse_boolean(args: Vec) -> SshParserResult { - match args.get(0).map(|x| x.as_str()) { + match args.first().map(|x| x.as_str()) { Some("yes") => Ok(true), Some("no") => Ok(false), Some(_) => Err(SshParserError::ExpectedBoolean), @@ -315,7 +315,7 @@ impl SshConfigParser { /// Parse comma separated list arguments fn parse_comma_separated_list(args: Vec) -> SshParserResult> { match args - .get(0) + .first() .map(|x| x.split(',').map(|x| x.to_string()).collect()) { Some(args) => Ok(args), @@ -360,7 +360,7 @@ impl SshConfigParser { /// Parse path argument fn parse_path(args: Vec) -> SshParserResult { - if let Some(s) = args.get(0) { + if let Some(s) = args.first() { Self::parse_path_arg(s) } else { Err(SshParserError::MissingArgument) @@ -384,7 +384,7 @@ impl SshConfigParser { /// Parse port number argument fn parse_port(args: Vec) -> SshParserResult { - match args.get(0).map(|x| u16::from_str(x)) { + match args.first().map(|x| u16::from_str(x)) { Some(Ok(val)) => Ok(val), Some(Err(_)) => Err(SshParserError::ExpectedPort), None => Err(SshParserError::MissingArgument), @@ -402,7 +402,7 @@ impl SshConfigParser { /// Parse unsigned argument fn parse_unsigned(args: Vec) -> SshParserResult { - match args.get(0).map(|x| usize::from_str(x)) { + match args.first().map(|x| usize::from_str(x)) { Some(Ok(val)) => Ok(val), Some(Err(_)) => Err(SshParserError::ExpectedUnsigned), None => Err(SshParserError::MissingArgument),