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 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,204 @@
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
+ say_debug "Checking #{path}:#{line}"
51
+
52
+ if file = @files.get(path)
53
+ return file.include?(line)
54
+ end
55
+
56
+ say_debug "\tSkip file (return false)"
57
+ return false
58
+ end
59
+
60
+ def set_root(_path_path)
61
+ using_path(root_path)
62
+ end
63
+
64
+ def paths
65
+ files.pluck(&:absolute_path)
66
+ end
67
+
68
+ def current_branch
69
+ repo.head.name
70
+ end
71
+
72
+ def has_reference?(reference)
73
+ repo.rev_parse(reference)
74
+ rescue Rugged::ReferenceError
75
+ return false
76
+ end
77
+
78
+ def local_branches
79
+ repo.branches.each_name(:local).to_a
80
+ end
81
+
82
+ def git_path
83
+ repo.workdir
84
+ end
85
+
86
+ def head
87
+ @head ||= repo.rev_parse("HEAD")
88
+ end
89
+
90
+ def upstream
91
+ @upstream ||= reference.resolve(with: repo)
92
+ end
93
+
94
+ private
95
+
96
+ def load_tracked!
97
+ params = {
98
+ # ignore_whitespace_change: true,
99
+ include_untracked_content: true,
100
+ recurse_untracked_dirs: true,
101
+ # ignore_whitespace_eol: true,
102
+ include_unmodified: false,
103
+ include_untracked: true,
104
+ ignore_submodules: true,
105
+ # ignore_whitespace: true,
106
+ include_ignored: false,
107
+ context_lines: 0
108
+ }
109
+
110
+ unless @paths.empty?
111
+ say_debug("Use @paths #{@paths.join(", ")}")
112
+ params[:disable_pathspec_match] = false
113
+ params[:paths] = @paths
114
+ end
115
+
116
+ say_debug("Run diff on #{reference}")
117
+ upstream.diff(head, **params).tap do |diff|
118
+ diff.find_similar!(
119
+ renames_from_rewrites: true,
120
+ renames: true,
121
+ copies: true
122
+ )
123
+ end.each_delta do |delta|
124
+ path = delta.new_file.fetch(:path)
125
+ say_debug("Found #{path} while diff")
126
+ try_store(path, [delta.status])
127
+ end
128
+ rescue Rugged::ReferenceError
129
+ abort_box($ERROR_INFO.to_s) do
130
+ prt "Reference {{error:#{reference}}} cannot be found in repository"
131
+ end
132
+ rescue Rugged::ConfigError
133
+ abort_box($ERROR_INFO.to_s) do
134
+ prt "No upstream branch set for {{error:#{current_branch}}}"
135
+ end
136
+ rescue TypeError
137
+ abort_box($ERROR_INFO.to_s) do
138
+ prt "Reference {{error:#{reference}}} is not pointing to a tree or commit"
139
+ end
140
+ end
141
+
142
+ def load!
143
+ load_tracked!
144
+ load_untracked!
145
+ end
146
+
147
+ # https://github.com/libgit2/rugged/blob/35102c0ca10ab87c4c4ffe2e25221d26993c069c/test/status_test.rb
148
+ # - +:index_new+: the file is new in the index
149
+ # - +:index_modified+: the file has been modified in the index
150
+ # - +:index_deleted+: the file has been deleted from the index
151
+ # - +:worktree_new+: the file is new in the working directory
152
+ # - +:worktree_modified+: the file has been modified in the working directory
153
+ # - +:worktree_deleted+: the file has been deleted from the working directory
154
+
155
+ MODIFIED = [:modified, :worktree_modified, :index_modified].freeze
156
+ IGNORED = [:ignored].freeze
157
+ STAGED = [:added, :index_new].freeze
158
+ UNTRACKED = [:worktree_new, :untracked].freeze
159
+ COPIED = [:copied].freeze
160
+ DELETED = [:deleted, :worktree_deleted, :index_deleted].freeze
161
+ RENAMED = [:renamed].freeze
162
+
163
+ SKIP = [*DELETED, *RENAMED, *COPIED, *IGNORED].freeze
164
+ ACCEPT = [*MODIFIED].freeze
165
+
166
+ def load_untracked!
167
+ repo.status do |path, status|
168
+ try_store(path, status)
169
+ end
170
+ end
171
+
172
+ def store(file)
173
+ say_debug("Trying to add #{file.absolute_path}")
174
+ if File.exist?(file.absolute_path)
175
+ @files.add(file)
176
+ else
177
+ say_debug "#{file} does not exist"
178
+ end
179
+ end
180
+
181
+ def try_store(path, status)
182
+ if SKIP.any?(&status.method(:include?))
183
+ return say_debug("Ignored {{warning:#{status.join(', ')}}} #{path}")
184
+ end
185
+
186
+ if STAGED.any?(&status.method(:include?))
187
+ return store(Rfix::Untracked.new(path, repo, nil))
188
+ end
189
+
190
+ if UNTRACKED.any?(&status.method(:include?))
191
+ unless load_untracked?
192
+ return say_debug("Ignore #{path} as untracked files are ignored: #{status}")
193
+ end
194
+
195
+ return store(Rfix::Untracked.new(path, repo, nil))
196
+ end
197
+
198
+ if ACCEPT.any?(&status.method(:include?))
199
+ return store(Rfix::Tracked.new(path, repo, reference))
200
+ end
201
+
202
+ say_debug "Status not found {{error:#{status.join(', ')}}} for {{italic:#{path}}}"
203
+ end
204
+ 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,72 @@
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
+ say_debug "Does {{yellow:#{set}}} contain {{red:#{line}}}"
9
+ set.include?(line)
10
+ end
11
+
12
+ private
13
+
14
+ # def set
15
+ # return NoFile.new(path) if @set.empty?
16
+ # return @set
17
+ # end
18
+
19
+ # def refresh!
20
+ # @changes = diff.each_line.to_a.map{ |l| l.new_lineno }.to_set
21
+ #
22
+ # if @changes.empty?
23
+ # @changes = NoFile.new(path)
24
+ # end
25
+ # rescue Rugged::TreeError
26
+ # @changed = NoFile.new(path)
27
+ # end
28
+
29
+ # def changes
30
+ # @changes or raise(Rfix::Error, "No changes found: #{self}")
31
+ # end
32
+
33
+ # def needs_update?
34
+ # current_changed_at = changed_at
35
+ # if @changed_at != current_changed_at
36
+ # @changed_at = current_changed_at
37
+ # return true
38
+ # end
39
+ #
40
+ # return false
41
+ # end
42
+
43
+ # def changed_at
44
+ # File.new(absolute_path).ctime
45
+ # end
46
+
47
+ def upstream
48
+ @upstream ||= ref.resolve(with: repo)
49
+ end
50
+
51
+ def head
52
+ @head ||= repo.rev_parse("HEAD")
53
+ end
54
+
55
+ def diff
56
+ upstream.diff_workdir({
57
+ include_untracked_content: true,
58
+ recurse_untracked_dirs: true,
59
+ include_untracked: true,
60
+ ignore_submodules: true,
61
+ include_ignored: false,
62
+ context_lines: 0,
63
+ paths: [path]
64
+ }).tap do |diff|
65
+ diff.find_similar!(
66
+ renames_from_rewrites: true,
67
+ renames: true,
68
+ copies: true
69
+ )
70
+ end
71
+ end
72
+ end