mudguard 0.1.4 → 0.1.5
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 +3 -0
- data/Gemfile.lock +1 -1
- data/Guardfile +1 -1
- data/exe/mudguard +5 -12
- data/lib/mudguard/application/application.rb +19 -0
- data/lib/mudguard/domain/dependency.rb +30 -0
- data/lib/mudguard/{error.rb → domain/error.rb} +3 -1
- data/lib/mudguard/domain/policies.rb +48 -0
- data/lib/mudguard/{ruby_analyser.rb → domain/source.rb} +26 -6
- data/lib/mudguard/infrastructure/cli/controller.rb +36 -0
- data/lib/mudguard/infrastructure/cli/notification_adapter.rb +18 -0
- data/lib/mudguard/infrastructure/cli/view.rb +14 -0
- data/lib/mudguard/infrastructure/persistence/policy_file.rb +23 -0
- data/lib/mudguard/infrastructure/persistence/ruby_files.rb +36 -0
- data/lib/mudguard/version.rb +1 -1
- data/lib/mudguard.rb +2 -17
- metadata +12 -8
- data/lib/mudguard/policies.rb +0 -23
- data/lib/mudguard/policy_file.rb +0 -17
- data/lib/mudguard/ruby_files.rb +0 -17
- data/lib/tasks/gem.rake +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6b60554fbef1a22d26bcc61a3b7362f9351d3a86464e1e1e3c29f44d6f8d44f
|
4
|
+
data.tar.gz: 2a3617b3c12dc0ce2ecafdf09b6b0d9eb1464b3f51e7f93360c875fc5d63a3ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 647203da7407adc474020ab9b559847ba0cdcbf308a031ca980f02d63c45222abc52c144c03f7bbc497f24f23a37541cb37f45fd555079b44f5d95bbe6c2fcba
|
7
|
+
data.tar.gz: 576533ce4ca809ea053bb8c3ea36f6ed20b51b989f071bbfb10204b91ecf1196d82e9af4132a92b431621618b6c5e8da09d1c8d6c9c1181664a4c67111a4277d
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/Guardfile
CHANGED
@@ -12,5 +12,5 @@ guard "rspec", rspec_options do
|
|
12
12
|
watch(%r{^lib/mudguard/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
13
|
watch(%r{^lib/mudguard/(.+)\.rb$}) { |m| Dir.glob("spec/lib/#{m[1]}_*.rb") }
|
14
14
|
watch("spec/spec_helper.rb") { "spec" }
|
15
|
-
watch(%r{^exe\/mudguard$}) { |_| "spec/
|
15
|
+
watch(%r{^exe\/mudguard$}) { |_| "spec/exe/mudguard_spec.rb" }
|
16
16
|
end
|
data/exe/mudguard
CHANGED
@@ -1,20 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "mudguard"
|
5
|
-
require "
|
4
|
+
require "mudguard/infrastructure/cli/view"
|
5
|
+
require "mudguard/infrastructure/cli/controller"
|
6
6
|
|
7
7
|
# Checks the dependencies of a ruby project
|
8
8
|
module Mudguard
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
puts opts
|
13
|
-
exit
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
directories = parser.parse!
|
18
|
-
ok = directories.all?(&Mudguard.method(:check))
|
9
|
+
view = Mudguard::Infrastructure::Cli::View.new
|
10
|
+
parser = Mudguard::Infrastructure::Cli::Controller.new(view: view)
|
11
|
+
ok = parser.parse!(ARGV)
|
19
12
|
exit(ok ? 0 : 1)
|
20
13
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../infrastructure/persistence/policy_file"
|
4
|
+
require_relative "../infrastructure/persistence/ruby_files"
|
5
|
+
|
6
|
+
# Contains methods to check if your project is a bit muddy
|
7
|
+
module Mudguard
|
8
|
+
# API to mudguard
|
9
|
+
module Application
|
10
|
+
class << self
|
11
|
+
def check(project_path, notification)
|
12
|
+
policy_file_path = File.expand_path("MudguardFile", project_path)
|
13
|
+
policies = Infrastructure::Persistence::PolicyFile.read(policy_file_path)
|
14
|
+
|
15
|
+
policies.check(Infrastructure::Persistence::RubyFiles.all(project_path), notification)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mudguard
|
4
|
+
module Domain
|
5
|
+
# A Dependency between Modules
|
6
|
+
class Dependency
|
7
|
+
def initialize(location: nil, dependency:)
|
8
|
+
@location = location
|
9
|
+
@dependency = dependency
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"{#{@location}, #{@dependency}}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"#{@location} #{@dependency}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def match(policy)
|
21
|
+
@dependency.match(policy)
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
@location == other.instance_eval { @location } &&
|
26
|
+
@dependency == other.instance_eval { @dependency }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mudguard
|
4
|
+
module Domain
|
5
|
+
# Contains the policies to be enforced
|
6
|
+
class Policies
|
7
|
+
def initialize(policies: [])
|
8
|
+
@policies = policies.map { |l| l.gsub(/\s/, "") }.map { |p| /^#{p}/ }
|
9
|
+
end
|
10
|
+
|
11
|
+
def check(sources, notification)
|
12
|
+
result = check_sources(sources, notification)
|
13
|
+
|
14
|
+
count = result[:count]
|
15
|
+
violations = result[:violations]
|
16
|
+
|
17
|
+
files = pluralize("file", count)
|
18
|
+
problems = pluralize("problem", violations)
|
19
|
+
notification.add("#{count} #{files} inspected, #{violations} #{problems} detected")
|
20
|
+
violations.zero?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def pluralize(word, count)
|
26
|
+
count == 1 ? word : "#{word}s"
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_sources(sources, notification)
|
30
|
+
sources.each_with_object(count: 0, violations: 0) do |source, result|
|
31
|
+
result[:count] += 1
|
32
|
+
dependencies = source.find_mod_dependencies
|
33
|
+
result[:violations] += check_dependencies(dependencies, notification)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_dependencies(dependencies, notification)
|
38
|
+
dependencies.reject { |d| check_dependency(d, notification) }.count
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_dependency(dependency, notification)
|
42
|
+
is_allowed = @policies.any? { |p| dependency.match(p) }
|
43
|
+
notification.add("#{dependency} not allowed") unless is_allowed
|
44
|
+
is_allowed
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,14 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "parser/current"
|
4
|
+
require "mudguard/domain/dependency"
|
4
5
|
|
5
6
|
module Mudguard
|
6
|
-
|
7
|
-
|
8
|
-
class
|
9
|
-
def
|
7
|
+
module Domain
|
8
|
+
# Represents a Ruby source file
|
9
|
+
class Source
|
10
|
+
def initialize(location: nil, code:)
|
11
|
+
@code = code
|
12
|
+
@location = location
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
@code == other.instance_eval { @code } && @location == other.instance_eval { @location }
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
@location
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_mod_dependencies
|
10
24
|
begin
|
11
|
-
root = Parser::CurrentRuby.parse(
|
25
|
+
root = Parser::CurrentRuby.parse(@code)
|
12
26
|
rescue Parser::SyntaxError
|
13
27
|
return []
|
14
28
|
end
|
@@ -26,12 +40,18 @@ module Mudguard
|
|
26
40
|
when type?(:class)
|
27
41
|
process_class(node.children, module_name)
|
28
42
|
when type?(:const)
|
29
|
-
[
|
43
|
+
[create_dependency(module_name, node)]
|
30
44
|
else
|
31
45
|
ignore_and_continue(node, module_name)
|
32
46
|
end
|
33
47
|
end
|
34
48
|
|
49
|
+
def create_dependency(module_name, node)
|
50
|
+
dependency = "#{module_name}->#{find_const_name(node.children)}"
|
51
|
+
location = "#{@location}:#{node.location.line}"
|
52
|
+
Dependency.new(location: location, dependency: dependency)
|
53
|
+
end
|
54
|
+
|
35
55
|
def ignore_and_continue(node, module_name)
|
36
56
|
case node
|
37
57
|
when children?
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "mudguard/application/application"
|
5
|
+
require_relative "notification_adapter"
|
6
|
+
|
7
|
+
module Mudguard
|
8
|
+
module Infrastructure
|
9
|
+
module Cli
|
10
|
+
# Parses the cli arguments
|
11
|
+
class Controller
|
12
|
+
def initialize(view:)
|
13
|
+
@view = view
|
14
|
+
@done = false
|
15
|
+
@parser = ::OptionParser.new do |opts|
|
16
|
+
opts.banner = "Usage: mudguard [options] [directory]"
|
17
|
+
opts.on("-h", "--help", "Prints this help") do
|
18
|
+
view.print(opts.to_s)
|
19
|
+
@done = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse!(argv)
|
25
|
+
directories = @parser.parse!(argv)
|
26
|
+
|
27
|
+
return true if @done
|
28
|
+
|
29
|
+
notification = NotificationAdapter.new(view: @view)
|
30
|
+
directories = [Dir.pwd] if directories.empty?
|
31
|
+
directories.all? { |d| Mudguard::Application.check(d, notification) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mudguard
|
4
|
+
module Infrastructure
|
5
|
+
module Cli
|
6
|
+
# Forwards Notification to the view for printing
|
7
|
+
class NotificationAdapter
|
8
|
+
def initialize(view:)
|
9
|
+
@view = view
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(text)
|
13
|
+
@view.print(text)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../domain/policies"
|
4
|
+
require_relative "../../domain/error"
|
5
|
+
|
6
|
+
module Mudguard
|
7
|
+
module Infrastructure
|
8
|
+
module Persistence
|
9
|
+
# A file containing the Mudguard-Policies
|
10
|
+
class PolicyFile
|
11
|
+
def self.read(policy_file)
|
12
|
+
policy_exists = File.exist?(policy_file)
|
13
|
+
|
14
|
+
unless policy_exists
|
15
|
+
raise Mudguard::Domain::Error, "expected policy file #{policy_file} doesn't exists"
|
16
|
+
end
|
17
|
+
|
18
|
+
Mudguard::Domain::Policies.new(policies: File.readlines(policy_file))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mudguard/domain/source"
|
4
|
+
|
5
|
+
module Mudguard
|
6
|
+
module Infrastructure
|
7
|
+
module Persistence
|
8
|
+
# Provides access to all ruby-files of a project
|
9
|
+
class RubyFiles
|
10
|
+
class << self
|
11
|
+
def all(project_path)
|
12
|
+
project_exists = Dir.exist?(project_path)
|
13
|
+
|
14
|
+
unless project_exists
|
15
|
+
raise Mudguard::Domain::Error, "expected project #{project_path} doesn't exists"
|
16
|
+
end
|
17
|
+
|
18
|
+
enumerate_files(project_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def enumerate_files(project_path)
|
24
|
+
project_path_name = Pathname.new(project_path)
|
25
|
+
ruby_files = File.join(project_path, "**", "*.rb")
|
26
|
+
Dir.glob(ruby_files).map do |f|
|
27
|
+
file_path_name = Pathname.new(f)
|
28
|
+
diff_path = file_path_name.relative_path_from(project_path_name).to_s
|
29
|
+
Mudguard::Domain::Source.new(location: File.join("./", diff_path), code: File.read(f))
|
30
|
+
end.lazy
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/mudguard/version.rb
CHANGED
data/lib/mudguard.rb
CHANGED
@@ -1,19 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative "mudguard/
|
5
|
-
require_relative "mudguard/ruby_files"
|
6
|
-
|
7
|
-
# Contains methods to check if your project is a bit muddy
|
8
|
-
module Mudguard
|
9
|
-
class << self
|
10
|
-
def check(project_path)
|
11
|
-
policy_file_path = File.expand_path("MudguardFile", project_path)
|
12
|
-
policies = PolicyFile.read(policy_file_path)
|
13
|
-
|
14
|
-
files = RubyFiles.all(project_path).map { |f| File.read(f) }
|
15
|
-
|
16
|
-
policies.check(files)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
3
|
+
require_relative "./mudguard/version"
|
4
|
+
require_relative "./mudguard/application/application"
|
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.1.
|
4
|
+
version: 0.1.5
|
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-03-
|
11
|
+
date: 2020-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -171,13 +171,17 @@ files:
|
|
171
171
|
- Rakefile
|
172
172
|
- exe/mudguard
|
173
173
|
- lib/mudguard.rb
|
174
|
-
- lib/mudguard/
|
175
|
-
- lib/mudguard/
|
176
|
-
- lib/mudguard/
|
177
|
-
- lib/mudguard/
|
178
|
-
- lib/mudguard/
|
174
|
+
- lib/mudguard/application/application.rb
|
175
|
+
- lib/mudguard/domain/dependency.rb
|
176
|
+
- lib/mudguard/domain/error.rb
|
177
|
+
- lib/mudguard/domain/policies.rb
|
178
|
+
- lib/mudguard/domain/source.rb
|
179
|
+
- lib/mudguard/infrastructure/cli/controller.rb
|
180
|
+
- lib/mudguard/infrastructure/cli/notification_adapter.rb
|
181
|
+
- lib/mudguard/infrastructure/cli/view.rb
|
182
|
+
- lib/mudguard/infrastructure/persistence/policy_file.rb
|
183
|
+
- lib/mudguard/infrastructure/persistence/ruby_files.rb
|
179
184
|
- lib/mudguard/version.rb
|
180
|
-
- lib/tasks/gem.rake
|
181
185
|
- lib/tasks/rubocop.rake
|
182
186
|
- lib/tasks/test.rake
|
183
187
|
- mudguard.gemspec
|
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
|
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
|