The rust-rm project welcomes contributions and corrections of all forms. This includes improvements to the documentation or code base, new tests, bug fixes, and implementations of new features. We recommend you open an issue before making any substantial changes so you can be sure your work won't be rejected. But for small changes, such as fixing a typo, you can open a Pull Request directly.
If you plan to make a contribution, please do make sure to read through the relevant sections of this document.
For security related issues, please refer to the security policy.
If you have problems with the software or think you've found a bug, please report it to the developers. We ask you to always open an issue describing the bug as soon as possible so that we, and others, are aware of the bug.
Before reporting a bug, make sure you've actually found a real bug. Carefully read the documentation and see if it really says you can do what you're trying to do. If it's not clear whether you should be able to do something or not, report that too; it's a bug in the documentation! Also, make sure the bug has not already been reported.
When preparing to report a bug, try to isolate it to a small working example that reproduces the problem. Then, create a bug report including this example and its results as well as any error or warning messages. Please don't paraphrase these messages: it's best to copy and paste them into your report. Finally, be sure to explain what you expected to happen; this will help us decide whether it is a bug or a problem with the documentation.
Once you have a precise problem you can report it as a bug report.
If you want the software to do something it currently does not, please report it to the developers. We ask you to always open an issue describing the feature as soon as possible so that we, and others, can consider and discuss it.
Before reporting a feature request, make sure you can't easily achieve what you want using existing features. Carefully read the documentation and experiment with the software. If it's not clear how to do something, report that too; it's a gap in the documentation! Also, make sure the feature has not already been requested.
Once you have a clear idea of what you need you can submit a feature request.
You are free to contribute by working on one of the confirmed or accepted and unassigned open issues and opening a Pull Request for it.
It is advised to indicate that you will be working on a issue by commenting on that issue. This is so others don't start working on the same issue as you are. Also, don't start working on an issue which someone else is working on - give everyone a chance to make contributions.
When you open a Pull Request that implements an issue make sure to link to that issue in the Pull Request description and explain how you implemented the issue as clearly as possible.
Note: If you, for whatever reason, can no longer continue your contribution please share this in the issue or your Pull Request. This gives others the opportunity to work on it. If we don't hear from you for an extended period of time we may decide to allow others to work on the issue you were assigned to.
To be able to contribute you need the following tooling:
- git v2;
- Just v1;
- Rust and Cargo v1.82 (edition 2021) with Clippy, rustfmt (see
rust-toolchain.toml
); - (Optional) cargo-all-features v1.7.0 or later;
- (Optional) cargo-deny v0.14.2 or later;
- (Optional) cargo-mutants v23.5.0 or later;
- (Optional) cargo-tarpaulin v0.31.2 or later;
- (Suggested) a code editor with EditorConfig support;
If you decide to make a contribution, please use the following workflow:
- Fork the repository.
- Create a new branch from the latest
main
. - Make your changes on the new branch.
- Commit to the new branch and push the commit(s).
- Open a Pull Request against
main
.
When contributing make sure your changes build and are formatted, tested, documented, and vetted. A simple way to verify if this is the case is using the command:
just verify
When making changes to the dependency tree be sure to also audit and validate license compliance against your changes using the command:
just audit compliance
As a Rust codebase, this project is build using Cargo. Ensure all changes you commit can be compiled. To compile the source code you can use the command:
just build
If your changes relate to a compile-time feature you can use the features
variable to adjust the
build, for example:
just features=gnu-mode build
For greater certainty that your changes are valid you can also use the build command used in continuous integration. This is more extensive but as a result also slower.
just ci-build
This project is formatted using rustfmt. Ensure all changes you commit are formatted. To format the source code run the command:
just fmt
Formatting is configured explicitly in the rustfmt.toml
file.
This project is extensively tested. Most source code changes should be accompanied by new tests or changes to the existing tests. To run all tests use the command:
just test
If necessary you can configure the feature set to test with using the features
variable to adjust
the build, for example:
just features=gnu-mode test
For greater certainty that your changes are valid you can also use the test command used in continuous integration. This is more extensive but as a result also slower.
Note: This includes running Special Tests, caution is advised.
just ci-test
To manually test something you can compile and run the program with any arguments using the
just run
command, for example:
just run --help
Due to the nature of this project many tests interact with the file system. Every test that does
interact with the file system uses its own temporary directory. By default, these are cleaned up
automatically (regardless of success). To preserve all temporary test directories you can set the
environment RUST_RM_DEBUG_TEST
.
Following Rust's official test organization guidelines, this project has:
-
Unit tests: for testing individual units of code. These tests are located next to the source code it tests. You can run only these tests using the command:
just test-unit
-
Integration tests: for testing the binary. These tests are located in the
tests/
directory. You can run only these tests using the command:just test-integration
A test can be written in different ways. This project uses three ways to write tests:
-
Oracle test: Simple tests that validate the behavior of the system for a given input-output pair (the oracle).
These tests are useful when the input domain is small (e.g. booleans only), to test edge cases, or if running the test is expensive (e.g. it interacts with the file system). If these conditions don't hold it is advised to use more advanced types of tests.
-
Parameterized test: Extends oracle tests by running a test with multiple input-output pairs.
These tests are useful to test the behavior of the system for related inputs, for different input-output pairs with similar behavior, or to test edge cases.
In this project parameterized tests are written using a helper function that runs the test on given inputs, and individual
#[test]
s that call this helper function with specific inputs. -
Property test (using proptest): Generalized tests that test for properties and invariants.
These tests are useful to test a wide range of inputs. They are also expressive in that they can be used to specify the general behavior of a system.
Note that property tests are bad at testing edge cases and that they should never be used for tests that interacts with the file system.
Test coverage can be used as a guide to writing tests - if a certain code path isn't covered by any tests it's behavior can't be validated automatically. To aid in writing tests this project is set up with test coverage powered by cargo-tarpaulin. To generate a coverage report for tests use the commands:
just coverage
This will generate a coverage report which can be found in the _reports/coverage/
directory.
If necessary you can configure the feature set to test using the features
variable to adjust the
build, for example:
just features=gnu-mode coverage
Mutation testing can be used as a guide to improve the test suite - if a mutation in the source code isn't detected by any test it indicates a gap in the suite. To aid in writing tests this project is set up with mutation testing powered by cargo-mutants. To generate a mutation report use the command:
just mutation
This will generate a mutation report which can be found in the _reports/mutants.out/
directory.
If necessary you can configure the feature set to mutation test using the features
variable to
adjust the build, for example:
just features=gnu-mode mutation
Some tests need to test the --trash
functionality. These tests aren't run by default to avoid
filling the trash with test files.
The following configuration must be used on all tests that (potentially) dispose of files to the trash:
#[cfg_attr(not(feature = "test-trash"), ignore = "Only run with the test-trash feature")]
To run tests involving the trash use the command:
just test_features=test-trash test
Some test (try to) perform potentially dangerous operations. These tests aren't run by default to avoid accidentally doing something disastrous.
The following configuration can be used to mark a test as dangerous:
#[cfg_attr(not(feature = "test-dangerous"), ignore = "Only run with the test-dangerous feature")]
To run dangerous tests use the command:
just test_features=test-dangerous test
Some tests work with symbolic links (symlinks). Working with symlinks on Windows requires elevated permissions, so these tests aren't run by default on Windows to avoid unexpected errors.
The following configuration must be used on all tests that (potentially) create symbolic links:
#[cfg_attr(
all(windows, not(feature = "test-symlink")),
ignore = "Only run with the test-symlink feature"
)]
To run tests involving symbolic links on Windows ensure you have elevated privileges and use the command:
just test_features=test-symlink test
Note: On non-Windows systems tests involving symlinks are run by default (regardless of the
test-symlink
feature).
This project is extensively documented. All source code should be documented to aid reuse without having to understand all code. All documentation is written for rustdoc. You can generate HTML formatted documentation for this project and its dependencies using the command:
just docs
Documentation in this project follows the following general structure:
/// [short sentence explaining what it is or does]
///
/// [more detailed explanation, optional]
///
/// [# Errors]
///
/// [describe when the function errors, if applicable]
///
/// [# Panics]
///
/// [describe when the function panics, if applicable]
///
/// [# Examples]
///
/// [code example, optional]
This project is vetted using standard Cargo commands as well as Clippy. To vet the source code run the command:
just vet
Clippy is configured explicitly through CLI arguments (see Justfile)
and the clippy.toml
file.
For greater certainty that your changes are valid you can also use the vet command used in continuous integration. This is more extensive but as a result also slower.
just ci-vet
This project uses cargo-deny to audit dependencies for known vulnerabilities. To audit the project dependencies run the command:
just audit
The configuration used for auditing is stored in deny.toml
.
This project uses cargo-deny to enforce a license policy on the project dependencies. To verify all dependency licenses are in compliance run the command:
just compliance
The license compliance policy is stored in deny.toml
.
Releases of this project are numbered based on the year and month in which they were released. Both
the year and month must always be represented with two digits, for example 23.01
for January 2023.
In the event a patch has to be released when a release already took place that month an incremental
integer suffix is added to the release number, for example 23.01-1
(i.e. 23.01 == 23.01-0
).
To create a new release, first update the release number in the CLI help text by changing the following line, for example:
- /// Remove (unlink) the PATH(s) - v23.06
+ /// Remove (unlink) the PATH(s) - v23.07
Commit this change with a message along the lines of "Version bump", for example:
git commit -m "Version bump"
Get this commit onto the project's default branch. When it is, tag the commit with same value used for the CLI help text. Give the tag an annotation with a list of changes since the last release, for example:
git tag -a v23.07
Push the tag to the GitHub repository, for example:
git push origin v23.07
This will trigger the publish.yml
workflow which will create a GitHub Release for the release
and compiled binaries for various platforms and architectures.
To get the most out of your code editor when contributing to this project you can use the tips provided here.
Add the following options to the .vscode/settings.json
file for this project:
{
// Control what build features rust-analyzer for VSCode considers to be enabled. Useful if you are
// working on code related to one of these features.
"rust-analyzer.cargo.noDefaultFeatures": true,
"rust-analyzer.cargo.features": [
"gnu-mode",
"trash",
],
}