Release/v2.0.4#41
Conversation
…ing. upgrading with enhanced clippy check (cargo clippy -- -W clippy::pedantic)
| runs-on: ubuntu-latest | ||
| needs: publish | ||
| outputs: | ||
| appname: ${{ needs.publish.outputs.appname }} | ||
| tag: ${{ needs.publish.outputs.tag }} | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Authenticate with custom registry | ||
| id: auth | ||
| uses: rust-lang/crates-io-auth-action@v1 | ||
|
|
||
| - name: publish | ||
| env: | ||
| CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} | ||
| run: | ||
| cargo publish --package sibling |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 months ago
In general, the fix is to add an explicit permissions block so the GITHUB_TOKEN is scoped to the least privileges required. You can add it at the top level (applying to all jobs) or per‑job. Since all jobs here are part of the same release/publish pipeline and at least the setup, documents and publish jobs clearly need to write releases (which uses contents: write), the simplest safe change is to define a workflow‑level permissions block with contents: write. That both satisfies CodeQL (permissions are now explicit) and matches the actual needs of the workflow.
The single best way to fix this without changing behavior is:
- Add a root‑level
permissionsblock right after thename: Publish(or just afteron:) in.github/workflows/publish.yaml. - Set
contents: writeso the jobs that create and upload releases continue to function. - Optionally, you could further restrict other scopes (e.g., leave all others at their implicit
none), but we won’t guess additional scopes:contents: writeis clearly needed and sufficient for interacting with releases.
Concretely, edit .github/workflows/publish.yaml near the top, add:
permissions:
contents: writeleaving all jobs and steps unchanged.
| @@ -6,6 +6,9 @@ | ||
| - main | ||
| types: [closed] | ||
|
|
||
| permissions: | ||
| contents: write | ||
|
|
||
| jobs: | ||
| setup: | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
Pull request overview
This pull request bumps the version from 2.0.3 to 2.0.4 with significant code improvements and API changes. The changes include refactoring from usize to i32 for directory counts, renaming internal fields, adding #[must_use] attributes, introducing a new JSON output format, and improving code quality throughout.
Changes:
- Version bumped to 2.0.4 across all package files and documentation
- API breaking changes:
Dirs::len()return type changed fromusizetoi32, andNexterFactory::build()now takes a reference parameter - New JSON output format added alongside existing CSV and list formats
- Code quality improvements including better error handling, consistent use of references, and simplified control flow
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| Cargo.toml | Version bump to 2.0.4 |
| README.md | Version badge updated to 2.0.4 |
| docs/config.toml | Documentation version updated to 2.0.4 |
| lib/README.md | Enhanced CLI reference with GitHub link |
| lib/src/lib.rs | Major refactoring: field renamed (dirs→entries), return type changed (usize→i32), improved error handling, added #[must_use] attributes, updated tests |
| cli/src/cli.rs | Replaced separate --csv and --list flags with unified --format enum |
| cli/src/printer.rs | Added JSON format support, simplified function signatures (removed Result wrapper) |
| cli/src/main.rs | Updated to use reference parameters for API calls |
| cli/src/init.rs | Simplified shell matching with pattern matching |
| cli/src/gencomp.rs | Refactored to use references instead of owned values |
| .github/workflows/publish.yaml | Added crates.io publishing workflow |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| entries: Vec<PathBuf>, | ||
| /// The parent directory that contains all the sibling directories. | ||
| parent: PathBuf, | ||
| /// The index of the current directory in the `dirs` vector. |
There was a problem hiding this comment.
The comment still refers to dirs vector but the field was renamed to entries. The comment should be updated to say "The index of the current directory in the entries vector."
| /// | ||
| /// ## Panics | ||
| /// | ||
| /// This function will panic if the number of directories exceeds `i32::MAX`. | ||
| #[must_use] | ||
| pub fn len(&self) -> i32 { | ||
| i32::try_from(self.entries.len()).unwrap() |
There was a problem hiding this comment.
Changing the return type from usize to i32 is a breaking API change that could affect external consumers of this library. While the reasoning may be valid (to align with the internal use of i32 for step calculations), this change should be carefully considered. It reduces the maximum supported number of directories from usize::MAX to i32::MAX (approximately 2.1 billion). Consider whether this limitation is acceptable, or if there's a better way to handle the internal arithmetic without changing the public API.
| /// | |
| /// ## Panics | |
| /// | |
| /// This function will panic if the number of directories exceeds `i32::MAX`. | |
| #[must_use] | |
| pub fn len(&self) -> i32 { | |
| i32::try_from(self.entries.len()).unwrap() | |
| #[must_use] | |
| pub fn len(&self) -> usize { | |
| self.entries.len() |
| /// Get the next directory using the given [`Nexter`] and step. | ||
| /// | ||
| /// ## Panics | ||
| /// |
There was a problem hiding this comment.
There is trailing whitespace on this line. Consider removing it for consistency with code style guidelines.
| let mut result = vec![]; | ||
| let current = dirs.current(); | ||
| let next_index = next.clone().map(|n| n.index() as i32).unwrap_or(-1); | ||
| let next_index = next.map_or(-1, |n| i32::try_from(n.index()).unwrap()); |
There was a problem hiding this comment.
The conversion from usize to i32 can panic if the index exceeds i32::MAX. While unlikely in practice, if the system has extremely large directory lists, this could cause a panic. Consider handling this error gracefully or documenting the assumption that directory indices will never exceed i32::MAX.
| /// Build a [`Nexter`] instance based on the given [`NexterType`]. | ||
| pub fn build(nexter_type: NexterType) -> Box<dyn Nexter> { | ||
| #[must_use] | ||
| pub fn build(nexter_type: &NexterType) -> Box<dyn Nexter> { |
There was a problem hiding this comment.
Changing the parameter from NexterType to &NexterType is a breaking API change. While it's a more idiomatic Rust pattern (especially since NexterType implements Clone and this avoids unnecessary cloning), external consumers will need to update their code. Ensure this breaking change is documented in the release notes.
| pub fn build(nexter_type: &NexterType) -> Box<dyn Nexter> { | |
| pub fn build(nexter_type: NexterType) -> Box<dyn Nexter> { |
| let length = dirs.len(); | ||
| log::trace!( | ||
| "next_impl(step={step}, current={}, next={next})", | ||
| dirs.current | ||
| ); | ||
| if next < 0 || next >= dirs.dirs.len() as i32 { | ||
| if next < 0 || next >= dirs.len() { | ||
| log::warn!( | ||
| "next_impl: out of range (next={next}, len={})", | ||
| dirs.dirs.len() | ||
| dirs.len() |
There was a problem hiding this comment.
The variable length is assigned on line 465 but only used once on line 478. Lines 470 and 473 call dirs.len() directly instead of using the cached value. For consistency and to avoid unnecessary repeated function calls, consider using length in all three places, or remove the variable if caching is not needed.
| let next = dirs.len() - 1; | ||
| Some(Dir::new_of_last_item(dirs, usize::try_from(next).unwrap())) |
There was a problem hiding this comment.
If the directory list is empty (len() returns 0), this code will compute 0 - 1 = -1 and then call usize::try_from(-1).unwrap() which will panic. Consider checking if the directory list is empty first and returning None in that case, or handle the empty case explicitly.
|
|
||
| fn next_impl(dirs: &Dirs, step: i32) -> Option<Dir<'_>> { | ||
| let next = dirs.current as i32 + step; | ||
| let next = i32::try_from(dirs.current).unwrap() + step; |
There was a problem hiding this comment.
If dirs.current exceeds i32::MAX, this conversion will panic. Since dirs.current is a usize, it could theoretically hold values larger than i32::MAX. While the panic documentation is added for len(), similar consideration should be given here. Consider documenting this constraint or handling the conversion error gracefully.
| let next = i32::try_from(dirs.current).unwrap() + step; | |
| let current_i32 = match i32::try_from(dirs.current) { | |
| Ok(v) => v, | |
| Err(_) => { | |
| log::error!( | |
| "next_impl: current index {} exceeds i32::MAX and cannot be converted", | |
| dirs.current | |
| ); | |
| return None; | |
| } | |
| }; | |
| let next = current_i32 + step; |
| /// | ||
| /// ## Panics | ||
| /// |
There was a problem hiding this comment.
There is trailing whitespace on this line. Consider removing it for consistency with code style guidelines.
| /// | |
| /// ## Panics | |
| /// | |
| /// | |
| /// ## Panics | |
| /// |
| } | ||
|
|
||
| /// Get the next directory using the given [`Nexter`] and step. | ||
| /// |
There was a problem hiding this comment.
There is trailing whitespace on this line. Consider removing it for consistency with code style guidelines.
No description provided.