specguard-ruby 0.3.15 → 0.3.17
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/README.md +6 -2
- data/lib/specguard/rspec/cli.rb +30 -18
- data/lib/specguard/rspec/file_selector.rb +54 -27
- data/lib/specguard/rspec.rb +5 -4
- data/lib/specguard/version.rb +1 -1
- 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: b2ae5e6b5a9750e2317709c9c5b4582d7237385e35a627cf03319087de12ed1f
|
|
4
|
+
data.tar.gz: 67733aa5aa6735a51e1e68097892da247b0c023e3a3bf09533e7f21e5abde790
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8aa45d1483899e69fbe71d5f819cc404db8086265fbda3566ab68e550544c9439d19014fb3b440b14a3065a339601015ff542e8f57da16a829685d9858403e0e
|
|
7
|
+
data.tar.gz: 4d0e70b0efe28ee9ae91362d29b4502a7c6ae53073b9857fc4ec295eed1cf588cfb9d5a6c507005944f2319644ec84821123a03a92bc9604a6f12d6bade8fb14
|
data/README.md
CHANGED
|
@@ -60,7 +60,7 @@ directory names, so `spec/vendor_helpers/` is still yours. A bundled Rails tree
|
|
|
60
60
|
(`bundle install --deployment` → `vendor/bundle/`) ships thousands of third-party gem
|
|
61
61
|
specs; the walk neither reports on them nor fails over their annotations, and the
|
|
62
62
|
zero-annotation coverage note counts only files you wrote — the same material
|
|
63
|
-
`--changed`
|
|
63
|
+
`--changed` fences out with the same directory list. When the fence removed files, the
|
|
64
64
|
`checked N spec files` line says how many (`skipping M in dependency or build
|
|
65
65
|
directories`); a file named explicitly on the command line is always checked.
|
|
66
66
|
|
|
@@ -76,7 +76,11 @@ paths (scratch directories, vendored code, build output) never enter the
|
|
|
76
76
|
selection — and untracked files obey the same scoping as diffed ones, so an
|
|
77
77
|
untracked spec outside the current directory is counted as outside, not
|
|
78
78
|
checked. When the untracked leg contributed, the `checked N spec files changed
|
|
79
|
-
since <base>` line says `including M untracked`.
|
|
79
|
+
since <base>` line says `including M untracked`. `--changed` applies the same
|
|
80
|
+
dependency/build directory fence to everything it selects: a tracked file is
|
|
81
|
+
never subject to `.gitignore`, so the diff leg needs the fence regardless —
|
|
82
|
+
and when the fence removed files, the selection line says how many
|
|
83
|
+
(`skipping M in dependency or build directories`).
|
|
80
84
|
In a **shallow** checkout — the default depth-1 `git clone`
|
|
81
85
|
behind `actions/checkout@v4` — the merge base with the default branch is not
|
|
82
86
|
in the clone's history, so the derived base is HEAD itself and the selection
|
data/lib/specguard/rspec/cli.rb
CHANGED
|
@@ -263,15 +263,15 @@ module SpecGuard
|
|
|
263
263
|
# "the machine reads the provenance the human does" a property of the
|
|
264
264
|
# code rather than a promise two copies could drift apart on.
|
|
265
265
|
#
|
|
266
|
-
# The
|
|
267
|
-
#
|
|
268
|
-
# `
|
|
266
|
+
# The fence count names its fence: both selection modes apply
|
|
267
|
+
# `FileSelector`'s `SKIPPED_DIRECTORIES` (the default walk and
|
|
268
|
+
# `--changed` alike), and a fence that actually removed files says
|
|
269
269
|
# how many — the narrowing must never be silent. The clause is
|
|
270
270
|
# count-gated exactly like the untracked one, so a run whose fence
|
|
271
271
|
# removed nothing prints byte-identically to before the fence existed.
|
|
272
272
|
def selection_line(selection)
|
|
273
273
|
untracked = selection.mode == :changed ? selection.stats&.untracked.to_i : 0
|
|
274
|
-
skipped = selection.
|
|
274
|
+
skipped = selection.skipped.to_i
|
|
275
275
|
"specguard-lint: checked #{selection.count} spec file#{'s' unless selection.count == 1}" \
|
|
276
276
|
"#{" changed since #{selection.base}" if selection.mode == :changed}" \
|
|
277
277
|
"#{" under #{Dir.pwd}" if selection.mode == :all}" \
|
|
@@ -320,28 +320,40 @@ module SpecGuard
|
|
|
320
320
|
"#{stats.changed} file#{'s' unless stats.changed == 1} changed against #{base}, " \
|
|
321
321
|
"none matching *_spec.rb or *_test.rb"
|
|
322
322
|
else
|
|
323
|
-
changed_excluded_reason(stats, base)
|
|
323
|
+
changed_excluded_reason(stats, base, selection.skipped)
|
|
324
324
|
end
|
|
325
325
|
end
|
|
326
326
|
|
|
327
|
-
# `outside_root
|
|
328
|
-
# branches of the same partition
|
|
329
|
-
#
|
|
327
|
+
# `outside_root`, `unreadable` and the directory-fence count are
|
|
328
|
+
# independent counters over disjoint branches of the same partition
|
|
329
|
+
# (`file_selector.rb`), so any two of them can be positive at once.
|
|
330
|
+
# Naming only the first one found is the failure the
|
|
330
331
|
# comment above forbids: the reader does the arithmetic, sees that
|
|
331
332
|
# `spec_matches - outside_root` files are unaccounted for, and concludes
|
|
332
333
|
# they were checked. They were not — the selection is empty. So the
|
|
333
|
-
# clauses are additive, and a selection emptied by
|
|
334
|
-
|
|
334
|
+
# clauses are additive, and a selection emptied by several causes says
|
|
335
|
+
# so.
|
|
336
|
+
def changed_excluded_reason(stats, base, skipped)
|
|
335
337
|
matched = "#{stats.spec_matches} changed spec file#{'s' unless stats.spec_matches == 1} against #{base}"
|
|
336
338
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
339
|
+
if stats.outside_root.positive?
|
|
340
|
+
reason = "#{matched}, but #{stats.outside_root} #{stats.outside_root == 1 ? 'is' : 'are'} " \
|
|
341
|
+
"outside #{Dir.pwd} (--changed selects only files under the current directory)"
|
|
342
|
+
reason += " and #{stats.unreadable} could not be read" if stats.unreadable.positive?
|
|
343
|
+
reason += " and #{skipped} in dependency or build directories" if skipped.positive?
|
|
344
|
+
reason
|
|
345
|
+
elsif stats.unreadable.positive? && skipped.positive?
|
|
346
|
+
"#{matched} could not be read and #{skipped} in dependency or build directories"
|
|
347
|
+
elsif skipped.positive?
|
|
348
|
+
# Every matching file the diff produced was fenced: the shape
|
|
349
|
+
# {all_fenced_reason} uses, in this mode's vocabulary.
|
|
350
|
+
"#{matched}, all in dependency or build directories"
|
|
351
|
+
else
|
|
352
|
+
# Nothing outside the root and nothing fenced: `unreadable` is then
|
|
353
|
+
# the only filter left that can have emptied the selection, so it
|
|
354
|
+
# needs no count of its own.
|
|
355
|
+
"#{matched} could not be read"
|
|
356
|
+
end
|
|
345
357
|
end
|
|
346
358
|
|
|
347
359
|
# The FAIL block, in the shape `bin/validate-intent --source` emits: two
|
|
@@ -16,13 +16,16 @@ module SpecGuard
|
|
|
16
16
|
# diff names paths, not directories, and a changed test file is a test
|
|
17
17
|
# file wherever the author put it.
|
|
18
18
|
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
19
|
+
# Both modes carry a fixed directory fence ({SKIPPED_DIRECTORIES}):
|
|
20
|
+
# dependency, build-output, scratch and VCS directories are never
|
|
21
|
+
# selected, so a bundled tree's `vendor/bundle/` gem specs are neither
|
|
22
|
+
# reported on nor failed over — third-party code the user did not write.
|
|
23
|
+
# The walk, which must keep working outside a repository, carries the
|
|
24
|
+
# boundary as a name list; `--changed` applies the same name list to the
|
|
25
|
+
# paths git hands back, because a tracked file is never subject to
|
|
26
|
+
# `.gitignore` and the diff leg therefore has no fence of its own.
|
|
27
|
+
# `--exclude-standard` additionally removes ignored *untracked* paths —
|
|
28
|
+
# it stacks with the name list in `--changed` and is no substitute for it.
|
|
26
29
|
#
|
|
27
30
|
# == Why `--changed` is not `git diff --name-only`
|
|
28
31
|
#
|
|
@@ -111,8 +114,12 @@ module SpecGuard
|
|
|
111
114
|
# the toplevel so its repo-root-relative output flows through the same
|
|
112
115
|
# scoping as the diff's (from a subdirectory `ls-files` emits
|
|
113
116
|
# cwd-relative paths, which would defeat it). `--exclude-standard` is the
|
|
114
|
-
# boundary: `.gitignore`d paths — scratch directories,
|
|
115
|
-
# output — never enter
|
|
117
|
+
# untracked leg's boundary: `.gitignore`d paths — scratch directories,
|
|
118
|
+
# vendored code, build output — never enter through it. It is a second
|
|
119
|
+
# removal, not the selection's only fence: ignored *tracked* paths still
|
|
120
|
+
# arrive on the diff leg (git never applies ignore rules to tracked
|
|
121
|
+
# files), which is why the {SKIPPED_DIRECTORIES} fence applies to the
|
|
122
|
+
# union as a whole. The two legs are disjoint by
|
|
116
123
|
# construction (an untracked path is never a diff path), so the union
|
|
117
124
|
# cannot double-count; {Stats.untracked} says how many of the selected
|
|
118
125
|
# files arrived via the untracked leg, and the empty-reason ladder's
|
|
@@ -149,11 +156,14 @@ module SpecGuard
|
|
|
149
156
|
# * `tmp` — Rails' scratch directory (caches, pids, sockets).
|
|
150
157
|
# * `log` — Rails' log directory.
|
|
151
158
|
#
|
|
152
|
-
# `--changed`
|
|
153
|
-
# `.gitignore
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
#
|
|
159
|
+
# `--changed` applies this same list itself: a tracked file is never
|
|
160
|
+
# subject to `.gitignore`, so `--exclude-standard` — which keeps
|
|
161
|
+
# `.gitignore`d paths (scratch directories, vendored code, build
|
|
162
|
+
# output) out of the untracked leg alone — cannot fence the diff leg
|
|
163
|
+
# and is an additional removal, never a substitute. The walk has no
|
|
164
|
+
# git to ask, because it must keep working outside a repository exactly
|
|
165
|
+
# where `--changed` correctly refuses, so it carries the boundary as a
|
|
166
|
+
# name list too. The list
|
|
157
167
|
# is matched against whole directory SEGMENTS of the root-relative path
|
|
158
168
|
# (see {skipped_directory?}), never as a substring — `spec/vendor_helpers/`
|
|
159
169
|
# is project code — and never against the absolute path.
|
|
@@ -193,16 +203,18 @@ module SpecGuard
|
|
|
193
203
|
|
|
194
204
|
# What a selection produced, plus enough context to report it honestly.
|
|
195
205
|
#
|
|
196
|
-
# `skipped` is the fence count
|
|
197
|
-
#
|
|
206
|
+
# `skipped` is the {SKIPPED_DIRECTORIES} fence count, carried by BOTH
|
|
207
|
+
# selection modes — `:all`'s walk and `:changed`'s union alike; an
|
|
208
|
+
# `:explicit` selection bypasses the fence and always reads 0 —
|
|
209
|
+
# defaulted to 0 so every construction site is untouched. It
|
|
198
210
|
# deliberately rides `Selection` rather than a new `Stats` member:
|
|
199
211
|
# `Stats` is documented as the `--changed` empty-reason ladder ("why an
|
|
200
|
-
# empty `--changed` selection is empty") and the fence is
|
|
201
|
-
#
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
#
|
|
212
|
+
# empty `--changed` selection is empty") and the fence is not an
|
|
213
|
+
# emptiness explanation — it is report context for a selection that may
|
|
214
|
+
# be perfectly full. `Selection` is what this file already uses to
|
|
215
|
+
# carry per-mode context (`base`, `note`, `stats` are all
|
|
216
|
+
# `--changed`-only and defaulted the same way), so the count follows
|
|
217
|
+
# that precedent instead of widening `Stats`'s contract.
|
|
206
218
|
Selection = Data.define(:files, :mode, :base, :note, :stats, :skipped) do
|
|
207
219
|
def initialize(files:, mode:, base: nil, note: nil, stats: nil, skipped: 0)
|
|
208
220
|
super
|
|
@@ -276,20 +288,23 @@ module SpecGuard
|
|
|
276
288
|
# consult it (a failed diff, a thin base note).
|
|
277
289
|
is_shallow = shallow_probe(root)
|
|
278
290
|
|
|
279
|
-
files, stats = changed_files(resolved, root, is_shallow)
|
|
291
|
+
files, stats, skipped = changed_files(resolved, root, is_shallow)
|
|
280
292
|
|
|
281
293
|
Selection.new(files: files, mode: :changed, base: resolved,
|
|
282
|
-
note: base_note(resolved, base_kind, root, is_shallow), stats: stats
|
|
294
|
+
note: base_note(resolved, base_kind, root, is_shallow), stats: stats,
|
|
295
|
+
skipped: skipped)
|
|
283
296
|
end
|
|
284
297
|
|
|
285
298
|
# Resolves git's repo-root-relative output into paths relative to `root`,
|
|
286
|
-
# dropping (and counting) everything the
|
|
299
|
+
# dropping (and counting) everything the scoping rules and the
|
|
300
|
+
# {SKIPPED_DIRECTORIES} fence exclude. The
|
|
287
301
|
# name set is the union of the diff leg and the untracked leg; each name
|
|
288
302
|
# is tagged with its leg so {Stats.untracked} can attribute the selected
|
|
289
303
|
# files the diff never saw. The legs are disjoint by construction (an
|
|
290
304
|
# untracked path is never a diff path), so the plain union cannot
|
|
291
305
|
# double-count and needs no dedup.
|
|
292
|
-
# @return [[Array<String>, Stats]]
|
|
306
|
+
# @return [[Array<String>, Stats, Integer]] the selected files, the
|
|
307
|
+
# filter stats, and how many files the directory fence removed.
|
|
293
308
|
def changed_files(base, root, is_shallow)
|
|
294
309
|
names = diff_names(base, root, is_shallow).map { |name| [name, false] }
|
|
295
310
|
|
|
@@ -307,6 +322,7 @@ module SpecGuard
|
|
|
307
322
|
outside = 0
|
|
308
323
|
unreadable = 0
|
|
309
324
|
untracked = 0
|
|
325
|
+
skipped = 0
|
|
310
326
|
specs.each do |(name, was_untracked)|
|
|
311
327
|
absolute = prefix + name
|
|
312
328
|
relative = strip_prefix(absolute, root_prefix)
|
|
@@ -314,6 +330,16 @@ module SpecGuard
|
|
|
314
330
|
outside += 1
|
|
315
331
|
elsif !File.file?(absolute)
|
|
316
332
|
unreadable += 1
|
|
333
|
+
elsif skipped_directory?(relative)
|
|
334
|
+
# The same {SKIPPED_DIRECTORIES} fence {select_all} applies,
|
|
335
|
+
# decided on the root-relative path at the same grain. It sits
|
|
336
|
+
# after the scoping arms so it counts a different exclusion and
|
|
337
|
+
# never perturbs `outside_root`/`unreadable`; because the union
|
|
338
|
+
# is already materialized here, one placement covers BOTH legs —
|
|
339
|
+
# the diff leg (where `.gitignore` cannot act, git never applies
|
|
340
|
+
# ignore rules to tracked files) and the untracked leg on a
|
|
341
|
+
# repository that does not ignore its vendored tree.
|
|
342
|
+
skipped += 1
|
|
317
343
|
else
|
|
318
344
|
files << relative
|
|
319
345
|
untracked += 1 if was_untracked
|
|
@@ -322,7 +348,8 @@ module SpecGuard
|
|
|
322
348
|
|
|
323
349
|
[files.sort,
|
|
324
350
|
Stats.new(changed: names.length, spec_matches: specs.length,
|
|
325
|
-
outside_root: outside, unreadable: unreadable, untracked: untracked)
|
|
351
|
+
outside_root: outside, unreadable: unreadable, untracked: untracked),
|
|
352
|
+
skipped]
|
|
326
353
|
end
|
|
327
354
|
|
|
328
355
|
# `--diff-filter=d` drops deleted paths — `git diff --name-only` lists
|
data/lib/specguard/rspec.rb
CHANGED
|
@@ -33,10 +33,11 @@ module SpecGuard
|
|
|
33
33
|
# without re-deriving the distinction from an error message.
|
|
34
34
|
class UsageError < Error; end
|
|
35
35
|
|
|
36
|
-
# The
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# as a
|
|
36
|
+
# The Go validator backend could not produce a verdict — the binary named
|
|
37
|
+
# by `SPECGUARD_VALIDATE_INTENT`, or the default binary the backend
|
|
38
|
+
# resolves when that is blank, is missing, will not execute, exited with a
|
|
39
|
+
# code that is not a verdict, or emitted something this cannot read as a
|
|
40
|
+
# report.
|
|
40
41
|
#
|
|
41
42
|
# Typed separately from {UsageError} because the two are different
|
|
42
43
|
# accusations ("you invoked me wrongly" vs "the tool I was told to use is
|
data/lib/specguard/version.rb
CHANGED