rfix 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +38 -0
  3. data/.gitignore +43 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +87 -0
  6. data/.travis.yml +37 -0
  7. data/Gemfile +2 -0
  8. data/Gemfile.base +14 -0
  9. data/Gemfile.base.lock +172 -0
  10. data/Gemfile.lock +181 -0
  11. data/Guardfile +16 -0
  12. data/LICENSE.txt +21 -0
  13. data/Makefile +4 -0
  14. data/README.md +92 -0
  15. data/Rakefile +27 -0
  16. data/bin/bundle +114 -0
  17. data/bin/console +29 -0
  18. data/bin/guard +29 -0
  19. data/bin/rake +29 -0
  20. data/bin/rfix +29 -0
  21. data/bin/rspec +29 -0
  22. data/bin/setup +29 -0
  23. data/ci/Gemfile.rubocop-0.80 +2 -0
  24. data/ci/Gemfile.rubocop-0.80.lock +170 -0
  25. data/ci/Gemfile.rubocop-0.81 +2 -0
  26. data/ci/Gemfile.rubocop-0.81.lock +170 -0
  27. data/ci/Gemfile.rubocop-0.82 +2 -0
  28. data/ci/Gemfile.rubocop-0.82.lock +170 -0
  29. data/ci/Gemfile.rubocop-0.83 +2 -0
  30. data/ci/Gemfile.rubocop-0.83.lock +168 -0
  31. data/ci/Gemfile.rubocop-0.84 +2 -0
  32. data/ci/Gemfile.rubocop-0.84.lock +171 -0
  33. data/ci/Gemfile.rubocop-0.85 +2 -0
  34. data/ci/Gemfile.rubocop-0.85.1 +2 -0
  35. data/ci/Gemfile.rubocop-0.85.1.lock +173 -0
  36. data/ci/Gemfile.rubocop-0.85.lock +173 -0
  37. data/exe/rfix +30 -0
  38. data/lib/rfix.rb +34 -0
  39. data/lib/rfix/box.rb +112 -0
  40. data/lib/rfix/branch.rb +31 -0
  41. data/lib/rfix/branches/base.rb +29 -0
  42. data/lib/rfix/branches/head.rb +13 -0
  43. data/lib/rfix/branches/main.rb +34 -0
  44. data/lib/rfix/branches/name.rb +23 -0
  45. data/lib/rfix/branches/reference.rb +21 -0
  46. data/lib/rfix/branches/upstream.rb +13 -0
  47. data/lib/rfix/cmd.rb +39 -0
  48. data/lib/rfix/commands/branch.rb +15 -0
  49. data/lib/rfix/commands/extensions/options.rb +8 -0
  50. data/lib/rfix/commands/help.rb +7 -0
  51. data/lib/rfix/commands/helper/args.rb +137 -0
  52. data/lib/rfix/commands/helper/help.rb +6 -0
  53. data/lib/rfix/commands/helper/loader.rb +6 -0
  54. data/lib/rfix/commands/helper/option.rb +0 -0
  55. data/lib/rfix/commands/helper/params.rb +0 -0
  56. data/lib/rfix/commands/helper/rubocop.rb +17 -0
  57. data/lib/rfix/commands/info.rb +30 -0
  58. data/lib/rfix/commands/lint.rb +23 -0
  59. data/lib/rfix/commands/local.rb +12 -0
  60. data/lib/rfix/commands/origin.rb +19 -0
  61. data/lib/rfix/commands/setup.rb +29 -0
  62. data/lib/rfix/commands/welcome.rb +24 -0
  63. data/lib/rfix/deleted.rb +13 -0
  64. data/lib/rfix/error.rb +2 -0
  65. data/lib/rfix/extensions/extensions.rb +18 -0
  66. data/lib/rfix/extensions/offense.rb +78 -0
  67. data/lib/rfix/extensions/string.rb +8 -0
  68. data/lib/rfix/file.rb +46 -0
  69. data/lib/rfix/file_cache.rb +59 -0
  70. data/lib/rfix/formatter.rb +126 -0
  71. data/lib/rfix/git_helper.rb +59 -0
  72. data/lib/rfix/log.rb +131 -0
  73. data/lib/rfix/no_file.rb +13 -0
  74. data/lib/rfix/rake/paths.rb +50 -0
  75. data/lib/rfix/rake/support.rb +75 -0
  76. data/lib/rfix/repository.rb +204 -0
  77. data/lib/rfix/rfix.rb +34 -0
  78. data/lib/rfix/tracked.rb +72 -0
  79. data/lib/rfix/tracked_file.rb +16 -0
  80. data/lib/rfix/untracked.rb +13 -0
  81. data/lib/rfix/version.rb +5 -0
  82. data/resources/ps.png +0 -0
  83. data/rfix.gemspec +68 -0
  84. data/tasks/bump.rake +11 -0
  85. data/tasks/bundle.rake +17 -0
  86. data/tasks/complex.rake +54 -0
  87. data/tasks/execute.rake +38 -0
  88. data/tasks/libgit2.rake +33 -0
  89. data/tasks/simple.rake +62 -0
  90. data/tasks/travis.rake +74 -0
  91. data/tasks/vendor.rake +34 -0
  92. metadata +350 -0
@@ -0,0 +1,13 @@
1
+ class Rfix::Deleted < Rfix::File
2
+ def include?(_)
3
+ return false
4
+ end
5
+
6
+ def refresh!
7
+ # NOP
8
+ end
9
+
10
+ def inspect
11
+ "<Deleted({{info:#{path}}})>"
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ class Rfix::Error < StandardError
2
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "rainbow"
5
+ require "rfix/log"
6
+
7
+ module Rfix::Ext
8
+ module CommentConfig
9
+ include Rfix::Log # TODO: Remove
10
+ # Called by RuboCop on every line to see
11
+ # if its suppose to run against it or not
12
+ def cop_enabled_at_line?(_cop, line)
13
+ Rfix.enabled?(processed_source.file_path, line) && super
14
+ rescue StandardError
15
+ say_abort "[Rfix::Enabled] #{$ERROR_INFO}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,78 @@
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
+ # TODO: Fix this, do not use Dir.getwd, use git root
37
+ location.source_buffer.name.sub(File.join(Dir.getwd, "/"), "")
38
+ end
39
+
40
+ def clickable_path
41
+ "{{italic:#{relative_path}:#{where}}}"
42
+ end
43
+
44
+ def clickable_plain_severity
45
+ to_url("https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/#{code}", code)
46
+ end
47
+
48
+ def clickable_severity
49
+ "{{#{severity.code}}} {{italic:#{clickable_plain_severity}}}"
50
+ end
51
+
52
+ def icon
53
+ return check.green if corrected?
54
+ return star.yellow if correctable?
55
+
56
+ cross.red
57
+ end
58
+
59
+ def to_clickable(url, title)
60
+ esc = CLI::UI::ANSI::ESC
61
+ cmd = esc + "]8;;"
62
+ slash = "\x07"
63
+ cmd + "#{escape(url)}#{slash}#{escape(title)}" + cmd + slash
64
+ end
65
+
66
+ def to_path(path, title)
67
+ to_clickable("file://#{path}", title)
68
+ end
69
+
70
+ def to_url(url, title)
71
+ to_clickable(url, title)
72
+ end
73
+
74
+ def escape(str)
75
+ Shellwords.escape(str)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,8 @@
1
+ require "rfix/log"
2
+
3
+ # TODO: Use refinements instead
4
+ class String
5
+ def fmt
6
+ Rfix::Log.fmt self
7
+ end
8
+ end
@@ -0,0 +1,46 @@
1
+ require "rugged"
2
+ require "shellwords"
3
+ require "digest"
4
+ require "listen"
5
+
6
+ class Rfix::File < Struct.new(:path, :repo, :ref)
7
+ include Rfix::Log
8
+
9
+ def initialize(path, repo, ref)
10
+ # check_absolute!(path)
11
+ super(path, repo, ref)
12
+ end
13
+
14
+ def check_absolute!(path)
15
+ if Pathname.new(path).absolute?
16
+ say_abort "Path must be relative #{path}"
17
+ end
18
+ end
19
+
20
+ def include?(_)
21
+ raise Rfix::Error.new("#include? not implemented")
22
+ end
23
+
24
+ def refresh!
25
+ raise Rfix::Error.new("#refresh! not implemented")
26
+ end
27
+
28
+ def inspect
29
+ raise Rfix::Error.new("#inspect not implemented")
30
+ end
31
+
32
+ def git_path
33
+ @git_path ||= Pathname.new(repo.workdir)
34
+ end
35
+
36
+ def absolute_path
37
+ path
38
+ # @absolute_path ||= to_abs(path)
39
+ end
40
+
41
+ def to_abs(path)
42
+ File.join(repo.workdir, path)
43
+ end
44
+
45
+ alias to_s path
46
+ end
@@ -0,0 +1,59 @@
1
+ class FileCache
2
+ attr_reader :root_path
3
+ include Rfix::Log
4
+
5
+ def initialize(path)
6
+ @files = Hash.new
7
+ @paths = Hash.new
8
+ @root_path = path
9
+ end
10
+
11
+ def add(file)
12
+ key = normalized_file_path(file)
13
+
14
+ if @files.key?(key)
15
+ return say_debug("File already exists with path {{error:#{file.path}}} using #{key}")
16
+ end
17
+
18
+ say_debug("Adding file with path {{green:#{file.path}}} using key {{info:#{key}}}")
19
+ @files[key] = file
20
+ end
21
+
22
+ def get(path)
23
+ key = normalize_path(path)
24
+
25
+ if file = @files[key]
26
+ say_debug("Found file #{file} with path #{path}")
27
+ return file
28
+ end
29
+
30
+ say_debug("Could {{error:NOT}} find path #{path}")
31
+ nil
32
+ end
33
+
34
+ def pluck(&block)
35
+ @files.values.map(&block)
36
+ end
37
+
38
+ private
39
+
40
+ def normalized_file_path(file)
41
+ normalize_path(file.absolute_path)
42
+ end
43
+
44
+ def to_abs(path)
45
+ File.join(root_path, path)
46
+ end
47
+
48
+ def normalize_path(path)
49
+ if cached = @paths[path]
50
+ return cached
51
+ end
52
+
53
+ if Pathname.new(path).absolute?
54
+ @paths[path] = File.realdirpath(path)
55
+ else
56
+ @paths[path] = File.realdirpath(to_abs(path))
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "rouge"
5
+ require "rainbow"
6
+ require "shellwords"
7
+
8
+ module Rfix
9
+ class Formatter < RuboCop::Formatter::SimpleTextFormatter
10
+ include Rfix::Log
11
+
12
+ def started(files)
13
+ theme = Rouge::Themes::Gruvbox.new
14
+ @formatter = Rouge::Formatters::TerminalTruecolor.new(theme)
15
+ @current = 0
16
+ @total = files.count
17
+ @files = {}
18
+ @lexer = Rouge::Lexers::Ruby.new
19
+ @pg = CLI::UI::Progress.new
20
+ @all_files = files
21
+ end
22
+
23
+ def truncate(path)
24
+ path.sub(::File.join(Dir.getwd, "/"), "")
25
+ end
26
+
27
+ def render_files(files)
28
+ return unless Rfix.test?
29
+
30
+ files.each do |file|
31
+ offenses = @files.fetch(file)
32
+ corrected = offenses.select(&:corrected?)
33
+
34
+ if offenses.empty?
35
+ say truncate(file)
36
+ elsif offenses.count == corrected.count
37
+ say truncate(file)
38
+ else
39
+ say_error truncate(file)
40
+ end
41
+ end
42
+ end
43
+
44
+ def finished(files)
45
+ render_files(files)
46
+
47
+ files.each do |file|
48
+ render_file(file, @files.fetch(file))
49
+ end
50
+
51
+ offenses = @files.values.flatten
52
+ corrected = offenses.select(&:corrected?)
53
+ out("\n") unless @total.zero?
54
+ report_summary(files.size, offenses.count, corrected.count)
55
+ end
56
+
57
+ def render_file(file, offenses)
58
+ return if offenses.empty?
59
+
60
+ offenses.each do |offense|
61
+ out("\n\n")
62
+ CLI::UI::Frame.open("#{offense.icon} #{offense.msg}", color: :reset)
63
+ report_line(file, offense, offense.location, offense.highlighted_area)
64
+ CLI::UI::Frame.close("#{offense.clickable_severity} » #{offense.clickable_path}", color: :reset)
65
+ end
66
+ end
67
+
68
+ def mark
69
+ CLI::UI::ANSI::ESC + "]1337;SetMark" + "\x07"
70
+ end
71
+
72
+ def file_finished(file, offenses)
73
+ out("\n") if @current == 0.0
74
+ @current += 1.0
75
+ unless Rfix.test?
76
+ @pg.tick(set_percent: (@current / @total))
77
+ end
78
+ @files[file] = offenses
79
+ end
80
+
81
+ def out(msg, format: true)
82
+ CLI::UI.puts(msg, to: output, format: format)
83
+ end
84
+
85
+ def fmt(msg)
86
+ CLI::UI.fmt(msg, enable_color: true)
87
+ end
88
+
89
+ def dim(value)
90
+ Rainbow(value).lightgray
91
+ end
92
+
93
+ def highlighted_source_line(offense)
94
+ source_before_highlight(offense) +
95
+ hightlight_source_tag(offense) +
96
+ source_after_highlight(offense)
97
+ end
98
+
99
+ def hightlight_source_tag(offense)
100
+ offense.highlighted_area.source
101
+ end
102
+
103
+ def source_before_highlight(offense)
104
+ source_line = offense.location.source_line
105
+ source_line[0...offense.highlighted_area.begin_pos]
106
+ end
107
+
108
+ def source_after_highlight(offense)
109
+ source_line = offense.location.source_line
110
+ source_line[offense.highlighted_area.end_pos..-1]
111
+ end
112
+
113
+ def report_line(_file, offense, _location, highlighted_area)
114
+ extra = " "
115
+ src = highlighted_source_line(offense).lines.map { |line| extra + line }.join("\n")
116
+ lines = @formatter.format(@lexer.lex(src)).gsub('\\e', CLI::UI::ANSI::ESC).lines.map(&:chomp)
117
+ out("\n\n")
118
+ out(lines.join("\n"), format: false)
119
+ b_pos = highlighted_area.begin_pos + extra.length
120
+ e_pos = highlighted_area.end_pos + extra.length
121
+ size = e_pos - b_pos
122
+ out((" " * b_pos) + Rainbow((" " * size)).underline.bold)
123
+ out("\n\n")
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "rfix"
5
+ require "rfix/log"
6
+ require "rfix/cmd"
7
+ require "shellwords"
8
+
9
+ module Rfix::GitHelper
10
+ include Rfix::Log
11
+ include Rfix::Cmd
12
+
13
+ def git(*params, root: Dir.pwd, quiet: false, &block)
14
+ args = split_args(params)
15
+ args.unshift *["--git-dir", File.join(root, ".git")]
16
+ args.unshift *["--work-tree", root]
17
+ cmd("git", *args, quiet: quiet, &block)
18
+ end
19
+
20
+ def split_args(params)
21
+ return if params.empty?
22
+ return split(params.first) if params.count == 1
23
+ return params
24
+ end
25
+
26
+ def split(str)
27
+ Shellwords.split(str)
28
+ end
29
+
30
+ def has_branch?(branch)
31
+ cmd_succeeded?("git", "cat-file", "-t", branch)
32
+ end
33
+
34
+ def dirty?(path)
35
+ Dir.chdir(path) do
36
+ !cmd_succeeded?("git diff --quiet")
37
+ end
38
+ end
39
+
40
+ def params
41
+ [
42
+ "--word-diff-regex=[^[:space:]]",
43
+ "--no-renames",
44
+ "--no-merges",
45
+ "--first-parent",
46
+ "--find-renames",
47
+ "--find-copies",
48
+ "--diff-filter=AMCR",
49
+ "-U0",
50
+ "--no-color",
51
+ "-p"
52
+ ]
53
+ end
54
+ end
55
+
56
+ # TODO: Rename above to just ::Git
57
+ module Rfix::Git
58
+ extend Rfix::GitHelper
59
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rfix"
4
+ require "cli/ui"
5
+
6
+ module Rfix::Log
7
+ extend self
8
+ def say(message)
9
+ prt("{{v}} #{message}")
10
+ end
11
+
12
+ def say_error(message)
13
+ prt("{{x}} #{message}")
14
+ end
15
+
16
+ def say_error_sub(message)
17
+ prt(message.to_s)
18
+ end
19
+
20
+ def error_box(title)
21
+ box(title, color: :red) { yield }
22
+ end
23
+
24
+ def abort_box(title)
25
+ error_box(title) { yield }
26
+ exit 1
27
+ end
28
+
29
+ def say_test(message)
30
+ prt("{{i}} #{strip(message)}")
31
+ end
32
+
33
+ def say_debug(message)
34
+ if debug? or test?
35
+ prt("{{i}} #{strip(message)}", to: $stderr)
36
+ end
37
+ end
38
+
39
+ def say_abort(message)
40
+ prt("{{x}} #{message}")
41
+ exit 1
42
+ end
43
+
44
+ def debug?
45
+ return false unless defined?(RSpec)
46
+ return RSpec.configuration.debug?
47
+ end
48
+
49
+ def test?
50
+ Rfix.test?
51
+ end
52
+
53
+ def say_exit(message)
54
+ prt("{{v}} #{message}")
55
+ exit 0
56
+ end
57
+
58
+ def say_plain(message)
59
+ prt(message)
60
+ end
61
+
62
+ def debug_box(title)
63
+ unless_debug do
64
+ box(title) { yield }
65
+ end
66
+ end
67
+
68
+ def prt(*args)
69
+ CLI::UI.puts(*args)
70
+ end
71
+
72
+ def fmt(*args)
73
+ CLI::UI.fmt(*args)
74
+ end
75
+
76
+ alias ftm fmt
77
+
78
+ def log_items(items, title:)
79
+ box("#{title} (#{items.count})") do
80
+ return margin(2) do
81
+ prt "{{warning:No items found}}"
82
+ end if items.empty?
83
+
84
+ items.each do |item|
85
+ if block_given?
86
+ say strip(yield item)
87
+ else
88
+ say strip(item.to_s)
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def box(title, color: :reset)
95
+ margin do
96
+ CLI::UI::Frame.open(title, color: color) do
97
+ margin(2) do
98
+ yield
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def strip(msg)
105
+ msg
106
+ # msg.gsub(current_path, "").gsub(Dir.pwd, ".").chomp
107
+ end
108
+
109
+ def current_path
110
+ File.join(Dir.pwd, "/")
111
+ end
112
+
113
+ def div(title, **args)
114
+ CLI::UI::Frame.divider(title, **args)
115
+ margin { yield }
116
+ end
117
+
118
+ def margin(n = 1)
119
+ new_line(n)
120
+ yield
121
+ new_line(n)
122
+ end
123
+
124
+ def new_line(n = 1)
125
+ say_plain("\n" * n)
126
+ end
127
+
128
+ def unless_debug
129
+ yield unless Rfix.debug?
130
+ end
131
+ end