Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command built-in (POSIX portability) #347

Merged
merged 25 commits into from
Feb 23, 2024
Merged

Command built-in (POSIX portability) #347

merged 25 commits into from
Feb 23, 2024

Conversation

magicant
Copy link
Owner

@magicant magicant commented Feb 22, 2024

Summary by CodeRabbit

  • New Features
    • Introduced the command built-in functionality in the yash shell, allowing users to execute utilities, search for commands, and identify command types and locations.
    • Added a method to retrieve the standard $PATH value across different system implementations.
  • Enhancements
    • Improved handling and execution of external utilities and shell functions, including better error handling and job control.
    • Enhanced command search functionality with more detailed categorization and precise searching capabilities.
  • Bug Fixes
    • Adjusted pattern matching for command execution to ensure accurate processing.
  • Tests
    • Added new test functions and scripts to validate the command built-in's functionality and compliance with POSIX standards.

The SearchEnv does not need to return the whole built-in set. It only
needs to return the built-in definition for a given name.
The SearchEnv does not need to expose the entire FunctionSet. Instead,
it should only expose the function that is being searched for. This
change makes the SearchEnv trait more focused and easier to implement.
When the command built-in is invoked with the -p option, it uses the
standard path to search for the command. To accommodate the dynamic
retrieval of the path from the underlying system, the PathEnv::path
function should return an Expansion instead of a reference to a variable.
The Expansion can contain an arbitrary owned string, allowing the
function to return a result that doesn't reference a value retained in
the environment.
To implement this method, we need to obtain the standard path from the
system. This is done by calling the new method `System::confstr_path`.
The command built-in is required to report the path to the built-in if
it is substitutive. To implement this, the `Builtin` variant of  the
`Target` enum is modified to include the path.
This is what is required by the POSIX standard.
POSIX forbids error messages in this case.
@magicant magicant self-assigned this Feb 22, 2024
Copy link

coderabbitai bot commented Feb 22, 2024

Walkthrough

The recent updates refine the command built-in functionality in the yash shell, focusing on execution, identification, and search to enhance command handling efficiency and user experience.

Changes

Files Change Summary
yash-builtin/src/command.rs
yash-builtin/src/command/identify.rs
yash-builtin/src/command/invoke.rs
yash-builtin/src/command/search.rs
yash-builtin/src/command/syntax.rs
Introduced and enhanced command built-in functionality, including execution, identification, and search of shell commands.
yash-builtin/src/lib.rs Added command module as a public entity when yash-semantics feature is enabled.
yash-env/src/builtin.rs
yash-env/src/system.rs
yash-env/src/system/real.rs
yash-env/src/system/virtual.rs
yash-env/src/variable.rs
yash-env/src/variable/quirk.rs
Improved hashing behavior, added $PATH retrieval methods, and enhanced variable handling.
yash-semantics/src/command/simple_command.rs
yash-semantics/src/command/simple_command/external.rs
yash-semantics/src/command/simple_command/function.rs
yash-semantics/src/command_search.rs
Adjusted pattern matching, refined external utility and function execution, and refactored command search functionality.
yash/tests/scripted_test.rs
yash/tests/scripted_test/command-p.sh
yash/tests/scripted_test/typeset-y.sh
Added tests for command built-in functionality and minor test script modifications.

🐇✨
In the world of code, where changes abound,
A rabbit hopped in, with improvements found.
Commands now swift, and errors few,
With each line refined, and functions anew.
Here's to the shell, ever so bright,
With yash's glow, shining light on the night.
🌟🐾

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 9

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 996323e and f233c23.
Files ignored due to path filters (2)
  • Cargo.lock is excluded by: !**/*.lock
  • yash-builtin/Cargo.toml is excluded by: !**/*.toml
Files selected for processing (19)
  • yash-builtin/src/command.rs (1 hunks)
  • yash-builtin/src/command/identify.rs (1 hunks)
  • yash-builtin/src/command/invoke.rs (1 hunks)
  • yash-builtin/src/command/search.rs (1 hunks)
  • yash-builtin/src/command/syntax.rs (1 hunks)
  • yash-builtin/src/lib.rs (3 hunks)
  • yash-env/src/builtin.rs (2 hunks)
  • yash-env/src/system.rs (3 hunks)
  • yash-env/src/system/real.rs (2 hunks)
  • yash-env/src/system/virtual.rs (3 hunks)
  • yash-env/src/variable.rs (2 hunks)
  • yash-env/src/variable/quirk.rs (4 hunks)
  • yash-semantics/src/command/simple_command.rs (2 hunks)
  • yash-semantics/src/command/simple_command/external.rs (5 hunks)
  • yash-semantics/src/command/simple_command/function.rs (1 hunks)
  • yash-semantics/src/command_search.rs (19 hunks)
  • yash/tests/scripted_test.rs (1 hunks)
  • yash/tests/scripted_test/command-p.sh (1 hunks)
  • yash/tests/scripted_test/typeset-y.sh (1 hunks)
Additional comments: 40
yash/tests/scripted_test.rs (1)
  • 116-119: The addition of the command_builtin test function correctly follows the established pattern for scripted tests in yash. It's well-structured and adheres to the best practices observed in the rest of the file.
yash/tests/scripted_test/command-p.sh (1)
  • 1-309: The command-p.sh script provides a comprehensive set of test cases for the command built-in functionality, covering a wide range of scenarios including interaction with functions, special built-ins, external commands, and the handling of environment variables. The script is well-structured, follows best practices for shell scripting, and correctly anticipates the expected outcomes for each test case.
yash-builtin/src/command/syntax.rs (2)
  • 52-56: The OPTION_SPECS constant defines the option specifications for the command built-in, including -p for using the standard search path, -v for identifying the command, and -V for verbose identification. This setup is clear and aligns with POSIX specifications for the command built-in. However, it's important to ensure that these options are mutually exclusive where applicable and that their precedence is correctly handled in the parsing logic.
  • 58-90: The parse function effectively interprets the options and operands to produce a Command instance, either Invoke or Identify, based on the presence of the -v or -V options. The function's logic is well-structured, but it's crucial to handle edge cases, such as when no command name is provided or when both -v and -V are specified. The current implementation correctly prioritizes the last specified option between -v and -V, which is a good practice for command-line tools.
yash-builtin/src/command/invoke.rs (2)
  • 31-47: The execute method in the Invoke struct correctly handles the execution flow, including searching for the command and invoking the target. The use of pattern matching with Some and else clauses for handling the absence of a command name or target is a modern Rust feature that enhances readability. However, it's important to ensure that error messages and exit statuses are consistent with POSIX specifications when a command is not found or cannot be invoked.
  • 55-77: The invoke_target function effectively delegates the invocation to the appropriate handler based on the target type (built-in, function, or external utility). This modular approach simplifies the code structure and makes it easier to maintain. However, it's crucial to ensure that the environment and fields are correctly passed to and handled by each target type, especially regarding environment variable scopes and command arguments.
yash-builtin/src/command.rs (1)
  • 110-244: The Command enum, along with the Invoke and Identify structs, are well-defined and encapsulate the parameters and logic for invoking and identifying commands. The main function effectively parses the arguments and executes the appropriate command based on the parsed input. This structure aligns with the expected functionality of the command built-in and provides a solid foundation for further enhancements. It's important to ensure that all possible error cases are handled gracefully and that the user is provided with clear and informative error messages.
yash-semantics/src/command/simple_command.rs (2)
  • 221-232: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [173-233]

The pattern matching adjustments in the impl Command for syntax::SimpleCommand block enhance the clarity and maintainability of the command execution logic. By explicitly handling each target type (built-in, function, external utility, and absent target), the code becomes more readable and easier to extend. It's important to ensure that each execution path correctly handles environment variables, arguments, and exit statuses according to POSIX standards.

  • 224-229: The introduction of new public exports (execute_function_body, replace_current_process, start_external_utility_in_subshell_and_wait, and to_c_strings) significantly improves the modularity and reusability of the command execution logic. These exports allow for more granular control over the execution process and facilitate testing. However, it's crucial to ensure that these functions are well-documented and that their interfaces are intuitive for other developers to use effectively.
yash-env/src/builtin.rs (2)
  • 37-37: The addition of the Hash trait to the Type enum is a positive change, enhancing the ability to use these types as keys in hash maps or sets, which can improve performance and usability in certain scenarios.
  • 246-246: Implementing the Hash trait for the Builtin struct is a logical step following the addition of the Hash trait to the Type enum. This change allows instances of Builtin to be used in hashed collections, potentially improving lookup and insertion performance.
yash-builtin/src/command/search.rs (3)
  • 33-68: The implementation of the SearchEnv struct and its integration with the PathEnv trait is well-structured and follows Rust's idiomatic practices. The use of the standard_path flag to determine the source of the path (standard vs. $PATH variable) is a thoughtful design choice that enhances flexibility.
  • 70-85: The integration of the SearchEnv struct with the yash_semantics::command_search::SearchEnv trait is correctly implemented. The conditional checks for Category::Builtin and Category::Function ensure that only the requested types of commands are searched, aligning with the intended functionality.
  • 88-260: The test cases provided in the file are comprehensive and cover a variety of scenarios, including standard and non-standard paths, as well as enabling and disabling search for built-ins and functions. These tests are crucial for ensuring the reliability and correctness of the command search functionality.
yash-env/src/variable/quirk.rs (4)
  • 21-21: The addition of the either crate and its usage in the split method of the Expansion enum is a good choice for handling different iterator types in a clean and efficient manner. This enhances the code's readability and maintainability.
  • 64-69: Implementing the Default trait for the Expansion enum to return Unset as the default value is a logical choice, ensuring that uninitialized expansions have a clear and consistent state.
  • 155-163: The addition of the From<Expansion<'_>> implementation for Option<Value> is a useful conversion feature, facilitating the transformation of expansions into optional values, which can simplify handling of variable expansions in different contexts.
  • 208-240: The split method added to the Expansion enum is a valuable utility for handling path-like expansions, allowing for easy splitting of scalar values by colons and handling arrays and unset values appropriately. This method enhances the flexibility and usability of the Expansion enum in path-related operations.
yash-builtin/src/lib.rs (2)
  • 55-56: The addition of the command module as a public entity when the yash-semantics feature is enabled is correctly implemented. This change aligns with the PR objectives to enhance the yash shell's command built-in functionality. The use of the feature flag is appropriate and follows Rust's best practices for conditional compilation.
  • 142-148: The addition of the command built-in to the BUILTINS array is correctly implemented, with appropriate properties (r#type: Mandatory, execute logic). This change aligns with the PR objectives to enhance the yash shell's command built-in functionality and follows the established pattern for built-ins.
yash-semantics/src/command/simple_command/function.rs (2)
  • 51-58: The modifications to the execute_function function, including the direct operation on the env parameter and the use of execute_function_body for executing the function body, are well-implemented. These changes enhance the modularity and flexibility of function execution within the shell, aligning with the PR objectives to improve shell functionality. The logic appears correct, and the implementation follows best practices for async function execution in Rust.
  • 48-89: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [60-90]

The introduction of the execute_function_body function is a significant improvement, allowing for custom variable assignments before executing the function body. This function enhances the shell's ability to handle function execution with more flexibility and aligns with the PR objectives to refine command execution logic. The implementation is correct, and the use of a modifier function for custom assignments before execution is a thoughtful addition.

yash-semantics/src/command/simple_command/external.rs (3)
  • 66-66: The error handling for when the path to the external utility is empty has been improved by providing a more descriptive error message and setting the exit status to NOT_FOUND. This is a positive change as it enhances user feedback and error clarity.
  • 78-80: The call to start_external_utility_in_subshell_and_wait and setting the env.exit_status based on its return value is a significant improvement. It encapsulates the logic for starting an external utility in a subshell, waiting for it to finish, and handling the exit status in a dedicated function, which enhances modularity and readability.
  • 131-137: The error handling within start_external_utility_in_subshell_and_wait when the execution fails due to an Errno is well-implemented. It provides clear feedback to the user about the failure to execute the external utility, including the utility name and the error description. This is a good practice for usability and debugging.
yash-semantics/src/command_search.rs (5)
  • 53-68: The refactoring of the Target enum to include a path field for Builtin is a thoughtful addition. It allows handling shadowed external utilities, which is crucial for a shell that aims to be POSIX-compliant. This change enhances the shell's ability to distinguish between built-in and external commands when their names collide.
  • 110-116: The modification to the PathEnv trait to return an Expansion type instead of a direct reference is a significant improvement. It allows for more dynamic handling of the $PATH variable, accommodating scenarios where the path may be computed at runtime. This change increases the flexibility and robustness of the command search mechanism.
  • 181-211: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [171-208]

The updates to the search function to handle external utility search more precisely based on the presence of slashes in the name are well-implemented. This logic aligns with POSIX standards and improves the shell's behavior in determining whether to treat a command as an external utility. The distinction between different types of built-ins (Special, Substitutive, etc.) and their handling in the search process is clear and well-structured.

  • 218-226: The search_path function's implementation is concise and effective. It iterates over directories specified in the $PATH variable and checks for the existence of the executable, which is a core requirement for command search functionality in a shell. The use of CString and handling of relative paths are appropriate for the context of a Unix-like environment.
  • 483-498: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [234-593]

The comprehensive test suite covering various scenarios, including empty environments, unmatched names, priority of built-ins over functions, and the search for external executables, is commendable. These tests ensure that the command search functionality behaves as expected under different conditions. It's particularly noteworthy how the tests account for the new path field in the Target::Builtin variant and the dynamic computation of the $PATH variable.

yash-builtin/src/command/identify.rs (7)
  • 1-15: The file header correctly includes the copyright notice and license information, ensuring compliance with the GNU General Public License version 3 or later. This is crucial for maintaining the legal integrity of the project.
  • 17-42: The module documentation and imports are well-organized, providing a clear overview of the file's purpose and the external dependencies required for its functionality. This helps in understanding the context and scope of the command identification features within the yash shell.
  • 43-60: The NotFound struct and its implementation of the MessageBase trait provide a structured way to handle and report command not found errors. This approach enhances error reporting by including both the command name and its origin, which can be very helpful for debugging and user feedback.
  • 62-80: The NormalizeEnv trait and its implementation for Env are crucial for abstracting the environment-specific operations needed for command normalization. This design promotes code reusability and maintainability by decoupling the normalization logic from the specific environment implementation.
  • 108-169: The describe_target function effectively generates a description of the given target, which is crucial for verbose output and debugging. The use of pattern matching on the target parameter is clean and ensures that each command type is handled appropriately. The implementation is concise and leverages Rust's powerful formatting capabilities.
  • 226-263: The Identify struct and its methods provide a high-level interface for performing command identification. The async execute method, in particular, demonstrates a good practice of separating the logic for generating results from the logic for handling output and errors. This separation of concerns aids in maintaining clean and testable code.
  • 265-582: The unit tests are comprehensive, covering various scenarios for command normalization and identification. These tests ensure that the functionality behaves as expected under different conditions. It's good practice to include such tests to validate the correctness of the code and prevent regressions in future changes.
yash-env/src/variable.rs (1)
  • 49-49: The import of Field is correctly added to support the new functionality in PositionalParams. This change aligns with the PR's objective to enhance command handling capabilities.
yash-env/src/system.rs (2)
  • 387-391: The addition of the confstr_path method to the System trait is a valuable enhancement for retrieving the standard $PATH value. This method abstracts the underlying system call or functionality to fetch the $PATH where utilities are expected to be found, which is crucial for shell operations and command execution. The method's documentation and signature are clear and concise, making its purpose and usage straightforward.
  • 957-959: The implementation of the confstr_path method in the SharedSystem struct correctly delegates the call to the contained System instance. This approach maintains the abstraction layer and allows for the method's use in both synchronous and asynchronous contexts within the shell environment. The implementation is concise and follows the established pattern for delegating System trait method calls within the SharedSystem struct.

yash-env/src/system/real.rs Outdated Show resolved Hide resolved
yash-builtin/src/command/identify.rs Outdated Show resolved Hide resolved
yash-builtin/src/command/identify.rs Outdated Show resolved Hide resolved
yash-env/src/variable.rs Show resolved Hide resolved
yash-env/src/system/virtual.rs Show resolved Hide resolved
yash-builtin/src/command/syntax.rs Show resolved Hide resolved
yash-builtin/src/command/syntax.rs Show resolved Hide resolved
yash-builtin/src/command/invoke.rs Show resolved Hide resolved
The char type may be i8, so we should convert.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f233c23 and e232de6.
Files selected for processing (1)
  • yash-env/src/system/real.rs (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • yash-env/src/system/real.rs

The NotFound error does not happen in the describe_target function, so
it should not be used as the error type. Instead, the function now
returns std::fmt::Error, which is the error type of the Write trait we
failed to handle gracefully.
This change splits the `identify` function into two functions:
`categorize` and `describe`. The `categorize` function determines the
category of the given command name, and the `describe` function produces
the description of the categorized command name that is finally printed
to the standard output. This change makes the code more modular and
easier to understand. Notably, the new `describe` function propagates
the `std::fmt::Result` error type, which was not handled gracefully in
the previous implementation.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between e232de6 and d82e2e1.
Files selected for processing (1)
  • yash-builtin/src/command/identify.rs (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • yash-builtin/src/command/identify.rs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d82e2e1 and 52df77e.
Files selected for processing (1)
  • yash-builtin/src/command/identify.rs (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • yash-builtin/src/command/identify.rs

@magicant magicant merged commit e212fc6 into master Feb 23, 2024
5 checks passed
@magicant magicant deleted the command-builtin branch February 23, 2024 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet

1 participant