rfix 2.0.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/exe/rfix +11 -90
  3. data/lib/rfix.rb +10 -9
  4. data/lib/rfix/branch/reference.rb +2 -2
  5. data/lib/rfix/branch/upstream.rb +2 -4
  6. data/lib/rfix/cli/command.rb +14 -1
  7. data/lib/rfix/cli/command/all.rb +21 -0
  8. data/lib/rfix/cli/command/base.rb +30 -19
  9. data/lib/rfix/cli/command/branch.rb +2 -0
  10. data/lib/rfix/cli/command/help.rb +2 -0
  11. data/lib/rfix/cli/command/info.rb +6 -1
  12. data/lib/rfix/cli/command/local.rb +2 -0
  13. data/lib/rfix/cli/command/origin.rb +2 -0
  14. data/lib/rfix/cli/command/setup.rb +2 -0
  15. data/lib/rfix/cli/command/status.rb +39 -0
  16. data/lib/rfix/collector.rb +69 -0
  17. data/lib/rfix/diff.rb +69 -0
  18. data/lib/rfix/extension/comment_config.rb +15 -0
  19. data/lib/rfix/extension/offense.rb +17 -14
  20. data/lib/rfix/extension/pastel.rb +7 -4
  21. data/lib/rfix/extension/progresbar.rb +15 -0
  22. data/lib/rfix/extension/strings.rb +10 -2
  23. data/lib/rfix/file.rb +5 -3
  24. data/lib/rfix/file/base.rb +21 -14
  25. data/lib/rfix/file/deleted.rb +2 -0
  26. data/lib/rfix/file/ignored.rb +2 -0
  27. data/lib/rfix/file/null.rb +17 -0
  28. data/lib/rfix/file/tracked.rb +39 -23
  29. data/lib/rfix/file/undefined.rb +17 -0
  30. data/lib/rfix/file/untracked.rb +3 -1
  31. data/lib/rfix/formatter.rb +67 -71
  32. data/lib/rfix/highlighter.rb +1 -3
  33. data/lib/rfix/rake/gemfile.rb +26 -23
  34. data/lib/rfix/repository.rb +59 -96
  35. data/lib/rfix/types.rb +24 -14
  36. data/lib/rfix/version.rb +1 -1
  37. data/rfix.gemspec +11 -3
  38. data/vendor/cli-ui/Gemfile +17 -0
  39. data/vendor/cli-ui/Gemfile.lock +60 -0
  40. data/vendor/cli-ui/LICENSE.txt +21 -0
  41. data/vendor/cli-ui/README.md +224 -0
  42. data/vendor/cli-ui/Rakefile +20 -0
  43. data/vendor/cli-ui/bin/console +14 -0
  44. data/vendor/cli-ui/cli-ui.gemspec +25 -0
  45. data/vendor/cli-ui/dev.yml +14 -0
  46. data/vendor/cli-ui/lib/cli/ui.rb +233 -0
  47. data/vendor/cli-ui/lib/cli/ui/ansi.rb +157 -0
  48. data/vendor/cli-ui/lib/cli/ui/color.rb +84 -0
  49. data/vendor/cli-ui/lib/cli/ui/formatter.rb +192 -0
  50. data/vendor/cli-ui/lib/cli/ui/frame.rb +269 -0
  51. data/vendor/cli-ui/lib/cli/ui/frame/frame_stack.rb +98 -0
  52. data/vendor/cli-ui/lib/cli/ui/frame/frame_style.rb +120 -0
  53. data/vendor/cli-ui/lib/cli/ui/frame/frame_style/box.rb +166 -0
  54. data/vendor/cli-ui/lib/cli/ui/frame/frame_style/bracket.rb +139 -0
  55. data/vendor/cli-ui/lib/cli/ui/glyph.rb +84 -0
  56. data/vendor/cli-ui/lib/cli/ui/os.rb +67 -0
  57. data/vendor/cli-ui/lib/cli/ui/printer.rb +59 -0
  58. data/vendor/cli-ui/lib/cli/ui/progress.rb +90 -0
  59. data/vendor/cli-ui/lib/cli/ui/prompt.rb +297 -0
  60. data/vendor/cli-ui/lib/cli/ui/prompt/interactive_options.rb +484 -0
  61. data/vendor/cli-ui/lib/cli/ui/prompt/options_handler.rb +29 -0
  62. data/vendor/cli-ui/lib/cli/ui/spinner.rb +66 -0
  63. data/vendor/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  64. data/vendor/cli-ui/lib/cli/ui/spinner/spin_group.rb +263 -0
  65. data/vendor/cli-ui/lib/cli/ui/stdout_router.rb +232 -0
  66. data/vendor/cli-ui/lib/cli/ui/terminal.rb +46 -0
  67. data/vendor/cli-ui/lib/cli/ui/truncater.rb +102 -0
  68. data/vendor/cli-ui/lib/cli/ui/version.rb +5 -0
  69. data/vendor/cli-ui/lib/cli/ui/widgets.rb +77 -0
  70. data/vendor/cli-ui/lib/cli/ui/widgets/base.rb +27 -0
  71. data/vendor/cli-ui/lib/cli/ui/widgets/status.rb +61 -0
  72. data/vendor/cli-ui/lib/cli/ui/wrap.rb +56 -0
  73. data/vendor/cli-ui/test/cli/ui/ansi_test.rb +32 -0
  74. data/vendor/cli-ui/test/cli/ui/cli_ui_test.rb +23 -0
  75. data/vendor/cli-ui/test/cli/ui/color_test.rb +40 -0
  76. data/vendor/cli-ui/test/cli/ui/formatter_test.rb +79 -0
  77. data/vendor/cli-ui/test/cli/ui/glyph_test.rb +68 -0
  78. data/vendor/cli-ui/test/cli/ui/printer_test.rb +103 -0
  79. data/vendor/cli-ui/test/cli/ui/progress_test.rb +46 -0
  80. data/vendor/cli-ui/test/cli/ui/prompt/options_handler_test.rb +39 -0
  81. data/vendor/cli-ui/test/cli/ui/prompt_test.rb +348 -0
  82. data/vendor/cli-ui/test/cli/ui/spinner/spin_group_test.rb +39 -0
  83. data/vendor/cli-ui/test/cli/ui/spinner_test.rb +141 -0
  84. data/vendor/cli-ui/test/cli/ui/stdout_router_test.rb +32 -0
  85. data/vendor/cli-ui/test/cli/ui/terminal_test.rb +26 -0
  86. data/vendor/cli-ui/test/cli/ui/truncater_test.rb +31 -0
  87. data/vendor/cli-ui/test/cli/ui/widgets/status_test.rb +49 -0
  88. data/vendor/cli-ui/test/cli/ui/widgets_test.rb +15 -0
  89. data/vendor/cli-ui/test/test_helper.rb +53 -0
  90. data/vendor/cli-ui/tmp/cache/bootsnap/compile-cache/d9/c036af0f3dc494 +0 -0
  91. data/vendor/cli-ui/tmp/cache/bootsnap/load-path-cache +0 -0
  92. data/vendor/dry-cli/lib/dry/cli/command.rb +2 -1
  93. data/vendor/dry-cli/tmp/cache/bootsnap/compile-cache/ff/a22a5daafbd74c +0 -0
  94. data/vendor/dry-cli/tmp/cache/bootsnap/load-path-cache +0 -0
  95. data/vendor/strings-ansi/tmp/cache/bootsnap/compile-cache/79/49cf49407b370e +0 -0
  96. data/vendor/strings-ansi/tmp/cache/bootsnap/load-path-cache +0 -0
  97. metadata +170 -9
  98. data/lib/rfix/extension/string.rb +0 -12
  99. data/lib/rfix/indicator.rb +0 -19
@@ -1,93 +1,109 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/module/concerning"
3
4
  require "active_support/core_ext/module/delegation"
4
- require "rubocop/formatter/simple_text_formatter"
5
- require "rubocop/cop/offense"
6
5
  require "dry/core/constants"
7
6
  require "dry/initializer"
7
+ require "tty/progressbar"
8
8
  require "tty/screen"
9
9
  require "tty/prompt"
10
+ require "tty/table"
10
11
  require "tty/box"
11
-
12
- RuboCop::Cop::Offense.prepend(Rfix::Extension::Offense)
12
+ require "rubocop"
13
13
 
14
14
  module Rfix
15
15
  class Formatter < RuboCop::Formatter::SimpleTextFormatter
16
- attr_reader :indicator
17
-
18
16
  include Dry::Core::Constants
19
17
  extend Dry::Initializer
20
18
  include Log
21
19
 
22
- option :indicator, default: -> { Indicator.new }
23
- option :reported_offenses
24
- option :options
25
- option :output
20
+ NoSuchFileError = Class.new(Error)
26
21
 
27
- PROMPT = TTY::Prompt.new(symbols: { marker: ">" })
28
- SPACE = " "
22
+ using(Module.new do
23
+ refine String do
24
+ def surround(value)
25
+ value + self + value
26
+ end
27
+ end
29
28
 
30
- delegate :say, to: :PROMPT
29
+ refine RuboCop::Cop::Offense.const_get(:PseudoSourceRange) do
30
+ def source_buffer
31
+ raise NoSuchFileError
32
+ end
33
+ end
34
+ end)
31
35
 
32
- class NullRepository
33
- include Singleton
36
+ option :reported_offenses, default: -> { EMPTY_ARRAY.dup }
37
+ option :progress
38
+ option :options
39
+ option :output
34
40
 
35
- def include_file?(*)
36
- true
37
- end
41
+ option :params do
42
+ option :repository
38
43
  end
39
44
 
45
+ SURROUNDING_LINES = 2
46
+ NEWLINE = "\n"
47
+ SPACE = " "
48
+ PADDING = 1
49
+
50
+ delegate :repository, to: :params
51
+
40
52
  def initialize(output, options = EMPTY_HASH)
41
- super(output: output, options: options, reported_offenses: EMPTY_ARRAY.dup)
53
+ TTY::ProgressBar.new(":current/:total (:eta) [:bar]", output: output).then do |bar|
54
+ super(output, output: output, options: options, params: options, progress: bar)
55
+ end
42
56
  end
43
57
 
44
58
  def started(files)
45
- # indicator.start("{{italic:rfix}} is linting {{bold:#{files.count}}} files, hold on ...")
46
- end
47
-
48
- # @files [Array<File>]
49
- def finished(files)
50
- # @indicator.stop
51
- mark_command_line
52
- report_summary(files)
59
+ progress.configure do |config|
60
+ config.bar_format = :block
61
+ config.total = files.count
62
+ config.clear_head = true
63
+ config.clear = true
64
+ config.width = width
65
+ end
53
66
  end
54
67
 
55
68
  # @file [File]
56
69
  # @offenses [Array<Offence>]
57
- def file_finished(*, offenses)
70
+ def file_finished(_file, offenses)
58
71
  @reported_offenses += offenses
59
72
 
60
- # @indicator.stop if offenses?
73
+ progress.advance
74
+ end
75
+
76
+ # @files [Array<File>]
77
+ def finished(files)
78
+ progress.finish
79
+ mark_command_line
80
+ reported_offenses.each do |offense|
81
+ progress.log(NEWLINE)
61
82
 
62
- length = offenses.length - 1
63
- offenses.each_with_index do |offense, _index|
64
83
  framed(offense) do
65
84
  report_line_with_highlight(offense)
66
85
  end
67
-
68
- puts
86
+ rescue NoSuchFileError
87
+ # NOP
69
88
  end
89
+ report_summary(files)
70
90
  end
71
91
 
72
92
  private
73
93
 
74
- using(Module.new do
75
- refine String do
76
- def surround(value)
77
- value + self + value
78
- end
79
- end
80
- end)
94
+ def width
95
+ TTY::Screen.width
96
+ end
81
97
 
82
98
  def framed(offense, &block)
83
- puts TTY::Box.frame({
84
- width: TTY::Screen.width,
85
- padding: [1, 1, 0, 1],
99
+ progress.log TTY::Box.frame({
100
+ width: width,
101
+ padding: [PADDING, PADDING, 0, PADDING],
86
102
  title: {
87
103
  top_left: "#{offense.icon} #{offense.msg}".surround(SPACE),
88
- bottom_left: offense.clickable_severity&.surround(SPACE),
89
- bottom_right: offense.clickable_path&.surround(SPACE)
90
- }.compact
104
+ bottom_left: offense.clickable_path(repository.path)&.surround(SPACE),
105
+ top_right: offense.cop_name.surround(SPACE)
106
+ }
91
107
  }, &block)
92
108
  end
93
109
 
@@ -100,34 +116,20 @@ module Rfix
100
116
  end
101
117
 
102
118
  def mark_command_line
103
- # "#{ESC}]1337;SetMark\a"
104
- "" # TODO: Activate
105
- end
106
-
107
- def report(msg, format: true)
108
- msg
109
- end
110
-
111
- def newline(amount = 1)
112
- report("\n" * amount)
119
+ # progress.log "\e]1337;SetMark\a"
113
120
  end
114
121
 
115
122
  def report_line_with_highlight(offense)
116
123
  location = offense.location
117
124
 
118
- unless location.respond_to?(:source_buffer)
119
- return "Source not found"
120
- end
121
-
122
125
  buffer = location.source_buffer
123
126
 
124
127
  source = buffer.source
125
128
  line = location.line
126
129
  last_line = buffer.last_line
127
- surrounding_lines = 2
128
130
 
129
- min_line = [line - surrounding_lines * 2, 1].max
130
- max_line = [line + surrounding_lines * 2, last_line].min
131
+ min_line = [line - SURROUNDING_LINES * 2, 1].max
132
+ max_line = [line + SURROUNDING_LINES * 2, last_line].min
131
133
 
132
134
  begin_index = buffer.line_range(min_line).begin_pos
133
135
  end_index = buffer.line_range(max_line).end_pos
@@ -135,13 +137,11 @@ module Rfix
135
137
  visible = begin_index...end_index
136
138
  highlight = location.to_range
137
139
 
138
- highlighter = Highlighter.new(
140
+ Highlighter.new(
139
141
  visible_lines: (min_line..max_line),
140
142
  highlight: highlight,
141
143
  visible: visible
142
- )
143
-
144
- (method(:report) << highlighter).call(source)
144
+ ).call(source)
145
145
  end
146
146
 
147
147
  def corrected
@@ -159,9 +159,5 @@ module Rfix
159
159
  def offenses?
160
160
  reported_offenses.any?
161
161
  end
162
-
163
- def repository
164
- NullRepository.instance
165
- end
166
162
  end
167
163
  end
@@ -71,10 +71,8 @@ module Rfix
71
71
 
72
72
  lines.reduce([0, 1]) do |(position, lineno), tokens|
73
73
  print_line_number = lambda do
74
- block.call(SPACE * 2)
75
-
76
74
  style = is_h[lineno] ? pastel.yellow.detach : pastel.dim.detach
77
- (block << style).call(lineno.to_s.ljust(4, SPACE) + SPACE)
75
+ block.call((SPACE * 2) + style.call(lineno.to_s.ljust(4, SPACE)) + SPACE)
78
76
  end
79
77
 
80
78
  tokens.reduce(position) do |index, (token, value)|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "dry/types"
2
4
  require "dry/struct"
3
5
  require "dry/logic"
@@ -9,7 +11,8 @@ module Rfix
9
11
  end
10
12
 
11
13
  class Gemfile < Dry::Struct
12
- include Dry::Core::Constants, FileUtils
14
+ include FileUtils
15
+ include Dry::Core::Constants
13
16
 
14
17
  module Types
15
18
  include Dry::Types()
@@ -32,26 +35,26 @@ module Rfix
32
35
 
33
36
  FORMAT = "Gemfile.rubocop-%s%s"
34
37
  VERSIONS = [
35
- '0.82',
36
- '0.83',
37
- '0.84',
38
- '0.92',
39
- '0.93',
40
- '1.0.0',
41
- '1.7.0',
42
- '1.5.0',
43
- '1.5.1',
44
- '1.5.2',
45
- '1.6.1',
46
- '1.8.1',
47
- '1.8.0',
48
- '1.9.0',
49
- '1.10.0',
50
- '1.11.0',
51
- '1.12.0',
52
- '1.12.1',
53
- '1.13.0'
54
- ]
38
+ "0.82",
39
+ "0.83",
40
+ "0.84",
41
+ "0.92",
42
+ "0.93",
43
+ "1.0.0",
44
+ "1.7.0",
45
+ "1.5.0",
46
+ "1.5.1",
47
+ "1.5.2",
48
+ "1.6.1",
49
+ "1.8.1",
50
+ "1.8.0",
51
+ "1.9.0",
52
+ "1.10.0",
53
+ "1.11.0",
54
+ "1.12.0",
55
+ "1.12.1",
56
+ "1.13.0"
57
+ ].freeze
55
58
 
56
59
  def self.call(*args, **kwargs, &block)
57
60
  (self | AST).call(*args, **kwargs, &block)
@@ -77,9 +80,9 @@ module Rfix
77
80
  end
78
81
 
79
82
  def bundle_lock
80
- sh *lock_args
83
+ sh(*lock_args)
81
84
  rescue RuntimeError
82
- sh *lock_args[0..-2]
85
+ sh(*lock_args[0..-2])
83
86
  end
84
87
 
85
88
  def lock_args
@@ -1,89 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/inflections"
3
4
  require "active_support/core_ext/module/delegation"
4
- require "dry/core/constants"
5
+ require "active_support/core_ext/object/inclusion"
5
6
  require "dry/core/memoizable"
7
+ require "dry/core/constants"
8
+ require "concurrent/map"
6
9
  require "dry/struct"
7
10
  require "rugged"
8
11
 
9
12
  module Rfix
10
13
  class Repository < Dry::Struct
11
14
  include Dry::Core::Constants
12
- include Log
15
+ include Dry::Core::Memoizable
13
16
 
14
17
  attribute :repository, Types.Instance(Rugged::Repository)
15
-
16
18
  attribute :reference, Types.Instance(Branch::Base)
19
+ attribute :current_path, Types::Path::Relative.default { Pathname(".").freeze }
17
20
 
18
- delegate :head, :branches, :workdir, :rev_parse, :diff_workdir, to: :repository
19
-
20
- OPTIONS = {
21
- include_untracked_content: true,
22
- ignore_whitespace_change: false,
23
- recurse_untracked_dirs: true,
24
- ignore_whitespace_eol: false,
25
- include_unmodified: true,
26
- include_untracked: true,
27
- ignore_submodules: true,
28
- include_ignored: false,
29
- context_lines: 0
30
- }.freeze
31
-
32
- def initialize(*)
33
- super
34
- call
35
- end
36
-
37
- def origin
38
- reference.resolve
39
- end
40
-
41
- def status(found = EMPTY_HASH.dup)
42
- @status ||= begin
43
- repository.status do |path, statuses|
44
- statuses.each do |status|
45
- (found[path] ||= []) << status
46
- end
47
- end
48
-
49
- if repository.head_unborn?
50
- return found
51
- end
52
-
53
- origin.diff_workdir(**OPTIONS.dup).tap do |diff|
54
- diff.find_similar!(
55
- renames_from_rewrites: true,
56
- renames: true,
57
- copies: true
58
- )
59
- end.each_delta.each_with_object(found) do |delta, acc|
60
- (acc[delta.new_file[:path]] ||= []) << delta.status
61
- end
62
- end
63
- end
64
-
65
- def call
66
- status.each do |path, statuses|
67
- build(path, statuses)
68
- end
69
- end
21
+ INCLUDED = [File::Untracked, File::Tracked].to_set.freeze
22
+ INIT = Hash.new { |h, k| h[k] = EMPTY_ARRAY.dup }.freeze
70
23
 
71
- def path
72
- Pathname(workdir)
73
- end
24
+ delegate_missing_to :repository
74
25
 
75
- # @path [String]
76
- def refresh!(*)
77
- # NOP
26
+ def self.method_added(name)
27
+ super.tap { memoize(name) }
78
28
  end
79
29
 
80
- # @path [String]
81
- # @line [Integer]
82
- # @return Bool
83
30
  def include?(path, line)
84
- get(path).include?(line)
85
- rescue KeyError
86
- false
31
+ cache[path].include?(line)
87
32
  end
88
33
 
89
34
  def skipped
@@ -91,62 +36,80 @@ module Rfix
91
36
  end
92
37
 
93
38
  def tracked
94
- files.values.select(&:tracked?)
39
+ files.select(&:tracked?)
95
40
  end
96
41
 
97
42
  def ignored
98
- files.values.select(&:ignored?)
43
+ files.select(&:ignored?)
99
44
  end
100
45
 
101
46
  def untracked
102
- files.values.select(&:untracked?)
47
+ files.select(&:untracked?)
103
48
  end
104
49
 
105
50
  def deleted
106
- files.values.select(&:deleted?)
51
+ files.select(&:deleted?)
107
52
  end
108
53
 
109
- def permitted
110
- untracked + tracked
54
+ def path
55
+ Pathname(workdir)
111
56
  end
112
57
 
113
- def to_s
114
- options = {
115
- untracked: untracked.map(&:basename).join(", "),
116
- tracked: tracked.map(&:basename).join(", "),
117
- ignored: ignored.map(&:basename).join(", "),
118
- deleted: deleted.map(&:basename).join(", ")
119
- }
120
-
121
- "Repository<Untracked: %<untracked>s, Tracked: %<tracked>s, Ignored: %<ignored>s, Deleted: %<deleted>s>" % options
58
+ def cache
59
+ Concurrent::Map.new do |storage, path|
60
+ storage.fetch(Types::Path::Absolute.call(path).to_s, File::Null)
61
+ end.tap do |storage|
62
+ files.each { |file| storage.compute_if_absent(file.key) { file } }
63
+ end
122
64
  end
123
65
 
124
66
  def files
125
- @files ||= EMPTY_HASH.dup
67
+ Diff.new(repository: self, current_path: current_path).deltas.map do |delta|
68
+ File::Tracked.call(**delta.new_file, repository: self, status: delta.status)
69
+ end
126
70
  end
127
71
 
128
- def paths
129
- permitted.map(&:basename)
72
+ def permitted
73
+ files
74
+ end
75
+
76
+ def to_s
77
+ files.each_with_object(INIT.dup) do |file, object|
78
+ object[file.class] << file
79
+ end.map do |type, files|
80
+ "%<type>s[%<count>i]:%<files>s" % {
81
+ files: files.map(&:to_s).join(", "),
82
+ type: type.name.demodulize,
83
+ count: files.count
84
+ }
85
+ end.then do |types|
86
+ "Repository<%<types>s>" % { types: types.join(", ") }
87
+ end
130
88
  end
89
+ alias inspect to_s
131
90
 
132
- def include_file?(path)
133
- permitted.include?(files.fetch(path, Undefined))
91
+ def paths
92
+ permitted.map(&:key).to_a
134
93
  end
135
94
 
136
- private
95
+ def include_file?(path, line = Undefined)
96
+ return cache[path].exists? if line == Undefined
137
97
 
138
- def store(file)
139
- files.store(file.key, file)
98
+ cache[path].include?(line)
140
99
  end
141
100
 
142
- def get(path)
143
- files.fetch(path)
101
+ alias contains? include_file?
102
+ alias include? include_file?
103
+
104
+ # TODO: Refactor
105
+ def origin
106
+ repository.lookup(repository.rev_parse(reference.name).oid)
107
+ rescue Rugged::Error, Rugged::InvalidError, Rugged::ReferenceError
108
+ raise Error, "Reference #{reference.name.inspect} not found"
144
109
  end
145
110
 
146
- def build(path, status)
147
- store(Rfix::File.call(basename: path, status: status, repository: self))
148
- rescue Dry::Struct::Error => e
149
- raise Error, { path: path, status: status, message: e.message }.inspect
111
+ def collector
112
+ Collector.call(repository: self, reference: reference.name)
150
113
  end
151
114
  end
152
115
  end