Class: GitHooksHelper::Hook

Inherits:
Object
  • Object
show all
Defined in:
lib/git-hooks-helper/hook.rb

Constant Summary collapse

RB_REGEXP =
/\.(rb|rake|task|prawn|[Rr]akefile|task)\z/.freeze
ERB_REGEXP =
/\.erb\z/.freeze
JS_REGEXP =
/\.js\z/.freeze
HAML_REGEXP =
/\.haml\z/.freeze
COFFEE_REGEXP =
/\.coffee\z/.freeze
SLIM_REGEXP =
/\.slim\z/.freeze
FILETYPES =
{
  rb:     RB_REGEXP,
  erb:    ERB_REGEXP,
  js:     JS_REGEXP,
  haml:   HAML_REGEXP,
  coffee: COFFEE_REGEXP,
  slim:   SLIM_REGEXP
}.freeze
RB_WARNING_REGEXP =
/[0-9]+:\s+warning:/.freeze
HAML_INVALID_REGEXP =
/error/.freeze
ERB_INVALID_REGEXP =
/invalid\z/.freeze
SLIM_INVALID_REGEXP =
/Slim::Parser/.freeze
COLOR_REGEXP =
/\e\[(\d+)m/.freeze

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ Hook

Set this to true if you want warnings to stop your commit



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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/git-hooks-helper/hook.rb', line 34

def initialize(&block)
  @ruby = GitHooksHelper::Ruby.new
  @debug = false

  @result = GitHooksHelper::Result.new(false)
  @changed_files = GitHooksHelper::Git.in_index
  debug("changed files")
  debug @changed_files
  instance_eval(&block) if block

  if @result.errors?
    status = 1
    puts "ERRORS:".red
    puts @result.errors.join("\n")
    puts "--------\n".red
  end

  if @result.warnings?
    if @result.stop_on_warnings
      puts "WARNINGS:".yellow
    else
      puts "Warnings:".yellow
    end
    puts @result.warnings.join("\n")
    puts "--------\n".yellow
  end

  if @result.perfect_commit?
    puts "Perfect commit!".green
  end

  if @result.continue?
    # all good
    puts("COMMIT OK:".green)
    exit 0
  else
    puts("COMMIT FAILED".red)
    exit 1
  end
end

Instance Method Details

#changed_files(filetypes = [:all]) ⇒ Object



115
116
117
118
# File 'lib/git-hooks-helper/hook.rb', line 115

def changed_files(filetypes = [:all])
  filetypes = Array(filetypes)
   @changed_files.select{ |file| file_matches_filetypes?(file, filetypes) and File.readable?(file) }
end

#check_best_practicesObject



179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/git-hooks-helper/hook.rb', line 179

def check_best_practices
  Open3.popen3("pwd") do |stdin, stdout, stderr|
    puts stdout.read
  end
  each_changed_file([:rb, :erb, :haml]) do |file|
    Open3.popen3("rails_best_practices --spec --test #{file}") do |stdin, stdout, stderr|
      @result.warn(stdout.read.split("\n").map do |line|
        if line =~ /#{file}/
          line.gsub(COLOR_REGEXP, '').strip
        end
      end.compact)
    end
  end
end

#check_erbObject



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/git-hooks-helper/hook.rb', line 136

def check_erb
  each_changed_file([:erb]) do |file|
    Open3.popen3("rails-erb-check #{file}") do |stdin, stdout, stderr|
      lines = stdout.read.split("\n")
      errors = lines.map do |line|
        if line.gsub(COLOR_REGEXP, '') =~ ERB_INVALID_REGEXP
          "#{file} => invalid ERB syntax"
        end
      end.compact
      @result.errors.concat errors
    end
  end
end

#check_hamlObject



165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/git-hooks-helper/hook.rb', line 165

def check_haml
  each_changed_file([:haml]) do |file|
    Open3.popen3("haml --check #{file}") do |stdin, stdout, stderr|
      lines = stderr.read.split("\n")
      errors = lines.map do |line|
        if line.gsub(COLOR_REGEXP, '') =~ HAML_INVALID_REGEXP
          "#{file} => invalid HAML syntax\n  #{line}"
        end
      end.compact
      @result.errors.concat errors
    end
  end
end

#check_ruby_syntaxObject



126
127
128
129
130
131
132
133
134
# File 'lib/git-hooks-helper/hook.rb', line 126

def check_ruby_syntax
  each_changed_file([:rb]) do |file|
    Open3.popen3(GitHooksHelper::Ruby.check_syntax(file)) do |stdin, stdout, stderr|
      stderr.read.split("\n").each do |line|
        line =~ RB_WARNING_REGEXP ? @result.warnings << line : @result.errors << line
      end
    end
  end
end

#check_slimObject



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/git-hooks-helper/hook.rb', line 150

def check_slim
  each_changed_file([:slim]) do |file|
    Open3.popen3("slimrb -c #{file}") do |stdin, stdout, stderr|
      lines = stderr.read.split("\n")
      # HELP NEEDED HERE.
      # Somewhy this appears in stderr when runnin in read world:
      # 'fatal: Not a git repository: '.git''
      errors = if lines.size > 0 && lines.any?{|line| line =~ SLIM_INVALID_REGEXP}
        # skip last 2 lines from output. There is only trace info.
        @result.errors << "#{file} => invalid SLIM syntax\n  " + lines[0..-3].join("\n  ")
      end
    end
  end
end

#debug(msg) ⇒ Object



241
242
243
# File 'lib/git-hooks-helper/hook.rb', line 241

def debug(msg)
  puts msg if @debug
end

#do_not_stop_on_warningsObject



87
88
89
# File 'lib/git-hooks-helper/hook.rb', line 87

def do_not_stop_on_warnings
  @result.stop_on_warnings = false
end

#each_changed_file(filetypes = [:all]) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/git-hooks-helper/hook.rb', line 103

def each_changed_file(filetypes = [:all])
  filetypes = Array(filetypes)
  if @result.continue?
    debug("Can continue")
    changed_files(filetypes).each do |file|
      yield file
    end
  else
    debug("Cannot continue")
  end
end

#file_matches_filetypes?(file, filetypes) ⇒ Boolean

Returns:

  • (Boolean)


120
121
122
123
124
# File 'lib/git-hooks-helper/hook.rb', line 120

def file_matches_filetypes?(file, filetypes)
  filetypes.any? do |type|
    file =~ FILETYPES[type] || type == :all
  end
end

#flog_methods(threshold = 20) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/git-hooks-helper/hook.rb', line 194

def flog_methods(threshold = 20)
  files = changed_files(:rb).join(' ')
  if files != ''
    Open3.popen3("flog -m #{files}") do |stdin, stdout, stderr|
      punishment = stdout.read.split("\n")[3..-1]
      punishment.each do |line|
        line   = line.split(" ")
        score  = line[0].to_f
        method = line[1].strip
        path   = line[2].strip
        if score >= threshold
          @result.warn("Flog for #{method} in #{path} returned #{score}")
        else
          break
        end
      end
    end
  end
end

#info(text) ⇒ Object



229
230
231
# File 'lib/git-hooks-helper/hook.rb', line 229

def info(text)
  puts(text.green)
end

#list_files(filetypes = [:all]) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/git-hooks-helper/hook.rb', line 95

def list_files(filetypes = [:all])
  puts "--- Listing files of type: #{filetypes}"
  each_changed_file(filetypes) do |file|
    puts file
  end
  puts "--- End of list"
end

#never_stopObject



91
92
93
# File 'lib/git-hooks-helper/hook.rb', line 91

def never_stop
  @result.never_stop = true
end

#notice(text) ⇒ Object



233
234
235
# File 'lib/git-hooks-helper/hook.rb', line 233

def notice(text)
  puts(text.yellow)
end

#start_debugObject



75
76
77
# File 'lib/git-hooks-helper/hook.rb', line 75

def start_debug
  @debug = true
end

#stop_debugObject



79
80
81
# File 'lib/git-hooks-helper/hook.rb', line 79

def stop_debug
  @debug = false
end

#stop_on_warningsObject



83
84
85
# File 'lib/git-hooks-helper/hook.rb', line 83

def stop_on_warnings
  @result.stop_on_warnings = true
end

#warn(text) ⇒ Object



237
238
239
# File 'lib/git-hooks-helper/hook.rb', line 237

def warn(text)
  puts(text.red)
end

#warning_on(*args) ⇒ Object

Maybe need options for different file types :rb :erb :js



215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/git-hooks-helper/hook.rb', line 215

def warning_on(*args)
  options = (args[-1].kind_of?(Hash) ? args.pop : {})
  each_changed_file(options[:in] || [:all]) do |file|
    Open3.popen3("fgrep -nH \"#{args.join("\n")}\" #{file}") do |stdin, stdout, stderr|
      err = stdout.read
      err.split("\n").each do |msg|
        args.each do |string|
          @result.warn("#{msg.split(" ").first} contains #{string}") if msg =~ /#{string}/
        end
      end
    end
  end
end