Class: FormatStaged
- Inherits:
-
Object
- Object
- FormatStaged
- Defined in:
- lib/format_staged.rb,
lib/format-staged/io.rb,
lib/format-staged/entry.rb,
lib/format-staged/version.rb
Defined Under Namespace
Classes: Entry
Constant Summary collapse
- VERSION =
'0.0.3'
Instance Attribute Summary collapse
-
#formatter ⇒ Object
readonly
Returns the value of attribute formatter.
-
#patterns ⇒ Object
readonly
Returns the value of attribute patterns.
-
#update ⇒ Object
readonly
Returns the value of attribute update.
-
#verbose ⇒ Object
readonly
Returns the value of attribute verbose.
-
#write ⇒ Object
readonly
Returns the value of attribute write.
Instance Method Summary collapse
- #format_file(file) ⇒ Object
- #format_object(file) ⇒ Object
- #get_output(*args, lines: true, silent: false) ⇒ Object
-
#initialize(formatter:, patterns:, update: true, write: true, verbose: true) ⇒ FormatStaged
constructor
A new instance of FormatStaged.
- #object_is_empty(hash) ⇒ Object
- #patch_working_file(file, new_hash) ⇒ Object
- #pipe_command(*args, source: nil) ⇒ Object
- #read_output(r, lines: true, silent: false) ⇒ Object
- #replace_file_in_index(file, new_hash) ⇒ Object
- #run ⇒ Object
Constructor Details
#initialize(formatter:, patterns:, update: true, write: true, verbose: true) ⇒ FormatStaged
Returns a new instance of FormatStaged.
12 13 14 15 16 17 18 |
# File 'lib/format_staged.rb', line 12 def initialize(formatter:, patterns:, update: true, write: true, verbose: true) @formatter = formatter @patterns = patterns @update = update @write = write @verbose = verbose end |
Instance Attribute Details
#formatter ⇒ Object (readonly)
Returns the value of attribute formatter.
10 11 12 |
# File 'lib/format_staged.rb', line 10 def formatter @formatter end |
#patterns ⇒ Object (readonly)
Returns the value of attribute patterns.
10 11 12 |
# File 'lib/format_staged.rb', line 10 def patterns @patterns end |
#update ⇒ Object (readonly)
Returns the value of attribute update.
10 11 12 |
# File 'lib/format_staged.rb', line 10 def update @update end |
#verbose ⇒ Object (readonly)
Returns the value of attribute verbose.
10 11 12 |
# File 'lib/format_staged.rb', line 10 def verbose @verbose end |
#write ⇒ Object (readonly)
Returns the value of attribute write.
10 11 12 |
# File 'lib/format_staged.rb', line 10 def write @write end |
Instance Method Details
#format_file(file) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/format_staged.rb', line 33 def format_file(file) new_hash = format_object file return true unless write if new_hash == file.dst_hash puts "Unchanged #{file.src_path}" return false end if object_is_empty new_hash puts "Skipping #{file.src_path}, formatted file is empty" return false end replace_file_in_index file, new_hash if update begin patch_working_file file, new_hash rescue StandardError => e puts "Warning: failed updating #{file.src_path} in working copy: #{e}" end end true end |
#format_object(file) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/format_staged.rb', line 61 def format_object(file) puts "Formatting #{file.src_path}" format_command = formatter.sub('{}', file.src_path.shellescape) pid1, r = pipe_command 'git', 'cat-file', '-p', file.dst_hash pid2, r = pipe_command format_command, source: r pid3, r = pipe_command 'git', 'hash-object', '-w', '--stdin', source: r result = read_output(r, lines: false).chomp Process.wait pid1 raise "Cannot read #{file.dst_hash} from object database" unless $CHILD_STATUS.success? Process.wait pid2 raise "Error formatting #{file.src_path}" unless $CHILD_STATUS.success? Process.wait pid3 raise 'Error writing formatted file back to object database' unless $CHILD_STATUS.success? && !result.empty? result end |
#get_output(*args, lines: true, silent: false) ⇒ Object
5 6 7 8 9 10 11 12 13 14 |
# File 'lib/format-staged/io.rb', line 5 def get_output(*args, lines: true, silent: false) puts "> #{args.join(' ')}" if @verbose r = IO.popen(args, err: :err) output = read_output(r, lines: lines, silent: silent) raise 'Failed to run command' unless $CHILD_STATUS.success? output end |
#object_is_empty(hash) ⇒ Object
84 85 86 87 |
# File 'lib/format_staged.rb', line 84 def object_is_empty(hash) size = get_output('git', 'cat-file', '-s', hash).first.to_i size.zero? end |
#patch_working_file(file, new_hash) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/format_staged.rb', line 89 def patch_working_file(file, new_hash) patch = get_output 'git', 'diff', file.dst_hash, new_hash, lines: false, silent: true patch.gsub! "a/#{file.dst_hash}", "a/#{file.src_path}" patch.gsub! "b/#{new_hash}", "b/#{file.src_path}" input, patch_out = IO.pipe pid, r = pipe_command 'git', 'apply', '-', source: input patch_out.write patch patch_out.close read_output r Process.wait pid raise 'Error applying patch' unless $CHILD_STATUS.success? end |
#pipe_command(*args, source: nil) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/format-staged/io.rb', line 16 def pipe_command(*args, source: nil) puts (source.nil? ? '> ' : '| ') + args.join(' ') if @verbose r, w = IO.pipe opts = {} opts[:in] = source unless source.nil? opts[:out] = w opts[:err] = :err pid = spawn(*args, **opts) w.close source&.close [pid, r] end |
#read_output(r, lines: true, silent: false) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/format-staged/io.rb', line 33 def read_output(r, lines: true, silent: false) result = r.read splits = result.split("\n") if @verbose && !silent splits.each do |line| puts "< #{line}" end end r.close lines ? splits : result end |
#replace_file_in_index(file, new_hash) ⇒ Object
106 107 108 |
# File 'lib/format_staged.rb', line 106 def replace_file_in_index(file, new_hash) get_output 'git', 'update-index', '--cacheinfo', "#{file.dst_mode},#{new_hash},#{file.src_path}" end |
#run ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/format_staged.rb', line 20 def run root = get_output('git', 'rev-parse', '--show-toplevel').first files = get_output('git', 'diff-index', '--cached', '--diff-filter=AM', '--no-renames', 'HEAD') .map { |line| Entry.new(line, root: root) } .reject(&:symlink?) .filter { |entry| entry.matches?(@patterns) } files.each do |file| format_file(file) end end |