This project is about creating a simple shell. Yes, our own little bash. We will learn a lot about processes and file descriptors.
- A custom shell interpreter similar to bash and zsh, called minishell
- Support for built-in shell commands echo, cd, pwd, export, unset, env and exit
- Full support for PATH resolution and the execve system call to run external commands
- Advanced command line editing using the readline library, including support for history
- Advanced error handling and reporting, with informative error messages and exit codes
- Support for input/output redirection and pipes
- Environment variable expansion and substitution using the $ symbol
- Advanced signal handling, including support for Ctrl+C and Ctrl+\ signals
- Comprehensive unit tests and system tests to ensure robustness and correctness
- Advanced debugging tools, including support for valgrind and fsanitize for memory leak detection and error reporting
- Convenient and intuitive Makefile commands for easy compilation, testing, and debugging of the project
- Clone the repo
git clone https://github.com/saladuit/minishell.git
- Create a new branch (
git checkout -b my_branch
) - Make changes and test them
- Push to the branch (
git push origin my_branch
) - Create a pull request to push to main
- Review
./minishell.out
make
: Compiles the projectmake debug
: Compiles the project with debug flagsmake fsan
: Compiles the project with debug flags and fsanitize=undefinedmake valgrind
: Runs the project with valgrind to detect memory leaks
make test
: Runs all unit tests and system testsmake test FILTER='<test_filter>'
: test a specific module within the systemmake test FILTER='minishell/export*'
: test the whole sytem and only the export casesmake test FILTER='lexer/*'
: test a module and run all casesmake ftest
: Same as make test but also compiles with fsanitize=undefinedmake ftest FILTER='<test_filter>'
: test a specific module within the systemmake ftest FILTER='minishell/export*'
: test the whole sytem and only the export casesmake ftest FILTER='lexer/*'
: test a module and run all cases
make re
: Same as make fclean and makemake test_re
: Same as make test but also removes all object files and executablesmake ftest_re
: Same as make ftest but also removes all object files and executables
make coverage
: Runs gcov on all source files and generates a coverage reportmake analyse
: Generates a coverage report and opens it up
make clean
: Removes all object filesmake fclean
: Removes all object files and executablesmake covclean
: Removes all coverage-related files and calls fclean
It is recommended to use Test-Driven Development as the main development cycle. This means that you should write a test for the code you are going to write before you write it. This helps ensure that your code behaves as expected and that you catch any bugs early in the development cycle.
When writing tests, please follow these naming conventions:
- The function with the assertion should be named
assert_<function_name>
. - The test macro should be defined like so:
Test(<function_name>, <descriptive_case_name>)
. - The test case itself should have preferably only one function call to the assertion function.
- Keep the test cases concise, descriptive and simple.
We use GitHub Actions to automatically run tests on every push to the main branch.
The c.yml
YAML file defines the build and test jobs that are run.
Specifically, it installs necessary dependencies, builds the project, runs tests, generates coverage reports,
and uploads the reports to Coveralls for code coverage analysis.
It is important to have this in place because it allows us to catch any potential errors or issues with the codebase early on in the development process. This helps to ensure that the codebase remains stable and functional. Additionally, it provides visibility into the code coverage of the project, which can help us identify areas that need more testing.
If you make changes to the codebase, please ensure that the build and tests pass before pushing your changes to the main branch.