ficha 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +95 -63
- data/lib/ficha/version.rb +1 -1
- data/lib/ficha.rb +39 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e0ab263b57722fe59e5b216c33254355114fed0ade17c25b3b8864d5bbc75ea0
|
|
4
|
+
data.tar.gz: 829c0cf34924b04facbcb3c7b72bb352d321f5444ecb5b995adb121189186e33
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dabc9d504f43b6b8e7e1ff95764640dec5b3963dd44b78538a9599bb59f5f035731c65fac1bdffee0d8b62523e15a87ecaf8c7bd5e7d6956b4799570ff5cae60
|
|
7
|
+
data.tar.gz: d2fe651ad51b0e2d1db39318894836ca4a0d6a91f8df2c09e7827dfaac6757a9ca1d386867fd9a9dd740ebe0989f209a9ef335199c8ba9fe59a85b2488dab4f0
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@ All notable changes to `ficha` will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
# 0.3.0 - 2025-12-11
|
|
8
|
+
|
|
9
|
+
### Added: Non-dry-run mode: print file contents by default
|
|
10
|
+
|
|
7
11
|
## [0.2.0] - 2025-12-09
|
|
8
12
|
|
|
9
13
|
### Added
|
data/README.md
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
> **Feature-aware file dumper for Ruby projects**
|
|
4
4
|
> Extract only the files you need — by model, endpoint, feature, or safe subset — without manual grepping.
|
|
5
5
|
|
|
6
|
-

|
|
7
|
-

|
|
6
|
+
[](https://www.gnu.org/licenses/agpl-3.0.html)
|
|
7
|
+
[](https://www.ruby-lang.org/)
|
|
8
|
+
[](https://github.com/it1ro/ficha/actions)
|
|
9
|
+
[](https://rubygems.org/gems/ficha)
|
|
8
10
|
|
|
9
11
|
`ficha` helps you **dump relevant files** from large Ruby/Rails codebases based on **semantic strategies**, not just file extensions.
|
|
10
12
|
Think of it as `grep` + `find` + domain knowledge — for developers who know *what* they need, but not *where* it is.
|
|
@@ -25,7 +27,7 @@ Perfect for:
|
|
|
25
27
|
# Dump all files related to the `User` model
|
|
26
28
|
ficha by-model:User
|
|
27
29
|
|
|
28
|
-
# Dump a "safe" subset (models,
|
|
30
|
+
# Dump a "safe" subset (models, controllers, specs, domain logic)
|
|
29
31
|
ficha full-safe
|
|
30
32
|
|
|
31
33
|
# Preview without writing
|
|
@@ -37,11 +39,14 @@ Output (dry-run):
|
|
|
37
39
|
```
|
|
38
40
|
app/models/user.rb
|
|
39
41
|
app/controllers/users_controller.rb
|
|
40
|
-
app/
|
|
42
|
+
app/domain/user.rb
|
|
41
43
|
spec/models/user_spec.rb
|
|
44
|
+
spec/domain/user_spec.rb
|
|
42
45
|
...
|
|
43
46
|
```
|
|
44
47
|
|
|
48
|
+
> ✅ Automatically **excludes sensitive files** like `master.key`, `.env*`, `credentials.yml.enc`.
|
|
49
|
+
|
|
45
50
|
---
|
|
46
51
|
|
|
47
52
|
## 🧩 Core Concepts
|
|
@@ -49,20 +54,22 @@ spec/models/user_spec.rb
|
|
|
49
54
|
`ficha` works by combining:
|
|
50
55
|
|
|
51
56
|
1. **Strategies** — rules that define *what to include* (e.g. `by-model`, `full-safe`)
|
|
52
|
-
2. **Config** — your project-specific paths, conventions, and overrides (`ficha.yml`)
|
|
53
|
-
3. **
|
|
54
|
-
4. **
|
|
57
|
+
2. **Config** — your project-specific paths, conventions, and overrides (`ficha.yml` or `.ficha.yml`)
|
|
58
|
+
3. **Template engine** — with filters like `underscore`, `pluralize` (via ActiveSupport)
|
|
59
|
+
4. **Engine** — resolves paths, applies filters, excludes sensitive/ignored files
|
|
60
|
+
5. **CLI** — your interface to run queries
|
|
55
61
|
|
|
56
62
|
```mermaid
|
|
57
63
|
graph LR
|
|
58
64
|
A[CLI: ficha by-model:User] --> B(Engine)
|
|
59
65
|
B --> C{Strategy: by-model}
|
|
60
66
|
B --> D[Config: ficha.yml]
|
|
61
|
-
C --> E[
|
|
67
|
+
C --> E[Apply template filters:<br>underscore, pluralize]
|
|
62
68
|
D --> F[Custom paths, excludes]
|
|
63
|
-
E --> G[
|
|
69
|
+
E --> G[Glob & match files]
|
|
64
70
|
F --> G
|
|
65
|
-
G --> H[
|
|
71
|
+
G --> H[Apply global filters]
|
|
72
|
+
H --> I[Output file list]
|
|
66
73
|
```
|
|
67
74
|
|
|
68
75
|
---
|
|
@@ -83,65 +90,57 @@ Then run:
|
|
|
83
90
|
bundle install
|
|
84
91
|
```
|
|
85
92
|
|
|
86
|
-
> 💡 `ficha` is
|
|
93
|
+
> 💡 `ficha` is a **dev-only CLI tool** — zero runtime impact.
|
|
87
94
|
|
|
88
95
|
---
|
|
89
96
|
|
|
90
97
|
## ⚙️ Configuration
|
|
91
98
|
|
|
92
|
-
|
|
99
|
+
`ficha` looks for config in this order:
|
|
100
|
+
|
|
101
|
+
1. `./.ficha.yml`
|
|
102
|
+
2. `./ficha.yml`
|
|
103
|
+
3. `~/.ficha.yml` (global fallback)
|
|
93
104
|
|
|
94
|
-
### Example `
|
|
105
|
+
### Example `ficha.yml`
|
|
95
106
|
|
|
96
107
|
```yaml
|
|
97
|
-
|
|
108
|
+
version: "1"
|
|
109
|
+
|
|
110
|
+
defaults:
|
|
111
|
+
sensitive_names: ["*.env*", "master.key", "credentials.yml.enc"]
|
|
112
|
+
ignored_extensions: [".lock", ".jpg", ".png", ".gif", ".pdf"]
|
|
98
113
|
|
|
99
114
|
strategies:
|
|
100
115
|
by-model:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- "app/
|
|
104
|
-
- "app/
|
|
105
|
-
- "
|
|
106
|
-
- "spec/
|
|
107
|
-
|
|
108
|
-
- "app/models/concerns/*"
|
|
116
|
+
params: [name]
|
|
117
|
+
include_paths:
|
|
118
|
+
- "app/models/{{name | underscore}}.rb"
|
|
119
|
+
- "app/controllers/{{name | pluralize | underscore}}_controller.rb"
|
|
120
|
+
- "app/domain/{{name | underscore}}.rb"
|
|
121
|
+
- "spec/models/{{name | underscore}}_spec.rb"
|
|
122
|
+
- "spec/domain/{{name | underscore}}_spec.rb"
|
|
109
123
|
|
|
110
124
|
full-safe:
|
|
111
|
-
|
|
125
|
+
include_paths:
|
|
112
126
|
- "app/models/**/*.rb"
|
|
113
127
|
- "app/controllers/**/*.rb"
|
|
114
|
-
- "app/
|
|
115
|
-
- "
|
|
128
|
+
- "app/domain/**/*.rb"
|
|
129
|
+
- "app/operations/**/*.rb"
|
|
130
|
+
- "app/services/**/*.rb"
|
|
131
|
+
- "spec/{models,controllers,domain,operations,services}/**/*.rb"
|
|
116
132
|
exclude:
|
|
117
133
|
- "spec/support/**/*"
|
|
118
|
-
|
|
119
|
-
paths:
|
|
120
|
-
root: "." # project root
|
|
121
|
-
output: "/tmp/ficha-out" # (future: where to copy files)
|
|
122
|
-
|
|
123
|
-
excludes:
|
|
124
|
-
- "tmp/**/*"
|
|
125
|
-
- "log/**/*"
|
|
126
|
-
- "vendor/**/*"
|
|
127
134
|
```
|
|
128
135
|
|
|
129
136
|
> ✅ **Philosophy**: Keep logic in config, not code.
|
|
130
|
-
> 🔒
|
|
137
|
+
> 🔒 Supports ERB if *really* needed (but discouraged for reproducibility).
|
|
131
138
|
|
|
132
139
|
---
|
|
133
140
|
|
|
134
|
-
## Global Configuration
|
|
135
|
-
|
|
136
|
-
If you don’t want to add `.ficha.yml` to every project, you can create a **global config** at `~/.ficha.yml`.
|
|
137
|
-
|
|
138
|
-
`ficha` will use it **only when no local `.ficha.yml` or `ficha.yml` is found**.
|
|
141
|
+
## 🌐 Global Configuration
|
|
139
142
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
> 🔒 Sensitive or project-specific paths (like `output`, `excludes`) should still go into local config.
|
|
143
|
-
|
|
144
|
-
Example `~/.ficha.yml`:
|
|
143
|
+
Create `~/.ficha.yml` to define **personal strategies** usable in any Ruby project:
|
|
145
144
|
|
|
146
145
|
```yaml
|
|
147
146
|
version: "1"
|
|
@@ -157,19 +156,41 @@ strategies:
|
|
|
157
156
|
- "app/jobs/{{name | underscore}}.rb"
|
|
158
157
|
```
|
|
159
158
|
|
|
160
|
-
Now
|
|
159
|
+
Now `ficha by-model:User` works **even in projects without local config**.
|
|
160
|
+
|
|
161
|
+
> 🔒 Project-specific paths (output, excludes) should stay in local config.
|
|
161
162
|
|
|
162
163
|
---
|
|
163
164
|
|
|
164
165
|
## 🎯 Built-in Strategies
|
|
165
166
|
|
|
166
|
-
| Strategy
|
|
167
|
-
|
|
168
|
-
| `full-safe`
|
|
169
|
-
| `by-model:X`
|
|
167
|
+
| Strategy | Purpose |
|
|
168
|
+
|----------------|--------|
|
|
169
|
+
| `full-safe` | Dumps core app logic: models, controllers, domain, operations, services, specs |
|
|
170
|
+
| `by-model:X` | Dumps everything related to model `X` (with inflection support) |
|
|
170
171
|
| *(more coming)* | — |
|
|
171
172
|
|
|
172
|
-
You can **extend
|
|
173
|
+
You can **extend or override** strategies in your config — no gem forking needed.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 🧩 Composition Support
|
|
178
|
+
|
|
179
|
+
Combine strategies using `compose`:
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
strategies:
|
|
183
|
+
user-plus-session:
|
|
184
|
+
compose:
|
|
185
|
+
- by-model:User
|
|
186
|
+
- by-model:Session
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Then run:
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
ficha user-plus-session --dry-run
|
|
193
|
+
```
|
|
173
194
|
|
|
174
195
|
---
|
|
175
196
|
|
|
@@ -182,15 +203,23 @@ Examples:
|
|
|
182
203
|
ficha # runs 'full-safe'
|
|
183
204
|
ficha by-model:User # model-aware dump
|
|
184
205
|
ficha full-safe --dry-run # preview only
|
|
206
|
+
ficha by-model:User --exclude spec # exclude specs
|
|
185
207
|
|
|
186
208
|
Options:
|
|
187
209
|
--help Show help
|
|
188
210
|
--dry-run Print matched files (default)
|
|
189
|
-
--exclude GLOB Exclude
|
|
211
|
+
--exclude GLOB Exclude paths (repeatable)
|
|
190
212
|
```
|
|
191
213
|
|
|
192
|
-
> ⚠️ **
|
|
193
|
-
|
|
214
|
+
> ⚠️ **File copying (non-dry-run)** is coming soon — you’ll be able to dump to dir/zip/tar!
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 🛡️ Security & Privacy
|
|
219
|
+
|
|
220
|
+
- **Never includes** sensitive files (`master.key`, `.env`, etc.)
|
|
221
|
+
- **Declarative config** reduces risk of accidental data exposure
|
|
222
|
+
- **AGPL-3.0 licensed** — ensures freedom and transparency
|
|
194
223
|
|
|
195
224
|
---
|
|
196
225
|
|
|
@@ -207,9 +236,9 @@ Tests use real fixtures in `test/fixtures/rails_app/` — easy to extend.
|
|
|
207
236
|
|
|
208
237
|
## 📜 License
|
|
209
238
|
|
|
210
|
-
AGPL-3.0 — because **privacy, self-hosting, and user freedom matter**.
|
|
239
|
+
[AGPL-3.0](./LICENSE) — because **privacy, self-hosting, and user freedom matter**.
|
|
211
240
|
|
|
212
|
-
You’re free to use `ficha` in any project
|
|
241
|
+
> You’re free to use `ficha` in any project. If you modify and redistribute it (e.g. as a hosted service), you must share the source.
|
|
213
242
|
|
|
214
243
|
---
|
|
215
244
|
|
|
@@ -217,16 +246,19 @@ You’re free to use `ficha` in any project, but if you modify and redistribute
|
|
|
217
246
|
|
|
218
247
|
PRs welcome! Especially:
|
|
219
248
|
|
|
220
|
-
- New strategies
|
|
221
|
-
- Non-dry-run output
|
|
222
|
-
-
|
|
223
|
-
-
|
|
249
|
+
- 🧠 New strategies (`by-service`, `by-endpoint`, etc.)
|
|
250
|
+
- 💾 Non-dry-run output (dir, zip, tar)
|
|
251
|
+
- 🚀 Performance & memory optimizations
|
|
252
|
+
- 🧪 Better Rails 7+/Ruby 3.4+ support
|
|
224
253
|
|
|
225
254
|
Please:
|
|
226
255
|
|
|
227
|
-
- Write tests
|
|
228
|
-
- Keep config declarative
|
|
229
|
-
- Respect the AGPL spirit
|
|
256
|
+
- ✅ Write tests
|
|
257
|
+
- 📜 Keep config declarative
|
|
258
|
+
- 🔐 Respect the AGPL spirit
|
|
259
|
+
|
|
260
|
+
> 🐞 Found a bug? Use the [issue template](./.github/issue_template.md).
|
|
261
|
+
> 💡 Have an idea? Open a [feature request](./.github/issue_template.md).
|
|
230
262
|
|
|
231
263
|
---
|
|
232
264
|
|
data/lib/ficha/version.rb
CHANGED
data/lib/ficha.rb
CHANGED
|
@@ -6,6 +6,8 @@ require_relative "ficha/template"
|
|
|
6
6
|
require_relative "ficha/engine"
|
|
7
7
|
require "optparse"
|
|
8
8
|
|
|
9
|
+
require "pry"
|
|
10
|
+
|
|
9
11
|
module Ficha
|
|
10
12
|
class CLI
|
|
11
13
|
def self.start(argv)
|
|
@@ -31,6 +33,15 @@ module Ficha
|
|
|
31
33
|
exit 1
|
|
32
34
|
end
|
|
33
35
|
|
|
36
|
+
def print_files(files, show_line_numbers: true)
|
|
37
|
+
files.each do |path|
|
|
38
|
+
next unless File.file?(path) && readable_text_file?(path)
|
|
39
|
+
|
|
40
|
+
puts "\n=== #{path} ==="
|
|
41
|
+
print_file_content(path, show_line_numbers: show_line_numbers)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
34
45
|
private
|
|
35
46
|
|
|
36
47
|
def handle_help!
|
|
@@ -46,11 +57,31 @@ module Ficha
|
|
|
46
57
|
if @options[:dry_run]
|
|
47
58
|
files.each { |f| puts f }
|
|
48
59
|
else
|
|
49
|
-
|
|
50
|
-
exit 1
|
|
60
|
+
print_files(files, show_line_numbers: false)
|
|
51
61
|
end
|
|
52
62
|
end
|
|
53
63
|
|
|
64
|
+
def print_file_content(path, show_line_numbers:)
|
|
65
|
+
if show_line_numbers
|
|
66
|
+
File.readlines(path).each_with_index(1) do |line, lineno|
|
|
67
|
+
printf "%<lineno>4d | %<content>s\n", lineno: lineno, content: line.chomp
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
puts File.read(path)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def readable_text_file?(path)
|
|
75
|
+
return false if File.size(path) > 1_000_000
|
|
76
|
+
|
|
77
|
+
File.open(path, "rb") do |f|
|
|
78
|
+
chunk = f.read(1024)
|
|
79
|
+
!chunk&.include?("\x00")
|
|
80
|
+
end
|
|
81
|
+
rescue StandardError
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
|
|
54
85
|
def execute_engine
|
|
55
86
|
config = Config.load
|
|
56
87
|
engine = Engine.new(
|
|
@@ -86,10 +117,13 @@ module Ficha
|
|
|
86
117
|
Usage:
|
|
87
118
|
ficha [STRATEGY:PARAMS...] [options]
|
|
88
119
|
|
|
120
|
+
By default, prints contents of matched files.
|
|
121
|
+
Use --dry-run to list paths only.
|
|
122
|
+
|
|
89
123
|
Examples:
|
|
90
|
-
ficha # full-safe
|
|
91
|
-
ficha by-model:User #
|
|
92
|
-
ficha full-safe --dry-run
|
|
124
|
+
ficha # print full-safe files
|
|
125
|
+
ficha by-model:User # print User-related files
|
|
126
|
+
ficha full-safe --dry-run # only list paths
|
|
93
127
|
|
|
94
128
|
Options:
|
|
95
129
|
HELP
|