format-staged 0.0.1 → 0.0.2
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/bin/git-format-staged +38 -19
- data/lib/format-staged/entry.rb +16 -8
- data/lib/format-staged/io.rb +21 -18
- data/lib/format-staged/version.rb +4 -2
- data/lib/format_staged.rb +112 -0
- metadata +50 -7
- data/lib/format-staged.rb +0 -109
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 80bea79a03480ca702efd9bec176a0a2e180e82e854c7300773b064bf4c46b1e
         | 
| 4 | 
            +
              data.tar.gz: 06356777c82f354560e700aef495929f1dc7e4d0d72c08456271a3b08fd3d8cc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bd2a7a026faf4ff75b34b69a26aba8df9ff9d18d15be75341c365a8c5bae010044010d2fe3976cd5b60ccc9e7f0d68c7a62955bc620c56b7ad3955779713ec95
         | 
| 7 | 
            +
              data.tar.gz: 126334604bfac8205438d64d597638490d560db058476f4a53b673f89f2b80cbc055a3f76863d5f6489b89f132140947794cb4a0cece89ea89ea287fe6c0c5f8
         | 
    
        data/bin/git-format-staged
    CHANGED
    
    | @@ -1,40 +1,59 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
             | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'format_staged'
         | 
| 3 5 | 
             
            require 'optparse'
         | 
| 4 6 |  | 
| 5 7 | 
             
            parameters = {
         | 
| 6 | 
            -
              : | 
| 7 | 
            -
              : | 
| 8 | 
            -
              : | 
| 8 | 
            +
              update: true,
         | 
| 9 | 
            +
              write: true,
         | 
| 10 | 
            +
              verbose: false
         | 
| 9 11 | 
             
            }
         | 
| 10 12 |  | 
| 11 13 | 
             
            parser = OptionParser.new do |opt|
         | 
| 12 14 | 
             
              opt.banner = "Usage: #{opt.program_name} [options] [patterns]"
         | 
| 13 | 
            -
              opt.separator  | 
| 14 | 
            -
              opt.on('-f', '--formatter COMMAND', | 
| 15 | 
            +
              opt.separator ''
         | 
| 16 | 
            +
              opt.on('-f', '--formatter COMMAND',
         | 
| 17 | 
            +
                     <<~DOC
         | 
| 18 | 
            +
                       Shell command to format files, will run once per file. Occurrences of the placeholder `{}` will \
         | 
| 19 | 
            +
                       be replaced with a path to the file being formatted. \
         | 
| 20 | 
            +
                       (Example: "prettier --stdin-filepath \'{}\'")
         | 
| 21 | 
            +
                     DOC
         | 
| 22 | 
            +
              ) do |o|
         | 
| 15 23 | 
             
                parameters[:formatter] = o
         | 
| 16 24 | 
             
              end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
              opt.on('--[no-]update-working-tree', | 
| 25 | 
            +
             | 
| 26 | 
            +
              opt.on('--[no-]update-working-tree',
         | 
| 27 | 
            +
                     <<~DOC
         | 
| 28 | 
            +
                       By default formatting changes made to staged file content will also be applied to working tree \
         | 
| 29 | 
            +
                       files via a patch. This option disables that behavior, leaving working tree files untouched.#{' '}
         | 
| 30 | 
            +
                     DOC
         | 
| 31 | 
            +
                    ) do |value|
         | 
| 19 32 | 
             
                parameters[:update] = value
         | 
| 20 33 | 
             
              end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              opt.on('--[no-]write', | 
| 34 | 
            +
             | 
| 35 | 
            +
              opt.on('--[no-]write',
         | 
| 36 | 
            +
                     <<~DOC
         | 
| 37 | 
            +
                       "Prevents #{opt.program_name} from modifying staged or working tree files. You can use this option \
         | 
| 38 | 
            +
                       to check staged changes with a linter instead of formatting. With this option stdout from the \
         | 
| 39 | 
            +
                       formatter command is ignored."
         | 
| 40 | 
            +
                     DOC
         | 
| 41 | 
            +
                    ) do |value|
         | 
| 23 42 | 
             
                parameters[:write] = value
         | 
| 24 43 | 
             
              end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
              opt.on( | 
| 44 | 
            +
             | 
| 45 | 
            +
              opt.on('-v', '--[no-]verbose', 'Shows commands being run') do |value|
         | 
| 27 46 | 
             
                parameters[:verbose] = value
         | 
| 28 47 | 
             
              end
         | 
| 29 48 |  | 
| 30 | 
            -
              opt.separator  | 
| 31 | 
            -
             | 
| 49 | 
            +
              opt.separator ''
         | 
| 50 | 
            +
             | 
| 32 51 | 
             
              opt.on_tail('-h', '--help', 'Prints this help') do
         | 
| 33 52 | 
             
                puts opt
         | 
| 34 53 | 
             
                exit
         | 
| 35 54 | 
             
              end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
              opt.on_tail('--version',  | 
| 55 | 
            +
             | 
| 56 | 
            +
              opt.on_tail('--version', 'Prints the version number and exits') do
         | 
| 38 57 | 
             
                puts FormatStaged::VERSION
         | 
| 39 58 | 
             
                exit
         | 
| 40 59 | 
             
              end
         | 
| @@ -43,9 +62,9 @@ end | |
| 43 62 | 
             
            parser.parse!
         | 
| 44 63 | 
             
            parameters[:patterns] = ARGV
         | 
| 45 64 |  | 
| 46 | 
            -
            if !parameters[:formatter]  | 
| 47 | 
            -
              puts  | 
| 48 | 
            -
             | 
| 65 | 
            +
            if !parameters[:formatter] || parameters[:patterns].empty?
         | 
| 66 | 
            +
              puts 'Missing formatter or file patterns!'
         | 
| 67 | 
            +
             | 
| 49 68 | 
             
              puts parser
         | 
| 50 69 | 
             
              exit
         | 
| 51 70 | 
             
            end
         | 
    
        data/lib/format-staged/entry.rb
    CHANGED
    
    | @@ -1,9 +1,19 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class FormatStaged
         | 
| 2 4 | 
             
              class Entry
         | 
| 3 | 
            -
                PATTERN =  | 
| 5 | 
            +
                PATTERN = /^
         | 
| 6 | 
            +
                  :(?<src_mode>\d+)\s
         | 
| 7 | 
            +
                  (?<dst_mode>\d+)\s
         | 
| 8 | 
            +
                  (?<src_hash>[a-f0-9]+)\s
         | 
| 9 | 
            +
                  (?<dst_hash>[a-f0-9]+)\s
         | 
| 10 | 
            +
                  (?<status>[A-Z])(?<score>\d+)?\t
         | 
| 11 | 
            +
                  (?<src_path>[^\t]+)
         | 
| 12 | 
            +
                  (?:\t(?<dst_path>[^\t]+))?
         | 
| 13 | 
            +
                  $/x.freeze
         | 
| 4 14 |  | 
| 5 15 | 
             
                attr_reader :src_mode, :dst_mode, :src_hash, :dst_hash, :status, :score, :src_path, :dst_path, :path, :root
         | 
| 6 | 
            -
             | 
| 16 | 
            +
             | 
| 7 17 | 
             
                def initialize(line, root:)
         | 
| 8 18 | 
             
                  matches = line.match(PATTERN) or raise "Cannot parse output #{line}"
         | 
| 9 19 | 
             
                  @src_mode = matches[:src_mode]
         | 
| @@ -17,17 +27,15 @@ class FormatStaged | |
| 17 27 | 
             
                  @path = File.expand_path(@src_path, root)
         | 
| 18 28 | 
             
                  @root = root
         | 
| 19 29 | 
             
                end
         | 
| 20 | 
            -
             | 
| 30 | 
            +
             | 
| 21 31 | 
             
                def symlink?
         | 
| 22 32 | 
             
                  @dst_mode == '120000'
         | 
| 23 33 | 
             
                end
         | 
| 24 | 
            -
             | 
| 34 | 
            +
             | 
| 25 35 | 
             
                def matches?(patterns)
         | 
| 26 36 | 
             
                  result = false
         | 
| 27 37 | 
             
                  patterns.each do |pattern|
         | 
| 28 | 
            -
                    if File.fnmatch? pattern, path, File::FNM_EXTGLOB
         | 
| 29 | 
            -
                      result = true
         | 
| 30 | 
            -
                    end
         | 
| 38 | 
            +
                    result = true if File.fnmatch? pattern, path, File::FNM_EXTGLOB
         | 
| 31 39 | 
             
                  end
         | 
| 32 40 | 
             
                  result
         | 
| 33 41 | 
             
                end
         | 
    
        data/lib/format-staged/io.rb
    CHANGED
    
    | @@ -1,40 +1,43 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'English'
         | 
| 4 | 
            +
            class FormatStaged
         | 
| 2 5 | 
             
              def get_output(*args, lines: true)
         | 
| 3 | 
            -
                puts  | 
| 4 | 
            -
             | 
| 6 | 
            +
                puts "> #{args.join(' ')}" if @verbose
         | 
| 7 | 
            +
             | 
| 5 8 | 
             
                output = IO.popen(args, err: :err) do |io|
         | 
| 6 9 | 
             
                  if lines
         | 
| 7 | 
            -
                    io.readlines.map | 
| 10 | 
            +
                    io.readlines.map(&:chomp)
         | 
| 8 11 | 
             
                  else
         | 
| 9 12 | 
             
                    io.read
         | 
| 10 13 | 
             
                  end
         | 
| 11 14 | 
             
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                if @verbose  | 
| 15 | 
            +
             | 
| 16 | 
            +
                if @verbose && lines
         | 
| 14 17 | 
             
                  output.each do |line|
         | 
| 15 18 | 
             
                    puts "< #{line}"
         | 
| 16 19 | 
             
                  end
         | 
| 17 20 | 
             
                end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                raise  | 
| 20 | 
            -
             | 
| 21 | 
            +
             | 
| 22 | 
            +
                raise 'Failed to run command' unless $CHILD_STATUS.success?
         | 
| 23 | 
            +
             | 
| 21 24 | 
             
                output
         | 
| 22 25 | 
             
              end
         | 
| 23 | 
            -
             | 
| 26 | 
            +
             | 
| 24 27 | 
             
              def pipe_command(*args, source: nil)
         | 
| 25 | 
            -
                puts (source.nil? ? '> ' : '| ') + args.join(' ') | 
| 28 | 
            +
                puts (source.nil? ? '> ' : '| ') + args.join(' ') if @verbose
         | 
| 26 29 | 
             
                r, w = IO.pipe
         | 
| 27 | 
            -
             | 
| 30 | 
            +
             | 
| 28 31 | 
             
                opts = {}
         | 
| 29 32 | 
             
                opts[:in] = source unless source.nil?
         | 
| 30 33 | 
             
                opts[:out] = w
         | 
| 31 34 | 
             
                opts[:err] = :err
         | 
| 32 | 
            -
             | 
| 35 | 
            +
             | 
| 33 36 | 
             
                pid = spawn(*args, **opts)
         | 
| 34 | 
            -
             | 
| 37 | 
            +
             | 
| 35 38 | 
             
                w.close
         | 
| 36 | 
            -
                source | 
| 37 | 
            -
             | 
| 38 | 
            -
                 | 
| 39 | 
            -
              end | 
| 39 | 
            +
                source&.close
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                [pid, r]
         | 
| 42 | 
            +
              end
         | 
| 40 43 | 
             
            end
         | 
| @@ -0,0 +1,112 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'English'
         | 
| 4 | 
            +
            require 'format-staged/version'
         | 
| 5 | 
            +
            require 'format-staged/entry'
         | 
| 6 | 
            +
            require 'format-staged/io'
         | 
| 7 | 
            +
            require 'shellwords'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class FormatStaged
         | 
| 10 | 
            +
              attr_reader :formatter, :patterns, :update, :write, :verbose
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              def initialize(formatter:, patterns:, update: true, write: true, verbose: true)
         | 
| 13 | 
            +
                @formatter = formatter
         | 
| 14 | 
            +
                @patterns = patterns
         | 
| 15 | 
            +
                @update = update
         | 
| 16 | 
            +
                @write = write
         | 
| 17 | 
            +
                @verbose = verbose
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def run
         | 
| 21 | 
            +
                root = get_output('git', 'rev-parse', '--show-toplevel').first
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                files = get_output('git', 'diff-index', '--cached', '--diff-filter=AM', '--no-renames', 'HEAD')
         | 
| 24 | 
            +
                        .map { |line| Entry.new(line, root: root) }
         | 
| 25 | 
            +
                        .reject(&:symlink?)
         | 
| 26 | 
            +
                        .filter { |entry| entry.matches?(@patterns) }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                files.each do |file|
         | 
| 29 | 
            +
                  format_file(file)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def format_file(file)
         | 
| 34 | 
            +
                new_hash = format_object file
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                return true unless write
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                if new_hash == file.dst_hash
         | 
| 39 | 
            +
                  puts "Unchanged #{file.src_path}"
         | 
| 40 | 
            +
                  return false
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                if object_is_empty new_hash
         | 
| 44 | 
            +
                  puts "Skipping #{file.src_path}, formatted file is empty"
         | 
| 45 | 
            +
                  return false
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                replace_file_in_index file, new_hash
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                if update
         | 
| 51 | 
            +
                  begin
         | 
| 52 | 
            +
                    patch_working_file file, new_hash
         | 
| 53 | 
            +
                  rescue StandardError => e
         | 
| 54 | 
            +
                    puts "Warning: failed updating #{file.src_path} in working copy: #{e}"
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                true
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def format_object(file)
         | 
| 62 | 
            +
                puts "Formatting #{file.src_path}"
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                format_command = formatter.sub('{}', file.src_path.shellescape)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                pid1, r = pipe_command 'git', 'cat-file', '-p', file.dst_hash
         | 
| 67 | 
            +
                pid2, r = pipe_command format_command, source: r
         | 
| 68 | 
            +
                pid3, r = pipe_command 'git', 'hash-object', '-w', '--stdin', source: r
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                result = r.readlines.map(&:chomp)
         | 
| 71 | 
            +
                if @verbose
         | 
| 72 | 
            +
                  result.each do |line|
         | 
| 73 | 
            +
                    puts "< #{line}"
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                Process.wait pid1
         | 
| 78 | 
            +
                raise "Cannot read #{file.dst_hash} from object database" unless $CHILD_STATUS.success?
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                Process.wait pid2
         | 
| 81 | 
            +
                raise "Error formatting #{file.src_path}" unless $CHILD_STATUS.success?
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                Process.wait pid3
         | 
| 84 | 
            +
                raise 'Error writing formatted file back to object database' unless $CHILD_STATUS.success? && !result.empty?
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                result.first
         | 
| 87 | 
            +
              end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
              def object_is_empty(hash)
         | 
| 90 | 
            +
                size = get_output('git', 'cat-file', '-s', hash).first.to_i
         | 
| 91 | 
            +
                size.zero?
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              def patch_working_file(file, new_hash)
         | 
| 95 | 
            +
                patch = get_output 'git', 'diff', file.dst_hash, new_hash, lines: false
         | 
| 96 | 
            +
                patch.gsub! "a/#{file.dst_hash}", "a/#{file.src_path}"
         | 
| 97 | 
            +
                patch.gsub! "b/#{new_hash}", "b/#{file.src_path}"
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                input, patch_out = IO.pipe
         | 
| 100 | 
            +
                pid, r = pipe_command 'git', 'apply', '-', source: input
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                patch_out.write patch
         | 
| 103 | 
            +
                patch_out.close
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                Process.wait pid
         | 
| 106 | 
            +
                raise 'Error applying patch' unless $CHILD_STATUS.success?
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              def replace_file_in_index(file, new_hash)
         | 
| 110 | 
            +
                get_output 'git', 'update-index', '--cacheinfo', "#{file.dst_mode},#{new_hash},#{file.src_path}"
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,15 +1,57 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: format-staged
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sven Weidauer
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-05- | 
| 12 | 
            -
            dependencies: | 
| 11 | 
            +
            date: 2022-05-25 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: rake
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '13.0'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '13.0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rubocop
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '1.29'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '1.29'
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: rubocop-rake
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: '0.6'
         | 
| 48 | 
            +
              type: :development
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: '0.6'
         | 
| 13 55 | 
             
            description: git format staged
         | 
| 14 56 | 
             
            email: sven@5sw.de
         | 
| 15 57 | 
             
            executables:
         | 
| @@ -18,23 +60,24 @@ extensions: [] | |
| 18 60 | 
             
            extra_rdoc_files: []
         | 
| 19 61 | 
             
            files:
         | 
| 20 62 | 
             
            - bin/git-format-staged
         | 
| 21 | 
            -
            - lib/format-staged.rb
         | 
| 22 63 | 
             
            - lib/format-staged/entry.rb
         | 
| 23 64 | 
             
            - lib/format-staged/io.rb
         | 
| 24 65 | 
             
            - lib/format-staged/version.rb
         | 
| 66 | 
            +
            - lib/format_staged.rb
         | 
| 25 67 | 
             
            homepage: https://github.com/5sw/format-staged
         | 
| 26 68 | 
             
            licenses:
         | 
| 27 69 | 
             
            - MIT
         | 
| 28 | 
            -
            metadata: | 
| 70 | 
            +
            metadata:
         | 
| 71 | 
            +
              rubygems_mfa_required: 'true'
         | 
| 29 72 | 
             
            post_install_message: 
         | 
| 30 73 | 
             
            rdoc_options: []
         | 
| 31 74 | 
             
            require_paths:
         | 
| 32 75 | 
             
            - lib
         | 
| 33 76 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 34 77 | 
             
              requirements:
         | 
| 35 | 
            -
              - - " | 
| 78 | 
            +
              - - "~>"
         | 
| 36 79 | 
             
                - !ruby/object:Gem::Version
         | 
| 37 | 
            -
                  version: ' | 
| 80 | 
            +
                  version: '2.7'
         | 
| 38 81 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 39 82 | 
             
              requirements:
         | 
| 40 83 | 
             
              - - ">="
         | 
    
        data/lib/format-staged.rb
    DELETED
    
    | @@ -1,109 +0,0 @@ | |
| 1 | 
            -
            require 'format-staged/version'
         | 
| 2 | 
            -
            require 'format-staged/entry'
         | 
| 3 | 
            -
            require 'format-staged/io'
         | 
| 4 | 
            -
            require 'shellwords'
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            class FormatStaged 
         | 
| 7 | 
            -
              attr_reader :formatter, :patterns, :update, :write, :verbose
         | 
| 8 | 
            -
              
         | 
| 9 | 
            -
              def initialize(formatter:, patterns:, update: true, write: true, verbose: true) 
         | 
| 10 | 
            -
                @formatter = formatter
         | 
| 11 | 
            -
                @patterns = patterns
         | 
| 12 | 
            -
                @update = update
         | 
| 13 | 
            -
                @write = write
         | 
| 14 | 
            -
                @verbose = verbose
         | 
| 15 | 
            -
              end
         | 
| 16 | 
            -
              
         | 
| 17 | 
            -
              def run()
         | 
| 18 | 
            -
                root = get_output('git', 'rev-parse', '--show-toplevel').first
         | 
| 19 | 
            -
                
         | 
| 20 | 
            -
                files = get_output('git', 'diff-index', '--cached', '--diff-filter=AM', '--no-renames', 'HEAD')
         | 
| 21 | 
            -
                  .map { |line| Entry.new(line, root: root) }
         | 
| 22 | 
            -
                  .reject { |entry| entry.symlink? }
         | 
| 23 | 
            -
                  .filter { |entry| entry.matches?(@patterns) }
         | 
| 24 | 
            -
                  
         | 
| 25 | 
            -
                  files.each do |file|
         | 
| 26 | 
            -
                    format_file(file)
         | 
| 27 | 
            -
                  end
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
                
         | 
| 30 | 
            -
                def format_file(file) 
         | 
| 31 | 
            -
                  new_hash = format_object file
         | 
| 32 | 
            -
                  
         | 
| 33 | 
            -
                  return true if not write 
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  if new_hash == file.dst_hash
         | 
| 36 | 
            -
                    puts "Unchanged #{file.src_path}"
         | 
| 37 | 
            -
                    return false
         | 
| 38 | 
            -
                  end
         | 
| 39 | 
            -
                  
         | 
| 40 | 
            -
                  if object_is_empty new_hash
         | 
| 41 | 
            -
                    puts "Skipping #{file.src_path}, formatted file is empty"
         | 
| 42 | 
            -
                    return false
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                  replace_file_in_index file, new_hash
         | 
| 46 | 
            -
                  
         | 
| 47 | 
            -
                  if update
         | 
| 48 | 
            -
                    begin
         | 
| 49 | 
            -
                      patch_working_file file, new_hash
         | 
| 50 | 
            -
                    rescue => error
         | 
| 51 | 
            -
                      puts "Warning: failed updating #{file.src_path} in working copy: #{error}"
         | 
| 52 | 
            -
                    end
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
                  
         | 
| 55 | 
            -
                  true
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
                
         | 
| 58 | 
            -
                def format_object(file)
         | 
| 59 | 
            -
                  puts "Formatting #{file.src_path}"
         | 
| 60 | 
            -
                  
         | 
| 61 | 
            -
                  format_command = formatter.sub("{}", file.src_path.shellescape)
         | 
| 62 | 
            -
                  
         | 
| 63 | 
            -
                  pid1, r = pipe_command "git", "cat-file", "-p", file.dst_hash
         | 
| 64 | 
            -
                  pid2, r = pipe_command format_command, source: r
         | 
| 65 | 
            -
                  pid3, r = pipe_command "git", "hash-object", "-w", "--stdin", source: r
         | 
| 66 | 
            -
                  
         | 
| 67 | 
            -
                  result = r.readlines.map { |it| it.chomp }
         | 
| 68 | 
            -
                  if @verbose
         | 
| 69 | 
            -
                    result.each do |line|
         | 
| 70 | 
            -
                      puts "< #{line}"
         | 
| 71 | 
            -
                    end
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
                
         | 
| 74 | 
            -
                  Process.wait pid1
         | 
| 75 | 
            -
                  raise "Cannot read #{file.dst_hash} from object database" unless $?.success?
         | 
| 76 | 
            -
                  
         | 
| 77 | 
            -
                  Process.wait pid2
         | 
| 78 | 
            -
                  raise "Error formatting #{file.src_path}" unless $?.success?
         | 
| 79 | 
            -
                  
         | 
| 80 | 
            -
                  Process.wait pid3
         | 
| 81 | 
            -
                  raise "Error writing formatted file back to object database" unless $?.success? && !result.empty?
         | 
| 82 | 
            -
                  
         | 
| 83 | 
            -
                  result.first
         | 
| 84 | 
            -
                end
         | 
| 85 | 
            -
                
         | 
| 86 | 
            -
                def object_is_empty(hash)
         | 
| 87 | 
            -
                  size = get_output("git", "cat-file", "-s", hash).first.to_i
         | 
| 88 | 
            -
                  size == 0
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                def patch_working_file(file, new_hash)
         | 
| 92 | 
            -
                  patch = get_output "git", "diff", file.dst_hash, new_hash, lines: false
         | 
| 93 | 
            -
                  patch.gsub! "a/#{file.dst_hash}", "a/#{file.src_path}"
         | 
| 94 | 
            -
                  patch.gsub! "b/#{new_hash}", "b/#{file.src_path}"
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                  input, patch_out = IO.pipe
         | 
| 97 | 
            -
                  pid, r = pipe_command "git", "apply", "-", source: input
         | 
| 98 | 
            -
                  
         | 
| 99 | 
            -
                  patch_out.write patch
         | 
| 100 | 
            -
                  patch_out.close
         | 
| 101 | 
            -
                  
         | 
| 102 | 
            -
                  Process.wait pid
         | 
| 103 | 
            -
                  raise "Error applying patch" unless $?.success?
         | 
| 104 | 
            -
                end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                def replace_file_in_index(file, new_hash)
         | 
| 107 | 
            -
                  get_output "git", "update-index", "--cacheinfo", "#{file.dst_mode},#{new_hash},#{file.src_path}"
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
            end
         |