Class: Everywhere::Ignore
- Inherits:
-
Object
- Object
- Everywhere::Ignore
- Defined in:
- lib/everywhere/ignore.rb
Overview
Shared source-exclusion rules: the built-in DEFAULTS, plus .everywhereignore
(dockerignore style) appended when the app has one. ONE source of truth so the
build receipt's source checksum (Receipt) and the Platform snapshot
(every platform build, later) describe exactly the same set of files — a
checksum that didn't match what actually ships would be worse than none.
Pattern semantics are a pragmatic subset of .dockerignore/.gitignore:
dist → a path segment named "dist", anywhere
vendor/bundle → that exact path (and everything under it)
*.log → glob against the full path and the basename
!keep/this.log → NEGATION: re-include a file an earlier pattern excluded
Rules are evaluated top to bottom and the LAST one that matches a path wins
(dockerignore semantics), so ordering matters: put ! re-includes after the
broad exclude they carve out of — and the app's file, coming last, can
re-include anything DEFAULTS excluded.
Constant Summary collapse
- FILE =
".everywhereignore"- FLAGS =
File::FNM_PATHNAME | File::FNM_DOTMATCH
- DEFAULTS =
Build products, caches, VCS, local state, and secrets. Excluding
.env*and the key/cert family keeps signing material out of both the checksum and any future snapshot. %w[ dist tmp log node_modules .git storage .bundle vendor/bundle coverage public/assets public/packs .DS_Store .env* *.log *.key *.pem *.crt *.p12 *.mobileprovision ].freeze
Instance Attribute Summary collapse
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
Class Method Summary collapse
-
.for(root) ⇒ Object
The app's file is layered ON TOP of DEFAULTS rather than replacing them: a project that adds one line to skip a fixture dir must not thereby start shipping .env and *.p12.
-
.parse(text) ⇒ Object
→ [{ negated:, pattern: }, ...] in file order.
Instance Method Summary collapse
-
#files(root) ⇒ Object
Every non-ignored regular file under root, as sorted root-relative paths.
-
#ignored?(rel) ⇒ Boolean
Last matching rule wins; a negated match re-includes.
-
#initialize(rules) ⇒ Ignore
constructor
A new instance of Ignore.
Constructor Details
#initialize(rules) ⇒ Ignore
Returns a new instance of Ignore.
61 62 63 |
# File 'lib/everywhere/ignore.rb', line 61 def initialize(rules) @rules = rules end |
Instance Attribute Details
#rules ⇒ Object (readonly)
Returns the value of attribute rules.
59 60 61 |
# File 'lib/everywhere/ignore.rb', line 59 def rules @rules end |
Class Method Details
.for(root) ⇒ Object
The app's file is layered ON TOP of DEFAULTS rather than replacing them:
a project that adds one line to skip a fixture dir must not thereby start
shipping .env and *.p12. Last match wins, so a user who really wants a
defaulted-out file back can still ! it in.
37 38 39 40 41 42 43 44 |
# File 'lib/everywhere/ignore.rb', line 37 def self.for(root) path = File.join(root, FILE) return new(parse(DEFAULTS.join("\n"))) unless File.exist?(path) # UTF-8 explicitly (and scrubbed): under LANG=C the bytes come back # US-ASCII and a non-ASCII path pattern makes the matching raise. new(parse(DEFAULTS.join("\n")) + parse(File.read(path, encoding: "UTF-8").scrub)) end |
.parse(text) ⇒ Object
→ [{ negated:, pattern: }, ...] in file order. Blank lines and whole-line
# comments are dropped; a leading ! marks a re-include.
48 49 50 51 52 53 54 55 56 57 |
# File 'lib/everywhere/ignore.rb', line 48 def self.parse(text) text.lines.filter_map do |raw| line = raw.chomp next if line.strip.empty? || line.lstrip.start_with?("#") negated = line.start_with?("!") pattern = (negated ? line[1..] : line).strip.sub(%r{\A/}, "").chomp("/") { negated: negated, pattern: pattern } unless pattern.empty? end end |
Instance Method Details
#files(root) ⇒ Object
Every non-ignored regular file under root, as sorted root-relative paths.
66 67 68 69 70 71 |
# File 'lib/everywhere/ignore.rb', line 66 def files(root) Dir.glob("**/*", File::FNM_DOTMATCH, base: root) .reject { |rel| ignored?(rel) } .select { |rel| File.file?(File.join(root, rel)) } .sort end |
#ignored?(rel) ⇒ Boolean
Last matching rule wins; a negated match re-includes. Default: kept.
74 75 76 77 78 79 80 81 |
# File 'lib/everywhere/ignore.rb', line 74 def ignored?(rel) base = rel.split("/").last return true if [".", ".."].include?(base) @rules.reduce(false) do |ignored, rule| match?(rule[:pattern], rel, base) ? !rule[:negated] : ignored end end |