diff --git a/.clippy.toml b/.clippy.toml index 23fc604ac95..abb24551adb 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1,11 @@ msrv = "1.64.0" # MSRV +warn-on-all-wildcard-imports = true +allow-expect-in-tests = true +allow-unwrap-in-tests = true +allow-dbg-in-tests = true +disallowed-methods = [ + { path = "std::option::Option::map_or", reason = "use `map(..).unwrap_or(..)`" }, + { path = "std::option::Option::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, + { path = "std::result::Result::map_or", reason = "use `map(..).unwrap_or(..)`" }, + { path = "std::result::Result::map_or_else", reason = "use `map(..).unwrap_or_else(..)`" }, +] diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 53161baf445..fa98339a47e 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -4,7 +4,33 @@ ], "semanticCommits": "enabled", "configMigration": true, + "dependencyDashboard": true, + "regexManagers": [ + { + "fileMatch": [ + "^rust-toolchain\\.toml$", + "Cargo.toml$", + "clippy.toml$", + "\.clippy.toml$", + "^\.github/workflows/ci.yml$", + "^\.github/workflows/rust-next.yml$", + ], + "matchStrings": [ + "MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)", + "(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV", + ], + "depNameTemplate": "rust", + "packageNameTemplate": "rust-lang/rust", + "datasourceTemplate": "github-releases", + } + ], "packageRules": [ + { + "commitMessageTopic": "MSRV", + "matchManagers": ["regex"], + "matchPackageNames": ["rust"], + "stabilityDays": 252, // 6 releases * 6 weeks per release * 7 days per week + }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies // - Take advantage of latest dev-dependencies diff --git a/.github/settings.yml b/.github/settings.yml index 658c28adc7e..3a2380bc0af 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -1,9 +1,9 @@ # These settings are synced to GitHub by https://probot.github.io/apps/settings/ repository: - description: A full featured, fast Command Line Argument Parser for Rust - homepage: docs.rs/clap - topics: rust cli command-line argparse clap + description: "A full featured, fast Command Line Argument Parser for Rust" + homepage: "docs.rs/clap" + topics: "rust cli command-line argparse clap" has_issues: true has_projects: false has_wiki: false diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 5b7e83ac684..de95fb23072 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -10,7 +10,7 @@ on: - '**/Cargo.lock' push: branches: - - main + - master env: RUST_BACKTRACE: 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d88fb8b029..67d3bf788a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,18 @@ name: CI + +permissions: + contents: read + on: pull_request: push: - branches: ["*master"] - schedule: - - cron: '3 3 3 * *' -permissions: - contents: read + branches: + - "*master" + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 jobs: ci: @@ -54,11 +60,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: Build run: make build-${{matrix.features}} @@ -101,11 +105,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} - uses: Swatinem/rust-cache@v2 - name: Check run: make check-${{ matrix.features }} @@ -122,11 +125,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: 1.64.0 # MSRV - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: UI Tests run: make test-ui-${{ matrix.features }} @@ -137,11 +138,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: 1.64.0 # MSRV - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: Check documentation env: @@ -154,13 +153,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: # Not MSRV because its harder to jump between versions and people are # more likely to have stable toolchain: stable - profile: minimal - override: true components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting @@ -172,11 +169,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: 1.64.0 # MSRV - profile: minimal - override: true components: clippy - uses: Swatinem/rust-cache@v2 - name: Lint (ultra-minimal) diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 5d2f2970ddf..509be0803ae 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -3,6 +3,14 @@ name: Lint Commits on: [pull_request] +permissions: + contents: read + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: committed: name: Lint Commits diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 314f08445a4..afa45f70200 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,9 +1,17 @@ name: pre-commit + +permissions: {} # none + on: pull_request: push: - branches: ["*master"] -permissions: {} # none + branches: [master] + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: pre-commit: permissions: diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 669375bbd50..996f09775a4 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -1,9 +1,16 @@ name: rust-next + +permissions: + contents: read + on: schedule: - cron: '3 3 3 * *' -permissions: - contents: read + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 jobs: test: @@ -50,11 +57,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: Build run: make build-${{matrix.features}} @@ -65,53 +70,3 @@ jobs: - name: Test (ultra-minimal) if: matrix.build == 'minimal' run: make test-minimal ARGS='--manifest-path Cargo.toml' - rustfmt: - name: rustfmt - strategy: - matrix: - rust: - - stable - - beta - continue-on-error: ${{ matrix.rust != 'stable' }} - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.rust }} - profile: minimal - override: true - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: Check formatting - run: cargo fmt --all -- --check - clippy: - name: clippy - strategy: - matrix: - rust: - - 1.64.0 # MSRV - - stable - continue-on-error: ${{ matrix.rust != '1.64.0' }} # MSRV - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.rust }} - profile: minimal - override: true - components: clippy - - uses: Swatinem/rust-cache@v2 - - name: Lint (ultra-minimal) - run: make clippy-minimal ARGS='--manifest-path Cargo.toml' - - name: Lint Minimal - run: make clippy-minimal - - name: Lint All - run: make clippy-full - - name: Lint (release) - run: make clippy-release diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index c00987ea985..f31c7ed8b98 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -1,9 +1,15 @@ name: Spelling -on: [pull_request] permissions: contents: read +on: [pull_request] + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: spelling: name: Spell Check with Typos diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79df3909b13..28abb8a5ea2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,11 @@ +exclude: | + (?x)^( + tests/.*| + CHANGELOG.md + )$ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + rev: v4.3.0 hooks: - id: check-yaml stages: [commit] @@ -14,8 +19,13 @@ repos: stages: [commit] - id: detect-private-key stages: [commit] + - repo: https://github.com/crate-ci/typos + rev: v1.11.1 + hooks: + - id: typos + stages: [commit] - repo: https://github.com/crate-ci/committed - rev: v1.0.1 + rev: v1.0.4 hooks: - id: committed stages: [commit-msg] diff --git a/Cargo.toml b/Cargo.toml index 6fba15a58d4..2e9f373faa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "clap_bench", "clap_builder", diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 261eeb9e9f8..8f71f43fee3 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -178,7 +178,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -199,3 +199,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + diff --git a/LICENSE-MIT b/LICENSE-MIT index 7b05b8453e9..a2d01088b6c 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,4 @@ -The MIT License (MIT) - -Copyright (c) 2015-2022 Kevin B. Knapp and Clap Contributors +Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/clap_builder/src/parser/arg_matcher.rs b/clap_builder/src/parser/arg_matcher.rs index d584689cdbc..30fdab1f9a6 100644 --- a/clap_builder/src/parser/arg_matcher.rs +++ b/clap_builder/src/parser/arg_matcher.rs @@ -130,7 +130,9 @@ impl ArgMatcher { } pub(crate) fn check_explicit(&self, arg: &Id, predicate: &ArgPredicate) -> bool { - self.get(arg).map_or(false, |a| a.check_explicit(predicate)) + self.get(arg) + .map(|a| a.check_explicit(predicate)) + .unwrap_or_default() } pub(crate) fn start_custom_arg(&mut self, arg: &Arg, source: ValueSource) { diff --git a/clap_builder/src/parser/parser.rs b/clap_builder/src/parser/parser.rs index c2910048528..70e04954e0a 100644 --- a/clap_builder/src/parser/parser.rs +++ b/clap_builder/src/parser/parser.rs @@ -305,7 +305,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_positionals() .last() - .map_or(false, |p_name| !p_name.is_last_set()); + .map(|p_name| !p_name.is_last_set()) + .unwrap_or_default(); let missing_pos = self.cmd.is_allow_missing_positional_set() && is_second_to_last @@ -779,9 +780,10 @@ impl<'cmd> Parser<'cmd> { matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) }) .filter(|&n| { - self.cmd.find(n).map_or(true, |a| { - !(a.is_hide_set() || required.contains(a.get_id())) - }) + self.cmd + .find(n) + .map(|a| !(a.is_hide_set() || required.contains(a.get_id()))) + .unwrap_or(true) }) .cloned() .collect(); @@ -810,9 +812,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| { - arg.is_allow_hyphen_values_set() && !arg.is_last_set() - }) + .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set()) + .unwrap_or_default() { debug!( "Parser::parse_long_args: positional at {} allows hyphens", @@ -847,7 +848,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| arg.is_allow_negative_numbers_set()) + .map(|arg| arg.is_allow_negative_numbers_set()) + .unwrap_or_default() && short_arg.is_number() { debug!("Parser::parse_short_arg: negative number"); @@ -856,9 +858,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| { - arg.is_allow_hyphen_values_set() && !arg.is_last_set() - }) + .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set()) + .unwrap_or_default() && short_arg .clone() .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default()) @@ -1536,7 +1537,7 @@ impl<'cmd> Parser<'cmd> { .filter(|arg_id| { matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) }) - .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set())) + .filter(|n| self.cmd.find(n).map(|a| !a.is_hide_set()).unwrap_or(true)) .cloned() .collect(); diff --git a/clap_builder/src/parser/validator.rs b/clap_builder/src/parser/validator.rs index 49d28a34f8c..5c3d34643ec 100644 --- a/clap_builder/src/parser/validator.rs +++ b/clap_builder/src/parser/validator.rs @@ -199,7 +199,10 @@ impl<'cmd> Validator<'cmd> { .map(|(n, _)| n) .filter(|n| { // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(false, |a| !a.is_hide_set()) + self.cmd + .find(n) + .map(|a| !a.is_hide_set()) + .unwrap_or_default() }) .filter(|key| !conflicting_keys.contains(key)) .cloned() @@ -445,7 +448,10 @@ impl<'cmd> Validator<'cmd> { .map(|(n, _)| n) .filter(|n| { // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(false, |a| !a.is_hide_set()) + self.cmd + .find(n) + .map(|a| !a.is_hide_set()) + .unwrap_or_default() }) .cloned() .chain(raw_req_args) diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs index a41eb8856e2..3150cac9511 100644 --- a/clap_complete/src/shells/zsh.rs +++ b/clap_complete/src/shells/zsh.rs @@ -672,7 +672,8 @@ fn write_positionals_of(p: &Command) -> String { help = arg .get_help() .map(|s| s.to_string()) - .map_or("".to_owned(), |v| " -- ".to_owned() + &v) + .map(|v| " -- ".to_owned() + &v) + .unwrap_or_else(|| "".to_owned()) .replace('[', "\\[") .replace(']', "\\]") .replace('\'', "'\\''") diff --git a/deny.toml b/deny.toml index c59b962e5c0..942e08db9c3 100644 --- a/deny.toml +++ b/deny.toml @@ -35,9 +35,12 @@ unlicensed = "deny" # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. allow = [ "MIT", + "MIT-0", "Apache-2.0", + "BSD-3-Clause", + "MPL-2.0", "Unicode-DFS-2016", - #"Apache-2.0 WITH LLVM-exception", + "CC0-1.0", ] # List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses diff --git a/tests/builder/multiple_values.rs b/tests/builder/multiple_values.rs index 5cbfee44081..8def2e84ca3 100644 --- a/tests/builder/multiple_values.rs +++ b/tests/builder/multiple_values.rs @@ -1297,7 +1297,6 @@ fn low_index_positional_with_extra_flags() { assert_eq!( m.get_many::("input") .unwrap() - .into_iter() .map(String::from) .collect::>(), vec![