rfix 1.0.7 → 1.0.8.pre.108

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.
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "rainbow"
5
+
6
+ module Rfix::Ext
7
+ module CommentConfig
8
+ # Called by RuboCop on every line to see
9
+ # if its suppose to run against it or not
10
+ def cop_enabled_at_line?(_cop, line)
11
+ Rfix.enabled?(processed_source.file_path, line) && super
12
+ end
13
+ end
14
+
15
+ module Runner
16
+ # Called _after_ @source has been 'auto fixed' by Rubocop
17
+ def check_for_infinite_loop(source, offences)
18
+ # rubocop:disable Style/Semicolon
19
+ Rfix.refresh!(source); super
20
+ # rubocop:enable Style/Semicolon
21
+ end
22
+ end
23
+
24
+ module Options
25
+ # Appends custom --args to RuboCop CLI
26
+ def define_options
27
+ super.tap do |options|
28
+ @ons.each do |args, block|
29
+ option(options, *args, &block)
30
+ end
31
+ end
32
+ end
33
+
34
+ # Helper method used by rfix to append cli --args to Rubocop
35
+ def on(*args, &block)
36
+ @ons ||= []
37
+ @ons += [[args, block]]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,77 @@
1
+ module Rfix::Ext
2
+ module Offense
3
+ def where
4
+ line.to_s + ":" + real_column.to_s
5
+ end
6
+
7
+ def info
8
+ message.split(": ", 2).last.delete("\n")
9
+ end
10
+
11
+ def msg
12
+ CLI::UI.resolve_text("{{italic:#{info}}}", truncate_to: CLI::UI::Terminal.width - 10)
13
+ end
14
+
15
+ def code
16
+ message.split(": ", 2).first
17
+ end
18
+
19
+ def star
20
+ Rainbow("⭑")
21
+ end
22
+
23
+ def cross
24
+ Rainbow("✗").red
25
+ end
26
+
27
+ def check
28
+ Rainbow("✓").green
29
+ end
30
+
31
+ def circle
32
+ Rainbow("⍟")
33
+ end
34
+
35
+ def relative_path
36
+ Rfix.to_relative(path: location.source_buffer.name)
37
+ end
38
+
39
+ def clickable_path
40
+ "{{italic:#{relative_path}:#{where}}}"
41
+ end
42
+
43
+ def clickable_plain_severity
44
+ to_url("https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/#{code}", code)
45
+ end
46
+
47
+ def clickable_severity
48
+ "{{#{severity.code}}} {{italic:#{clickable_plain_severity}}}"
49
+ end
50
+
51
+ def icon
52
+ return check.green if corrected?
53
+ return star.yellow if correctable?
54
+
55
+ cross.red
56
+ end
57
+
58
+ def to_clickable(url, title)
59
+ esc = CLI::UI::ANSI::ESC
60
+ cmd = esc + "]8;;"
61
+ slash = "\x07"
62
+ cmd + "#{escape(url)}#{slash}#{escape(title)}" + cmd + slash
63
+ end
64
+
65
+ def to_path(path, title)
66
+ to_clickable("file://#{path}", title)
67
+ end
68
+
69
+ def to_url(url, title)
70
+ to_clickable(url, title)
71
+ end
72
+
73
+ def escape(str)
74
+ Shellwords.escape(str)
75
+ end
76
+ end
77
+ end
@@ -30,37 +30,14 @@ module Rfix
30
30
  report_summary(files.size, offenses.count, corrected.count)
31
31
  end
32
32
 
33
- def to_clickable(url, title)
34
- esc = CLI::UI::ANSI::ESC
35
- cmd = esc + "]8;;"
36
- slash = "\x07"
37
- cmd + "#{escape(url)}#{slash}#{escape(title)}" + cmd + slash
38
- end
39
-
40
- def to_path(path, title)
41
- to_clickable("file://#{path}", title)
42
- end
43
-
44
- def to_url(url, title)
45
- to_clickable(url, title)
46
- end
47
-
48
- def escape(str)
49
- Shellwords.escape(str)
50
- end
51
-
52
33
  def render_file(file, offenses)
53
34
  return if offenses.empty?
54
35
 
55
- path = Rfix.to_relative(path: file)
56
- url = to_url(file, path)
57
36
  offenses.each do |offense|
58
37
  out("\n\n")
59
- clickable_path = "{{italic:#{path}:#{offense.where}}}"
60
- clickable_code = to_url("https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/#{offense.code}", offense.code)
61
38
  CLI::UI::Frame.open("#{offense.icon} #{offense.msg}", color: :reset)
62
39
  report_line(file, offense, offense.location, offense.highlighted_area)
63
- CLI::UI::Frame.close("#{clickable_path} » {{italic:#{clickable_code}}}", color: :reset)
40
+ CLI::UI::Frame.close("#{offense.clickable_severity} » #{offense.clickable_path}", color: :reset)
64
41
  end
65
42
  end
66
43
 
@@ -0,0 +1,12 @@
1
+ require "bundler"
2
+
3
+ module GemHelper
4
+ def source_for(name:, &block)
5
+ bundle_root = Bundler.bundle_path.join('bundler/gems')
6
+ path = Dir.glob(bundle_root.join("#{name}-*").to_s).first
7
+ path or raise "Could not find source for #{name}, run bundle install first"
8
+ block(path)
9
+ rescue StandardError => e
10
+ puts "[Bundler] #{e}"
11
+ end
12
+ end
@@ -19,7 +19,9 @@ module Rfix::GitHelper
19
19
  "--no-renames",
20
20
  "--no-merges",
21
21
  "--first-parent",
22
- "--diff-filter=AM",
22
+ "--find-renames",
23
+ "--find-copies",
24
+ "--diff-filter=AMCR",
23
25
  "-U0",
24
26
  "--no-color",
25
27
  "-p"
@@ -13,11 +13,11 @@ module Rfix::Log
13
13
  end
14
14
 
15
15
  def say_error_sub(message)
16
- CLI::UI.puts("#{message}")
16
+ CLI::UI.puts(message.to_s)
17
17
  end
18
18
 
19
19
  def say_debug(message)
20
- CLI::UI.puts("{{*}} #{message}")
20
+ CLI::UI.puts("{{*}} [{{info:Debug}}] #{message}")
21
21
  end
22
22
 
23
23
  def say_abort(message)
@@ -0,0 +1,56 @@
1
+ require "tmpdir"
2
+
3
+ module RakeHelper
4
+ include Rfix::Log
5
+ include Rfix::Cmd
6
+ include Rfix::GitHelper
7
+
8
+ def dirty?
9
+ !cmd_succeeded?("git diff --quiet")
10
+ end
11
+
12
+ def clone(github:, ref:)
13
+ Dir.mktmpdir(github.split("/")) do |src|
14
+ say "Clone {{info:#{github}}}, hold on ..."
15
+ git("clone", "https://github.com/#{github}", src)
16
+ Dir.chdir(src) do
17
+ say "Check out {{info:#{ref}}}"
18
+ git("reset", "--hard", ref)
19
+ git("clean", "-f", "-d")
20
+ end
21
+
22
+ dest = File.join("vendor", github)
23
+ say "Copy files to {{info:#{dest}}}"
24
+ FileUtils.mkdir_p(dest)
25
+ FileUtils.copy_entry(src, dest, true, true, true)
26
+ end
27
+ end
28
+
29
+ def gemfiles
30
+ Dir.glob("ci/Gemfile*").unshift("Gemfile").reject do |path|
31
+ [".lock", ".base"].include?(File.extname(path))
32
+ end
33
+ end
34
+
35
+ def gemlocks
36
+ Dir.glob("ci/Gemfile*.lock").unshift("Gemfile.lock")
37
+ end
38
+
39
+ def source_for(name:)
40
+ bundle_root = Bundler.bundle_path.join('bundler/gems')
41
+ path = Dir.glob(bundle_root.join("#{name}-*").to_s).first
42
+ path or raise "Could not find source for #{name}, run bundle install first"
43
+ end
44
+
45
+ def dest_for(name:)
46
+ File.join(__dir__, 'vendor', name)
47
+ end
48
+
49
+ def osx?
50
+ ENV.fetch("TRAVIS_OS_NAME") == "osx"
51
+ end
52
+
53
+ def brew_url(ref:)
54
+ "https://raw.githubusercontent.com/Homebrew/homebrew-core/#{ref}/Formula/git.rb"
55
+ end
56
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Layout/LineLength
4
+
3
5
  require "rubocop"
4
6
  require "optparse"
5
7
  require "rbconfig"
@@ -13,6 +15,66 @@ module Rfix
13
15
  include GitHelper
14
16
  include Log
15
17
 
18
+ def thanks
19
+ tx = []
20
+ tx << "\n{{v}} Thank you for installing {{green:rfix v#{Rfix::VERSION}}}!\n"
21
+ tx << "{{i}} Run {{command:rfix}} for avalible commands or any of the following to get started:"
22
+ tx << ""
23
+ # tx << "Here are a few examples that might be useful:"
24
+ indent = " " * 3
25
+ tx << "#{indent}{{command:rfix local}} {{italic:# Auto-fixes commits not yet pushed to upstream}}"
26
+ tx << "#{indent}{{command:rfix origin}} {{italic:# Auto-fixes commits between HEAD and origin branch}}"
27
+ tx << "#{indent}{{command:rfix lint}} {{italic:# Lints commits and untracked files not yet pushed to upstream}}"
28
+ tx << ""
29
+ tx << "{{*}} {{bold:ProTip:}} Append {{command:--dry}} to run {{command:rfix}} in read-only mode"
30
+ tx << ""
31
+ tx << "{{i}} {{bold:Issues}} {{italic:https://github.com/oleander/rfix-rb/issues}}"
32
+ tx << "{{i}} {{bold:Readme}} {{italic:https://github.com/oleander/rfix-rb/blob/master/README.md}}"
33
+ tx << "{{i}} {{bold:Travis}} {{italic:https://travis-ci.org/github/oleander/rfix-rb}}"
34
+ tx << ""
35
+ tx << "{{italic:~ Linus}}\n\n"
36
+ CLI::UI.fmt(tx.join("\n"), enable_color: true)
37
+ end
38
+
39
+ def help
40
+ cmds = []
41
+ cmds << "\t{{bold:rfix [cmd] [options]}} -- {{italic:--dry --help --list-files --limit-files --config --untracked}}"
42
+ cmds << "\t{{bold:rfix branch <branch>}} -- {{italic:Fix changes made between HEAD and <branch>}}"
43
+ cmds << "\t{{bold:rfix origin}} -- {{italic:Fix changes made between HEAD and origin branch}}"
44
+ cmds << "\t{{bold:rfix local}} -- {{italic:Fix changes not yet pushed to upstream branch}}"
45
+ cmds << "\t{{bold:rfix info}} -- {{italic:Display runtime dependencies and their versions}}"
46
+ cmds << "\t{{bold:rfix all}} -- {{italic:Fix all files in this repository}} {{warning:(not recommended)}}"
47
+ cmds << "\t{{bold:rfix lint}} -- {{italic:Shortcut for 'local --dry --untracked'}}"
48
+ CLI::UI.fmt(cmds.join("\n"), enable_color: true)
49
+ end
50
+
51
+ def config
52
+ @config
53
+ end
54
+
55
+ def no_auto_correct!
56
+ @config[:auto_correct] = false
57
+ end
58
+
59
+ def auto_correct!
60
+ @config[:auto_correct] = true
61
+ end
62
+
63
+ def load_config
64
+ yield @store
65
+ rescue RuboCop::Error => e
66
+ say_abort "[Config:RuboCop] #{e}"
67
+ rescue TypeError => e
68
+ say_abort "[Config:Type] #{e}"
69
+ rescue Psych::SyntaxError => e
70
+ say_abort "[Config:Syntax] #{e}"
71
+ end
72
+
73
+ def lint_mode!
74
+ no_auto_correct!
75
+ load_untracked!
76
+ end
77
+
16
78
  def git_version
17
79
  cmd("git --version").last.split(/\s+/, 3).last
18
80
  end
@@ -33,9 +95,24 @@ module Rfix
33
95
  @global_enable
34
96
  end
35
97
 
98
+ def store
99
+ @store
100
+ end
101
+
102
+ def clear_cache!
103
+ RuboCop::ResultCache.cleanup(@store, true)
104
+ end
105
+
36
106
  def init!
37
107
  @files ||= {}
38
108
  @global_enable = false
109
+ @config = {
110
+ force_exclusion: true,
111
+ formatters: ["Rfix::Formatter"]
112
+ }
113
+
114
+ @store = RuboCop::ConfigStore.new
115
+ auto_correct!
39
116
  end
40
117
 
41
118
  def files
@@ -83,7 +160,7 @@ module Rfix
83
160
  end
84
161
 
85
162
  def has_branch?(name)
86
- Open3.capture2e("git", "cat-file", "-t", name).last.success?
163
+ cmd_succeeded?("git", "cat-file", "-t", name)
87
164
  end
88
165
 
89
166
  # Ref since last push
@@ -100,6 +177,12 @@ module Rfix
100
177
 
101
178
  private
102
179
 
180
+ def old?
181
+ # For version 0.80.x .. 0.83.x:
182
+ # Otherwise it will exit with status code = 1
183
+ (0.80..0.83).include?(RuboCop::Version::STRING.to_f)
184
+ end
185
+
103
186
  def get_file(path, &block)
104
187
  if file = @files[path]
105
188
  block.call(file)
@@ -107,9 +190,7 @@ module Rfix
107
190
  end
108
191
 
109
192
  def list_untrack_files
110
- git("status", "-u", "--porcelain", "--no-column").map do |line|
111
- line.split(" ", 2).map(&:strip)
112
- end.select { |el| el.first == "??" }.map(&:last)
193
+ git("ls-files", "--exclude-standard", "--others")
113
194
  end
114
195
 
115
196
  def cached(files)
@@ -119,3 +200,5 @@ module Rfix
119
200
  end
120
201
  end
121
202
  end
203
+
204
+ # rubocop:enable Layout/LineLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rfix
4
- VERSION = "1.0.7"
4
+ VERSION = "1.0.8"
5
5
  end
Binary file
@@ -2,8 +2,11 @@
2
2
 
3
3
  require "pathname"
4
4
  require_relative "lib/rfix/version"
5
+ # require_relative "lib/rfix/gem_helper"
5
6
 
6
7
  Gem::Specification.new do |spec|
8
+ # extend GemHelper
9
+
7
10
  spec.name = "rfix"
8
11
 
9
12
  if ENV["TRAVIS"]
@@ -17,18 +20,16 @@ Gem::Specification.new do |spec|
17
20
  spec.authors = ["Linus Oleander"]
18
21
  spec.email = ["linus@oleander.nu"]
19
22
 
20
- spec.summary = "RuboCop CLI that only complains about your latest changes"
23
+ # rubocop:disable Layout/LineLength
24
+ spec.summary = "RuboCop CLI that only lints and auto-fixes code you committed by utilizing `git-log` and `git-diff`"
25
+ # rubocop:enable Layout/LineLength
26
+
21
27
  spec.description = <<~TEXT
22
- #{spec.summary}
23
- Uses 'git diff' to determine what changes were made then runs RuboCop against them
28
+ RuboCop CLI that only lints and auto-fixes code you committed by utilizing `git-log` and `git-diff`. Rfix CLI makes it possible to lint (`rfix lint`) and auto-fix (`rfix local|origin|branch`) code changes since a certain point in history. You can auto-fix code committed since creating the current branch (`rfix origin`) or since pushing to upstream (`rfix local`).
24
29
 
25
- $ rfix branch <branch> -- Fix changes made between HEAD and <branch>
26
- $ rfix origin -- Fix changes made between HEAD and origin branch
27
- $ rfix local -- Fix changes not yet pushed to upstream branch
28
- $ rfix info -- Display runtime dependencies and their versions
29
- $ rfix all -- Fix all files in this repository (not recommended)
30
+ Includes a RuboCop formatter with syntax highlighting and build in hyperlinks for offense documentation.
30
31
 
31
- Optional args: --dry --help --list-files --limit-files --config --untracked
32
+ Holds the same CLI arguments as RuboCop. Run `rfix --help` for a complete list or `rfix` for supported commands.
32
33
  TEXT
33
34
  spec.homepage = "https://github.com/oleander/rfix-rb"
34
35
  spec.license = "MIT"
@@ -42,13 +43,19 @@ Gem::Specification.new do |spec|
42
43
  `git ls-files -z`.split("\x0").reject(&validate_file)
43
44
  end
44
45
 
45
- spec.files += Dir.glob("vendor/cli-ui/lib/**/*").reject(&validate_file)
46
+ spec.files += Dir.glob("vendor/shopify/cli-ui/lib/**/*").reject(&validate_file)
46
47
 
47
48
  spec.bindir = "exe"
48
49
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
49
- spec.require_paths = ["lib", "vendor/cli-ui/lib"]
50
+ spec.require_paths = ["lib", "vendor/shopify/cli-ui/lib"]
51
+
52
+ spec.requirements << "git, v2.0+"
50
53
 
51
54
  spec.add_runtime_dependency "rainbow", "~> 3.0"
52
55
  spec.add_runtime_dependency "rouge", "~> 3.20"
53
- spec.add_runtime_dependency "rubocop", "~> 0.80"
56
+ spec.add_runtime_dependency "rubocop", ">= 0.80"
57
+
58
+ spec.add_development_dependency "rspec", "~> 3.0"
59
+ spec.add_development_dependency "aruba", "~> 1.0"
60
+ spec.add_development_dependency "rake", "~> 12.3"
54
61
  end