pdd 0.20.6 → 0.20.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![EO principles respected here](https://www.elegantobjects.org/badge.svg)](https://www.elegantobjects.org)
|
6
6
|
[![Managed by Zerocracy](https://www.0crat.com/badge/C3T46CUJJ.svg)](https://www.0crat.com/p/C3T46CUJJ)
|
7
|
-
[![DevOps By Rultor.com](http://www.rultor.com/b/
|
7
|
+
[![DevOps By Rultor.com](http://www.rultor.com/b/cqfn/pdd)](http://www.rultor.com/p/cqfn/pdd)
|
8
8
|
[![We recommend RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
|
9
9
|
|
10
|
-
[![Build Status](https://travis-ci.org/
|
11
|
-
[![Build status](https://ci.appveyor.com/api/projects/status/b59sdhuu0gcku15b?svg=true)](https://ci.appveyor.com/project/
|
12
|
-
[![PDD status](http://www.0pdd.com/svg?name=
|
13
|
-
[![Test Coverage](https://img.shields.io/codecov/c/github/
|
14
|
-
[![Hits-of-Code](https://hitsofcode.com/github/
|
15
|
-
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/
|
10
|
+
[![Build Status](https://travis-ci.org/cqfn/pdd.svg)](https://travis-ci.org/cqfn/pdd)
|
11
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/b59sdhuu0gcku15b?svg=true)](https://ci.appveyor.com/project/cqfn/pdd)
|
12
|
+
[![PDD status](http://www.0pdd.com/svg?name=cqfn/pdd)](http://www.0pdd.com/p?name=cqfn/pdd)
|
13
|
+
[![Test Coverage](https://img.shields.io/codecov/c/github/cqfn/pdd.svg)](https://codecov.io/github/cqfn/pdd?branch=master)
|
14
|
+
[![Hits-of-Code](https://hitsofcode.com/github/cqfn/pdd)](https://hitsofcode.com/view/github/cqfn/pdd)
|
15
|
+
[![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/cqfn/pdd/blob/master/LICENSE.txt)
|
16
16
|
|
17
17
|
[![Gem Version](https://badge.fury.io/rb/pdd.svg)](http://badge.fury.io/rb/pdd)
|
18
|
-
[![Maintainability](https://api.codeclimate.com/v1/badges/c8e46256fdd8ddc817e5/maintainability)](https://codeclimate.com/github/
|
19
|
-
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/
|
18
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/c8e46256fdd8ddc817e5/maintainability)](https://codeclimate.com/github/cqfn/pdd/maintainability)
|
19
|
+
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](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
|