Skip to content

Commit fd686b7

Browse files
committed
Commit initial repo
0 parents  commit fd686b7

33 files changed

+3875
-0
lines changed

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
os: [ubuntu-latest, macos-latest]
15+
ruby-version: ['3.2', '3.3', '3.4']
16+
17+
runs-on: ${{ matrix.os }}
18+
19+
steps:
20+
- uses: actions/checkout@v5
21+
22+
- uses: ruby/setup-ruby@v1
23+
with:
24+
ruby-version: ${{ matrix.ruby-version }}
25+
bundler-cache: true
26+
27+
- name: Run all checks
28+
run: bundle exec rake check

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.bundle/
2+
vendor/
3+
Gemfile.lock
4+
pkg/
5+
*.gem
6+
*.bundle
7+
*.so
8+
*.dll
9+
*.dylib
10+
*.dSYM/
11+
lib/fdr/fdr_native.bundle
12+
lib/fdr/fdr_native.so
13+
ext/fdr_native/target/
14+
ext/fdr_native/Cargo.lock
15+
ext/fdr_native/Makefile
16+
ext/fdr_native/mkmf.log
17+
ext/fdr_native/tmp/
18+
ext/fdr_native/.rb-sys/

.rubocop.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
plugins:
2+
- rubocop-minitest
3+
- rubocop-rake
4+
5+
AllCops:
6+
NewCops: enable
7+
TargetRubyVersion: 3.2
8+
9+
Metrics/BlockLength:
10+
Exclude:
11+
- "spec/**/*.rb"
12+
- "*.gemspec"
13+
14+
Metrics/MethodLength:
15+
Max: 20
16+
17+
Metrics/ParameterLists:
18+
Max: 20
19+
20+
Layout/LineLength:
21+
Exclude:
22+
- "*.gemspec"
23+
24+
Layout/SpaceInsideHashLiteralBraces:
25+
EnforcedStyle: no_space
26+
27+
Style/Alias:
28+
EnforcedStyle: prefer_alias

Gemfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
source 'https://rubygems.org'
4+
5+
gemspec
6+
7+
group :development do
8+
gem 'benchmark', '~> 0.4'
9+
gem 'benchmark-ips', '~> 2'
10+
gem 'minitest', '~> 5'
11+
gem 'minitest-proveit', '~> 1'
12+
13+
gem 'rake', '~> 13', require: false
14+
gem 'rubocop', '~> 1.69', require: false
15+
gem 'rubocop-minitest', '~> 0.36', require: false
16+
gem 'rubocop-rake', '~> 0.6', require: false
17+
end

LICENSE

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Fdr is a clone of fd, using the same core libraries and sharing some
2+
implementation details and code. Both are MIT license.
3+
4+
Copyright (c) Shannon Skipper
5+
Copyright (c) 2017-present The fd developers
6+
7+
MIT License
8+
9+
Permission is hereby granted, free of charge, to any person obtaining
10+
a copy of this software and associated documentation files (the
11+
"Software"), to deal in the Software without restriction, including
12+
without limitation the rights to use, copy, modify, merge, publish,
13+
distribute, sublicense, and/or sell copies of the Software, and to
14+
permit persons to whom the Software is furnished to do so, subject to
15+
the following conditions:
16+
17+
The above copyright notice and this permission notice shall be
18+
included in all copies or substantial portions of the Software.
19+
20+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Fdr
2+
3+
`Fdr` is a fast file search gem for Ruby, implemented with a Rust native extension inspired directly by [fd](https://github.com/sharkdp/fd). `Fdr` uses the same core dependencies as `fd` and `ripgrep`, including [ignore](https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore), [regex](https://github.com/rust-lang/regex), [globset](https://github.com/BurntSushi/ripgrep/tree/master/crates/globset) and [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam).
4+
5+
`Fdr` intentionally lacks an `fdr` executable, since `fd` is perfect for that job. If you need a fast file searching in a CLI tool use, use `fd`. If you need fast file searching from your Ruby code, use `Fdr`.
6+
7+
## Installation
8+
9+
```bash
10+
gem install fdr
11+
```
12+
13+
### Requirements
14+
- Ruby 3.2+
15+
- Rust
16+
17+
## Usage
18+
19+
```ruby
20+
require 'fdr'
21+
22+
Fdr.search(extension: 'rb')
23+
24+
Fdr.search(
25+
pattern: 'test',
26+
paths: %w[lib spec],
27+
type: 'f'
28+
)
29+
30+
Fdr.search(
31+
pattern: 'config',
32+
paths: %w[app config],
33+
extension: 'yml',
34+
type: 'f',
35+
max_depth: 3,
36+
hidden: true
37+
)
38+
39+
Fdr.search(
40+
pattern: '\.test\.js$',
41+
paths: %w[src test],
42+
exclude: %w[node_modules vendor],
43+
case_sensitive: true
44+
)
45+
46+
Fdr.search(pattern: '**/*.{rb,rake}', glob: true)
47+
48+
Fdr.search(
49+
extension: 'log',
50+
min_size: 1024 * 1024,
51+
changed_within: 86400,
52+
paths: %w[logs]
53+
)
54+
55+
# Aliases for `Fdr.search`, if you prefer:
56+
Fdr.entries(extension: 'rb')
57+
Fdr.scan(extension: 'rb')
58+
```
59+
60+
### Gaps
61+
62+
Some non-CLI features that `fd` implements that are lacking `Fdr` including owner filters, support for nonfile types, smart case switching with patterns and `.fdignore` support.

Rakefile

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# frozen_string_literal: true
2+
3+
require 'bundler/gem_tasks'
4+
require 'rubocop/rake_task'
5+
require 'fileutils'
6+
7+
task default: :check
8+
9+
desc 'Compile native extension'
10+
task :compile do
11+
Dir.chdir('ext/fdr_native') do
12+
ruby 'extconf.rb'
13+
sh 'make'
14+
15+
FileUtils.mkdir_p '../../lib/fdr'
16+
ext = RUBY_PLATFORM.include?('darwin') ? 'bundle' : 'so'
17+
FileUtils.cp "fdr_native.#{ext}", "../../lib/fdr/fdr_native.#{ext}"
18+
end
19+
end
20+
21+
desc 'Run Ruby tests'
22+
task test: :compile do
23+
Dir.glob('spec/**/*_spec.rb').each do |file|
24+
ruby '-Ilib:spec', file
25+
end
26+
end
27+
28+
desc 'Clean build artifacts'
29+
task :clean do
30+
FileUtils.rm_f Dir['lib/fdr/*.{bundle,so}']
31+
Dir.chdir('ext/fdr_native') do
32+
sh 'make clean' if File.exist?('Makefile')
33+
end
34+
end
35+
36+
desc 'Deep clean including Cargo artifacts'
37+
task clobber: :clean do
38+
Dir.chdir('ext/fdr_native') do
39+
sh 'cargo clean'
40+
end
41+
end
42+
43+
RuboCop::RakeTask.new
44+
45+
namespace :rust do
46+
desc 'Run Rust tests'
47+
task :test do
48+
Dir.chdir('ext/fdr_native') do
49+
sh 'cargo test --all-targets --all-features'
50+
end
51+
end
52+
53+
desc 'Lint Rust code with clippy'
54+
task :lint do
55+
Dir.chdir('ext/fdr_native') do
56+
sh 'cargo clippy --all-targets --all-features -- -D warnings'
57+
end
58+
end
59+
60+
desc 'Check Rust code formatting'
61+
task :format do
62+
Dir.chdir('ext/fdr_native') do
63+
sh 'cargo fmt --all --check'
64+
end
65+
end
66+
67+
desc 'Run all Rust checks'
68+
task check: %i[format lint test]
69+
end
70+
71+
desc 'Run all checks (Rust + Ruby)'
72+
task check: %i[rust:format rust:lint rust:test test rubocop]
73+
74+
desc 'Build gem after compiling extension'
75+
task build: :compile

ext/fdr_native/Cargo.toml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[workspace]
2+
members = ["core", "ffi"]
3+
resolver = "2"
4+
5+
[workspace.dependencies]
6+
fdr-core = { path = "./core" }
7+
8+
[workspace.lints.clippy]
9+
# Clippy lint groups
10+
cargo = { level = "deny", priority = -1 }
11+
correctness = { level = "deny", priority = -1 }
12+
nursery = { level = "deny", priority = -1 }
13+
pedantic = { level = "deny", priority = -1 }
14+
perf = { level = "deny", priority = -1 }
15+
style = { level = "deny", priority = -1 }
16+
suspicious = { level = "deny", priority = -1 }
17+
18+
# Clippy nursery group allows
19+
redundant_pub_crate = "allow"
20+
missing_const_for_fn = "allow"
21+
22+
# Clippy cargo group allows
23+
cargo_common_metadata = "allow"
24+
multiple_crate_versions = "allow"
25+
26+
# Clippy pedantic group allows (common patterns in this codebase)
27+
missing_errors_doc = "allow"
28+
missing_panics_doc = "allow"
29+
must_use_candidate = "allow"
30+
module_name_repetitions = "allow"
31+
cast_possible_truncation = "allow"
32+
cast_sign_loss = "allow"
33+
cast_precision_loss = "allow"
34+
35+
# Clippy restriction lints (cherry-picked for security & correctness)
36+
boxed_local = "deny"
37+
clone_on_copy = "deny"
38+
cognitive_complexity = "deny"
39+
panic = "deny"
40+
print_stdout = "deny"
41+
print_stderr = "deny"
42+
unwrap_used = "deny"
43+
todo = "deny"
44+
unimplemented = "deny"
45+
undocumented_unsafe_blocks = "deny"
46+
multiple_unsafe_ops_per_block = "deny"
47+
indexing_slicing = "deny"
48+
allow_attributes_without_reason = "deny"
49+
50+
[workspace.lints.rust]
51+
# Rust lint groups
52+
future_incompatible = "deny"
53+
let_underscore = "deny"
54+
nonstandard_style = "deny"
55+
rust_2018_compatibility = "deny"
56+
rust_2018_idioms = "deny"
57+
rust_2021_compatibility = "deny"
58+
rust_2024_compatibility = "deny"
59+
unused = "deny"
60+
61+
# Rust lints (not covered by groups above)
62+
single_use_lifetimes = "deny"
63+
trivial_casts = "deny"
64+
trivial_numeric_casts = "deny"
65+
unreachable_pub = "deny"
66+
67+
# Safety: deny unsafe code (works with clippy's undocumented_unsafe_blocks above)
68+
unsafe_code = "deny"

ext/fdr_native/core/Cargo.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[package]
2+
name = "fdr-core"
3+
version = "0.1.0"
4+
edition = "2024"
5+
description = "Core library for fdr - fast directory recursion for Ruby using the ignore crate"
6+
license = "MIT"
7+
repository = "https://github.com/havenwood/fdr"
8+
publish = false
9+
10+
[lints]
11+
workspace = true
12+
13+
[dependencies]
14+
# For walking directories in parallel (same as fd uses)
15+
ignore = "0.4"
16+
17+
# For regex support
18+
regex = "1.12"
19+
20+
# For glob pattern support
21+
globset = "0.4"
22+
23+
# For parallel result collection
24+
crossbeam-channel = "0.5"
25+
26+
# For error handling
27+
anyhow = "1.0"
28+
29+
# jemalloc for better performance (23% improvement, same as fd uses)
30+
# Note: Disabled on macOS due to jemalloc bug, see https://github.com/sharkdp/fd/issues/498
31+
[target.'cfg(all(not(windows), not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), not(target_os = "openbsd"), not(target_os = "illumos"), not(all(target_env = "musl", target_pointer_width = "32")), not(target_arch = "riscv64")))'.dependencies]
32+
tikv-jemallocator = "0.6"
33+
34+
[dev-dependencies]
35+
tempfile = "3.14"

0 commit comments

Comments
 (0)