diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index eccc4ada..36047ca7 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -77,7 +77,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1.2.0 - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -95,14 +95,14 @@ jobs: run: | git submodule update --init --recursive - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' - - uses: pnpm/action-setup@v3 + - uses: pnpm/action-setup@v4 with: version: 8 @@ -265,7 +265,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install nightly toolchain uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index f8ea27a8..ddbd3c6e 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -39,7 +39,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1.2.0 - name: Checkout sources - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install stable toolchain uses: actions-rs/toolchain@v1 @@ -58,14 +58,14 @@ jobs: run: | git submodule update --init --recursive - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 cache: "npm" - - uses: pnpm/action-setup@v3 + - uses: pnpm/action-setup@v4 with: version: 8 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e282b58d..2d4a7b86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Extract Tag Name id: extract_tag_name diff --git a/README.md b/README.md index 8012be23..ed616368 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,9 @@ Cyfrinup is a CLI tool that simplifies the installation and management of Cyfrin curl -L https://raw.githubusercontent.com/Cyfrin/aderyn/dev/cyfrinup/install | bash ``` +If you get a `failed writing body` error in Windows, it's most likely because you don't have Windows Distribution system. + +You can fix this by going to Microsoft Store, download Ubuntu, and have it running. #### Step 2: Update Path The installer will prompt you to run a `source` command. Either run this command, or reload your terminal. @@ -126,11 +129,11 @@ Usage: `aderyn [OPTIONS] ` ``: The path to the root of the codebase to be analyzed. Defaults to the current directory. Options: - - `-s`, `--src`: Path to the source contracts. If not provided, or if aderyn can't find famous files to read (like `foundry.toml`, which it automatically searches for) the ROOT directory will be used. + - `-s`, `--src`: Path to the source contracts. Used to avoid analyzing libraries, tests or scripts and focus on the contracts. If not provided, or if aderyn can't find famous files to read (like `foundry.toml`, which it automatically searches for) the ROOT directory will be used. - In foundry projects, this is usually the `src/` folder unless stated otherwise in `foundry.toml`. - In Hardhat projects, this is usually the `contracts/` folder unless stated otherwise in the config. - - `-i`, `--path-includes `: List of path strings to include, delimited by comma (no spaces). Any solidity file path not containing these strings will be ignored - - `-x`, `--path-excludes `: List of path strings to exclude, delimited by comma (no spaces). Any solidity file path containing these strings will be ignored + - `-i`, `--path-includes `: List of path strings to include, delimited by comma (no spaces). It allows to include only one or more specific contracts in the analysis. Any solidity file path not containing these strings will be ignored. + - `-x`, `--path-excludes `: List of path strings to exclude, delimited by comma (no spaces). It allows to exclude one or more specific contracts from the analysis. Any solidity file path containing these strings will be ignored - `-o`, `--output `: Desired file path for the final report (will overwrite the existing one) [default: report.md] - `-n`, `--no-snippets`: Do not include code snippets in the report (reduces report size in large repos) - `-h`, `--help`: Print help diff --git a/aderyn/README.md b/aderyn/README.md index 43a3c4e9..34276632 100644 --- a/aderyn/README.md +++ b/aderyn/README.md @@ -132,11 +132,11 @@ Usage: `aderyn [OPTIONS] ` ``: The path to the root of the codebase to be analyzed. Defaults to the current directory. Options: - - `-s`, `--src`: Path to the source contracts. If not provided, or if aderyn can't find famous files to read (like `foundry.toml`, which it automatically searches for) the ROOT directory will be used. + - `-s`, `--src`: Path to the source contracts. Used to avoid analyzing libraries, tests or scripts and focus on the contracts. If not provided, or if aderyn can't find famous files to read (like `foundry.toml`, which it automatically searches for) the ROOT directory will be used. - In foundry projects, this is usually the `src/` folder unless stated otherwise in `foundry.toml`. - In Hardhat projects, this is usually the `contracts/` folder unless stated otherwise in the config. - - `-i`, `--path-includes `: List of path strings to include, delimited by comma (no spaces). Any solidity file path not containing these strings will be ignored - - `-x`, `--path-excludes `: List of path strings to exclude, delimited by comma (no spaces). Any solidity file path containing these strings will be ignored + - `-i`, `--path-includes `: List of path strings to include, delimited by comma (no spaces). It allows to include only one or more specific contracts in the analysis. Any solidity file path not containing these strings will be ignored. + - `-x`, `--path-excludes `: List of path strings to exclude, delimited by comma (no spaces). It allows to exclude one or more specific contracts from the analysis. Any solidity file path containing these strings will be ignored - `-o`, `--output `: Desired file path for the final report (will overwrite the existing one) [default: report.md] - `-n`, `--no-snippets`: Do not include code snippets in the report (reduces report size in large repos) - `-h`, `--help`: Print help diff --git a/aderyn/src/main.rs b/aderyn/src/main.rs index f0b857aa..7a588f76 100644 --- a/aderyn/src/main.rs +++ b/aderyn/src/main.rs @@ -19,25 +19,31 @@ pub struct CommandLineArgs { #[arg(default_value = ".")] root: String, - /// Path to the source contracts. If not provided, the ROOT directory will be used. + /// Path to the source contracts. + /// Used to avoid analyzing libraries, tests or scripts and focus on the contracts. /// - /// For example, in a foundry repo: + /// In Foundry projects, it's auto-captured by foundry.toml and it's usually + /// not necessary to provide it. /// - /// --src=src/ - /// - /// In a hardhat repo: + /// In a Hardhat project: /// /// --src=contracts/ #[clap(short, long, use_value_delimiter = true)] src: Option>, /// List of path strings to include, delimited by comma (no spaces). - /// Any solidity file path not containing these strings will be ignored + /// + /// It allows to include only one or more specific contracts in the analysis: + /// aderyn -i src/MyContract.sol + /// aderyn -i src/MyContract.sol,src/MyOtherContract.sol #[clap(short = 'i', long, use_value_delimiter = true)] path_includes: Option>, /// List of path strings to exclude, delimited by comma (no spaces). - /// Any solidity file path containing these strings will be ignored + /// + /// It allows to exclude one or more specific contracts from the analysis: + /// aderyn -x src/MyContract.sol + /// aderyn -x src/MyContract.sol,src/MyOtherContract.sol #[clap(short = 'x', long, use_value_delimiter = true)] path_excludes: Option>, diff --git a/aderyn_core/src/context/browser/extractor.rs b/aderyn_core/src/context/browser/extractor.rs index 2d30d0e4..350f0a85 100644 --- a/aderyn_core/src/context/browser/extractor.rs +++ b/aderyn_core/src/context/browser/extractor.rs @@ -147,7 +147,7 @@ impl<'a> ExtractReferencedDeclarationsConditionally<'a> { } } -impl<'a> ASTConstVisitor for ExtractReferencedDeclarationsConditionally<'a> { +impl ASTConstVisitor for ExtractReferencedDeclarationsConditionally<'_> { fn visit_member_access(&mut self, node: &MemberAccess) -> Result { if !self.condition.as_ref()(node.id, self.context) { return Ok(true); diff --git a/aderyn_core/src/context/browser/storage_vars.rs b/aderyn_core/src/context/browser/storage_vars.rs index e49b1dde..a7ebf589 100644 --- a/aderyn_core/src/context/browser/storage_vars.rs +++ b/aderyn_core/src/context/browser/storage_vars.rs @@ -61,7 +61,7 @@ impl<'a> Add> for ApproximateStorageChangeFin } } -impl<'a> Debug for ApproximateStorageChangeFinder<'a> { +impl Debug for ApproximateStorageChangeFinder<'_> { // Do not print context. Hence, debug is custom derived for this struct fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Manipulated directly: {:?}", self.directly_manipulated_state_variables)?; @@ -213,7 +213,7 @@ impl<'a> ApproximateStorageChangeFinder<'a> { } } -impl<'a> ASTConstVisitor for ApproximateStorageChangeFinder<'a> { +impl ASTConstVisitor for ApproximateStorageChangeFinder<'_> { fn visit_unary_operation(&mut self, node: &UnaryOperation) -> Result { // WRITE HEURISTICS // Catch unary operations that manipulate variables diff --git a/aderyn_core/src/context/graph/callgraph_tests.rs b/aderyn_core/src/context/graph/callgraph_tests.rs index 2855e79e..3d4c5bfe 100644 --- a/aderyn_core/src/context/graph/callgraph_tests.rs +++ b/aderyn_core/src/context/graph/callgraph_tests.rs @@ -157,7 +157,7 @@ mod callgraph_test_functions { outward_side_effects_modifier_definitions_names: Vec, } - impl<'a> Tracker<'a> { + impl Tracker<'_> { fn new(context: &WorkspaceContext) -> Tracker { Tracker { context, diff --git a/aderyn_core/src/detect/high/const_func_change_state.rs b/aderyn_core/src/detect/high/const_func_change_state.rs index 007277d4..c45f8c5d 100644 --- a/aderyn_core/src/detect/high/const_func_change_state.rs +++ b/aderyn_core/src/detect/high/const_func_change_state.rs @@ -74,7 +74,7 @@ struct StateVariableChangeTracker<'a> { context: &'a WorkspaceContext, } -impl<'a> CallGraphVisitor for StateVariableChangeTracker<'a> { +impl CallGraphVisitor for StateVariableChangeTracker<'_> { fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> { if self.state_var_has_changed { return Ok(()); diff --git a/aderyn_core/src/detect/high/delegate_call_no_address_check.rs b/aderyn_core/src/detect/high/delegate_call_no_address_check.rs index 35806677..e77d57ee 100644 --- a/aderyn_core/src/detect/high/delegate_call_no_address_check.rs +++ b/aderyn_core/src/detect/high/delegate_call_no_address_check.rs @@ -71,7 +71,7 @@ struct DelegateCallNoAddressChecksTracker<'a> { context: &'a WorkspaceContext, } -impl<'a> CallGraphVisitor for DelegateCallNoAddressChecksTracker<'a> { +impl CallGraphVisitor for DelegateCallNoAddressChecksTracker<'_> { fn visit_any(&mut self, node: &crate::context::workspace_context::ASTNode) -> eyre::Result<()> { if !self.has_address_checks && helpers::has_binary_checks_on_some_address(node) { self.has_address_checks = true; diff --git a/aderyn_core/src/detect/high/incorrect_erc20_interface.rs b/aderyn_core/src/detect/high/incorrect_erc20_interface.rs index c466aeb7..4b527266 100644 --- a/aderyn_core/src/detect/high/incorrect_erc20_interface.rs +++ b/aderyn_core/src/detect/high/incorrect_erc20_interface.rs @@ -113,7 +113,7 @@ mod erc_matching_function_signature_helper { } // Helps with checking if a function definition satisifed a signature matcher - impl<'a> SignatureMatcher<'a> { + impl SignatureMatcher<'_> { fn satisfies(&self, func: &FunctionDefinition) -> Option { if func.name != self.name { return Some(false); diff --git a/aderyn_core/src/detect/high/incorrect_erc721_interface.rs b/aderyn_core/src/detect/high/incorrect_erc721_interface.rs index f15dc1f4..f87cfe67 100644 --- a/aderyn_core/src/detect/high/incorrect_erc721_interface.rs +++ b/aderyn_core/src/detect/high/incorrect_erc721_interface.rs @@ -127,7 +127,7 @@ mod erc721_matching_function_signature_helper { } // Helps with checking if a function definition satisifed a signature matcher - impl<'a> SignatureMatcher<'a> { + impl SignatureMatcher<'_> { fn satisfies(&self, func: &FunctionDefinition) -> bool { if func.name != self.name { return false; diff --git a/aderyn_core/src/detect/high/nested_struct_in_mapping.rs b/aderyn_core/src/detect/high/nested_struct_in_mapping.rs index d18d8fb3..fed71f73 100644 --- a/aderyn_core/src/detect/high/nested_struct_in_mapping.rs +++ b/aderyn_core/src/detect/high/nested_struct_in_mapping.rs @@ -29,7 +29,7 @@ fn version_req_allows_below_0_5_0(version_req: &VersionReq) -> bool { } let comparator = &version_req.comparators[0]; - comparator.major == 0 && comparator.minor.map_or(false, |m| m < 5) + comparator.major == 0 && comparator.minor.is_some_and(|m| m < 5) } impl IssueDetector for NestedStructInMappingDetector { diff --git a/aderyn_core/src/detect/high/state_variable_shadowing.rs b/aderyn_core/src/detect/high/state_variable_shadowing.rs index 3d13c5fb..f8792fca 100644 --- a/aderyn_core/src/detect/high/state_variable_shadowing.rs +++ b/aderyn_core/src/detect/high/state_variable_shadowing.rs @@ -107,7 +107,7 @@ fn allows_below_0_6_0(version_req: &VersionReq) -> bool { } let comparator = &version_req.comparators[0]; - comparator.major == 0 && comparator.minor.map_or(false, |m| m < 6) + comparator.major == 0 && comparator.minor.is_some_and(|m| m < 6) } impl IssueDetector for StateVariableShadowingDetector { diff --git a/aderyn_core/src/detect/low/assert_state_change.rs b/aderyn_core/src/detect/low/assert_state_change.rs index 80b262b0..d3d8b20a 100644 --- a/aderyn_core/src/detect/low/assert_state_change.rs +++ b/aderyn_core/src/detect/low/assert_state_change.rs @@ -69,7 +69,7 @@ mod assert_state_change_tracker { context: &'a WorkspaceContext, } - impl<'a> CallGraphVisitor for StateVariableChangeTracker<'a> { + impl CallGraphVisitor for StateVariableChangeTracker<'_> { fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> { if self.has_some_state_variable_changed { return Ok(()); diff --git a/aderyn_core/src/detect/low/cache_array_length.rs b/aderyn_core/src/detect/low/cache_array_length.rs index 8c2dfccd..cf941c0f 100644 --- a/aderyn_core/src/detect/low/cache_array_length.rs +++ b/aderyn_core/src/detect/low/cache_array_length.rs @@ -160,7 +160,7 @@ mod loop_investigation_helper { changes: Option>, } - impl<'a> CallGraphVisitor for StateVariableChangeTracker<'a> { + impl CallGraphVisitor for StateVariableChangeTracker<'_> { fn visit_any(&mut self, node: &ASTNode) -> eyre::Result<()> { let changes = ApproximateStorageChangeFinder::from(self.context, node); if self.changes.is_none() { diff --git a/aderyn_core/src/detect/low/costly_operations_inside_loops.rs b/aderyn_core/src/detect/low/costly_operations_inside_loops.rs index 7341afd0..88803422 100644 --- a/aderyn_core/src/detect/low/costly_operations_inside_loops.rs +++ b/aderyn_core/src/detect/low/costly_operations_inside_loops.rs @@ -80,7 +80,7 @@ struct StateVariableChangeTracker<'a> { context: &'a WorkspaceContext, } -impl<'a> CallGraphVisitor for StateVariableChangeTracker<'a> { +impl CallGraphVisitor for StateVariableChangeTracker<'_> { fn visit_any(&mut self, node: &crate::ast::ASTNode) -> eyre::Result<()> { if self.state_var_has_changed { return Ok(()); diff --git a/aderyn_core/src/detect/low/deprecated_oz_functions.rs b/aderyn_core/src/detect/low/deprecated_oz_functions.rs index 11e00e09..003902d4 100644 --- a/aderyn_core/src/detect/low/deprecated_oz_functions.rs +++ b/aderyn_core/src/detect/low/deprecated_oz_functions.rs @@ -31,7 +31,7 @@ impl IssueDetector for DeprecatedOZFunctionsDetector { directive .absolute_path .as_ref() - .map_or(false, |path| path.contains("openzeppelin")) + .is_some_and(|path| path.contains("openzeppelin")) }) && identifier.name == "_setupRole" { capture!(self, context, identifier); @@ -51,7 +51,7 @@ impl IssueDetector for DeprecatedOZFunctionsDetector { directive .absolute_path .as_ref() - .map_or(false, |path| path.contains("openzeppelin")) + .is_some_and(|path| path.contains("openzeppelin")) }) && member_access.member_name == "safeApprove" { capture!(self, context, member_access); diff --git a/aderyn_core/src/detect/low/function_init_state_vars.rs b/aderyn_core/src/detect/low/function_init_state_vars.rs index de6ad3ec..b030de04 100644 --- a/aderyn_core/src/detect/low/function_init_state_vars.rs +++ b/aderyn_core/src/detect/low/function_init_state_vars.rs @@ -93,7 +93,7 @@ impl<'a> NonConstantStateVariableReferenceDeclarationTracker<'a> { } } -impl<'a> CallGraphVisitor for NonConstantStateVariableReferenceDeclarationTracker<'a> { +impl CallGraphVisitor for NonConstantStateVariableReferenceDeclarationTracker<'_> { fn visit_any(&mut self, node: &ASTNode) -> eyre::Result<()> { // We already know the condition is satisifed if self.makes_a_reference { diff --git a/aderyn_core/src/detect/low/missing_inheritance.rs b/aderyn_core/src/detect/low/missing_inheritance.rs index cca19ec7..5399b19e 100644 --- a/aderyn_core/src/detect/low/missing_inheritance.rs +++ b/aderyn_core/src/detect/low/missing_inheritance.rs @@ -74,7 +74,7 @@ impl IssueDetector for MissingInheritanceDetector { continue; } if let Some(ASTNode::ContractDefinition(c)) = context.nodes.get(contract_id) { - if c.kind != ContractKind::Contract || c.is_abstract.map_or(false, identity) { + if c.kind != ContractKind::Contract || c.is_abstract.is_some_and(identity) { continue; } } @@ -100,7 +100,7 @@ impl IssueDetector for MissingInheritanceDetector { if let Some(ASTNode::ContractDefinition(c)) = context.nodes.get(potentially_missing_inheritance) { - if c.kind == ContractKind::Interface || c.is_abstract.map_or(false, identity) { + if c.kind == ContractKind::Interface || c.is_abstract.is_some_and(identity) { // Check that the contract is compatible with the missing inheritance if missing_function_selectors.iter().all(|s| contract_selectors.contains(s)) { diff --git a/aderyn_core/src/detect/low/return_bomb.rs b/aderyn_core/src/detect/low/return_bomb.rs index bf1483ff..0d958591 100644 --- a/aderyn_core/src/detect/low/return_bomb.rs +++ b/aderyn_core/src/detect/low/return_bomb.rs @@ -130,7 +130,7 @@ struct CallNoAddressChecksTracker<'a> { context: &'a WorkspaceContext, } -impl<'a> CallGraphVisitor for CallNoAddressChecksTracker<'a> { +impl CallGraphVisitor for CallNoAddressChecksTracker<'_> { fn visit_any(&mut self, node: &crate::context::workspace_context::ASTNode) -> eyre::Result<()> { if !self.has_address_checks && helpers::has_binary_checks_on_some_address(node) { self.has_address_checks = true; diff --git a/aderyn_core/src/detect/low/state_variable_could_be_constant.rs b/aderyn_core/src/detect/low/state_variable_could_be_constant.rs index dba18ccd..b69c4812 100644 --- a/aderyn_core/src/detect/low/state_variable_could_be_constant.rs +++ b/aderyn_core/src/detect/low/state_variable_could_be_constant.rs @@ -142,7 +142,7 @@ mod function_state_changes_finder_helper { changes: Option>, } - impl<'a> CallGraphVisitor for StateVariableChangeTracker<'a> { + impl CallGraphVisitor for StateVariableChangeTracker<'_> { fn visit_any(&mut self, node: &ASTNode) -> eyre::Result<()> { let changes = ApproximateStorageChangeFinder::from(self.context, node); if self.changes.is_none() { diff --git a/aderyn_core/src/detect/low/unsafe_oz_erc721_mint.rs b/aderyn_core/src/detect/low/unsafe_oz_erc721_mint.rs index d63da743..dfce8626 100644 --- a/aderyn_core/src/detect/low/unsafe_oz_erc721_mint.rs +++ b/aderyn_core/src/detect/low/unsafe_oz_erc721_mint.rs @@ -31,7 +31,7 @@ impl IssueDetector for UnsafeERC721MintDetector { directive .absolute_path .as_ref() - .map_or(false, |path| path.contains("openzeppelin")) + .is_some_and(|path| path.contains("openzeppelin")) }) && identifier.name == "_mint" { let this_contract_definition = identifier diff --git a/aderyn_core/src/fscloc/util.rs b/aderyn_core/src/fscloc/util.rs index c9263a0a..58b01ead 100644 --- a/aderyn_core/src/fscloc/util.rs +++ b/aderyn_core/src/fscloc/util.rs @@ -50,10 +50,6 @@ impl FromStr for CodeIterator { type Err = usize; fn from_str(code: &str) -> Result::Err> { - return Ok(CodeIterator { - content: code.chars().collect::>(), - curr_pos: 0, - line_no: 1, - }); + Ok(CodeIterator { content: code.chars().collect::>(), curr_pos: 0, line_no: 1 }) } } diff --git a/aderyn_core/src/report/json_printer.rs b/aderyn_core/src/report/json_printer.rs index e742a7e6..4169c744 100644 --- a/aderyn_core/src/report/json_printer.rs +++ b/aderyn_core/src/report/json_printer.rs @@ -24,17 +24,6 @@ pub struct JsonContent { pub struct JsonPrinter; -/** - * JSON should mimick MD - { - "files_summary": {...}, - "files_details": {...}, - "issue_summary": {...}, - "high_issues": {...}, - ... - } -*/ - impl ReportPrinter<()> for JsonPrinter { fn print_report( &self, diff --git a/cyfrinup/install b/cyfrinup/install index b257974e..d14639a4 100755 --- a/cyfrinup/install +++ b/cyfrinup/install @@ -1,5 +1,5 @@ #!/usr/bin/env bash -set -e +set -eo pipefail # ----------------------------------------------------------- # Forked from Foundry. @@ -32,7 +32,8 @@ banner echo Installing cyfrinup... -CYFRIN_DIR="$HOME/.cyfrin" +BASE_DIR="${XDG_CONFIG_HOME:-$HOME}" +CYFRIN_DIR="${CYFRIN_DIR:-"$BASE_DIR/.cyfrin"}" CYFRIN_BIN_DIR="$CYFRIN_DIR/bin" CYFRINUP_URL="https://raw.githubusercontent.com/Cyfrin/aderyn/master/cyfrinup/cyfrinup" @@ -46,7 +47,7 @@ chmod +x $BIN_PATH # Store the correct profile file (i.e. .profile for bash or .zshrc for ZSH). case $SHELL in */zsh) - PROFILE=$HOME/.zshrc + PROFILE="${ZDOTDIR-"$HOME"}/.zshenv" PREF_SHELL=zsh ;; */bash) @@ -57,6 +58,10 @@ case $SHELL in PROFILE=$HOME/.config/fish/config.fish PREF_SHELL=fish ;; +*/ash) + PROFILE=$HOME/.profile + PREF_SHELL=ash + ;; *) echo "cyfrinup: could not detect shell, manually add ${CYFRIN_BIN_DIR} to your PATH." exit 1 @@ -65,8 +70,15 @@ esac # Only add cyfrinup if it isn't already in PATH. if [[ ":$PATH:" != *":${CYFRIN_BIN_DIR}:"* ]]; then # Add the cyfrinup directory to the path and ensure the old PATH variables remain. - echo >> $PROFILE && echo "export PATH=\"\$PATH:$CYFRIN_BIN_DIR\"" >> $PROFILE + if [[ "$PREF_SHELL" == "fish" ]]; then + echo >> "$PROFILE" && echo "fish_add_path -a $CYFRIN_BIN_DIR" >> "$PROFILE" + else + echo >> "$PROFILE" && echo "export PATH=\"\$PATH:$CYFRIN_BIN_DIR\"" >> "$PROFILE" + fi fi +# Export the PATH directly in the current session +export PATH="$PATH:$CYFRIN_BIN_DIR" + echo && echo "Detected your preferred shell is ${PREF_SHELL} and added cyfrinup to PATH. Run 'source ${PROFILE}' or start a new terminal session to use cyfrin." echo "Then, simply run 'cyfrinup' to install Cyfrin tool suite" \ No newline at end of file