Add filter command, expand Ball public API, and unpack -O#6
Open
gillisd wants to merge 21 commits into
Open
Conversation
- remove_entry - count - files
- env.sh off.sh on.sh codeball.txt ball.tar.gz
tar2ball.rb and tarscript.rb were scratch experiments (left-in binding.irb, undeclared Ronin::Support). They are not required by any code and were being packaged into the gem. Delete them.
warning was listed after zeitwerk, tripping Gemspec/OrderedDependencies. Reorder alphabetically. Also gitignore docs/superpowers/ (local planning artifacts) and exclude docs/**/* from RuboCop so rubocop-md does not lint planning documents.
filter decided FILE-vs-stdin from stdin.tty?, so the documented 'filter PATTERN FILE' form silently failed in any non-interactive context (pipes, scripts, CI): the file was swallowed as a pattern and empty stdin was read. Now split_source treats the trailing arg as the ball file when it names a real file, else reads stdin, and the ball is read via File.read/stdin.read (no Kernel#open). Add integration coverage for file/stdin, glob semantics, -v, empty input, and a nonexistent trailing arg. Also clears the AbcSize/MethodLength/Security/Open offenses.
The -O option introduced an open-based read (Security/Open) and pushed run over AbcSize. Match filter's approach: read via File.read/stdin.read (no Kernel#open) with an ENOENT guard, and extract report_warnings/dump_to_stdout/extract_to_disk. Emit entry.contents for -O. Add integration tests for the -O dump-to-stdout path and the nonexistent-file error.
A DRY refactor dropped the body check from valid?, so an entry with a matching header and footer but no body was both valid? and truncated? (contradictory) -- reachable via Entry#name=. Restore the body guard to match master's behavior. Empty files are unaffected (they carry a non-nil empty Body).
dump_to_stdout used puts, which appends a newline to content lacking a trailing one -- breaking the advertised tar -Ox parity and corrupting binary output. Use print for a raw byte copy, and assert exact output in the spec. Also fix an Analagous->Analogous typo in the option help.
Owner
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
split_source consumed a lone argument as the ball file whenever it named an existing file, leaving zero patterns so every entry was silently dropped; and it treated an unreadable file as the source, raising an uncaught Errno::EACCES. Only take the trailing arg as the file when a preceding pattern exists and the file is readable; otherwise treat it as a pattern and read stdin. Add regression specs for both.
These readers were public, exposing the live internal arrays so callers could push entries/warnings directly and bypass add_entry's warning bookkeeping. Restore them to private (as on master); nothing reads them externally. Add a spec locking the encapsulation.
The class comment claimed Ball does not touch the filesystem, but the load_file factory reads from disk. Reword to say an instance does no I/O while the load_file factory reads the source file.
name= had no callers and set header+footer without a body, yielding an entry that was both invalid? and truncated? -- a third construction path that violated the documented Header -> Body -> Footer state machine. Delete it; entries are built via the Stream and Entry.from_file paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
codeball filtersubcommand plus supportingBallpublic-APIadditions and an
unpack -O(dump-to-stdout) option, and brings thebranch to a clean, fully-tested, mergeable state.
Features
codeball filter PATTERNS... [FILE]— keep or drop entries in a ball byshell-style glob (
File::FNM_PATHNAME | FNM_EXTGLOB, so*stops at/,**/recurses,{rb,py}brace-expands).-v/--inversekeepsnon-matching entries. Reads the ball from a FILE argument or stdin.
unpack -O— write extracted contents to stdout instead of files(raw bytes, analogous to
tar -Ox).Ball/EntryAPI (remove_entry,each_entry/each_text_entry,serialize, etc.) underpinning the above.Notable fixes made while getting this merge-ready
stdin.tty?,so the documented
filter PATTERN FILEform silently failed in anynon-interactive context (pipes, scripts, CI) — the file was swallowed as a
pattern and empty stdin was read. Now the trailing arg is treated as the ball
file when it names a real file, else stdin is read. Input is read without
Kernel#open(noSecurity/Open).Entry#valid?regression: a DRY refactor had dropped thebodycheck, soan entry with a matching header+footer but no body was both
valid?andtruncated?. Restored the body guard.unpack -Ofidelity: switchedputs→printso raw bytes are emittedwithout an appended newline (true
tar -Oxparity), including for binary.tar2ball.rb/tarscript.rbexperiment scripts; ordered thegemspec dependencies; excluded local planning docs from VCS/lint.
Testing
bundle exec rakeis fully green: Minitest 0 failures, RSpec 239 examples, 0failures, RuboCop 52 files, 0 offenses. New integration specs cover
filter(file/stdin, glob semantics,-v, empty input, nonexistent trailingarg) and
unpack -O/ not-found / explicit-, plus a unit test for theEntry#valid?body requirement.Follow-ups (non-blocking)
Ball.load_fileraises a bareRuntimeError; considerErrno::ENOENT.Ball#remove_entry's String-identifier path orthe
Entry#name=setter.minitest-reporterschange(separate PR). Whichever merges second will need a trivial
Gemfilerebase.