mutant 0.11.24 → 0.11.25

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fce1f18a168ceb279743d1d6a1bb46226568faba189d4fb6eb7a789a6cd1a4c5
4
- data.tar.gz: 6353bde0559ed50cd5f6111f17b815e072b92c9c70d11b8cc5354b6adf0d790b
3
+ metadata.gz: 582339f240c2c234a6130ff32d7c998318b9b82670321483d5b66351524acfb9
4
+ data.tar.gz: 1f027e4239fc3bb5b518e796249ab4ac9cf2902d938995adfbd276af2fb69951
5
5
  SHA512:
6
- metadata.gz: 67ad06623a1b89faf01739d36a89b3226bd3f07324ccc6252e7457e1c5fd6000bb14332825dd5df5a9294fdab1338b27b71e3baeffd676f14c8ac6ed6ca8aaa7
7
- data.tar.gz: 68b0a0396ac6d25270d54069ea49eaaa0c70409ec684615673a8f84193ea568d005f3606b51f3868911e05e4695ed04db80532c04b0070130d915dd2a2d371bf
6
+ metadata.gz: 823420ff1abcf0b8ac2e8c79012962a355f85324195cefc4d1daf9a60537f5773d2d125ec76881462b6f59d61081a2875c9f5c168ede8cbab190f7cc45a9a665
7
+ data.tar.gz: 1ebafd946b6b3404835653a3a024e655b9961d418247201ba14080fb772df20cab6295609acaee00d41bd9820f8fdb492b8b0606791435be395f863588cde104
@@ -4,50 +4,84 @@ module Mutant
4
4
  module License
5
5
  class Subscription
6
6
  class Commercial < self
7
- class Author
8
- include Anima.new(:email)
9
-
10
- alias_method :to_s, :email
11
- public :to_s
12
- end
7
+ include AbstractType
13
8
 
14
9
  def self.from_json(value)
15
- new(licensed: value.fetch('authors').to_set { |email| Author.new(email: email) })
10
+ {
11
+ 'individual' => Individual,
12
+ 'organization' => Organization
13
+ }.fetch(value.fetch('type', 'individual')).from_json(value)
16
14
  end
17
15
 
18
- def call(world)
19
- candidates = candidates(world)
16
+ class Organization < self
17
+ SUBSCRIPTION_NAME = 'commercial organization'
20
18
 
21
- if (licensed & candidates).any?
22
- success
23
- else
24
- failure(licensed, candidates)
19
+ def self.from_json(value)
20
+ new(licensed: value.fetch('repositories').map(&Repository.public_method(:parse)).to_set)
25
21
  end
26
- end
27
22
 
28
- private
23
+ def call(world)
24
+ Repository.load_from_git(world).bind(&method(:check_subscription))
25
+ end
29
26
 
30
- def candidates(world)
31
- git_author(world).merge(commit_author(world))
32
- end
27
+ private
33
28
 
34
- def git_author(world)
35
- capture(world, %w[git config --get user.email])
29
+ def check_subscription(actual)
30
+ if licensed.any? { |repository| actual.any? { |other| repository.allow?(other) } }
31
+ success
32
+ else
33
+ failure(licensed, actual)
34
+ end
35
+ end
36
36
  end
37
37
 
38
- def commit_author(world)
39
- capture(world, %w[git show --quiet --pretty=format:%ae])
40
- end
38
+ class Individual < self
39
+ SUBSCRIPTION_NAME = 'commercial individual'
41
40
 
42
- def capture(world, command)
43
- world
44
- .capture_stdout(command)
45
- .fmap(&:chomp)
46
- .fmap { |email| Author.new(email: email) }
47
- .fmap { |value| Set.new([value]) }
48
- .from_right { Set.new }
49
- end
41
+ class Author
42
+ include Anima.new(:email)
43
+
44
+ alias_method :to_s, :email
45
+ public :to_s
46
+ end
47
+
48
+ def self.from_json(value)
49
+ new(licensed: value.fetch('authors').to_set { |email| Author.new(email: email) })
50
+ end
50
51
 
52
+ def call(world)
53
+ candidates = candidates(world)
54
+
55
+ if (licensed & candidates).any?
56
+ success
57
+ else
58
+ failure(licensed, candidates)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def candidates(world)
65
+ git_author(world).merge(commit_author(world))
66
+ end
67
+
68
+ def git_author(world)
69
+ capture(world, %w[git config --get user.email])
70
+ end
71
+
72
+ def commit_author(world)
73
+ capture(world, %w[git show --quiet --pretty=format:%ae])
74
+ end
75
+
76
+ def capture(world, command)
77
+ world
78
+ .capture_stdout(command)
79
+ .fmap(&:chomp)
80
+ .fmap { |email| Author.new(email: email) }
81
+ .fmap { |value| Set.new([value]) }
82
+ .from_right { Set.new }
83
+ end
84
+ end # Individual
51
85
  end # Commercial
52
86
  end # Subscription
53
87
  end # License
@@ -4,63 +4,14 @@ module Mutant
4
4
  module License
5
5
  class Subscription
6
6
  class Opensource < self
7
- class Repository
8
- include Anima.new(:host, :path)
9
-
10
- REMOTE_REGEXP = /\A[^\t]+\t(?<url>[^ ]+) \((?:fetch|push)\)\n\z/.freeze
11
- GIT_SSH_REGEXP = %r{\A[^@]+@(?<host>[^:/]+)[:/](?<path>.+?)(?:\.git)?\z}.freeze
12
- GIT_HTTPS_REGEXP = %r{\Ahttps://(?<host>[^/]+)/(?<path>.+?)(?:\.git)?\z}.freeze
13
-
14
- private_constant(*constants(false))
15
-
16
- def to_s
17
- [host, path].join('/')
18
- end
19
-
20
- def self.parse(input)
21
- host, path = *input.split('/', 2).map(&:downcase)
22
- new(host: host, path: path)
23
- end
24
-
25
- def self.parse_remote(input)
26
- match = REMOTE_REGEXP.match(input) or
27
- fail "Unmatched remote line: #{input.inspect}"
28
-
29
- parse_url(match[:url])
30
- end
31
- private_class_method :parse_remote
32
-
33
- def self.parse_url(input)
34
- match = GIT_SSH_REGEXP.match(input) || GIT_HTTPS_REGEXP.match(input)
35
-
36
- unless match
37
- fail "Unmatched git remote URL: #{input.inspect}"
38
- end
39
-
40
- new(host: match[:host], path: match[:path].downcase)
41
- end
42
- private_class_method :parse_url
43
-
44
- def allow?(other)
45
- other.host.eql?(host) && path_match?(other.path)
46
- end
47
-
48
- private
49
-
50
- def path_match?(other_path)
51
- path.eql?(other_path) || (path.end_with?('/*') && other_path.start_with?(path[..-2]))
52
- end
53
- end # Opensource
7
+ SUBSCRIPTION_NAME = 'opensource repository'
54
8
 
55
9
  def self.from_json(value)
56
10
  new(licensed: value.fetch('repositories').map(&Repository.public_method(:parse)).to_set)
57
11
  end
58
12
 
59
13
  def call(world)
60
- world
61
- .capture_stdout(%w[git remote --verbose])
62
- .fmap(&method(:parse_remotes))
63
- .bind(&method(:check_subscription))
14
+ Repository.load_from_git(world).bind(&method(:check_subscription))
64
15
  end
65
16
 
66
17
  private
@@ -73,10 +24,6 @@ module Mutant
73
24
  end
74
25
  end
75
26
 
76
- def parse_remotes(input)
77
- input.lines.map(&Repository.method(:parse_remote)).to_set
78
- end
79
-
80
27
  end # Opensource
81
28
  end # Subscription
82
29
  end # License
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module License
5
+ class Subscription
6
+ class Repository
7
+ include Anima.new(:host, :path)
8
+
9
+ REMOTE_REGEXP = /\A[^\t]+\t(?<url>[^ ]+) \((?:fetch|push)\)\n\z/.freeze
10
+ GIT_SSH_REGEXP = %r{\A[^@]+@(?<host>[^:/]+)[:/](?<path>.+?)(?:\.git)?\z}.freeze
11
+ GIT_HTTPS_REGEXP = %r{\Ahttps://(?<host>[^/]+)/(?<path>.+?)(?:\.git)?\z}.freeze
12
+ WILDCARD = '/*'
13
+ WILDCARD_RANGE = (..-WILDCARD.length).freeze
14
+
15
+ private_constant(*constants(false))
16
+
17
+ def to_s
18
+ [host, path].join('/')
19
+ end
20
+
21
+ def self.load_from_git(world)
22
+ world
23
+ .capture_stdout(%w[git remote --verbose])
24
+ .fmap(&method(:parse_remotes))
25
+ end
26
+
27
+ def self.parse_remotes(input)
28
+ input.lines.map(&method(:parse_remote)).to_set
29
+ end
30
+ private_class_method :parse_remotes
31
+
32
+ def self.parse(input)
33
+ host, path = *input.split('/', 2).map(&:downcase)
34
+ new(host: host, path: path)
35
+ end
36
+
37
+ def self.parse_remote(input)
38
+ match = REMOTE_REGEXP.match(input) or
39
+ fail "Unmatched remote line: #{input.inspect}"
40
+
41
+ parse_url(match[:url])
42
+ end
43
+ private_class_method :parse_remote
44
+
45
+ def self.parse_url(input)
46
+ match = GIT_SSH_REGEXP.match(input) || GIT_HTTPS_REGEXP.match(input)
47
+
48
+ unless match
49
+ fail "Unmatched git remote URL: #{input.inspect}"
50
+ end
51
+
52
+ new(host: match[:host], path: match[:path].downcase)
53
+ end
54
+ private_class_method :parse_url
55
+
56
+ def allow?(other)
57
+ other.host.eql?(host) && path_match?(other.path)
58
+ end
59
+
60
+ private
61
+
62
+ def path_match?(other_path)
63
+ path.eql?(other_path) || wildcard_match?(path, other_path) || wildcard_match?(other_path, path)
64
+ end
65
+
66
+ def wildcard_match?(left, right)
67
+ left.end_with?(WILDCARD) && right.start_with?(left[WILDCARD_RANGE])
68
+ end
69
+ end # Repository
70
+ end # Subscription
71
+ end # License
72
+ end # Mutant
@@ -54,7 +54,7 @@ module Mutant
54
54
  end
55
55
 
56
56
  def subscription_name
57
- self.class.name.split('::').last.downcase
57
+ self.class::SUBSCRIPTION_NAME
58
58
  end
59
59
 
60
60
  def failure_message(expected, actual)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.11.24'
5
+ VERSION = '0.11.25'
6
6
  end # Mutant
data/lib/mutant.rb CHANGED
@@ -251,8 +251,9 @@ module Mutant
251
251
  require 'mutant/range'
252
252
  require 'mutant/license'
253
253
  require 'mutant/license/subscription'
254
- require 'mutant/license/subscription/opensource'
255
254
  require 'mutant/license/subscription/commercial'
255
+ require 'mutant/license/subscription/opensource'
256
+ require 'mutant/license/subscription/repository'
256
257
  require 'mutant/segment'
257
258
  require 'mutant/segment/recorder'
258
259
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.24
4
+ version: 0.11.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-11 00:00:00.000000000 Z
11
+ date: 2023-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs
@@ -220,6 +220,7 @@ files:
220
220
  - lib/mutant/license/subscription.rb
221
221
  - lib/mutant/license/subscription/commercial.rb
222
222
  - lib/mutant/license/subscription/opensource.rb
223
+ - lib/mutant/license/subscription/repository.rb
223
224
  - lib/mutant/loader.rb
224
225
  - lib/mutant/matcher.rb
225
226
  - lib/mutant/matcher/chain.rb