rfix 1.2.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 (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 +201 -0
  77. data/lib/rfix/rfix.rb +34 -0
  78. data/lib/rfix/tracked.rb +76 -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 NoFile < Struct.new(:path)
2
+ def include?(_line)
3
+ return true
4
+ end
5
+
6
+ def divide
7
+ Set.new
8
+ end
9
+
10
+ def empty?
11
+ false
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ module Travis
2
+ SETUP = "travis:setup".freeze
3
+ INSTALL = "travis:install".freeze
4
+ TASKS = "travis:tasks:all".freeze
5
+ GIT = "travis:git:config".freeze
6
+ end
7
+
8
+ module Bundle
9
+ INSTALL = "bundle:install".freeze
10
+ ADD = "bundle:git:add".freeze
11
+ TAG = "rally-point".freeze
12
+ REBUILD = "bundle:rebuild".freeze
13
+ BUILD = "bundle:build".freeze
14
+ ROOT = Dir.getwd
15
+ CONFIG = File.join(ROOT, ".rubocop.yml")
16
+ DIR = File.join(ROOT, "spec/fixtures")
17
+ TMP = File.join(ROOT, "tmp")
18
+
19
+ module Simple
20
+ FILE = File.join(DIR, "simple.bundle")
21
+ REPO = File.join(TMP, "simple")
22
+ REBUILD = "bundle:simple:rebuild".freeze
23
+ BUILD = "bundle:simple:build".freeze
24
+ FLUSH = "bundle:simple:flush".freeze
25
+ TEST = "bundle:simple:test".freeze
26
+ TAG = Bundle::TAG
27
+ end
28
+
29
+ module Complex
30
+ FILE = File.join(DIR, "complex.bundle")
31
+ REPO = File.join(TMP, "complex")
32
+ GITHUB = "https://github.com/oleander/git-fame-rb".freeze
33
+ REBUILD = "bundle:complex:rebuild".freeze
34
+ BUILD = "bundle:complex:build".freeze
35
+ FLUSH = "bundle:complex:flush".freeze
36
+ TEST = "bundle:complex:test".freeze
37
+ TAG = Bundle::TAG
38
+ end
39
+ end
40
+
41
+ module Vendor
42
+ ROOT = File.expand_path(File.join(__dir__, "../../.."))
43
+ DIR = File.join(ROOT, "vendor/shopify")
44
+ REPO = File.join(DIR, "cli-ui")
45
+ GITHUB = "https://github.com/shopify/cli-ui".freeze
46
+ START = "ef976d".freeze
47
+ BUILD = "vendor:shopify:build".freeze
48
+ REBUILD = "vendor:shopify:rebuild".freeze
49
+ TEST = "vendor:shopify:test".freeze
50
+ end
@@ -0,0 +1,75 @@
1
+ require "colorize"
2
+ require "fileutils"
3
+ require "shellwords"
4
+
5
+ module Rfix::Support
6
+ include FileUtils
7
+
8
+ alias _sh sh
9
+ alias _cd cd
10
+ alias _rm_rf rm_rf
11
+ alias _rm_f rm_f
12
+ alias _mkdir_p mkdir_p
13
+ alias _chdir chdir
14
+
15
+ def gemfiles
16
+ Dir["Gemfile*", "ci/Gemfile*"]
17
+ end
18
+
19
+ def say(msg)
20
+ $stderr.puts "#{'==>'.blue} #{to_relative(msg).italic}"
21
+ end
22
+
23
+ def sh(*args)
24
+ args = args.map(&:shellsplit).flatten
25
+ colorize args
26
+ _sh(*args)
27
+ end
28
+
29
+ def chdir(*args, &block)
30
+ colorize :cd, args
31
+ _chdir(*args, &block)
32
+ end
33
+
34
+ def rm_rf(*args)
35
+ colorize :rm, args
36
+ _rm_rf(*args)
37
+ end
38
+
39
+ def rm_f(*args)
40
+ colorize :rm, args
41
+ _rm_f(*args)
42
+ end
43
+
44
+ def cd(*args, &block)
45
+ colorize :cd, args
46
+ _cd(*args, &block)
47
+ end
48
+
49
+ def mkdir_p(*args)
50
+ colorize :mkdir, args
51
+ _mkdir_p(*args)
52
+ end
53
+
54
+ def clone_and_run(&block)
55
+ Dir.mktmpdir do |repo|
56
+ sh "git clone", Bundle::Complex::FILE, repo, "--branch", "master"
57
+ Dir.chdir(repo) { block.call(repo) }
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def current_path
64
+ File.join(Dir.getwd, "/")
65
+ end
66
+
67
+ def to_relative(path)
68
+ path.to_s.gsub(current_path, "")
69
+ end
70
+
71
+ def colorize(*args)
72
+ head, *tail = args.flatten.map(&method(:to_relative))
73
+ say [head.yellow, tail.join(" ").italic].join(" ")
74
+ end
75
+ end
@@ -0,0 +1,201 @@
1
+ require "rugged"
2
+ require "rfix/file"
3
+ require "rfix/file_cache"
4
+ require "rfix/untracked"
5
+ require "rfix/tracked"
6
+
7
+ class Rfix::Repository
8
+ include Rfix::Log
9
+ attr_reader :files, :repo
10
+
11
+ def initialize(root_path:, load_untracked: false, reference: Rfix::Branch::HEAD, paths: [])
12
+ unless File.exist?(root_path)
13
+ raise Rfix::Error, "#{root_path} does not exist"
14
+ end
15
+
16
+ unless Pathname.new(root_path).absolute?
17
+ raise Rfix::Error, "#{root_path} is not absolute"
18
+ end
19
+
20
+ unless reference.is_a?(Rfix::Branch::Base)
21
+ raise Rfix::Error.new("Need Branch::Base, got {{error:#{reference.class}}}")
22
+ end
23
+
24
+ @files = FileCache.new(root_path)
25
+ @repo = Rugged::Repository.new(root_path)
26
+ @paths = paths
27
+ @reference = reference
28
+ @load_untracked = load_untracked
29
+
30
+ load!
31
+ end
32
+
33
+ def load_untracked?
34
+ @load_untracked
35
+ end
36
+
37
+ def load_tracked?
38
+ !! @reference
39
+ end
40
+
41
+ def reference
42
+ @reference
43
+ end
44
+
45
+ def refresh!(path)
46
+ @files.get(path).refresh!
47
+ end
48
+
49
+ def include?(path, line)
50
+ if file = @files.get(path)
51
+ return file.include?(line)
52
+ end
53
+
54
+ return false
55
+ end
56
+
57
+ def set_root(_path_path)
58
+ using_path(root_path)
59
+ end
60
+
61
+ def paths
62
+ files.pluck(&:absolute_path)
63
+ end
64
+
65
+ def current_branch
66
+ repo.head.name
67
+ end
68
+
69
+ def has_reference?(reference)
70
+ repo.rev_parse(reference)
71
+ rescue Rugged::ReferenceError
72
+ return false
73
+ end
74
+
75
+ def local_branches
76
+ repo.branches.each_name(:local).to_a
77
+ end
78
+
79
+ def git_path
80
+ repo.workdir
81
+ end
82
+
83
+ def head
84
+ @head ||= repo.rev_parse("HEAD")
85
+ end
86
+
87
+ def upstream
88
+ @upstream ||= reference.resolve(with: repo)
89
+ end
90
+
91
+ private
92
+
93
+ def load_tracked!
94
+ params = {
95
+ # ignore_whitespace_change: true,
96
+ include_untracked_content: true,
97
+ recurse_untracked_dirs: true,
98
+ # ignore_whitespace_eol: true,
99
+ include_unmodified: false,
100
+ include_untracked: true,
101
+ ignore_submodules: true,
102
+ # ignore_whitespace: true,
103
+ include_ignored: false,
104
+ context_lines: 0
105
+ }
106
+
107
+ unless @paths.empty?
108
+ say_debug("Use @paths #{@paths.join(", ")}")
109
+ params[:disable_pathspec_match] = false
110
+ params[:paths] = @paths
111
+ end
112
+
113
+ say_debug("Run diff on #{reference}")
114
+ upstream.diff(head, **params).tap do |diff|
115
+ diff.find_similar!(
116
+ renames_from_rewrites: true,
117
+ renames: true,
118
+ copies: true
119
+ )
120
+ end.each_delta do |delta|
121
+ path = delta.new_file.fetch(:path)
122
+ say_debug("Found #{path} while diff")
123
+ try_store(path, [delta.status])
124
+ end
125
+ rescue Rugged::ReferenceError
126
+ abort_box($ERROR_INFO.to_s) do
127
+ prt "Reference {{error:#{reference}}} cannot be found in repository"
128
+ end
129
+ rescue Rugged::ConfigError
130
+ abort_box($ERROR_INFO.to_s) do
131
+ prt "No upstream branch set for {{error:#{current_branch}}}"
132
+ end
133
+ rescue TypeError
134
+ abort_box($ERROR_INFO.to_s) do
135
+ prt "Reference {{error:#{reference}}} is not pointing to a tree or commit"
136
+ end
137
+ end
138
+
139
+ def load!
140
+ load_tracked!
141
+ load_untracked!
142
+ end
143
+
144
+ # https://github.com/libgit2/rugged/blob/35102c0ca10ab87c4c4ffe2e25221d26993c069c/test/status_test.rb
145
+ # - +:index_new+: the file is new in the index
146
+ # - +:index_modified+: the file has been modified in the index
147
+ # - +:index_deleted+: the file has been deleted from the index
148
+ # - +:worktree_new+: the file is new in the working directory
149
+ # - +:worktree_modified+: the file has been modified in the working directory
150
+ # - +:worktree_deleted+: the file has been deleted from the working directory
151
+
152
+ MODIFIED = [:modified, :worktree_modified, :index_modified].freeze
153
+ IGNORED = [:ignored].freeze
154
+ STAGED = [:added, :index_new].freeze
155
+ UNTRACKED = [:worktree_new, :untracked].freeze
156
+ COPIED = [:copied].freeze
157
+ DELETED = [:deleted, :worktree_deleted, :index_deleted].freeze
158
+ RENAMED = [:renamed].freeze
159
+
160
+ SKIP = [*DELETED, *RENAMED, *COPIED, *IGNORED].freeze
161
+ ACCEPT = [*MODIFIED].freeze
162
+
163
+ def load_untracked!
164
+ repo.status do |path, status|
165
+ try_store(path, status)
166
+ end
167
+ end
168
+
169
+ def store(file)
170
+ say_debug("Trying to add #{file.absolute_path}")
171
+ if File.exist?(file.absolute_path)
172
+ @files.add(file)
173
+ else
174
+ say_debug "#{file} does not exist"
175
+ end
176
+ end
177
+
178
+ def try_store(path, status)
179
+ if SKIP.any?(&status.method(:include?))
180
+ return say_debug("Ignored {{warning:#{status.join(', ')}}} #{path}")
181
+ end
182
+
183
+ if STAGED.any?(&status.method(:include?))
184
+ return store(Rfix::Untracked.new(path, repo, nil))
185
+ end
186
+
187
+ if UNTRACKED.any?(&status.method(:include?))
188
+ unless load_untracked?
189
+ return say_debug("Ignore #{path} as untracked files are ignored: #{status}")
190
+ end
191
+
192
+ return store(Rfix::Untracked.new(path, repo, nil))
193
+ end
194
+
195
+ if ACCEPT.any?(&status.method(:include?))
196
+ return store(Rfix::Tracked.new(path, repo, reference))
197
+ end
198
+
199
+ say_debug "Status not found {{error:#{status.join(', ')}}} for {{italic:#{path}}}"
200
+ end
201
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "rfix/log"
5
+
6
+ module Rfix
7
+ include Log
8
+ attr_accessor :repo
9
+ attr_accessor :test
10
+
11
+ alias test? test
12
+
13
+ def global_enable!
14
+ @global_enable = true
15
+ end
16
+
17
+ def global_enable?
18
+ @global_enable
19
+ end
20
+
21
+ def refresh!(source)
22
+ return true if global_enable?
23
+
24
+ repo.refresh!(source.file_path)
25
+ end
26
+
27
+ def enabled?(path, line)
28
+ return true if global_enable?
29
+
30
+ repo.include?(path, line)
31
+ end
32
+ end
33
+
34
+ # rubocop:enable Layout/LineLength
@@ -0,0 +1,76 @@
1
+ require "rfix/no_file"
2
+
3
+ class Rfix::Tracked < Rfix::File
4
+ include Rfix::Log
5
+
6
+ def include?(line)
7
+ set = diff.each_line.to_a.map{ |l| l.new_lineno }.reject { |l| l == -1 }.to_set
8
+ set.include?(line)
9
+ end
10
+
11
+ private
12
+
13
+ # def set
14
+ # return NoFile.new(path) if @set.empty?
15
+ # return @set
16
+ # end
17
+
18
+ # def refresh!
19
+ # @changes = diff.each_line.to_a.map{ |l| l.new_lineno }.to_set
20
+ #
21
+ # if @changes.empty?
22
+ # @changes = NoFile.new(path)
23
+ # end
24
+ # rescue Rugged::TreeError
25
+ # @changed = NoFile.new(path)
26
+ # end
27
+
28
+ # def changes
29
+ # @changes or raise(Rfix::Error, "No changes found: #{self}")
30
+ # end
31
+
32
+ # def needs_update?
33
+ # current_changed_at = changed_at
34
+ # if @changed_at != current_changed_at
35
+ # @changed_at = current_changed_at
36
+ # return true
37
+ # end
38
+ #
39
+ # return false
40
+ # end
41
+
42
+ # def changed_at
43
+ # File.new(absolute_path).ctime
44
+ # end
45
+
46
+ def upstream
47
+ @upstream ||= ref.resolve(with: repo)
48
+ end
49
+
50
+ def head
51
+ @head ||= repo.rev_parse("HEAD")
52
+ end
53
+
54
+ def diff
55
+ upstream.diff(head, {
56
+ include_untracked_content: true,
57
+ # ignore_whitespace_change: true,
58
+ recurse_untracked_dirs: true,
59
+ disable_pathspec_match: false,
60
+ # ignore_whitespace_eol: false,
61
+ include_untracked: true,
62
+ # ignore_whitespace: true,
63
+ ignore_submodules: true,
64
+ include_ignored: false,
65
+ context_lines: 0,
66
+ paths: [path]
67
+ }).tap do |diff|
68
+ diff.find_similar!(
69
+ renames_from_rewrites: true,
70
+ # ignore_whitespace: true,
71
+ renames: true,
72
+ copies: true
73
+ )
74
+ end
75
+ end
76
+ end