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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 496e19f7e52e61e225538dea7b4c30c8381d8687b226355ba5912847c08b7a12
4
- data.tar.gz: af98dadc7f8a44cb987cda56a07f07d28fa9082d486dd3092eead7715112cbc3
3
+ metadata.gz: e0ab263b57722fe59e5b216c33254355114fed0ade17c25b3b8864d5bbc75ea0
4
+ data.tar.gz: 829c0cf34924b04facbcb3c7b72bb352d321f5444ecb5b995adb121189186e33
5
5
  SHA512:
6
- metadata.gz: 959e3c3e460f16cc0f507c23c23ab5817320e3524066bb7fb87d9ba1113bc26ba4c0bfb484f43e6cfaae4794eb32167096b1e4c991a94ad10cb67d2f24d915a0
7
- data.tar.gz: e717d46c80e33f9990c7fad060764a05adaed236e3996d294dcde16dbba1c3f7ef71c35269920ffa5342ffa15cbeb88eafc076a75c5e93c0951c36b9b7bdb083
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
- ![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)
7
- ![Ruby](https://img.shields.io/badge/ruby-3.0%2B-red)
6
+ [![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)](https://www.gnu.org/licenses/agpl-3.0.html)
7
+ [![Ruby](https://img.shields.io/badge/ruby-3.0%2B-red)](https://www.ruby-lang.org/)
8
+ [![CI](https://github.com/it1ro/ficha/actions/workflows/main.yml/badge.svg)](https://github.com/it1ro/ficha/actions)
9
+ [![Gem Version](https://badge.fury.io/rb/ficha.svg)](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, serializers, controllers, specs)
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/serializers/user_serializer.rb
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. **Engine** — the resolver that applies strategies to your codebase
54
- 4. **CLI** — your interface to run queries
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[Match model, controller, serializer...]
67
+ C --> E[Apply template filters:<br>underscore, pluralize]
62
68
  D --> F[Custom paths, excludes]
63
- E --> G[File list]
69
+ E --> G[Glob & match files]
64
70
  F --> G
65
- G --> H[Output or copy]
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 designed as a **dev-only CLI tool** — it doesn’t affect your runtime.
93
+ > 💡 `ficha` is a **dev-only CLI tool** — zero runtime impact.
87
94
 
88
95
  ---
89
96
 
90
97
  ## ⚙️ Configuration
91
98
 
92
- By default, `ficha` looks for `config/ficha.yml` (in Rails) or `.ficha.yml` (in any project).
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 `config/ficha.yml`
105
+ ### Example `ficha.yml`
95
106
 
96
107
  ```yaml
97
- # ficha.yml — declarative, extensible, no Ruby code!
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
- include:
102
- - "app/models/{{name}}.rb"
103
- - "app/controllers/{{name.pluralize}}_controller.rb"
104
- - "app/serializers/{{name}}_serializer.rb"
105
- - "spec/models/{{name}}_spec.rb"
106
- - "spec/requests/{{name.pluralize}}_spec.rb"
107
- exclude:
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
- include:
125
+ include_paths:
112
126
  - "app/models/**/*.rb"
113
127
  - "app/controllers/**/*.rb"
114
- - "app/serializers/**/*.rb"
115
- - "spec/{models,controllers,serializers}/**/*.rb"
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
- > 🔒 Config supports ERB if you *really* need dynamic values (but avoid it for reproducibility).
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
- This is useful for defining your personal strategies (e.g. `by-model`, `by-job`) once and reusing them everywhere.
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 you can run ficha by-model:User in any Ruby project — even without a local config!
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 | Purpose |
167
- |---------------|--------|
168
- | `full-safe` | Dumps core app code: models, controllers, serializers, related specs |
169
- | `by-model:X` | Dumps everything related to model `X` (convention-based) |
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 strategies** in your `ficha.yml` — no need to fork the gem.
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 additional paths (can be used multiple times)
211
+ --exclude GLOB Exclude paths (repeatable)
190
212
  ```
191
213
 
192
- > ⚠️ **Non-dry-run mode** (actual file copying) is **not implemented yet** coming soon!
193
- > You’ll be able to dump to a directory, zip, or tar.
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, but if you modify and redistribute it (e.g. as a hosted service), you must share the source.
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 formats (dir, zip, tar)
222
- - Better Rails/7+ support
223
- - Performance optimizations
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ficha
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
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
- warn "Non-dry-run mode not implemented yet"
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 dump
91
- ficha by-model:User # dump User-related files
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ficha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilmir Karimov