rfix 1.2.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.
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