pdd 0.20.6 → 0.21.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codecov.yml +20 -0
  3. data/.github/workflows/rake.yml +24 -0
  4. data/.gitignore +5 -5
  5. data/.overcommit.yml +96 -0
  6. data/.pdd +3 -0
  7. data/.rubocop.yml +3 -4
  8. data/.rultor.yml +8 -15
  9. data/.simplecov +6 -6
  10. data/Gemfile +1 -1
  11. data/LICENSE.txt +1 -1
  12. data/README.md +67 -37
  13. data/Rakefile +7 -1
  14. data/assets/puzzles.xsd +1 -1
  15. data/assets/puzzles.xsl +1 -1
  16. data/bin/pdd +31 -18
  17. data/features/catches_broken_puzzles.feature +3 -36
  18. data/features/cli.feature +1 -1
  19. data/features/html_output.feature +1 -1
  20. data/features/parsing.feature +31 -1
  21. data/features/rake.feature +14 -12
  22. data/features/step_definitions/steps.rb +7 -10
  23. data/features/support/env.rb +1 -1
  24. data/features/uses_config.feature +1 -1
  25. data/lib/pdd/puzzle.rb +1 -1
  26. data/lib/pdd/rake_task.rb +11 -12
  27. data/lib/pdd/rule/duplicates.rb +2 -1
  28. data/lib/pdd/rule/estimates.rb +1 -1
  29. data/lib/pdd/rule/roles.rb +2 -1
  30. data/lib/pdd/rule/text.rb +2 -1
  31. data/lib/pdd/source.rb +86 -75
  32. data/lib/pdd/sources.rb +42 -21
  33. data/lib/pdd/version.rb +3 -3
  34. data/lib/pdd.rb +20 -13
  35. data/pdd.gemspec +8 -5
  36. data/test/test__helper.rb +15 -2
  37. data/test/test_duplicates.rb +2 -2
  38. data/test/test_estimates.rb +2 -2
  39. data/test/test_pdd.rb +4 -2
  40. data/test/test_rake_task.rb +7 -4
  41. data/test/test_roles.rb +2 -2
  42. data/test/test_source.rb +168 -51
  43. data/test/test_source_todo.rb +38 -29
  44. data/test/test_sources.rb +18 -3
  45. data/test/test_text.rb +2 -2
  46. data/utils/glob.rb +65 -0
  47. metadata +37 -7
  48. data/.travis.yml +0 -13
  49. data/appveyor.yml +0 -21
data/lib/pdd/sources.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -18,58 +18,79 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
- require 'shellwords'
21
+ require 'rainbow'
22
22
  require 'English'
23
+ require 'filemagic'
23
24
  require_relative 'source'
25
+ require_relative '../../utils/glob'
24
26
 
25
27
  module PDD
26
28
  # Code base abstraction
27
29
  class Sources
28
30
  # Ctor.
29
31
  # +dir+:: Directory with source code files
30
- def initialize(dir, ptns = [])
32
+ def initialize(dir)
31
33
  @dir = File.absolute_path(dir)
32
- @exclude = ptns + ['.git/**/*']
34
+ @exclude = ['.git/**/*']
35
+ @include = []
33
36
  end
34
37
 
35
38
  # Fetch all sources.
36
39
  def fetch
40
+ exclude_paths = @exclude.map do |ptn|
41
+ Glob.new(File.join(@dir, ptn)).to_regexp
42
+ end
37
43
  files = Dir.glob(
38
44
  File.join(@dir, '**/*'), File::FNM_DOTMATCH
39
- ).reject { |f| File.directory?(f) }
40
- excluded = 0
41
- @exclude.each do |ptn|
42
- Dir.glob(File.join(@dir, ptn), File::FNM_DOTMATCH) do |f|
43
- files.delete_if { |i| i == f }
44
- excluded += 1
45
- end
45
+ ).reject do |f|
46
+ File.directory?(f) || exclude_paths.any? { |ptn| f.match(ptn) }
46
47
  end
47
- PDD.log.info "#{files.size} file(s) found, #{excluded} excluded"
48
+ files += Dir.glob(
49
+ @include.map { |ptn| File.join(@dir, ptn) }
50
+ ).reject { |f| File.directory?(f) }
51
+ files = files.uniq # remove duplicates
48
52
  files.reject { |f| binary?(f) }.map do |file|
49
53
  path = file[@dir.length + 1, file.length]
50
54
  VerboseSource.new(path, Source.new(file, path))
51
55
  end
52
56
  end
53
57
 
54
- def exclude(ptn)
55
- Sources.new(@dir, @exclude.push(ptn))
58
+ def exclude(paths)
59
+ paths = paths.nil? ? [] : paths
60
+ paths = paths.is_a?(Array) ? paths : [paths]
61
+ @exclude.push(*paths)
62
+ paths&.each do |path|
63
+ PDD.log.info "#{Rainbow('Excluding').orange} #{path}"
64
+ end
65
+ self
66
+ end
67
+
68
+ def include(paths)
69
+ paths = paths.nil? ? [] : paths
70
+ paths = paths.is_a?(Array) ? paths : [paths]
71
+ @include.push(*paths)
72
+ paths&.each do |path|
73
+ PDD.log.info "#{Rainbow('Including').blue} #{path}"
74
+ end
75
+ self
56
76
  end
57
77
 
58
78
  private
59
79
 
60
- # @todo #98:30min Change the implementation of this method
61
- # to also work in Windows machines. Investigate the possibility
62
- # of use a gem for this. After that, remove the skip of the test
63
- # `test_ignores_binary_files` in `test_sources.rb`.
64
80
  def binary?(file)
65
- return false if Gem.win_platform?
66
- `grep -qI '.' #{Shellwords.escape(file)}`
67
- if $CHILD_STATUS.success?
81
+ if text_file?(file)
68
82
  false
69
83
  else
70
84
  PDD.log.info "#{file} is a binary file (#{File.size(file)} bytes)"
71
85
  true
72
86
  end
73
87
  end
88
+
89
+ def text_file?(file)
90
+ fm = FileMagic.new(FileMagic::MAGIC_MIME)
91
+ fm.file(file) =~ %r{^text/}
92
+ ensure
93
+ fm.close
94
+ end
74
95
  end
75
96
  end
data/lib/pdd/version.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -20,8 +20,8 @@
20
20
 
21
21
  # PDD main module.
22
22
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
23
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
23
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module PDD
26
- VERSION = '0.20.6'.freeze
26
+ VERSION = '0.21.0'.freeze
27
27
  end
data/lib/pdd.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -30,7 +30,7 @@ require_relative 'pdd/rule/roles'
30
30
 
31
31
  # PDD main module.
32
32
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
33
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
33
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
34
34
  # License:: MIT
35
35
  module PDD
36
36
  # If it breaks.
@@ -52,21 +52,25 @@ module PDD
52
52
  # Get logger.
53
53
  def self.log
54
54
  unless defined?(@logger)
55
- @logger = Logger.new(STDOUT)
55
+ @logger = Logger.new($stdout)
56
56
  @logger.formatter = proc { |severity, _, _, msg|
57
- if severity == 'ERROR'
57
+ case severity
58
+ when 'ERROR'
58
59
  "#{Rainbow(severity).red}: #{msg}\n"
60
+ when 'WARN'
61
+ "#{Rainbow(severity).orange}: #{msg}\n"
59
62
  else
60
63
  "#{msg}\n"
61
64
  end
62
65
  }
63
- @logger.level = Logger::ERROR
66
+ @logger.level = Logger::WARN
64
67
  end
65
68
  @logger
66
69
  end
67
70
 
68
71
  class << self
69
72
  attr_writer :logger
73
+ attr_accessor :opts
70
74
  end
71
75
 
72
76
  # Code base abstraction
@@ -75,6 +79,7 @@ module PDD
75
79
  # +opts+:: Options
76
80
  def initialize(opts)
77
81
  @opts = opts
82
+ PDD.opts = opts
78
83
  PDD.log.level = Logger::INFO if @opts[:verbose]
79
84
  PDD.log.level = Logger::ERROR if @opts[:quiet]
80
85
  PDD.log.info "My version is #{PDD::VERSION}"
@@ -83,17 +88,15 @@ module PDD
83
88
 
84
89
  # Generate XML.
85
90
  def xml
86
- dir = @opts[:source] ? @opts[:source] : Dir.pwd
87
- PDD.log.info "Reading #{dir}"
91
+ dir = @opts[:source] || Dir.pwd
92
+ PDD.log.info "Reading from root dir #{dir}"
88
93
  require_relative 'pdd/sources'
89
- sources = Sources.new(dir)
90
- @opts[:exclude]&.each do |p|
91
- sources = sources.exclude(p)
92
- PDD.log.info "Excluding #{p}"
93
- end
94
+ sources = Sources.new(File.expand_path(dir))
95
+ sources.exclude((@opts[:exclude] || []) + (@opts['skip-gitignore'] || []))
96
+ sources.include(@opts[:include])
94
97
  sanitize(
95
98
  rules(
96
- Nokogiri::XML::Builder.new do |xml|
99
+ Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
97
100
  xml << "<?xml-stylesheet type='text/xsl' href='#{xsl}'?>"
98
101
  xml.puzzles(attrs) do
99
102
  sources.fetch.each do |source|
@@ -145,16 +148,19 @@ module PDD
145
148
  unless list.select { |r| r.start_with?('max-duplicates:') }.empty?
146
149
  raise PDD::Error, 'You can\'t modify max-duplicates, it\'s always 1'
147
150
  end
151
+
148
152
  list.push('max-duplicates:1').map do |r|
149
153
  name, value = r.split(':')
150
154
  rule = RULES[name]
151
155
  raise "Rule '#{name}' doesn't exist" if rule.nil?
156
+
152
157
  rule.new(doc, value).errors.each do |e|
153
158
  PDD.log.error e
154
159
  total += 1
155
160
  end
156
161
  end
157
162
  raise PDD::Error, "#{total} errors, see log above" unless total.zero?
163
+
158
164
  xml
159
165
  end
160
166
 
@@ -166,6 +172,7 @@ module PDD
166
172
  errors.each { |e| PDD.log.error e }
167
173
  PDD.log.error(xml) unless errors.empty?
168
174
  raise SchemaError, errors.join('; ') unless errors.empty?
175
+
169
176
  xml
170
177
  end
171
178
  end
data/pdd.gemspec CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -20,17 +20,18 @@
20
20
 
21
21
  require 'English'
22
22
 
23
- lib = File.expand_path('../lib', __FILE__)
23
+ lib = File.expand_path('lib', __dir__)
24
24
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
25
25
  require_relative 'lib/pdd/version'
26
26
 
27
27
  Gem::Specification.new do |s|
28
28
  s.specification_version = 2 if s.respond_to? :specification_version=
29
29
  if s.respond_to? :required_rubygems_version=
30
- s.required_rubygems_version = Gem::Requirement.new('>= 0')
30
+ s.required_rubygems_version =
31
+ Gem::Requirement.new('>= 0')
31
32
  end
32
33
  s.rubygems_version = '2.3'
33
- s.required_ruby_version = '>= 2.3'
34
+ s.required_ruby_version = '~> 2.3'
34
35
  s.name = 'pdd'
35
36
  s.version = PDD::VERSION
36
37
  s.license = 'MIT'
@@ -38,7 +39,7 @@ Gem::Specification.new do |s|
38
39
  s.description = 'Collects PDD puzzles from a source code base'
39
40
  s.authors = ['Yegor Bugayenko']
40
41
  s.email = 'yegor256@gmail.com'
41
- s.homepage = 'http://github.com/yegor256/pdd'
42
+ s.homepage = 'http://github.com/cqfn/pdd'
42
43
  s.files = `git ls-files`.split($RS)
43
44
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
44
45
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -46,6 +47,7 @@ Gem::Specification.new do |s|
46
47
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
47
48
  s.add_runtime_dependency 'nokogiri', '~> 1.10'
48
49
  s.add_runtime_dependency 'rainbow', '~> 3.0'
50
+ s.add_runtime_dependency 'ruby-filemagic', '~> 0.7.2'
49
51
  s.add_runtime_dependency 'slop', '~> 4.6'
50
52
  s.add_development_dependency 'aruba', '~> 0.14.1'
51
53
  s.add_development_dependency 'codecov', '0.2.12'
@@ -56,5 +58,6 @@ Gem::Specification.new do |s|
56
58
  s.add_development_dependency 'rspec-rails', '3.1.0'
57
59
  s.add_development_dependency 'rubocop', '0.52.1'
58
60
  s.add_development_dependency 'rubocop-rspec', '1.15.1'
61
+ s.add_development_dependency 'slop', '4.9.1'
59
62
  s.add_development_dependency 'xcop', '0.5.8'
60
63
  end
data/test/test__helper.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -18,7 +18,7 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
- STDOUT.sync = true
21
+ $stdout.sync = true
22
22
 
23
23
  require 'simplecov'
24
24
  SimpleCov.start
@@ -29,3 +29,16 @@ end
29
29
 
30
30
  require 'minitest/autorun'
31
31
  require_relative '../lib/pdd'
32
+
33
+ def stub_source_find_github_user(file, path = '')
34
+ source = PDD::Source.new(file, path)
35
+ verbose_source = PDD::VerboseSource.new(file, source)
36
+ fake = proc do |info = {}|
37
+ email, author = info.values_at(:email, :author)
38
+ { 'login' => 'yegor256' } if email == 'yegor256@gmail.com' ||
39
+ author == 'Yegor Bugayenko'
40
+ end
41
+ source.stub :find_github_user, fake do
42
+ yield verbose_source
43
+ end
44
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,7 +24,7 @@ require_relative '../lib/pdd/rule/duplicates'
24
24
 
25
25
  # PDD::Rule::MaxDuplicates class test.
26
26
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
27
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
28
28
  # License:: MIT
29
29
  class TestMaxDuplicates < Minitest::Test
30
30
  def test_max_duplicates
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,7 +24,7 @@ require_relative '../lib/pdd/rule/estimates'
24
24
 
25
25
  # PDD::Rule::Estimate module tests.
26
26
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
27
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
28
28
  # License:: MIT
29
29
  class TestEstimates < Minitest::Test
30
30
  def test_min
data/test/test_pdd.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -26,7 +26,7 @@ require_relative '../lib/pdd'
26
26
 
27
27
  # PDD main module test.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
29
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
30
30
  # License:: MIT
31
31
  class TestPDD < Minitest::Test
32
32
  def test_basic
@@ -75,6 +75,7 @@ class TestPDD < Minitest::Test
75
75
  git add -f .
76
76
  git commit --quiet -am 'first version'
77
77
  ")
78
+
78
79
  matches(
79
80
  Nokogiri::XML(PDD::Base.new(opts).xml),
80
81
  [
@@ -95,6 +96,7 @@ class TestPDD < Minitest::Test
95
96
  Slop.parse args do |o|
96
97
  o.bool '-v', '--verbose'
97
98
  o.bool '-q', '--quiet'
99
+ o.bool '--skip-errors'
98
100
  o.string '-s', '--source'
99
101
  o.array '-e', '--exclude'
100
102
  o.array '-r', '--rule'
@@ -5,11 +5,14 @@ require_relative '../lib/pdd/rake_task'
5
5
 
6
6
  # Test for RakeTask
7
7
  class TestRakeTask < Minitest::Test
8
- def test_base
9
- PDD::RakeTask.new(:pdd1)
10
- error = assert_raises SystemExit do
8
+ def test_basic
9
+ Dir.mktmpdir 'test' do |dir|
10
+ file = File.join(dir, 'a.txt')
11
+ File.write(file, "\x40todo #55 hello!")
12
+ PDD::RakeTask.new(:pdd1) do |task|
13
+ task.quiet = true
14
+ end
11
15
  Rake::Task['pdd1'].invoke
12
16
  end
13
- assert_equal('NOT IMPLEMENTED', error.message)
14
17
  end
15
18
  end
data/test/test_roles.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2014-2020 Yegor Bugayenko
1
+ # Copyright (c) 2014-2022 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,7 +24,7 @@ require_relative '../lib/pdd/rule/roles'
24
24
 
25
25
  # PDD::Rule::Role module tests.
26
26
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
- # Copyright:: Copyright (c) 2014-2020 Yegor Bugayenko
27
+ # Copyright:: Copyright (c) 2014-2022 Yegor Bugayenko
28
28
  # License:: MIT
29
29
  class TestRoles < Minitest::Test
30
30
  def test_incorrect_role