pdd 0.20.3 → 0.20.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 923491c89e00bd204e14a12c1c3d2f792c44c14b
4
- data.tar.gz: 70ed765544c00e134373e5db4a4801afd4c5de53
2
+ SHA256:
3
+ metadata.gz: cc5c52ddb7620147399b0ed8cec3d13900d1d36e695c42021cf2e887b4b80d7c
4
+ data.tar.gz: 6da8a3a29675c6359e427d2c16048f32a032fcc25247447ce110ac3e649b147b
5
5
  SHA512:
6
- metadata.gz: a4b425410f882fcf7400ede903ba3b9d6ed983d96dc91c58e6d70c0d911202f37db1b40657b7115a50e5afd081917882ca54df65656f020f792f91c33ce8aea5
7
- data.tar.gz: 3c02e5936c0538054a83a408b0f9083d8f45fbeabe0712f99c368b7455d3d5a31571a043623342ec85275353c6b37df136af2c5313dbbc102ea13fee4c347520
6
+ metadata.gz: e986672fe0a226d5577bd35d296f9d55685d0d77384e516d535b5cdd672a43c8e4d33a9167b6cf9e0397738b4dc7967a904324f5e77c6c48413bc4663d2e61c3
7
+ data.tar.gz: c0086dc48c63539c09ea70bcea1d7fba64c1eb48fc51a6a2ffa65740e0333a38b6bb93b7dfe634b0e4e99d173539b19054922d2cbfebc78a88dc32a42f41bb36
@@ -2,6 +2,8 @@ assets:
2
2
  rubygems.yml: zerocracy/home#assets/rubygems.yml
3
3
  s3cfg: zerocracy/home#assets/s3cfg
4
4
  install: |
5
+ export GEM_HOME=~/.ruby
6
+ export GEM_PATH=$GEM_HOME:$GEM_PATH
5
7
  sudo gem install pdd
6
8
  sudo gem install xcop
7
9
  release:
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  <img src="https://avatars2.githubusercontent.com/u/24456188" width="64px" height="64px"/>
2
2
 
3
+ [![Donate via Zerocracy](https://www.0crat.com/contrib-badge/C3T46CUJJ.svg)](https://www.0crat.com/contrib/C3T46CUJJ)
4
+
3
5
  [![EO principles respected here](http://www.elegantobjects.org/badge.svg)](http://www.elegantobjects.org)
4
6
  [![Managed by Zerocracy](https://www.0crat.com/badge/C3T46CUJJ.svg)](https://www.0crat.com/p/C3T46CUJJ)
5
7
  [![DevOps By Rultor.com](http://www.rultor.com/b/yegor256/pdd)](http://www.rultor.com/p/yegor256/pdd)
@@ -13,6 +15,7 @@
13
15
  [![Dependency Status](https://gemnasium.com/yegor256/pdd.svg)](https://gemnasium.com/yegor256/pdd)
14
16
  [![Maintainability](https://api.codeclimate.com/v1/badges/c8e46256fdd8ddc817e5/maintainability)](https://codeclimate.com/github/yegor256/pdd/maintainability)
15
17
  [![Test Coverage](https://img.shields.io/codecov/c/github/yegor256/pdd.svg)](https://codecov.io/github/yegor256/pdd?branch=master)
18
+ [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/yegor256/pdd/master/frames)
16
19
 
17
20
  ## What This is for?
18
21
 
@@ -53,6 +56,16 @@ pdd --exclude=src/**/* # exclude all files in src/
53
56
  Every puzzle has to be formatted like this (pay attention
54
57
  to the leading space in every consecutive line):
55
58
 
59
+ ```java
60
+ /**
61
+ * @todo #[issue#]<:[time]></[role]> <[description]>
62
+ */
63
+ [related code]
64
+ ```
65
+ \[\] - Replace with apropriate data (see text enclosed in brackets)
66
+ <> - Omitable (enclosed data can be left out)
67
+
68
+ Example:
56
69
  ```java
57
70
  /**
58
71
  * @todo #234:15m/DEV This is something to do later
@@ -168,9 +181,19 @@ The most interesting parts of each puzzle are:
168
181
 
169
182
  * `lines` is where the puzzle is found, inside the file.
170
183
 
171
- ## How to contribute?
184
+ # How to contribute
185
+
186
+ Read [these guidelines](https://www.yegor256.com/2014/04/15/github-guidelines.html).
187
+ Make sure you build is green before you contribute
188
+ your pull request. You will need to have [Ruby](https://www.ruby-lang.org/en/) 2.3+ and
189
+ [Bundler](https://bundler.io/) installed. Then:
190
+
191
+ ```
192
+ $ bundle update
193
+ $ rake
194
+ ```
172
195
 
173
- Just submit a pull request. Make sure `rake` passes.
196
+ If it's clean and you don't see any error messages, submit your pull request.
174
197
 
175
198
  This is how you run the tool locally to test how it works:
176
199
 
data/bin/pdd CHANGED
@@ -100,7 +100,7 @@ rescue SystemExit => ex
100
100
  PDD.log.info "Exit code is #{ex.status}"
101
101
  exit(ex.status)
102
102
  rescue PDD::Error => ex
103
- puts "#{Rainbow('ERROR').red}: #{ex.message}. \
103
+ puts "#{Rainbow('ERROR').red}: #{ex.message}
104
104
  If you can't understand the cause of this issue or you don't know \
105
105
  how to fix it, please submit a GitHub issue, we will try to help you: \
106
106
  https://github.com/yegor256/pdd/issues. This tool is still in its beta \
@@ -19,6 +19,8 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'digest/md5'
22
+ require 'net/http'
23
+ require 'json'
22
24
  require 'shellwords'
23
25
  require_relative '../pdd'
24
26
  require_relative '../pdd/puzzle'
@@ -41,23 +43,13 @@ module PDD
41
43
  lines = File.readlines(@file, encoding: 'UTF-8')
42
44
  lines.each_with_index do |line, idx|
43
45
  begin
44
- /[^\s]\x40todo/.match(line) do |_|
45
- raise Error, "\x40todo must have a leading space to become \
46
- a puzzle, as this page explains: https://github.com/yegor256/pdd#how-to-format"
47
- end
48
- /\x40todo(?!\s+#)/.match(line) do |_|
49
- raise Error, "\x40todo found, but puzzle can't be parsed, \
50
- most probably because \x40todo is not followed by a puzzle marker, \
51
- as this page explains: https://github.com/yegor256/pdd#how-to-format"
52
- end
53
- /\x40todo\s+#\s/.match(line) do |_|
54
- raise Error, "\x40todo found, but there is an unexpected space \
55
- after the hash sign, it should not be there, \
56
- see https://github.com/yegor256/pdd#how-to-format"
57
- end
46
+ check_rules(line)
58
47
  %r{(.*(?:^|\s))\x40todo\s+#([\w\-\.:/]+)\s+(.+)}.match(line) do |m|
59
48
  puzzles << puzzle(lines.drop(idx + 1), m, idx)
60
49
  end
50
+ %r{(.*(?:^|\s))TODO:?\s+#([\w\-\.:/]+)\s+(.+)}.match(line) do |m|
51
+ puzzles << puzzle(lines.drop(idx + 1), m, idx)
52
+ end
61
53
  rescue Error, ArgumentError => ex
62
54
  raise Error, "puzzle at line ##{idx + 1}; #{ex.message}"
63
55
  end
@@ -67,10 +59,49 @@ see https://github.com/yegor256/pdd#how-to-format"
67
59
 
68
60
  private
69
61
 
62
+ def get_no_leading_space_error(todo)
63
+ "#{todo} must have a leading space to become \
64
+ a puzzle, as this page explains: https://github.com/yegor256/pdd#how-to-format"
65
+ end
66
+
67
+ def get_no_puzzle_marker_error(todo)
68
+ "#{todo} found, but puzzle can't be parsed, \
69
+ most probably because #{todo} is not followed by a puzzle marker, \
70
+ as this page explains: https://github.com/yegor256/pdd#how-to-format"
71
+ end
72
+
73
+ def get_space_after_hash_error(todo)
74
+ "#{todo} found, but there is an unexpected space \
75
+ after the hash sign, it should not be there, \
76
+ see https://github.com/yegor256/pdd#how-to-format"
77
+ end
78
+
79
+ def check_rules(line)
80
+ /[^\s]\x40todo/.match(line) do |_|
81
+ raise Error, get_no_leading_space_error("\x40todo")
82
+ end
83
+ /\x40todo(?!\s+#)/.match(line) do |_|
84
+ raise Error, get_no_puzzle_marker_error("\x40todo")
85
+ end
86
+ /\x40todo\s+#\s/.match(line) do |_|
87
+ raise Error, get_space_after_hash_error("\x40todo")
88
+ end
89
+ /[^\s]TODO:?/.match(line) do |_|
90
+ raise Error, get_no_leading_space_error('TODO')
91
+ end
92
+ /TODO(?!:?\s+#)/.match(line) do |_|
93
+ raise Error, get_no_puzzle_marker_error('TODO')
94
+ end
95
+ /TODO:?\s+#\s/.match(line) do |_|
96
+ raise Error, get_space_after_hash_error('TODO')
97
+ end
98
+ end
99
+
70
100
  # Fetch puzzle
71
101
  def puzzle(lines, match, idx)
72
102
  tail = tail(lines, match[1], idx)
73
103
  body = (match[3] + ' ' + tail.join(' ')).gsub(/\s+/, ' ').strip
104
+ body = body.chomp('*/-->').strip
74
105
  marker = marker(match[2])
75
106
  Puzzle.new(
76
107
  marker.merge(
@@ -136,7 +167,7 @@ at position ##{prefix.length + 1}."
136
167
  git = "cd #{dir} && git"
137
168
  if `#{git} rev-parse --is-inside-work-tree 2>/dev/null`.strip == 'true'
138
169
  cmd = "#{git} blame -L #{pos},#{pos} --porcelain #{name}"
139
- Hash[
170
+ add_github_login(Hash[
140
171
  `#{cmd}`.split("\n").map do |line|
141
172
  if line =~ /^author /
142
173
  [:author, line.sub(/^author /, '')]
@@ -151,11 +182,41 @@ at position ##{prefix.length + 1}."
151
182
  ]
152
183
  end
153
184
  end.compact
154
- ]
185
+ ])
155
186
  else
156
187
  {}
157
188
  end
158
189
  end
190
+
191
+ def add_github_login(info)
192
+ login = find_github_login(info[:email])
193
+ info[:author] = "@#{login}" unless login.empty?
194
+ info
195
+ end
196
+
197
+ def get_json(query)
198
+ uri = URI.parse(query)
199
+ http = Net::HTTP.new(uri.hostname, uri.port)
200
+ http.use_ssl = uri.scheme == 'https'
201
+ req = Net::HTTP::Get.new(uri.request_uri)
202
+ req.set_content_type('application/json')
203
+ res = http.request(req)
204
+ JSON.parse res.body
205
+ end
206
+
207
+ def find_github_user(email)
208
+ base_uri = 'https://api.github.com/search/users'
209
+ query = base_uri + "?q=#{email}+in:email&perpage=1"
210
+ json = get_json query
211
+ json['items'].first
212
+ end
213
+
214
+ def find_github_login(email)
215
+ user = find_github_user email
216
+ user['login']
217
+ rescue StandardError
218
+ ''
219
+ end
159
220
  end
160
221
 
161
222
  # Verbose Source.
@@ -57,13 +57,17 @@ module PDD
57
57
 
58
58
  private
59
59
 
60
- def binary?(f)
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
+ def binary?(file)
61
65
  return false if Gem.win_platform?
62
- `grep -qI '.' #{Shellwords.escape(f)}`
66
+ `grep -qI '.' #{Shellwords.escape(file)}`
63
67
  if $CHILD_STATUS.success?
64
68
  false
65
69
  else
66
- PDD.log.info "#{f} is a binary file (#{File.size(f)} bytes)"
70
+ PDD.log.info "#{file} is a binary file (#{File.size(file)} bytes)"
67
71
  true
68
72
  end
69
73
  end
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2014-2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module PDD
26
- VERSION = '0.20.3'.freeze
26
+ VERSION = '0.20.4'.freeze
27
27
  end
@@ -28,16 +28,14 @@ require_relative '../lib/pdd/sources'
28
28
  # Copyright:: Copyright (c) 2014-2018 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  class TestSource < Minitest::Test
31
- # @todo #85:30min Make this test pass on AppVeyor.
32
31
  def test_parsing
33
- skip('Skipped because it fails on AppVeyor')
34
32
  Dir.mktmpdir 'test' do |dir|
35
33
  file = File.join(dir, 'a.txt')
36
34
  File.write(
37
35
  file,
38
36
  "
39
37
  * \x40todo #44 привет,
40
- * how are you\t\r\tdoing?
38
+ * how are you\t\tdoing?
41
39
  * -something else
42
40
  Something else
43
41
  ~~ \x40todo #ABC-3 this is another puzzle
@@ -90,7 +88,6 @@ class TestSource < Minitest::Test
90
88
  end
91
89
 
92
90
  def test_failing_on_broken_unicode
93
- skip if Gem.win_platform?
94
91
  Dir.mktmpdir 'test' do |dir|
95
92
  file = File.join(dir, 'xx.txt')
96
93
  File.write(file, ' * \x40todo #44 this is a broken unicode: ' + 0x92.chr)
@@ -101,7 +98,6 @@ class TestSource < Minitest::Test
101
98
  end
102
99
 
103
100
  def test_failing_on_invalid_puzzle_without_hash_sign
104
- skip('doesnt work now')
105
101
  Dir.mktmpdir 'test' do |dir|
106
102
  file = File.join(dir, 'a.txt')
107
103
  File.write(
@@ -113,7 +109,7 @@ class TestSource < Minitest::Test
113
109
  error = assert_raises PDD::Error do
114
110
  PDD::VerboseSource.new(file, PDD::Source.new(file, 'hey')).puzzles
115
111
  end
116
- assert !error.message.index('Incorrect format').nil?
112
+ assert !error.message.index('is not followed by a puzzle marker').nil?
117
113
  end
118
114
  end
119
115
 
@@ -198,4 +194,39 @@ class TestSource < Minitest::Test
198
194
  assert_match(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/, puzzle.props[:time])
199
195
  end
200
196
  end
197
+
198
+ def test_uses_github_login
199
+ skip if Gem.win_platform?
200
+ Dir.mktmpdir 'test' do |dir|
201
+ raise unless system("
202
+ cd '#{dir}'
203
+ git init --quiet .
204
+ git config user.email yegor256@gmail.com
205
+ git config user.name test
206
+ echo '\x40todo #1 this is the puzzle' > a.txt
207
+ git add a.txt
208
+ git commit --quiet -am 'first version'
209
+ ")
210
+ list = PDD::Source.new(File.join(dir, 'a.txt'), '').puzzles
211
+ assert_equal 1, list.size
212
+ puzzle = list.first
213
+ assert_equal '@yegor256', puzzle.props[:author]
214
+ end
215
+ end
216
+
217
+ def test_skips_thymeleaf_close_tag
218
+ Dir.mktmpdir 'test' do |dir|
219
+ file = File.join(dir, 'a.txt')
220
+ File.write(
221
+ file,
222
+ '<!--/* @todo #123 puzzle info */-->'
223
+ )
224
+ list = PDD::VerboseSource.new(file, PDD::Source.new(file, 'hey')).puzzles
225
+ assert_equal 1, list.size
226
+ puzzle = list.first
227
+ assert_equal '1-1', puzzle.props[:lines]
228
+ assert_equal 'puzzle info', puzzle.props[:body]
229
+ assert_equal '123', puzzle.props[:ticket]
230
+ end
231
+ end
201
232
  end
@@ -0,0 +1,168 @@
1
+ # Copyright (c) 2014-2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'minitest/autorun'
22
+ require 'tmpdir'
23
+ require_relative '../lib/pdd'
24
+ require_relative '../lib/pdd/sources'
25
+
26
+ class TestSourceTodo < Minitest::Test
27
+ def check_valid_puzzle(text, lines, body, ticket)
28
+ Dir.mktmpdir 'test' do |dir|
29
+ file = File.join(dir, 'a.txt')
30
+ File.write(file, text)
31
+ list = PDD::VerboseSource.new(file, PDD::Source.new(file, 'hey')).puzzles
32
+ assert_equal 1, list.size
33
+ puzzle = list.first
34
+ assert_equal lines, puzzle.props[:lines]
35
+ assert_equal body, puzzle.props[:body]
36
+ assert_equal ticket, puzzle.props[:ticket]
37
+ end
38
+ end
39
+
40
+ def check_invalid_puzzle(text, error_msg)
41
+ Dir.mktmpdir 'test' do |dir|
42
+ file = File.join(dir, 'a.txt')
43
+ File.write(file, text)
44
+ error = assert_raises PDD::Error do
45
+ PDD::VerboseSource.new(file, PDD::Source.new(file, 'hey')).puzzles
46
+ end
47
+ assert !error.message.index(error_msg).nil?
48
+ end
49
+ end
50
+
51
+ def test_todo_parsing
52
+ check_valid_puzzle(
53
+ "
54
+ // TODO #45 task description
55
+ ",
56
+ '2-2',
57
+ 'task description',
58
+ '45'
59
+ )
60
+ end
61
+
62
+ def test_todo_parsing_multi_line
63
+ check_valid_puzzle(
64
+ "
65
+ // TODO #45 task description
66
+ // second line
67
+ ",
68
+ '2-3',
69
+ 'task description second line',
70
+ '45'
71
+ )
72
+ end
73
+
74
+ def test_todo_colon_parsing
75
+ check_valid_puzzle(
76
+ "
77
+ // TODO: #45 task description
78
+ ",
79
+ '2-2',
80
+ 'task description',
81
+ '45'
82
+ )
83
+ end
84
+
85
+ def test_todo_colon_parsing_multi_line
86
+ check_valid_puzzle(
87
+ "
88
+ // TODO: #45 task description
89
+ // second line
90
+ ",
91
+ '2-3',
92
+ 'task description second line',
93
+ '45'
94
+ )
95
+ end
96
+
97
+ def test_todo_failing_no_space_on_second_line
98
+ check_invalid_puzzle(
99
+ "
100
+ * TODO #45 this puzzle
101
+ * has not space on second line",
102
+ 'Space expected'
103
+ )
104
+ end
105
+
106
+ def test_todo_colon_failing_no_space_on_second_line
107
+ check_invalid_puzzle(
108
+ "
109
+ * TODO: #45 this puzzle
110
+ * has not space on second line",
111
+ 'Space expected'
112
+ )
113
+ end
114
+
115
+ def test_todo_failing_no_ticket
116
+ check_invalid_puzzle(
117
+ "
118
+ * TODO this puzzle misses ticket name/number
119
+ ",
120
+ 'TODO is not followed by'
121
+ )
122
+ end
123
+
124
+ def test_todo_colon_failing_no_ticket
125
+ check_invalid_puzzle(
126
+ "
127
+ * TODO: this puzzle misses ticket name/number
128
+ ",
129
+ 'TODO is not followed by'
130
+ )
131
+ end
132
+
133
+ def test_todo_failing_space_after_hash
134
+ check_invalid_puzzle(
135
+ "
136
+ * TODO # 45 this puzzle has space after hash
137
+ ",
138
+ 'TODO found, but there is an unexpected space after the hash sign'
139
+ )
140
+ end
141
+
142
+ def test_todo_colon_failing_space_after_hash
143
+ check_invalid_puzzle(
144
+ "
145
+ * TODO: # 45 this puzzle has space after hash
146
+ ",
147
+ 'TODO found, but there is an unexpected space after the hash sign'
148
+ )
149
+ end
150
+
151
+ def test_todo_failing_no_space_before
152
+ check_invalid_puzzle(
153
+ "
154
+ *TODO #45 this puzzle has no space before todo
155
+ ",
156
+ 'TODO must have a leading space'
157
+ )
158
+ end
159
+
160
+ def test_todo_colon_failing_no_space_before
161
+ check_invalid_puzzle(
162
+ "
163
+ *TODO: #45 this puzzle has no space before todo
164
+ ",
165
+ 'TODO must have a leading space'
166
+ )
167
+ end
168
+ end
@@ -82,6 +82,13 @@ class TestSources < Minitest::Test
82
82
  end
83
83
  end
84
84
 
85
+ def test_excludes_recursively
86
+ in_temp(['a/first.txt', 'b/c/second.txt', 'b/c/d/third.txt']) do |dir|
87
+ list = PDD::Sources.new(dir).exclude('**/*').fetch
88
+ assert_equal 0, list.size
89
+ end
90
+ end
91
+
85
92
  def test_fails_with_verbose_output
86
93
  in_temp do |dir|
87
94
  File.write(File.join(dir, 'z1.txt'), "\x40todobroken\n")
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.3
4
+ version: 0.20.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-05 00:00:00.000000000 Z
11
+ date: 2018-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -233,6 +233,7 @@ files:
233
233
  - test/test_pdd.rb
234
234
  - test/test_roles.rb
235
235
  - test/test_source.rb
236
+ - test/test_source_todo.rb
236
237
  - test/test_sources.rb
237
238
  - test/test_text.rb
238
239
  - test_assets/aladdin.jpg
@@ -261,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
262
  version: '0'
262
263
  requirements: []
263
264
  rubyforge_project:
264
- rubygems_version: 2.6.8
265
+ rubygems_version: 2.7.6
265
266
  signing_key:
266
267
  specification_version: 2
267
268
  summary: Puzzle Driven Development collector
@@ -283,5 +284,6 @@ test_files:
283
284
  - test/test_pdd.rb
284
285
  - test/test_roles.rb
285
286
  - test/test_source.rb
287
+ - test/test_source_todo.rb
286
288
  - test/test_sources.rb
287
289
  - test/test_text.rb