mudguard 0.1.4 → 0.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.
- checksums.yaml +4 -4
- data/.gitignore +8 -0
- data/.mudguard.yml +6 -0
- data/.rubocop.yml +2 -0
- data/Gemfile.lock +25 -23
- data/Guardfile +1 -1
- data/README.md +62 -9
- data/exe/mudguard +5 -12
- data/lib/mudguard.rb +2 -17
- data/lib/mudguard/application/application.rb +33 -0
- data/lib/mudguard/domain/const_visitor.rb +20 -0
- data/lib/mudguard/domain/consts.rb +81 -0
- data/lib/mudguard/domain/dependencies.rb +47 -0
- data/lib/mudguard/domain/dependency.rb +28 -0
- data/lib/mudguard/domain/dependency_visitor.rb +32 -0
- data/lib/mudguard/{error.rb → domain/error.rb} +3 -1
- data/lib/mudguard/domain/policies.rb +49 -0
- data/lib/mudguard/domain/source.rb +79 -0
- data/lib/mudguard/domain/source_policies.rb +8 -0
- data/lib/mudguard/domain/source_processor.rb +92 -0
- data/lib/mudguard/domain/texts.rb +42 -0
- data/lib/mudguard/infrastructure/cli/controller.rb +78 -0
- data/lib/mudguard/infrastructure/cli/notification_adapter.rb +26 -0
- data/lib/mudguard/infrastructure/cli/view.rb +14 -0
- data/lib/mudguard/infrastructure/persistence/.mudguard.template.yml +6 -0
- data/lib/mudguard/infrastructure/persistence/policy_file.rb +46 -0
- data/lib/mudguard/infrastructure/persistence/project_repository.rb +31 -0
- data/lib/mudguard/infrastructure/persistence/ruby_files.rb +39 -0
- data/lib/mudguard/infrastructure/rake/task.rb +28 -0
- data/lib/mudguard/version.rb +1 -1
- data/mudguard.gemspec +2 -1
- metadata +40 -11
- data/lib/mudguard/policies.rb +0 -23
- data/lib/mudguard/policy_file.rb +0 -17
- data/lib/mudguard/ruby_analyser.rb +0 -74
- data/lib/mudguard/ruby_files.rb +0 -17
- data/lib/tasks/gem.rake +0 -15
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require_relative "../../domain/policies"
|
5
|
+
require_relative "../../domain/error"
|
6
|
+
|
7
|
+
module Mudguard
|
8
|
+
module Infrastructure
|
9
|
+
module Persistence
|
10
|
+
# A file containing the Mudguard-Policies
|
11
|
+
class PolicyFile
|
12
|
+
class << self
|
13
|
+
def read(project_path)
|
14
|
+
policy_file = File.join(project_path, ".mudguard.yml")
|
15
|
+
policy_exists = File.exist?(policy_file)
|
16
|
+
|
17
|
+
unless policy_exists
|
18
|
+
template_file = File.join(__dir__, ".mudguard.template.yml")
|
19
|
+
FileUtils.cp(template_file, policy_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
read_yml(policy_file)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def read_yml(policy_file)
|
28
|
+
yaml_file = File.read(policy_file)
|
29
|
+
yaml = YAML.safe_load(yaml_file, [Symbol], [], policy_file) || {}
|
30
|
+
yaml.transform_values { |value| (value || []).map(&method(:unsymbolize)) }
|
31
|
+
rescue Psych::SyntaxError => e
|
32
|
+
raise Mudguard::Domain::Error, "#{policy_file} is invalid (#{e.message})"
|
33
|
+
end
|
34
|
+
|
35
|
+
def unsymbolize(dependency)
|
36
|
+
if dependency.is_a?(Symbol)
|
37
|
+
":#{dependency}"
|
38
|
+
else
|
39
|
+
dependency
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "policy_file"
|
4
|
+
require_relative "ruby_files"
|
5
|
+
require_relative "../../domain/source_policies"
|
6
|
+
|
7
|
+
module Mudguard
|
8
|
+
module Infrastructure
|
9
|
+
module Persistence
|
10
|
+
# Provides access to the persisted source and policies
|
11
|
+
class ProjectRepository
|
12
|
+
class << self
|
13
|
+
def load_source_policies(project_path)
|
14
|
+
file = PolicyFile.read(project_path)
|
15
|
+
scopes = file.flat_map do |patterns, policies|
|
16
|
+
sources = RubyFiles.select(project_path, patterns: [patterns])
|
17
|
+
sources.flat_map { |s| { source: s, policies: policies } }
|
18
|
+
end
|
19
|
+
|
20
|
+
sources = scopes.group_by { |e| e[:source] }
|
21
|
+
|
22
|
+
sources.map do |source, group|
|
23
|
+
policies = group.flat_map { |r| r[:policies] }.uniq
|
24
|
+
Domain::SourcePolicies.new(source: source, policies: policies)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "mudguard/domain/source"
|
5
|
+
|
6
|
+
module Mudguard
|
7
|
+
module Infrastructure
|
8
|
+
module Persistence
|
9
|
+
# Provides access to all ruby-files of a project
|
10
|
+
class RubyFiles
|
11
|
+
class << self
|
12
|
+
def select(project_path, patterns: nil)
|
13
|
+
project_exists = Dir.exist?(project_path)
|
14
|
+
|
15
|
+
unless project_exists
|
16
|
+
raise Mudguard::Domain::Error, "expected project #{project_path} doesn't exists"
|
17
|
+
end
|
18
|
+
|
19
|
+
patterns = [File.join("**", "*.rb")] if patterns.nil?
|
20
|
+
enumerate_files(project_path, patterns)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def enumerate_files(project_path, patterns)
|
26
|
+
project_path_name = Pathname.new(project_path)
|
27
|
+
ruby_files = patterns.map { |p| File.join(project_path, p) }
|
28
|
+
Dir.glob(ruby_files).map do |f|
|
29
|
+
file_path_name = Pathname.new(f)
|
30
|
+
diff_path = file_path_name.relative_path_from(project_path_name).to_s
|
31
|
+
Mudguard::Domain::Source.new(location: File.join("./", diff_path),
|
32
|
+
code_loader: -> { File.read(f) })
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
require "rake/tasklib"
|
5
|
+
require_relative "../../application/application"
|
6
|
+
require_relative "../../infrastructure/cli/notification_adapter"
|
7
|
+
require_relative "../../infrastructure/cli/view"
|
8
|
+
|
9
|
+
module Mudguard
|
10
|
+
module Infrastructure
|
11
|
+
module Rake
|
12
|
+
# Provides Mudguard Rake Tasks
|
13
|
+
class Task < ::Rake::TaskLib
|
14
|
+
def initialize(project_dir: Dir.pwd)
|
15
|
+
@project_dir = project_dir
|
16
|
+
|
17
|
+
desc "Run Mudguard"
|
18
|
+
task(:mudguard) do
|
19
|
+
view = Mudguard::Infrastructure::Cli::View.new
|
20
|
+
notification = Mudguard::Infrastructure::Cli::NotificationAdapter.new(view: view)
|
21
|
+
ok = Application.check(@project_dir, notification)
|
22
|
+
abort unless ok
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mudguard/version.rb
CHANGED
data/mudguard.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = "mudguard helps your ruby project not becoming a "\
|
14
14
|
"'Big ball of mud'"
|
15
|
-
spec.homepage = "https://
|
15
|
+
spec.homepage = "https://github.com/Enceradeira/mudguard"
|
16
16
|
spec.license = "MIT"
|
17
17
|
|
18
18
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -40,4 +40,5 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency "rubocop", "~>0.80"
|
41
41
|
|
42
42
|
spec.add_dependency "parser", "~>2.7"
|
43
|
+
spec.add_dependency "rake", "~> 13.0"
|
43
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mudguard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorg Jenni
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '2.7'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rake
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '13.0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '13.0'
|
153
167
|
description:
|
154
168
|
email:
|
155
169
|
- jorg.jenni@jennius.co.uk
|
@@ -160,6 +174,7 @@ extra_rdoc_files: []
|
|
160
174
|
files:
|
161
175
|
- ".envrc"
|
162
176
|
- ".gitignore"
|
177
|
+
- ".mudguard.yml"
|
163
178
|
- ".rubocop.yml"
|
164
179
|
- ".ruby-version"
|
165
180
|
- CODE_OF_CONDUCT.md
|
@@ -171,23 +186,37 @@ files:
|
|
171
186
|
- Rakefile
|
172
187
|
- exe/mudguard
|
173
188
|
- lib/mudguard.rb
|
174
|
-
- lib/mudguard/
|
175
|
-
- lib/mudguard/
|
176
|
-
- lib/mudguard/
|
177
|
-
- lib/mudguard/
|
178
|
-
- lib/mudguard/
|
189
|
+
- lib/mudguard/application/application.rb
|
190
|
+
- lib/mudguard/domain/const_visitor.rb
|
191
|
+
- lib/mudguard/domain/consts.rb
|
192
|
+
- lib/mudguard/domain/dependencies.rb
|
193
|
+
- lib/mudguard/domain/dependency.rb
|
194
|
+
- lib/mudguard/domain/dependency_visitor.rb
|
195
|
+
- lib/mudguard/domain/error.rb
|
196
|
+
- lib/mudguard/domain/policies.rb
|
197
|
+
- lib/mudguard/domain/source.rb
|
198
|
+
- lib/mudguard/domain/source_policies.rb
|
199
|
+
- lib/mudguard/domain/source_processor.rb
|
200
|
+
- lib/mudguard/domain/texts.rb
|
201
|
+
- lib/mudguard/infrastructure/cli/controller.rb
|
202
|
+
- lib/mudguard/infrastructure/cli/notification_adapter.rb
|
203
|
+
- lib/mudguard/infrastructure/cli/view.rb
|
204
|
+
- lib/mudguard/infrastructure/persistence/.mudguard.template.yml
|
205
|
+
- lib/mudguard/infrastructure/persistence/policy_file.rb
|
206
|
+
- lib/mudguard/infrastructure/persistence/project_repository.rb
|
207
|
+
- lib/mudguard/infrastructure/persistence/ruby_files.rb
|
208
|
+
- lib/mudguard/infrastructure/rake/task.rb
|
179
209
|
- lib/mudguard/version.rb
|
180
|
-
- lib/tasks/gem.rake
|
181
210
|
- lib/tasks/rubocop.rake
|
182
211
|
- lib/tasks/test.rake
|
183
212
|
- mudguard.gemspec
|
184
213
|
- pkg/mudguard-0.1.0.gem
|
185
|
-
homepage: https://
|
214
|
+
homepage: https://github.com/Enceradeira/mudguard
|
186
215
|
licenses:
|
187
216
|
- MIT
|
188
217
|
metadata:
|
189
|
-
homepage_uri: https://
|
190
|
-
source_code_uri: https://
|
218
|
+
homepage_uri: https://github.com/Enceradeira/mudguard
|
219
|
+
source_code_uri: https://github.com/Enceradeira/mudguard
|
191
220
|
post_install_message:
|
192
221
|
rdoc_options: []
|
193
222
|
require_paths:
|
data/lib/mudguard/policies.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "ruby_analyser"
|
4
|
-
|
5
|
-
module Mudguard
|
6
|
-
# Contains the policies to be enforced
|
7
|
-
class Policies
|
8
|
-
def initialize(policies: [])
|
9
|
-
@policies = policies.map { |l| l.gsub(/\s/, "") }.map { |p| /^#{p}/ }
|
10
|
-
end
|
11
|
-
|
12
|
-
def check(sources)
|
13
|
-
sources.all? do |source|
|
14
|
-
dependencies = RubyAnalyser.find_mod_dependencies(source)
|
15
|
-
dependencies.all? do |d|
|
16
|
-
@policies.any? do |p|
|
17
|
-
d.match?(p)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/mudguard/policy_file.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "policies"
|
4
|
-
require_relative "error"
|
5
|
-
|
6
|
-
module Mudguard
|
7
|
-
# A file containing the Mudguard-Policies
|
8
|
-
class PolicyFile
|
9
|
-
def self.read(policy_file)
|
10
|
-
policy_exists = File.exist?(policy_file)
|
11
|
-
|
12
|
-
raise Error, "expected policy file #{policy_file} doesn't exists" unless policy_exists
|
13
|
-
|
14
|
-
Policies.new(policies: File.readlines(policy_file))
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "parser/current"
|
4
|
-
|
5
|
-
module Mudguard
|
6
|
-
# Analyses Ruby-Source and returns extracted information
|
7
|
-
class RubyAnalyser
|
8
|
-
class << self
|
9
|
-
def find_mod_dependencies(source)
|
10
|
-
begin
|
11
|
-
root = Parser::CurrentRuby.parse(source)
|
12
|
-
rescue Parser::SyntaxError
|
13
|
-
return []
|
14
|
-
end
|
15
|
-
return [] if root.nil?
|
16
|
-
|
17
|
-
process(root)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def process(node, module_name = "")
|
23
|
-
case node
|
24
|
-
when type?(:module)
|
25
|
-
process_module(node.children)
|
26
|
-
when type?(:class)
|
27
|
-
process_class(node.children, module_name)
|
28
|
-
when type?(:const)
|
29
|
-
["#{module_name}->#{find_const_name(node.children)}"]
|
30
|
-
else
|
31
|
-
ignore_and_continue(node, module_name)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def ignore_and_continue(node, module_name)
|
36
|
-
case node
|
37
|
-
when children?
|
38
|
-
node.children.flat_map { |c| process(c, module_name) }
|
39
|
-
else
|
40
|
-
[]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def process_module(children)
|
45
|
-
module_name = find_const_name(children[0].children)
|
46
|
-
process(children[1], module_name)
|
47
|
-
end
|
48
|
-
|
49
|
-
def process_class(children, module_name)
|
50
|
-
process(children[1], module_name)
|
51
|
-
end
|
52
|
-
|
53
|
-
def find_const_name(children)
|
54
|
-
return nil if children.nil?
|
55
|
-
|
56
|
-
module_name = find_const_name(children[0]&.children)
|
57
|
-
const_name = children[1].to_s
|
58
|
-
if module_name.nil?
|
59
|
-
const_name
|
60
|
-
else
|
61
|
-
"#{module_name}::#{const_name}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def children?
|
66
|
-
->(n) { n.respond_to?(:children) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def type?(type)
|
70
|
-
->(n) { n.respond_to?(:type) && n.type == type }
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/mudguard/ruby_files.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mudguard
|
4
|
-
# Provides access to all ruby-files of a project
|
5
|
-
class RubyFiles
|
6
|
-
class << self
|
7
|
-
def all(project_path)
|
8
|
-
project_exists = Dir.exist?(project_path)
|
9
|
-
|
10
|
-
raise Error, "expected project #{project_path} doesn't exists" unless project_exists
|
11
|
-
|
12
|
-
ruby_files = File.join(project_path, "**", "*.rb")
|
13
|
-
Dir.glob(ruby_files).lazy
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/tasks/gem.rake
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rspec/core/rake_task"
|
4
|
-
require "mudguard/version"
|
5
|
-
|
6
|
-
namespace :gem do
|
7
|
-
desc "Publishes the gem on rubygems.org"
|
8
|
-
task publish: "gem:build" do
|
9
|
-
exec("gem push mudguard-#{Mudguard::VERSION}.gem")
|
10
|
-
end
|
11
|
-
desc "Builds the gem"
|
12
|
-
task :build do
|
13
|
-
exec("gem build mudguard.gemspec")
|
14
|
-
end
|
15
|
-
end
|