rfix 2.0.4 → 3.0.0

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 (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
data/lib/rfix/diff.rb ADDED
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/struct"
4
+ require "rugged"
5
+
6
+ module Rfix
7
+ class Diff < Dry::Struct
8
+ # https://github.com/libgit2/rugged/blob/master/ext/rugged/rugged_diff.c
9
+
10
+ attribute :options, Types::Hash.default(EMPTY_HASH)
11
+ attribute :current_path, Types::Path::Relative.default(Pathname(".").freeze)
12
+ attribute :repository, Repository
13
+
14
+ delegate :index, :origin, to: :repository
15
+ delegate :each_line, to: :diff
16
+
17
+ alias lines each_line
18
+
19
+ OPTIONS = {
20
+ context_lines: 1,
21
+ ignore_whitespace: true,
22
+ ignore_whitespace_change: true,
23
+ ignore_whitespace_eol: true,
24
+ disable_pathspec_match: false,
25
+ ignore_submodules: true,
26
+ include_ignored: false,
27
+ include_unmodified: false,
28
+ skip_binary_check: true,
29
+ ignore_filemode: true,
30
+ include_untracked_content: false,
31
+ include_typechange: false
32
+ }.freeze
33
+
34
+ def deltas
35
+ diff.deltas.reject(&:deleted?)
36
+ end
37
+
38
+ def files
39
+ deltas.map(&:new_file).map do |file|
40
+ repository.path.join(file.fetch(:path))
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def diff
47
+ origin.diff(index, **extended_options).tap do |diff|
48
+ diff.merge!(index.diff(**extended_options))
49
+ diff.find_similar!(all: true, ignore_whitespace: true)
50
+ end
51
+ end
52
+
53
+ def absolute_path
54
+ repository.path.join(current_path)
55
+ end
56
+
57
+ def extended_options
58
+ unless absolute_path.exist?
59
+ raise Error, "#{current_path} path does not exist in #{repository.path}"
60
+ end
61
+
62
+ unless absolute_path.directory?
63
+ raise Error, "#{current_path} is not a directory"
64
+ end
65
+
66
+ OPTIONS.merge(**options, paths: [current_path.join("**/*").to_s])
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ class CommentConfig
7
+ concerning :Fallback, prepend: true do
8
+ def cop_enabled_at_line?(_, line)
9
+ super && repository.include?(processed_source.file_path, line)
10
+ rescue StandardError => e
11
+ abort e.full_message(highlight: true)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,14 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/inflections"
4
+ require "dry/core/constants"
4
5
  require "shellwords"
5
6
  require "pathname"
6
7
  require "tty-link"
7
8
  require "rainbow"
9
+ require "rubocop"
10
+ require "rubocop/cop/offense"
8
11
 
9
- module Rfix
10
- module Extension
11
- module Offense
12
+ module RuboCop
13
+ module Cop
14
+ class Offense
15
+ # concerning :Features do
12
16
  STAR = Rainbow("⭑").yellow
13
17
  CROSS = Rainbow("✗").red
14
18
  CHECK = Rainbow("✓").green
@@ -32,32 +36,30 @@ module Rfix
32
36
  message.split(": ", 2).first
33
37
  end
34
38
 
35
- def relative_path
39
+ def relative_path(root_path)
36
40
  return EMPTY_STRING unless location.respond_to?(:source_buffer)
37
41
 
38
- location.source_buffer.name.sub(Dir.pwd, EMPTY_STRING).chars.drop_while do |char|
39
- char == "/"
40
- end.join
41
- rescue ArgumentError
42
- nil
42
+ Pathname(location.source_buffer.name).relative_path_from(root_path)
43
43
  end
44
44
 
45
- def clickable_path
46
- Rainbow("#{relative_path}:#{where}").italic
45
+ def clickable_path(root_path)
46
+ Rainbow("#{relative_path(root_path)}:#{where}").italic
47
47
  end
48
48
 
49
- def clickable_plain_severity
49
+ def href
50
50
  cop_name.split("/", 2).then do |department, cop|
51
51
  return nil if [cop, department].any?(&:nil?)
52
52
 
53
53
  { type: department.parameterize, cop: cop.parameterize }
54
54
  end.then do |options|
55
55
  "https://docs.rubocop.org/rubocop/cops_%<type>s.html#%<type>s%<cop>s" % options
56
- end.then do |url|
57
- TTY::Link.link_to(cop_name, url)
58
56
  end
59
57
  end
60
58
 
59
+ def clickable_plain_severity
60
+ TTY::Link.link_to(cop_name, href)
61
+ end
62
+
61
63
  def clickable_severity
62
64
  clickable_plain_severity && Rainbow(clickable_plain_severity).italic
63
65
  end
@@ -74,6 +76,7 @@ module Rfix
74
76
  def escape(str)
75
77
  Shellwords.escape(str)
76
78
  end
79
+ # end
77
80
  end
78
81
  end
79
82
  end
@@ -1,11 +1,14 @@
1
- require "strings-ansi"
1
+ # frozen_string_literal: true
2
+
2
3
  require "pastel"
4
+ require "strings"
3
5
 
4
6
  module Pastel
5
7
  class Color
6
- def strip(*strings)
7
- modified = strings.map(&Strings::ANSI.method(:sanitize))
8
- modified.size == 1 ? modified[0] : modified
8
+ concerning :Fallback, prepend: true do
9
+ def strip(*strings)
10
+ super(*strings.map(&Strings::ANSI.method(:sanitize)))
11
+ end
9
12
  end
10
13
  end
11
14
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty/progressbar"
4
+
5
+ module TTY
6
+ class ProgressBar
7
+ concerning :Log, prepend: true do
8
+ def log(input)
9
+ input.each_line do |line|
10
+ super(line.strip)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "strings"
2
4
 
3
5
  module Strings
4
6
  module Wrap
5
- def self.wrap(line, *, **)
6
- line
7
+ concerning :Fallback, prepend: true do
8
+ class_methods do
9
+ def wrap(line, *, **)
10
+ super
11
+ rescue IndexError
12
+ line
13
+ end
14
+ end
7
15
  end
8
16
  end
9
17
  end
data/lib/rfix/file.rb CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  module Rfix
4
4
  module File
5
- Self = Deleted | Ignored | Tracked | Untracked
5
+ def self.sum
6
+ Deleted | Ignored | Tracked | Untracked
7
+ end
6
8
 
7
- def self.call(input)
8
- Self.call(input)
9
+ class << self
10
+ delegate :call, to: :sum
9
11
  end
10
12
  end
11
13
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/string/inflections"
3
4
  require "rugged"
4
5
  require "pathname"
5
6
  require "dry/struct"
@@ -35,32 +36,38 @@ module Rfix
35
36
  abstract_class self
36
37
 
37
38
  attribute :repository, Repository
38
- attribute :basename, Types::String
39
+ attribute :basename, Types::Path::Relative
39
40
 
40
- UNTRACKED = [:worktree_new, :index_new]
41
- DELETED = [:deleted, :worktree_deleted]
42
- IGNORED = [:ignored, :unmodified].freeze
41
+ UNTRACKED = %i[worktree_new index_new].freeze
42
+ DELETED = %i[deleted worktree_deleted].freeze
43
+ IGNORED = %i[ignored unmodified].freeze
43
44
  TRACKED = [:added].freeze
44
45
 
45
- def key
46
- path.to_s
46
+ delegate :delete, to: :path
47
+ delegate :to_s, to: :basename
48
+
49
+ def to_table
50
+ [basename]
47
51
  end
48
52
 
49
- # @return [Pathnane]
50
- def path
51
- repository.path.join(basename)
53
+ def key
54
+ raise NotImplementedError
52
55
  end
53
56
 
54
- def include?(*, **)
55
- raise NotImplementedError, self.class.name
57
+ def lines
58
+ EMPTY_ARRAY
56
59
  end
57
60
 
58
- def refresh!(*)
59
- # NOP
61
+ def contains?(file)
62
+ path == file
60
63
  end
61
64
 
62
65
  def inspect
63
- "<#{self.class.name}(#{status.join(', ')}:#{basename})>"
66
+ "<#{self.class.name.demodulize}(#{status.join(', ')}:#{self})>"
67
+ end
68
+
69
+ def exists?
70
+ false
64
71
  end
65
72
 
66
73
  %i[untracked? tracked? ignored? deleted?].each do |name|
@@ -3,6 +3,8 @@
3
3
  module Rfix
4
4
  module File
5
5
  class Deleted < Base
6
+ ID = "[D]".color(:red).freeze
7
+
6
8
  attribute :status, Types::Status::Deleted
7
9
 
8
10
  def deleted?
@@ -3,6 +3,8 @@
3
3
  module Rfix
4
4
  module File
5
5
  class Ignored < Base
6
+ ID = "[I]".color(:blue).freeze
7
+
6
8
  attribute :status, Types::Status::Ignored
7
9
 
8
10
  def include?(*)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rfix
4
+ module File
5
+ module Null
6
+ def include?(*)
7
+ false
8
+ end
9
+
10
+ def exists?
11
+ false
12
+ end
13
+
14
+ module_function :include?, :exists?
15
+ end
16
+ end
17
+ end
@@ -1,41 +1,57 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rainbow/ext/string"
4
+
3
5
  module Rfix
4
6
  module File
5
- class Tracked < Base
6
- attribute :status, Types::Status::Tracked
7
+ class Tracked < Dry::Struct
8
+ ID = "[T]".color(:lightseagreen).freeze
9
+
10
+ attribute :status, Types::Symbol
11
+ attribute :path, Types::Path::Relative
12
+ attribute :repository, Repository
13
+
14
+ delegate :include?, to: :lines
15
+
16
+ def key
17
+ absolute_path.to_s
18
+ end
7
19
 
8
- OPTIONS = {
9
- include_untracked_content: true,
10
- recurse_untracked_dirs: true,
11
- include_untracked: true,
12
- ignore_submodules: true,
13
- include_ignored: false,
14
- context_lines: 0
15
- }.freeze
20
+ def absolute_path
21
+ repository.path.join(path)
22
+ end
16
23
 
17
- def include?(line)
18
- diff.each_line.map(&:new_lineno).select(&:positive?).to_set.include?(line)
24
+ def exists?
25
+ true
19
26
  end
20
27
 
21
28
  def tracked?
22
29
  true
23
30
  end
24
31
 
25
- private
32
+ def to_s
33
+ "%s:%s" % [path, to_str_range]
34
+ end
35
+
36
+ def to_str_range
37
+ lines
38
+ .to_a
39
+ .sort
40
+ .chunk_while { |i, j| i + 1 == j }
41
+ .map { |a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
42
+ .join(",")
43
+ .then { |res| res.empty? ? "-" : res }
44
+ end
26
45
 
27
- def options
28
- OPTIONS.dup.merge(paths: [basename])
46
+ def to_table
47
+ [path, to_str_range]
29
48
  end
30
49
 
31
- def diff
32
- repository.origin.diff_workdir(**options).tap do |diff|
33
- diff.find_similar!(
34
- renames_from_rewrites: true,
35
- renames: true,
36
- copies: true
37
- )
38
- end
50
+ def lines
51
+ Diff.new(repository: repository, options: {
52
+ paths: [path.to_path],
53
+ disable_pathspec_match: true,
54
+ }).lines.lazy.map(&:new_lineno).select(&:positive?)
39
55
  end
40
56
  end
41
57
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rfix
4
+ module File
5
+ class Undefined < Base
6
+ ID = "[U]".color(:orange).freeze
7
+
8
+ def include?(*)
9
+ false
10
+ end
11
+
12
+ def ignored?
13
+ true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/types"
4
+ require "rainbow/ext/string"
4
5
 
5
6
  module Rfix
6
7
  module File
7
8
  class Untracked < Base
9
+ ID = "[U]".color(:palevioletred)
10
+
8
11
  attribute :status, Types::Status::Untracked
9
12
 
10
13
  def untracked?
@@ -14,7 +17,6 @@ module Rfix
14
17
  def include?(*)
15
18
  true
16
19
  end
17
-
18
20
  end
19
21
  end
20
22
  end