pdd 0.20.6 → 0.20.7
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/.pdd +1 -0
- data/.simplecov +1 -1
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +36 -29
- data/Rakefile +1 -1
- data/assets/puzzles.xsd +1 -1
- data/assets/puzzles.xsl +1 -1
- data/bin/pdd +17 -5
- data/features/catches_broken_puzzles.feature +1 -16
- data/features/step_definitions/steps.rb +1 -1
- data/features/support/env.rb +1 -1
- data/lib/pdd/puzzle.rb +1 -1
- data/lib/pdd/rule/duplicates.rb +1 -1
- data/lib/pdd/rule/estimates.rb +1 -1
- data/lib/pdd/rule/roles.rb +1 -1
- data/lib/pdd/rule/text.rb +1 -1
- data/lib/pdd/source.rb +34 -25
- data/lib/pdd/sources.rb +14 -1
- data/lib/pdd/version.rb +3 -3
- data/lib/pdd.rb +10 -3
- data/pdd.gemspec +2 -2
- data/test/test__helper.rb +14 -1
- data/test/test_duplicates.rb +2 -2
- data/test/test_estimates.rb +2 -2
- data/test/test_pdd.rb +3 -2
- data/test/test_roles.rb +2 -2
- data/test/test_source.rb +130 -46
- data/test/test_source_todo.rb +24 -9
- data/test/test_sources.rb +16 -2
- data/test/test_text.rb +2 -2
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8220e74b7aca6e6feddfe8ccad195c1156386ad766ae1dd31311122242c1292c
|
|
4
|
+
data.tar.gz: 97816bbe7fdfdb29d595683dd98b6eb41d6bc1880e269c4dc11eee4a2b02f582
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c4128efeb2b302351595bbe99978845e8d8d546f11e341c0d0308821e673f6f2aa2730c4d2170751d711892d17942563275641b8dbec04916d9bb7bac8715f2a
|
|
7
|
+
data.tar.gz: 501ddaf76735e9ce50ae3a233c45331d568075979ef3875395e7d361139e008954de9767e14856af7d247adf2a597254b3e89104cc96e5832baa03a278f89a3c
|
data/.pdd
CHANGED
data/.simplecov
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.elegantobjects.org)
|
|
6
6
|
[](https://www.0crat.com/p/C3T46CUJJ)
|
|
7
|
-
[](http://www.rultor.com/p/cqfn/pdd)
|
|
8
8
|
[](https://www.jetbrains.com/ruby/)
|
|
9
9
|
|
|
10
|
-
[](https://ci.appveyor.com/project/
|
|
12
|
-
[](https://github.com/
|
|
10
|
+
[](https://travis-ci.org/cqfn/pdd)
|
|
11
|
+
[](https://ci.appveyor.com/project/cqfn/pdd)
|
|
12
|
+
[](http://www.0pdd.com/p?name=cqfn/pdd)
|
|
13
|
+
[](https://codecov.io/github/cqfn/pdd?branch=master)
|
|
14
|
+
[](https://hitsofcode.com/view/github/cqfn/pdd)
|
|
15
|
+
[](https://github.com/cqfn/pdd/blob/master/LICENSE.txt)
|
|
16
16
|
|
|
17
17
|
[](http://badge.fury.io/rb/pdd)
|
|
18
|
-
[](https://codeclimate.com/github/
|
|
19
|
-
[](http://rubydoc.info/github/
|
|
18
|
+
[](https://codeclimate.com/github/cqfn/pdd/maintainability)
|
|
19
|
+
[](http://rubydoc.info/github/cqfn/pdd/master/frames)
|
|
20
20
|
|
|
21
21
|
Read this article about
|
|
22
22
|
[_Puzzle Driven Development_](http://www.yegor256.com/2009/03/04/pdd.html).
|
|
@@ -60,10 +60,12 @@ to the leading space in every consecutive line):
|
|
|
60
60
|
*/
|
|
61
61
|
[related code]
|
|
62
62
|
```
|
|
63
|
+
|
|
63
64
|
\[\] - Replace with apropriate data (see text enclosed in brackets)
|
|
64
|
-
<>
|
|
65
|
+
<> - Omitable (enclosed data can be left out)
|
|
65
66
|
|
|
66
67
|
Example:
|
|
68
|
+
|
|
67
69
|
```java
|
|
68
70
|
/**
|
|
69
71
|
* @todo #234:15m/DEV This is something to do later
|
|
@@ -82,10 +84,13 @@ The specified markers will be included in the issues body
|
|
|
82
84
|
along with some predefined text. If your comment is longer
|
|
83
85
|
than 40 characters, it will be truncated in the title.
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
There are 3 supported keywords, one of which must precede the mandatory
|
|
88
|
+
puzzle marker. They are `@todo`, `TODO` and `TODO:`.
|
|
89
|
+
|
|
90
|
+
As an example, it starts with `@todo`, followed by a space and a mandatory
|
|
91
|
+
puzzle **marker**. Possible formats of puzzle markers (it doesn't matter what the
|
|
87
92
|
line starts with and where it is located,
|
|
88
|
-
as long as you have
|
|
93
|
+
as long as you have one of the 3 supported keywords right in front
|
|
89
94
|
of the mandatory marker):
|
|
90
95
|
|
|
91
96
|
```
|
|
@@ -94,12 +99,14 @@ of the mandatory marker):
|
|
|
94
99
|
# @todo #55:45min
|
|
95
100
|
@todo #67/DES
|
|
96
101
|
;; @todo #678:40m/DEV
|
|
102
|
+
// TODO: #1:30min
|
|
103
|
+
(* TODO #42 *)
|
|
97
104
|
```
|
|
98
105
|
|
|
99
106
|
Here `DES` and `DEV` are the roles of people who must fix that puzzles;
|
|
100
107
|
`45min` and `40m` is the amount of time the puzzle should take;
|
|
101
|
-
`224`, `TEST-13`, `55`, `67`, and `
|
|
102
|
-
puzzles are coming from.
|
|
108
|
+
`224`, `TEST-13`, `55`, `67`, `678`, `1`, and `42` are the IDs of the tickets
|
|
109
|
+
these puzzles are coming from.
|
|
103
110
|
|
|
104
111
|
Markers are absolutely necessary for all puzzles, because they allow
|
|
105
112
|
us to build a hierarchical dependency tree of all puzzles, like
|
|
@@ -122,18 +129,18 @@ parameter specified after a colon.
|
|
|
122
129
|
|
|
123
130
|
Here is a list of rules available now:
|
|
124
131
|
|
|
125
|
-
|
|
132
|
+
- `min-estimate:15` blocks all puzzles that don't have an estimate
|
|
126
133
|
or their estimates are less than 15 minutes.
|
|
127
134
|
|
|
128
|
-
|
|
135
|
+
- `max-estimate:120` blocks all puzzles with estimates over 120 minutes.
|
|
129
136
|
|
|
130
|
-
|
|
137
|
+
- `available-roles:DEV,IMP,DES` specifies a list of roles that
|
|
131
138
|
are allowed in puzzles. Puzzles without explicitly specified
|
|
132
139
|
roles will be rejected.
|
|
133
140
|
|
|
134
|
-
|
|
141
|
+
- `min-words:5` blocks puzzles with descriptions shorter than five words.
|
|
135
142
|
|
|
136
|
-
|
|
143
|
+
- `max-duplicates:1` blocks more than one duplicate of any puzzle.
|
|
137
144
|
This rule is used by default and you can't configure it at the moment,
|
|
138
145
|
it must always be set to `1`.
|
|
139
146
|
|
|
@@ -166,18 +173,18 @@ The XML produced will look approximately like this (here is a
|
|
|
166
173
|
[XSD Schema](http://pdd-xsd.teamed.io/0.19.4.xsd) is here.
|
|
167
174
|
The most interesting parts of each puzzle are:
|
|
168
175
|
|
|
169
|
-
|
|
170
|
-
|
|
176
|
+
- `ticket` is a ticket name puzzle marker starts from, in most
|
|
177
|
+
cases it will be the number of GitHub issue.
|
|
171
178
|
|
|
172
|
-
|
|
179
|
+
- `estimate` is the amount of minutes the puzzle is supposed to take.
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
- `id` is a unique ID of the puzzle. It is calculated by the
|
|
182
|
+
internal algorithm that takes into account only the text of the puzzle.
|
|
183
|
+
Thus, if you move the puzzle from one file to another, the ID won't
|
|
184
|
+
change. Also, changing the location of a puzzle inside a file
|
|
185
|
+
won't change its ID.
|
|
179
186
|
|
|
180
|
-
|
|
187
|
+
- `lines` is where the puzzle is found, inside the file.
|
|
181
188
|
|
|
182
189
|
## How to contribute
|
|
183
190
|
|
data/Rakefile
CHANGED
data/assets/puzzles.xsd
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<!--
|
|
3
3
|
(The MIT License)
|
|
4
4
|
|
|
5
|
-
Copyright (c) 2014-
|
|
5
|
+
Copyright (c) 2014-2021 Yegor Bugayenko
|
|
6
6
|
|
|
7
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
of this software and associated documentation files (the 'Software'), to deal
|
data/assets/puzzles.xsl
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<!--
|
|
3
3
|
(The MIT License)
|
|
4
4
|
|
|
5
|
-
Copyright (c) 2014-
|
|
5
|
+
Copyright (c) 2014-2021 Yegor Bugayenko
|
|
6
6
|
|
|
7
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
of this software and associated documentation files (the 'Software'), to deal
|
data/bin/pdd
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
# Copyright (c) 2014-
|
|
2
|
+
# Copyright (c) 2014-2021 Yegor Bugayenko
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the 'Software'), to deal
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
|
|
22
22
|
STDOUT.sync = true
|
|
23
23
|
|
|
24
|
+
require 'shellwords'
|
|
25
|
+
require 'English'
|
|
26
|
+
require 'find'
|
|
24
27
|
require 'slop'
|
|
25
28
|
require 'nokogiri'
|
|
26
29
|
require 'rainbow'
|
|
@@ -39,6 +42,11 @@ begin
|
|
|
39
42
|
end
|
|
40
43
|
args += ARGV
|
|
41
44
|
|
|
45
|
+
dir = Dir.pwd
|
|
46
|
+
@dir = File.absolute_path(dir)
|
|
47
|
+
files = Dir.glob(
|
|
48
|
+
File.join(@dir, '**/*'), File::FNM_DOTMATCH
|
|
49
|
+
).reject { |f| File.directory?(f) }
|
|
42
50
|
begin
|
|
43
51
|
opts = Slop.parse(args, strict: true, help: true) do |o|
|
|
44
52
|
o.banner = "Usage (#{PDD::VERSION}): pdd [options]"
|
|
@@ -46,6 +54,8 @@ begin
|
|
|
46
54
|
o.bool '-v', '--verbose', 'Enable verbose mode (a lot of logging)'
|
|
47
55
|
o.bool '-q', '--quiet', 'Enable quiet mode (almost no logging)'
|
|
48
56
|
o.bool '--skip-gitignore', 'Don\'t look into .gitignore for excludes'
|
|
57
|
+
o.bool '--skip-errors', 'Suppress error as warning and skip badly
|
|
58
|
+
formatted puzzles'
|
|
49
59
|
o.bool '-i', '--version', 'Show current version' do
|
|
50
60
|
puts PDD::VERSION
|
|
51
61
|
exit
|
|
@@ -54,6 +64,8 @@ begin
|
|
|
54
64
|
o.string '-f', '--file', 'File to save XML into'
|
|
55
65
|
o.array '-e', '--exclude', 'Glob pattern to exclude, e.g. "**/*.jpg"',
|
|
56
66
|
default: []
|
|
67
|
+
o.array '-n', '--include', 'Glob pattern to include, e.g. "**/*.jpg"',
|
|
68
|
+
default: [files]
|
|
57
69
|
o.string '-t', '--format', 'Format of the report (xml|html)'
|
|
58
70
|
o.array(
|
|
59
71
|
'-r', '--rule', 'Rule to apply (can be used many times)',
|
|
@@ -67,7 +79,7 @@ begin
|
|
|
67
79
|
if opts.help?
|
|
68
80
|
puts opts
|
|
69
81
|
puts "This is our README to learn more: \
|
|
70
|
-
https://github.com/
|
|
82
|
+
https://github.com/cqfn/pdd/blob/master/README.md"
|
|
71
83
|
exit
|
|
72
84
|
end
|
|
73
85
|
|
|
@@ -76,7 +88,7 @@ https://github.com/yegor256/pdd/blob/master/README.md"
|
|
|
76
88
|
end
|
|
77
89
|
|
|
78
90
|
if opts['skip-gitignore']
|
|
79
|
-
raise 'For --skip-gitignore see https://github.com/
|
|
91
|
+
raise 'For --skip-gitignore see https://github.com/cqfn/pdd/issues/80'
|
|
80
92
|
end
|
|
81
93
|
|
|
82
94
|
Encoding.default_external = Encoding::UTF_8
|
|
@@ -103,9 +115,9 @@ rescue PDD::Error => ex
|
|
|
103
115
|
puts "#{Rainbow('ERROR').red}: #{ex.message}
|
|
104
116
|
If you can't understand the cause of this issue or you don't know \
|
|
105
117
|
how to fix it, please submit a GitHub issue, we will try to help you: \
|
|
106
|
-
https://github.com/
|
|
118
|
+
https://github.com/cqfn/pdd/issues. This tool is still in its beta \
|
|
107
119
|
version and we will appreciate your feedback. Here is where you can find \
|
|
108
|
-
more documentation: https://github.com/
|
|
120
|
+
more documentation: https://github.com/cqfn/pdd/blob/master/README.md."
|
|
109
121
|
PDD.log.info 'Exit code is 1'
|
|
110
122
|
exit(1)
|
|
111
123
|
rescue StandardError => ex
|
|
@@ -21,22 +21,7 @@ Feature: Catches Broken Puzzles
|
|
|
21
21
|
}
|
|
22
22
|
"""
|
|
23
23
|
When I run pdd it fails with "Space expected"
|
|
24
|
-
When I run pdd it fails with "
|
|
25
|
-
|
|
26
|
-
Scenario: Throwing exception on another broken puzzle
|
|
27
|
-
Given I have a "Sample.java" file with content:
|
|
28
|
-
"""
|
|
29
|
-
public class Main {
|
|
30
|
-
/**
|
|
31
|
-
* @todo #13 This puzzle has an incorrect format
|
|
32
|
-
* because its second line starts with too many spaces
|
|
33
|
-
*/
|
|
34
|
-
public void main(String[] args) {
|
|
35
|
-
// later
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
"""
|
|
39
|
-
When I run pdd it fails with "Too many leading spaces"
|
|
24
|
+
When I run pdd it fails with "Sample.java:6"
|
|
40
25
|
|
|
41
26
|
Scenario: Throwing exception on yet another broken puzzle
|
|
42
27
|
Given I have a "Sample.java" file with content:
|
data/features/support/env.rb
CHANGED
data/lib/pdd/puzzle.rb
CHANGED
data/lib/pdd/rule/duplicates.rb
CHANGED
data/lib/pdd/rule/estimates.rb
CHANGED
data/lib/pdd/rule/roles.rb
CHANGED
data/lib/pdd/rule/text.rb
CHANGED
data/lib/pdd/source.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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,6 +26,7 @@ require_relative '../pdd'
|
|
|
26
26
|
require_relative '../pdd/puzzle'
|
|
27
27
|
|
|
28
28
|
module PDD
|
|
29
|
+
MARKERS = ["\x40todo", 'TODO:?'].freeze
|
|
29
30
|
# Source.
|
|
30
31
|
class Source
|
|
31
32
|
# Ctor.
|
|
@@ -36,21 +37,27 @@ module PDD
|
|
|
36
37
|
@path = path
|
|
37
38
|
end
|
|
38
39
|
|
|
40
|
+
def match_markers(line)
|
|
41
|
+
MARKERS.map do |mkr|
|
|
42
|
+
%r{(.*(?:^|\s))#{mkr}\s+#([\w\-\.:/]+)\s+(.+)}.match(line)
|
|
43
|
+
end.compact
|
|
44
|
+
end
|
|
45
|
+
|
|
39
46
|
# Fetch all puzzles.
|
|
40
47
|
def puzzles
|
|
41
|
-
PDD.log.info "Reading #{@path}..."
|
|
48
|
+
PDD.log.info "Reading #{@path} ..."
|
|
42
49
|
puzzles = []
|
|
43
50
|
lines = File.readlines(@file, encoding: 'UTF-8')
|
|
44
51
|
lines.each_with_index do |line, idx|
|
|
45
52
|
begin
|
|
46
53
|
check_rules(line)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
puzzles << puzzle(lines.drop(idx + 1), m, idx)
|
|
50
|
-
end
|
|
54
|
+
match_markers(line).each do |m|
|
|
55
|
+
puzzles << puzzle(lines.drop(idx + 1), m, idx)
|
|
51
56
|
end
|
|
52
57
|
rescue Error, ArgumentError => ex
|
|
53
|
-
|
|
58
|
+
message = "#{@path}:#{idx + 1} #{ex.message}"
|
|
59
|
+
raise Error, message unless PDD.opts && PDD.opts['skip-errors']
|
|
60
|
+
PDD.log.warn message
|
|
54
61
|
end
|
|
55
62
|
end
|
|
56
63
|
puzzles
|
|
@@ -60,19 +67,19 @@ module PDD
|
|
|
60
67
|
|
|
61
68
|
def get_no_leading_space_error(todo)
|
|
62
69
|
"#{todo} must have a leading space to become \
|
|
63
|
-
a puzzle, as this page explains: https://github.com/
|
|
70
|
+
a puzzle, as this page explains: https://github.com/cqfn/pdd#how-to-format"
|
|
64
71
|
end
|
|
65
72
|
|
|
66
73
|
def get_no_puzzle_marker_error(todo)
|
|
67
74
|
"#{todo} found, but puzzle can't be parsed, \
|
|
68
75
|
most probably because #{todo} is not followed by a puzzle marker, \
|
|
69
|
-
as this page explains: https://github.com/
|
|
76
|
+
as this page explains: https://github.com/cqfn/pdd#how-to-format"
|
|
70
77
|
end
|
|
71
78
|
|
|
72
79
|
def get_space_after_hash_error(todo)
|
|
73
80
|
"#{todo} found, but there is an unexpected space \
|
|
74
81
|
after the hash sign, it should not be there, \
|
|
75
|
-
see https://github.com/
|
|
82
|
+
see https://github.com/cqfn/pdd#how-to-format"
|
|
76
83
|
end
|
|
77
84
|
|
|
78
85
|
def check_rules(line)
|
|
@@ -118,7 +125,7 @@ see https://github.com/yegor256/pdd#how-to-format"
|
|
|
118
125
|
match = re.match(text)
|
|
119
126
|
if match.nil?
|
|
120
127
|
raise "Invalid puzzle marker \"#{text}\", most probably formatted \
|
|
121
|
-
against the rules explained here: https://github.com/
|
|
128
|
+
against the rules explained here: https://github.com/cqfn/pdd#how-to-format"
|
|
122
129
|
end
|
|
123
130
|
{
|
|
124
131
|
ticket: match[1],
|
|
@@ -137,20 +144,13 @@ against the rules explained here: https://github.com/yegor256/pdd#how-to-format"
|
|
|
137
144
|
# Fetch puzzle tail (all lines after the first one)
|
|
138
145
|
def tail(lines, prefix, start)
|
|
139
146
|
lines
|
|
140
|
-
.take_while { |t| t.start_with?(prefix) }
|
|
147
|
+
.take_while { |t| match_markers(t).none? && t.start_with?(prefix) }
|
|
141
148
|
.map { |t| t[prefix.length, t.length] }
|
|
142
149
|
.take_while { |t| t =~ /^[ a-zA-Z0-9]/ }
|
|
143
150
|
.each_with_index do |t, i|
|
|
144
151
|
next if t.start_with?(' ')
|
|
145
152
|
raise Error, "Space expected at #{start + i + 2}:#{prefix.length}; \
|
|
146
153
|
make sure all lines in the puzzle body have a single leading space."
|
|
147
|
-
end
|
|
148
|
-
.each_with_index do |t, i|
|
|
149
|
-
next if t !~ /^\s{2,}/
|
|
150
|
-
raise Error, "Too many leading spaces \
|
|
151
|
-
at #{start + i + 2}:#{prefix.length}; \
|
|
152
|
-
make sure all lines that include the puzzle body start \
|
|
153
|
-
at position ##{prefix.length + 1}."
|
|
154
154
|
end
|
|
155
155
|
.map { |t| t[1, t.length] }
|
|
156
156
|
end
|
|
@@ -188,7 +188,7 @@ at position ##{prefix.length + 1}."
|
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
def add_github_login(info)
|
|
191
|
-
login = find_github_login(info
|
|
191
|
+
login = find_github_login(info)
|
|
192
192
|
info[:author] = "@#{login}" unless login.empty?
|
|
193
193
|
info
|
|
194
194
|
end
|
|
@@ -203,15 +203,24 @@ at position ##{prefix.length + 1}."
|
|
|
203
203
|
JSON.parse res.body
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
def find_github_user(
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
def find_github_user(info)
|
|
207
|
+
email, author = info.values_at(:email, :author)
|
|
208
|
+
# if email is not defined, changes have not been committed
|
|
209
|
+
return if email.nil?
|
|
210
|
+
base_uri = 'https://api.github.com/search/users?per_page=1'
|
|
211
|
+
query = base_uri + "&q=#{email}+in:email"
|
|
209
212
|
json = get_json query
|
|
213
|
+
# find user by name instead since users can make github email private
|
|
214
|
+
unless json['total_count'].positive?
|
|
215
|
+
return if author.nil?
|
|
216
|
+
query = base_uri + "&q=#{author}+in:fullname"
|
|
217
|
+
json = get_json query
|
|
218
|
+
end
|
|
210
219
|
json['items'].first
|
|
211
220
|
end
|
|
212
221
|
|
|
213
|
-
def find_github_login(
|
|
214
|
-
user = find_github_user
|
|
222
|
+
def find_github_login(info)
|
|
223
|
+
user = find_github_user info
|
|
215
224
|
user['login']
|
|
216
225
|
rescue StandardError
|
|
217
226
|
''
|
data/lib/pdd/sources.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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,6 +30,7 @@ module PDD
|
|
|
30
30
|
def initialize(dir, ptns = [])
|
|
31
31
|
@dir = File.absolute_path(dir)
|
|
32
32
|
@exclude = ptns + ['.git/**/*']
|
|
33
|
+
@include = ptns + ['.git/**/*']
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
# Fetch all sources.
|
|
@@ -37,6 +38,14 @@ module PDD
|
|
|
37
38
|
files = Dir.glob(
|
|
38
39
|
File.join(@dir, '**/*'), File::FNM_DOTMATCH
|
|
39
40
|
).reject { |f| File.directory?(f) }
|
|
41
|
+
included = 0
|
|
42
|
+
@include.each do |ptn|
|
|
43
|
+
Dir.glob(File.join(@dir, ptn), File::FNM_DOTMATCH) do |f|
|
|
44
|
+
files.keep_if { |i| i != f }
|
|
45
|
+
included += 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
PDD.log.info "#{files.size} file(s) found, #{included} files included"
|
|
40
49
|
excluded = 0
|
|
41
50
|
@exclude.each do |ptn|
|
|
42
51
|
Dir.glob(File.join(@dir, ptn), File::FNM_DOTMATCH) do |f|
|
|
@@ -55,6 +64,10 @@ module PDD
|
|
|
55
64
|
Sources.new(@dir, @exclude.push(ptn))
|
|
56
65
|
end
|
|
57
66
|
|
|
67
|
+
def include(ptn)
|
|
68
|
+
Sources.new(@dir, @include.push(ptn))
|
|
69
|
+
end
|
|
70
|
+
|
|
58
71
|
private
|
|
59
72
|
|
|
60
73
|
# @todo #98:30min Change the implementation of this method
|
data/lib/pdd/version.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
23
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
24
24
|
# License:: MIT
|
|
25
25
|
module PDD
|
|
26
|
-
VERSION = '0.20.
|
|
26
|
+
VERSION = '0.20.7'.freeze
|
|
27
27
|
end
|
data/lib/pdd.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
33
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
34
34
|
# License:: MIT
|
|
35
35
|
module PDD
|
|
36
36
|
# If it breaks.
|
|
@@ -56,17 +56,20 @@ module PDD
|
|
|
56
56
|
@logger.formatter = proc { |severity, _, _, msg|
|
|
57
57
|
if severity == 'ERROR'
|
|
58
58
|
"#{Rainbow(severity).red}: #{msg}\n"
|
|
59
|
+
elsif severity == 'WARN'
|
|
60
|
+
"#{Rainbow(severity).orange}: #{msg}\n"
|
|
59
61
|
else
|
|
60
62
|
"#{msg}\n"
|
|
61
63
|
end
|
|
62
64
|
}
|
|
63
|
-
@logger.level = Logger::
|
|
65
|
+
@logger.level = Logger::WARN
|
|
64
66
|
end
|
|
65
67
|
@logger
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
class << self
|
|
69
71
|
attr_writer :logger
|
|
72
|
+
attr_accessor :opts
|
|
70
73
|
end
|
|
71
74
|
|
|
72
75
|
# Code base abstraction
|
|
@@ -75,6 +78,7 @@ module PDD
|
|
|
75
78
|
# +opts+:: Options
|
|
76
79
|
def initialize(opts)
|
|
77
80
|
@opts = opts
|
|
81
|
+
PDD.opts = opts
|
|
78
82
|
PDD.log.level = Logger::INFO if @opts[:verbose]
|
|
79
83
|
PDD.log.level = Logger::ERROR if @opts[:quiet]
|
|
80
84
|
PDD.log.info "My version is #{PDD::VERSION}"
|
|
@@ -87,6 +91,9 @@ module PDD
|
|
|
87
91
|
PDD.log.info "Reading #{dir}"
|
|
88
92
|
require_relative 'pdd/sources'
|
|
89
93
|
sources = Sources.new(dir)
|
|
94
|
+
@opts[:include]&.each do |p|
|
|
95
|
+
sources = sources.include(p)
|
|
96
|
+
end
|
|
90
97
|
@opts[:exclude]&.each do |p|
|
|
91
98
|
sources = sources.exclude(p)
|
|
92
99
|
PDD.log.info "Excluding #{p}"
|
data/pdd.gemspec
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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
|
|
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
|
|
|
38
38
|
s.description = 'Collects PDD puzzles from a source code base'
|
|
39
39
|
s.authors = ['Yegor Bugayenko']
|
|
40
40
|
s.email = 'yegor256@gmail.com'
|
|
41
|
-
s.homepage = 'http://github.com/
|
|
41
|
+
s.homepage = 'http://github.com/cqfn/pdd'
|
|
42
42
|
s.files = `git ls-files`.split($RS)
|
|
43
43
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
44
44
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
data/test/test__helper.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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
|
|
@@ -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
|
data/test/test_duplicates.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
27
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
28
28
|
# License:: MIT
|
|
29
29
|
class TestMaxDuplicates < Minitest::Test
|
|
30
30
|
def test_max_duplicates
|
data/test/test_estimates.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
27
|
+
# Copyright:: Copyright (c) 2014-2021 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-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
29
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
30
30
|
# License:: MIT
|
|
31
31
|
class TestPDD < Minitest::Test
|
|
32
32
|
def test_basic
|
|
@@ -95,6 +95,7 @@ class TestPDD < Minitest::Test
|
|
|
95
95
|
Slop.parse args do |o|
|
|
96
96
|
o.bool '-v', '--verbose'
|
|
97
97
|
o.bool '-q', '--quiet'
|
|
98
|
+
o.bool '--skip-errors'
|
|
98
99
|
o.string '-s', '--source'
|
|
99
100
|
o.array '-e', '--exclude'
|
|
100
101
|
o.array '-r', '--rule'
|
data/test/test_roles.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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-
|
|
27
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
28
28
|
# License:: MIT
|
|
29
29
|
class TestRoles < Minitest::Test
|
|
30
30
|
def test_incorrect_role
|
data/test/test_source.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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
|
|
@@ -25,7 +25,7 @@ require_relative '../lib/pdd/sources'
|
|
|
25
25
|
|
|
26
26
|
# Source test.
|
|
27
27
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
28
|
-
# Copyright:: Copyright (c) 2014-
|
|
28
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
29
29
|
# License:: MIT
|
|
30
30
|
class TestSource < Minitest::Test
|
|
31
31
|
def test_parsing
|
|
@@ -42,15 +42,39 @@ class TestSource < Minitest::Test
|
|
|
42
42
|
~~ and it also has to work
|
|
43
43
|
"
|
|
44
44
|
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
stub_source_find_github_user(file, 'hey') do |source|
|
|
46
|
+
list = source.puzzles
|
|
47
|
+
assert_equal 2, list.size
|
|
48
|
+
puzzle = list.first
|
|
49
|
+
assert_equal '2-3', puzzle.props[:lines]
|
|
50
|
+
assert_equal 'привет, how are you doing?', puzzle.props[:body]
|
|
51
|
+
assert_equal '44', puzzle.props[:ticket]
|
|
52
|
+
assert puzzle.props[:author].nil?
|
|
53
|
+
assert puzzle.props[:email].nil?
|
|
54
|
+
assert puzzle.props[:time].nil?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_parsing_leading_spaces
|
|
60
|
+
Dir.mktmpdir 'test' do |dir|
|
|
61
|
+
file = File.join(dir, 'a.txt')
|
|
62
|
+
File.write(
|
|
63
|
+
file,
|
|
64
|
+
"
|
|
65
|
+
* \x40todo #56:30min this is a
|
|
66
|
+
* multi-line
|
|
67
|
+
* comment!
|
|
68
|
+
"
|
|
69
|
+
)
|
|
70
|
+
stub_source_find_github_user(file, 'hey') do |source|
|
|
71
|
+
list = source.puzzles
|
|
72
|
+
assert_equal 1, list.size
|
|
73
|
+
puzzle = list.first
|
|
74
|
+
assert_equal '2-4', puzzle.props[:lines]
|
|
75
|
+
assert_equal 'this is a multi-line comment!', puzzle.props[:body]
|
|
76
|
+
assert_equal '56', puzzle.props[:ticket]
|
|
77
|
+
end
|
|
54
78
|
end
|
|
55
79
|
end
|
|
56
80
|
|
|
@@ -65,12 +89,39 @@ class TestSource < Minitest::Test
|
|
|
65
89
|
"
|
|
66
90
|
)
|
|
67
91
|
error = assert_raises PDD::Error do
|
|
68
|
-
|
|
92
|
+
stub_source_find_github_user(file, 'hey', &:puzzles)
|
|
69
93
|
end
|
|
70
94
|
assert !error.message.index('Space expected').nil?
|
|
71
95
|
end
|
|
72
96
|
end
|
|
73
97
|
|
|
98
|
+
def test_succeed_despite_bad_puzzles
|
|
99
|
+
Dir.mktmpdir 'test' do |dir|
|
|
100
|
+
file = File.join(dir, 'a.txt')
|
|
101
|
+
File.write(
|
|
102
|
+
file,
|
|
103
|
+
"
|
|
104
|
+
* \x40todo #44 this is an incorrectly formatted puzzle,
|
|
105
|
+
* with a second line without a leading space
|
|
106
|
+
Another badly formatted puzzle
|
|
107
|
+
* \x40todo this puzzle misses ticket name/number
|
|
108
|
+
Something else
|
|
109
|
+
* \x40todo #123 This puzzle is correctly formatted
|
|
110
|
+
"
|
|
111
|
+
)
|
|
112
|
+
PDD.opts = { 'skip-errors' => true }
|
|
113
|
+
stub_source_find_github_user(file, 'hey') do |source|
|
|
114
|
+
list = source.puzzles
|
|
115
|
+
PDD.opts = nil
|
|
116
|
+
assert_equal 1, list.size
|
|
117
|
+
puzzle = list.first
|
|
118
|
+
assert_equal '7-7', puzzle.props[:lines]
|
|
119
|
+
assert_equal 'This puzzle is correctly formatted', puzzle.props[:body]
|
|
120
|
+
assert_equal '123', puzzle.props[:ticket]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
74
125
|
def test_failing_on_incomplete_puzzle
|
|
75
126
|
Dir.mktmpdir 't5' do |dir|
|
|
76
127
|
file = File.join(dir, 'ff.txt')
|
|
@@ -81,7 +132,7 @@ class TestSource < Minitest::Test
|
|
|
81
132
|
"
|
|
82
133
|
)
|
|
83
134
|
error = assert_raises PDD::Error do
|
|
84
|
-
|
|
135
|
+
stub_source_find_github_user(file, 'ff', &:puzzles)
|
|
85
136
|
end
|
|
86
137
|
assert !error.to_s.index("\x40todo is not followed by").nil?
|
|
87
138
|
end
|
|
@@ -92,7 +143,7 @@ class TestSource < Minitest::Test
|
|
|
92
143
|
file = File.join(dir, 'xx.txt')
|
|
93
144
|
File.write(file, ' * \x40todo #44 this is a broken unicode: ' + 0x92.chr)
|
|
94
145
|
assert_raises PDD::Error do
|
|
95
|
-
|
|
146
|
+
stub_source_find_github_user(file, 'xx', &:puzzles)
|
|
96
147
|
end
|
|
97
148
|
end
|
|
98
149
|
end
|
|
@@ -107,7 +158,7 @@ class TestSource < Minitest::Test
|
|
|
107
158
|
"
|
|
108
159
|
)
|
|
109
160
|
error = assert_raises PDD::Error do
|
|
110
|
-
|
|
161
|
+
stub_source_find_github_user(file, 'hey', &:puzzles)
|
|
111
162
|
end
|
|
112
163
|
assert !error.message.index('is not followed by a puzzle marker').nil?
|
|
113
164
|
end
|
|
@@ -123,7 +174,7 @@ class TestSource < Minitest::Test
|
|
|
123
174
|
"
|
|
124
175
|
)
|
|
125
176
|
error = assert_raises PDD::Error do
|
|
126
|
-
|
|
177
|
+
stub_source_find_github_user(file, 'x', &:puzzles)
|
|
127
178
|
end
|
|
128
179
|
assert !error.message.index("\x40todo must have a leading space").nil?
|
|
129
180
|
end
|
|
@@ -139,7 +190,7 @@ class TestSource < Minitest::Test
|
|
|
139
190
|
"
|
|
140
191
|
)
|
|
141
192
|
error = assert_raises PDD::Error do
|
|
142
|
-
|
|
193
|
+
stub_source_find_github_user(file, 'x', &:puzzles)
|
|
143
194
|
end
|
|
144
195
|
assert !error.message.index('an unexpected space').nil?
|
|
145
196
|
end
|
|
@@ -153,20 +204,23 @@ class TestSource < Minitest::Test
|
|
|
153
204
|
cd '#{dir}'
|
|
154
205
|
git init --quiet .
|
|
155
206
|
git config user.email test@teamed.io
|
|
156
|
-
git config user.name
|
|
207
|
+
git config user.name test_unknown
|
|
157
208
|
echo '\x40todo #1 this is the puzzle' > a.txt
|
|
158
209
|
git add a.txt
|
|
159
210
|
git commit --quiet -am 'first version'
|
|
160
211
|
")
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
212
|
+
stub_source_find_github_user(File.join(dir, 'a.txt')) do |source|
|
|
213
|
+
list = source.puzzles
|
|
214
|
+
assert_equal 1, list.size
|
|
215
|
+
puzzle = list.first
|
|
216
|
+
assert_equal '1-de87adc8', puzzle.props[:id]
|
|
217
|
+
assert_equal '1-1', puzzle.props[:lines]
|
|
218
|
+
assert_equal 'this is the puzzle', puzzle.props[:body]
|
|
219
|
+
assert_equal 'test_unknown', puzzle.props[:author]
|
|
220
|
+
assert_equal 'test@teamed.io', puzzle.props[:email]
|
|
221
|
+
assert_match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/,
|
|
222
|
+
puzzle.props[:time])
|
|
223
|
+
end
|
|
170
224
|
end
|
|
171
225
|
end
|
|
172
226
|
|
|
@@ -183,15 +237,18 @@ class TestSource < Minitest::Test
|
|
|
183
237
|
git add a.txt
|
|
184
238
|
git commit --quiet -am 'first version'
|
|
185
239
|
")
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
240
|
+
stub_source_find_github_user(File.join(dir, 'a.txt')) do |source|
|
|
241
|
+
list = source.puzzles
|
|
242
|
+
assert_equal 1, list.size
|
|
243
|
+
puzzle = list.first
|
|
244
|
+
assert_equal '1-de87adc8', puzzle.props[:id]
|
|
245
|
+
assert_equal '1-1', puzzle.props[:lines]
|
|
246
|
+
assert_equal 'this is the puzzle', puzzle.props[:body]
|
|
247
|
+
assert_equal 'test', puzzle.props[:author]
|
|
248
|
+
assert_nil puzzle.props[:email]
|
|
249
|
+
assert_match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/,
|
|
250
|
+
puzzle.props[:time])
|
|
251
|
+
end
|
|
195
252
|
end
|
|
196
253
|
end
|
|
197
254
|
|
|
@@ -207,10 +264,35 @@ class TestSource < Minitest::Test
|
|
|
207
264
|
git add a.txt
|
|
208
265
|
git commit --quiet -am 'first version'
|
|
209
266
|
")
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
267
|
+
stub_source_find_github_user(File.join(dir, 'a.txt')) do |source|
|
|
268
|
+
list = source.puzzles
|
|
269
|
+
assert_equal 1, list.size
|
|
270
|
+
puzzle = list.first
|
|
271
|
+
assert_equal '@yegor256', puzzle.props[:author]
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def test_skips_uncommitted_changes
|
|
277
|
+
skip if Gem.win_platform?
|
|
278
|
+
Dir.mktmpdir 'test' do |dir|
|
|
279
|
+
raise unless system("
|
|
280
|
+
cd '#{dir}'
|
|
281
|
+
git init --quiet .
|
|
282
|
+
git config user.email yegor256@gmail.com
|
|
283
|
+
git config user.name test
|
|
284
|
+
echo 'hi' > a.txt
|
|
285
|
+
git add a.txt
|
|
286
|
+
git commit --quiet -am 'first version'
|
|
287
|
+
echo '\x40todo #1 this is a puzzle uncommitted' > a.txt
|
|
288
|
+
")
|
|
289
|
+
stub_source_find_github_user(File.join(dir, 'a.txt')) do |source|
|
|
290
|
+
list = source.puzzles
|
|
291
|
+
assert_equal 1, list.size
|
|
292
|
+
puzzle = list.first
|
|
293
|
+
assert_nil puzzle.props[:email]
|
|
294
|
+
assert_equal 'Not Committed Yet', puzzle.props[:author]
|
|
295
|
+
end
|
|
214
296
|
end
|
|
215
297
|
end
|
|
216
298
|
|
|
@@ -221,12 +303,14 @@ class TestSource < Minitest::Test
|
|
|
221
303
|
file,
|
|
222
304
|
'<!--/* @todo #123 puzzle info */-->'
|
|
223
305
|
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
306
|
+
stub_source_find_github_user(file, 'hey') do |source|
|
|
307
|
+
list = source.puzzles
|
|
308
|
+
assert_equal 1, list.size
|
|
309
|
+
puzzle = list.first
|
|
310
|
+
assert_equal '1-1', puzzle.props[:lines]
|
|
311
|
+
assert_equal 'puzzle info', puzzle.props[:body]
|
|
312
|
+
assert_equal '123', puzzle.props[:ticket]
|
|
313
|
+
end
|
|
230
314
|
end
|
|
231
315
|
end
|
|
232
316
|
end
|
data/test/test_source_todo.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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,16 +24,18 @@ require_relative '../lib/pdd'
|
|
|
24
24
|
require_relative '../lib/pdd/sources'
|
|
25
25
|
|
|
26
26
|
class TestSourceTodo < Minitest::Test
|
|
27
|
-
def check_valid_puzzle(text, lines, body, ticket)
|
|
27
|
+
def check_valid_puzzle(text, lines, body, ticket, count = 1)
|
|
28
28
|
Dir.mktmpdir 'test' do |dir|
|
|
29
29
|
file = File.join(dir, 'a.txt')
|
|
30
30
|
File.write(file, text)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
stub_source_find_github_user(file, 'hey') do |source|
|
|
32
|
+
list = source.puzzles
|
|
33
|
+
assert_equal count, list.size
|
|
34
|
+
puzzle = list.first
|
|
35
|
+
assert_equal lines, puzzle.props[:lines]
|
|
36
|
+
assert_equal body, puzzle.props[:body]
|
|
37
|
+
assert_equal ticket, puzzle.props[:ticket]
|
|
38
|
+
end
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -42,7 +44,7 @@ class TestSourceTodo < Minitest::Test
|
|
|
42
44
|
file = File.join(dir, 'a.txt')
|
|
43
45
|
File.write(file, text)
|
|
44
46
|
error = assert_raises PDD::Error do
|
|
45
|
-
|
|
47
|
+
stub_source_find_github_user(file, 'hey', &:puzzles)
|
|
46
48
|
end
|
|
47
49
|
assert !error.message.index(error_msg).nil?
|
|
48
50
|
end
|
|
@@ -82,6 +84,19 @@ class TestSourceTodo < Minitest::Test
|
|
|
82
84
|
)
|
|
83
85
|
end
|
|
84
86
|
|
|
87
|
+
def test_multiple_todo_colon
|
|
88
|
+
check_valid_puzzle(
|
|
89
|
+
"
|
|
90
|
+
// TODO: #45 task description
|
|
91
|
+
// TODO: #46 another task description
|
|
92
|
+
",
|
|
93
|
+
'2-2',
|
|
94
|
+
'task description',
|
|
95
|
+
'45',
|
|
96
|
+
2
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
85
100
|
def test_todo_colon_parsing_multi_line
|
|
86
101
|
check_valid_puzzle(
|
|
87
102
|
"
|
data/test/test_sources.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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/sources'
|
|
|
26
26
|
|
|
27
27
|
# Sources test.
|
|
28
28
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
29
|
-
# Copyright:: Copyright (c) 2014-
|
|
29
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
30
30
|
# License:: MIT
|
|
31
31
|
class TestSources < Minitest::Test
|
|
32
32
|
def test_iterator
|
|
@@ -89,6 +89,20 @@ class TestSources < Minitest::Test
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
+
def test_includes_by_pattern
|
|
93
|
+
in_temp(['a/first.txt', 'b/c/d/second.txt']) do |dir|
|
|
94
|
+
list = PDD::Sources.new(dir).include('b/c/d/second.txt').fetch
|
|
95
|
+
assert_equal 1, list.size
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_includes_recursively
|
|
100
|
+
in_temp(['a/first.txt', 'b/c/second.txt', 'b/c/d/third.txt']) do |dir|
|
|
101
|
+
list = PDD::Sources.new(dir).include('**/*').fetch
|
|
102
|
+
assert_equal 0, list.size
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
92
106
|
def test_fails_with_verbose_output
|
|
93
107
|
in_temp do |dir|
|
|
94
108
|
File.write(File.join(dir, 'z1.txt'), "\x40todobroken\n")
|
data/test/test_text.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2014-
|
|
1
|
+
# Copyright (c) 2014-2021 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/text'
|
|
|
24
24
|
|
|
25
25
|
# PDD::Rule::Text module tests.
|
|
26
26
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
27
|
-
# Copyright:: Copyright (c) 2014-
|
|
27
|
+
# Copyright:: Copyright (c) 2014-2021 Yegor Bugayenko
|
|
28
28
|
# License:: MIT
|
|
29
29
|
class TestText < Minitest::Test
|
|
30
30
|
def test_min_words
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pdd
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.20.
|
|
4
|
+
version: 0.20.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yegor Bugayenko
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-08-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: nokogiri
|
|
@@ -258,7 +258,7 @@ files:
|
|
|
258
258
|
- test_assets/cambria.woff
|
|
259
259
|
- test_assets/elegant-objects.png
|
|
260
260
|
- test_assets/favicon.ico
|
|
261
|
-
homepage: http://github.com/
|
|
261
|
+
homepage: http://github.com/cqfn/pdd
|
|
262
262
|
licenses:
|
|
263
263
|
- MIT
|
|
264
264
|
metadata: {}
|
|
@@ -278,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
278
278
|
- !ruby/object:Gem::Version
|
|
279
279
|
version: '0'
|
|
280
280
|
requirements: []
|
|
281
|
-
rubygems_version: 3.
|
|
281
|
+
rubygems_version: 3.1.2
|
|
282
282
|
signing_key:
|
|
283
283
|
specification_version: 2
|
|
284
284
|
summary: Puzzle Driven Development collector
|