Skip to content

Commit d0200ef

Browse files
committed
chore(git): merge from master
2 parents e7dee6b + 555982a commit d0200ef

11 files changed

Lines changed: 389 additions & 0 deletions

.devcontainer/devcontainer.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "parallel-disk-usage (Rust only)",
3+
"image": "mcr.microsoft.com/devcontainers/rust:1",
4+
"customizations": {
5+
"vscode": {
6+
"extensions": [
7+
"rust-lang.rust-analyzer",
8+
"timonwong.shellcheck",
9+
"mkhl.shfmt"
10+
]
11+
}
12+
},
13+
"postCreateCommand": "bash .devcontainer/post-create.sh"
14+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "parallel-disk-usage (full)",
3+
"image": "mcr.microsoft.com/devcontainers/rust:1",
4+
"features": {
5+
"ghcr.io/devcontainers/features/node:1": {
6+
"version": "lts",
7+
"nodeGypDependencies": true
8+
},
9+
"ghcr.io/devcontainers/features/python:1": {
10+
"version": "3.12",
11+
"installTools": true
12+
},
13+
"ghcr.io/devcontainers-contrib/features/shellcheck:1": {},
14+
"ghcr.io/devcontainers-contrib/features/shfmt:1": {}
15+
},
16+
"customizations": {
17+
"vscode": {
18+
"extensions": [
19+
"rust-lang.rust-analyzer",
20+
"timonwong.shellcheck",
21+
"mkhl.shfmt"
22+
]
23+
}
24+
},
25+
"postCreateCommand": "bash .devcontainer/full/post-create.sh"
26+
}

.devcontainer/full/post-create.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
echo "Installing Python dependencies..." >&2
5+
python3 -m pip install --user toml
6+
7+
echo "Installing pnpm and project Node dependencies..." >&2
8+
npm install -g pnpm@7.9.0
9+
(cd ci/github-actions && pnpm install --frozen-lockfile)
10+
11+
bash "$(dirname "$0")/../install-rust-toolchain.sh"
12+
bash "$(dirname "$0")/../install-hyperfine.sh"

.devcontainer/install-hyperfine.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
# Shared helper: install hyperfine binary from GitHub releases into ~/.local/bin
3+
set -euo pipefail
4+
5+
arch="$(uname -m)"
6+
case "$arch" in
7+
x86_64) hyperfine_target="x86_64-unknown-linux-musl" ;;
8+
aarch64) hyperfine_target="aarch64-unknown-linux-musl" ;;
9+
*)
10+
echo "ERROR: Unsupported architecture for hyperfine prebuilt binary: $arch" >&2
11+
exit 1
12+
;;
13+
esac
14+
15+
mkdir -p "$HOME/.local/bin"
16+
17+
echo "Installing hyperfine from GitHub release..." >&2
18+
hyperfine_version="1.20.0"
19+
hyperfine_archive="hyperfine-v${hyperfine_version}-${hyperfine_target}"
20+
hyperfine_url="https://github.com/sharkdp/hyperfine/releases/download/v${hyperfine_version}/${hyperfine_archive}.tar.gz"
21+
curl -fsSL "$hyperfine_url" | tar -xz --strip-components=1 -C "$HOME/.local/bin" "${hyperfine_archive}/hyperfine"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5+
6+
echo "Installing Rust toolchain from rust-toolchain..." >&2
7+
rustup toolchain install "$(<"$REPO_ROOT/rust-toolchain")"
8+
rustup component add clippy rustfmt rust-analyzer

.devcontainer/post-create.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
mkdir -p "$HOME/.local/bin"
5+
6+
bash "$(dirname "$0")/install-rust-toolchain.sh"
7+
bash "$(dirname "$0")/install-hyperfine.sh"
8+
9+
arch="$(uname -m)"
10+
11+
echo "Installing shellcheck from GitHub release..." >&2
12+
shellcheck_version="0.11.0"
13+
case "$arch" in
14+
x86_64) shellcheck_arch="linux.x86_64" ;;
15+
aarch64) shellcheck_arch="linux.aarch64" ;;
16+
*)
17+
echo "ERROR: Unsupported architecture for shellcheck prebuilt binary: $arch" >&2
18+
exit 1
19+
;;
20+
esac
21+
shellcheck_archive="shellcheck-v${shellcheck_version}.${shellcheck_arch}"
22+
shellcheck_url="https://github.com/koalaman/shellcheck/releases/download/v${shellcheck_version}/${shellcheck_archive}.tar.gz"
23+
curl -fsSL "$shellcheck_url" | tar -xz --strip-components=1 -C "$HOME/.local/bin" "shellcheck-v${shellcheck_version}/shellcheck"
24+
25+
echo "Installing shfmt from GitHub release..." >&2
26+
shfmt_version="3.13.0"
27+
case "$arch" in
28+
x86_64) shfmt_arch="linux_amd64" ;;
29+
aarch64) shfmt_arch="linux_arm64" ;;
30+
*)
31+
echo "ERROR: Unsupported architecture for shfmt prebuilt binary: $arch" >&2
32+
exit 1
33+
;;
34+
esac
35+
shfmt_url="https://github.com/mvdan/sh/releases/download/v${shfmt_version}/shfmt_v${shfmt_version}_${shfmt_arch}"
36+
curl -fsSL "$shfmt_url" -o "$HOME/.local/bin/shfmt"
37+
chmod +x "$HOME/.local/bin/shfmt"

.github/copilot-instructions.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# AI Instructions
2+
3+
Read and follow the CONTRIBUTING.md file in this repository for all code style conventions, commit message format, and development guidelines.
4+
5+
## Quick Reference
6+
7+
- Commit format: Conventional Commits — `type(scope): lowercase description`
8+
- Version releases are the only exception: just the version number (e.g. `0.21.1`)
9+
- Prefer merged imports
10+
- Use descriptive generic names (`Size`, `Report`), not single letters
11+
- Prefer `where` clauses for multiple trait bounds
12+
- Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated
13+
- Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]`
14+
- Minimize `unwrap()` in non-test code — use proper error handling
15+
- `#![deny(warnings)]` is active — code must be warning-free
16+
- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
17+
- If the AI agent is Claude Code, `gh` (GitHub CLI) is not installed — do not attempt to use it
18+
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes

AGENTS.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# AI Instructions
2+
3+
Read and follow the CONTRIBUTING.md file in this repository for all code style conventions, commit message format, and development guidelines.
4+
5+
## Quick Reference
6+
7+
- Commit format: Conventional Commits — `type(scope): lowercase description`
8+
- Version releases are the only exception: just the version number (e.g. `0.21.1`)
9+
- Prefer merged imports
10+
- Use descriptive generic names (`Size`, `Report`), not single letters
11+
- Prefer `where` clauses for multiple trait bounds
12+
- Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated
13+
- Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]`
14+
- Minimize `unwrap()` in non-test code — use proper error handling
15+
- `#![deny(warnings)]` is active — code must be warning-free
16+
- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
17+
- If the AI agent is Claude Code, `gh` (GitHub CLI) is not installed — do not attempt to use it
18+
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes

CLAUDE.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# AI Instructions
2+
3+
Read and follow the CONTRIBUTING.md file in this repository for all code style conventions, commit message format, and development guidelines.
4+
5+
## Quick Reference
6+
7+
- Commit format: Conventional Commits — `type(scope): lowercase description`
8+
- Version releases are the only exception: just the version number (e.g. `0.21.1`)
9+
- Prefer merged imports
10+
- Use descriptive generic names (`Size`, `Report`), not single letters
11+
- Prefer `where` clauses for multiple trait bounds
12+
- Derive order: std traits → comparison traits → `Hash` → derive_more → feature-gated
13+
- Custom errors: `#[derive(Debug, Display, Error)]` + `#[non_exhaustive]`
14+
- Minimize `unwrap()` in non-test code — use proper error handling
15+
- `#![deny(warnings)]` is active — code must be warning-free
16+
- Install toolchain before running tests: `rustup toolchain install "$(< rust-toolchain)" && rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy`
17+
- If the AI agent is Claude Code, `gh` (GitHub CLI) is not installed — do not attempt to use it
18+
- Run `FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh` to validate changes

CONTRIBUTING.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Contributing to parallel-disk-usage
2+
3+
## Commit Message Convention
4+
5+
This project uses [Conventional Commits](https://www.conventionalcommits.org/).
6+
7+
### Format
8+
9+
```
10+
type(scope): lowercase description
11+
```
12+
13+
### Rules
14+
15+
- **Types:** `feat`, `fix`, `refactor`, `perf`, `docs`, `style`, `chore`, `ci`, `test`, `lint`
16+
- **Scopes** (optional): `cli`, `api`, `deps`, `readme`, `benchmark`, `toolchain`, `test`, or other relevant area
17+
- **Description:** always lowercase after the colon, no trailing period, brief (3-7 words preferred)
18+
- **Breaking changes:** append `!` before the colon (e.g. `feat(cli)!: remove deprecated flag`)
19+
- **Code identifiers** in descriptions should be wrapped in backticks (e.g. `` chore(deps): update `rand` ``)
20+
21+
### Exception: Version Releases
22+
23+
Version release commits use **only** the version number as the message — no type prefix:
24+
25+
```
26+
0.21.1
27+
```
28+
29+
## Code Style
30+
31+
Automated tools enforce formatting (`cargo fmt`) and linting (`cargo clippy`). The following conventions are **not** enforced by those tools and must be followed manually.
32+
33+
### Import Organization
34+
35+
Prefer **merged imports** — combine multiple items from the same crate or module into a single `use` statement with braces rather than separate `use` lines. Import ordering is enforced by `cargo fmt`. Platform-specific imports (`#[cfg(unix)]`) go in a separate block after the main imports.
36+
37+
```rust
38+
use crate::{
39+
args::{Args, Quantity, Threads},
40+
bytes_format::BytesFormat,
41+
size,
42+
};
43+
use clap::Parser;
44+
use pipe_trait::Pipe;
45+
use std::{io::stdin, time::Duration};
46+
47+
#[cfg(unix)]
48+
use crate::get_size::{GetBlockCount, GetBlockSize};
49+
```
50+
51+
### Module Organization
52+
53+
- Use the flat file pattern (`module.rs`) rather than `module/mod.rs` for submodules.
54+
- List `pub mod` declarations first, then `pub use` re-exports, then private imports and items.
55+
- Use `pub use` to re-export key types at the module level for convenience.
56+
57+
```rust
58+
pub mod error_only_reporter;
59+
pub mod error_report;
60+
pub mod event;
61+
62+
pub use error_only_reporter::ErrorOnlyReporter;
63+
pub use error_report::ErrorReport;
64+
pub use event::Event;
65+
```
66+
67+
- Type aliases using `pub use ... as ...` are used to provide semantic alternative names:
68+
69+
```rust
70+
pub use Reflection as DataTreeReflection;
71+
```
72+
73+
### Derive Macro Ordering
74+
75+
When deriving multiple traits, use this order and split across multiple `#[derive(...)]` lines for readability:
76+
77+
1. **Standard traits:** `Debug`, `Default`, `Clone`, `Copy`
78+
2. **Comparison traits:** `PartialEq`, `Eq`, `PartialOrd`, `Ord`
79+
3. **Hash**
80+
4. **`derive_more` traits:** `Display`, `From`, `Into`, `Add`, `AddAssign`, etc.
81+
5. **Feature-gated derives** on a separate `#[cfg_attr(...)]` line
82+
83+
```rust
84+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
85+
#[derive(From, Into, Add, AddAssign, Sub, SubAssign, Sum)]
86+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
87+
pub struct Bytes(u64);
88+
```
89+
90+
### Generic Parameter Naming
91+
92+
Use **descriptive names** for type parameters, not single letters:
93+
94+
- `Size`, `Name`, `SizeGetter`, `HardlinksRecorder`, `Report`
95+
96+
Single-letter generics are acceptable only in very short, self-contained trait impls.
97+
98+
### Trait Bounds
99+
100+
Prefer `where` clauses over inline bounds when there are multiple constraints:
101+
102+
```rust
103+
impl<Size, SizeGetter, HardlinksRecorder, Report>
104+
From<FsTreeBuilder<'a, Size, SizeGetter, HardlinksRecorder, Report>>
105+
for DataTree<OsStringDisplay, Size>
106+
where
107+
Report: Reporter<Size> + Sync + ?Sized,
108+
Size: size::Size + Send + Sync,
109+
SizeGetter: GetSize<Size = Size> + Sync,
110+
HardlinksRecorder: RecordHardlinks<Size, Report> + Sync + ?Sized,
111+
```
112+
113+
### Visibility
114+
115+
- Use `pub` for the public API surface.
116+
- Use `pub(crate)` for items shared within the crate but not exposed externally.
117+
- Default to private for everything else.
118+
119+
### Error Handling
120+
121+
- Define custom error enums with `#[derive(Debug, Display, Error)]` from `derive_more`.
122+
- Mark error enums as `#[non_exhaustive]`.
123+
- Minimize `unwrap()` in non-test code — use proper error propagation. `unwrap()` is acceptable in tests and for provably infallible operations (with a comment explaining why). When deliberately ignoring an error, use `.ok()` with a comment explaining why.
124+
125+
```rust
126+
#[derive(Debug, Display, Error)]
127+
#[non_exhaustive]
128+
pub enum RuntimeError {
129+
#[display("SerializationFailure: {_0}")]
130+
SerializationFailure(serde_json::Error),
131+
}
132+
```
133+
134+
### Documentation Comments
135+
136+
- Use `///` doc comments for all public types, traits, functions, and fields.
137+
- Use `//!` module-level doc comments at the top of `lib.rs` and significant modules.
138+
- Include usage examples with `/// ```no_run` blocks for key public APIs.
139+
- Reference related types with `[`backtick links`](crate::path)` syntax.
140+
141+
### Feature Gating
142+
143+
- Use `#[cfg(feature = "...")]` for optional functionality (e.g., `json`, `cli`).
144+
- Use `#[cfg(unix)]` for POSIX-specific code.
145+
- Use `#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]` for conditional derives.
146+
147+
### Pattern Matching
148+
149+
Use exhaustive matching. When mapping enum variants to values, prefer the concise wrapping style:
150+
151+
```rust
152+
ExitCode::from(match self {
153+
RuntimeError::SerializationFailure(_) => 2,
154+
RuntimeError::DeserializationFailure(_) => 3,
155+
})
156+
```
157+
158+
### Struct Field Ordering
159+
160+
Order fields logically by purpose, not alphabetically. Group related fields together. Document every public field with `///` comments.
161+
162+
### Macros
163+
164+
Use macros to reduce boilerplate for repetitive patterns (e.g. newtype wrappers, trait impls for multiple numeric types). Keep macros well-scoped and documented.
165+
166+
### Warnings Policy
167+
168+
The crate uses `#![deny(warnings)]` — all warnings are treated as errors. Code must compile warning-free.
169+
170+
## Setup
171+
172+
Install the required Rust toolchain and components before running any checks:
173+
174+
```sh
175+
rustup toolchain install "$(< rust-toolchain)"
176+
rustup component add --toolchain "$(< rust-toolchain)" rustfmt clippy
177+
```
178+
179+
## Automated Checks
180+
181+
Before submitting, ensure:
182+
183+
- `cargo fmt -- --check` passes
184+
- `cargo clippy` passes (on all feature combinations)
185+
- `cargo test` passes
186+
- The project builds with no default features, default features, and all features
187+
188+
The CI script `test.sh` runs all of these across 5 feature combinations. You can run it locally with:
189+
190+
```sh
191+
FMT=true LINT=true BUILD=true TEST=true DOC=true ./test.sh
192+
```

0 commit comments

Comments
 (0)