todidnt 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/README.md +33 -0
- data/Rakefile +4 -0
- data/bin/todidnt +8 -3
- data/lib/todidnt/todo_line.rb +1 -1
- data/lib/todidnt.rb +53 -9
- data/test/lib.rb +5 -2
- data/test/test_todo_line.rb +108 -0
- data/todidnt.gemspec +2 -2
- metadata +6 -6
- data/README +0 -9
- data/test/todo_line.rb +0 -86
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Todidnt
|
2
|
+
====
|
3
|
+
|
4
|
+
(:construction: This project is currently under construction! :construction:)
|
5
|
+
|
6
|
+
Todidnt is a utility to help you track down TODOs and FIXMEs that you always
|
7
|
+
said you'd do but haven't done yet.
|
8
|
+
|
9
|
+
Usage
|
10
|
+
----
|
11
|
+
|
12
|
+
Install the gem:
|
13
|
+
|
14
|
+
gem install todidnt
|
15
|
+
|
16
|
+
Then, run `todidnt` in any Git repository directory:
|
17
|
+
|
18
|
+
$ todidnt
|
19
|
+
|
20
|
+
TODO[1]
|
21
|
+
----
|
22
|
+
|
23
|
+
- Optimizing blame step
|
24
|
+
- Filtering by author, label
|
25
|
+
- Fancy formatted reports
|
26
|
+
- TODO stats
|
27
|
+
|
28
|
+
Credit
|
29
|
+
----
|
30
|
+
|
31
|
+
Paul Battley (@threedaymonk) for initial idea/implementation and witty name.
|
32
|
+
|
33
|
+
1: Oh, the irony.
|
data/Rakefile
ADDED
data/bin/todidnt
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
|
5
|
-
require_relative '../lib/todidnt'
|
4
|
+
require 'todidnt'
|
6
5
|
|
7
6
|
options = {:path => '.'}
|
7
|
+
command = ARGV.shift
|
8
|
+
|
8
9
|
ARGV.options do |opts|
|
9
10
|
opts.on('-p', '--path PATH', 'Git directory to run Todidnt in (default: current directory)') do |path|
|
10
11
|
options[:path] = path
|
11
12
|
end
|
12
13
|
|
14
|
+
opts.on('-d', '--date STRING', 'Fuzzy string for overdue date comparison, e.g. last week or 7/2/2013 (default: today)') do |date|
|
15
|
+
options[:date] = date
|
16
|
+
end
|
17
|
+
|
13
18
|
opts.on_tail('-h', '--help', 'Show this message') do
|
14
19
|
puts opts
|
15
20
|
exit
|
@@ -18,4 +23,4 @@ ARGV.options do |opts|
|
|
18
23
|
opts.parse!
|
19
24
|
end
|
20
25
|
|
21
|
-
Todidnt::
|
26
|
+
Todidnt::CLI.run(command, options)
|
data/lib/todidnt/todo_line.rb
CHANGED
@@ -2,7 +2,7 @@ module Todidnt
|
|
2
2
|
class TodoLine
|
3
3
|
IGNORE = %r{assets/js|third_?party|node_modules|jquery|Binary}
|
4
4
|
|
5
|
-
attr_reader :filename, :line_number, :content, :author
|
5
|
+
attr_reader :filename, :line_number, :content, :author, :timestamp
|
6
6
|
|
7
7
|
def self.all(expressions)
|
8
8
|
options = [['-n']]
|
data/lib/todidnt.rb
CHANGED
@@ -1,10 +1,57 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require 'todidnt/git_repo'
|
2
|
+
require 'todidnt/git_command'
|
3
|
+
require 'todidnt/todo_line'
|
4
|
+
|
5
|
+
require 'chronic'
|
4
6
|
|
5
7
|
module Todidnt
|
6
|
-
class
|
7
|
-
|
8
|
+
class CLI
|
9
|
+
VALID_COMMANDS = %w{all overdue}
|
10
|
+
|
11
|
+
def self.run(command, options)
|
12
|
+
if command && VALID_COMMANDS.include?(command)
|
13
|
+
self.send(command, options)
|
14
|
+
elsif command
|
15
|
+
$stderr.puts("Sorry, `#{command}` is not a valid command.")
|
16
|
+
exit
|
17
|
+
else
|
18
|
+
$stderr.puts("You must specify a command! Try `todidnt all`.")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.all(options)
|
23
|
+
all_lines = self.all_lines(options)
|
24
|
+
|
25
|
+
puts "\nResults:"
|
26
|
+
all_lines.sort_by do |line|
|
27
|
+
line.timestamp
|
28
|
+
end.each do |line|
|
29
|
+
puts line.pretty
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.overdue(options)
|
34
|
+
date = Chronic.parse(options[:date] || 'now', :context => :past)
|
35
|
+
if date.nil?
|
36
|
+
$stderr.puts("Invalid date passed: #{options[:date]}")
|
37
|
+
exit
|
38
|
+
else
|
39
|
+
puts "Finding overdue TODOs (created before #{date.strftime('%F')})..."
|
40
|
+
end
|
41
|
+
|
42
|
+
all_lines = self.all_lines(options)
|
43
|
+
|
44
|
+
puts "\nResults:"
|
45
|
+
all_lines.sort_by do |line|
|
46
|
+
line.timestamp
|
47
|
+
end.select do |line|
|
48
|
+
line.timestamp < date.to_i
|
49
|
+
end.each do |line|
|
50
|
+
puts line.pretty
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.all_lines(options)
|
8
55
|
GitRepo.new(options[:path]).run do |path|
|
9
56
|
puts "Running in #{path || 'current directory'}..."
|
10
57
|
lines = TodoLine.all(["TODO"])
|
@@ -15,10 +62,7 @@ module Todidnt
|
|
15
62
|
$stdout.write "\rBlamed: #{i}/#{lines.count}"
|
16
63
|
end
|
17
64
|
|
18
|
-
|
19
|
-
lines.each do |line|
|
20
|
-
puts line.pretty
|
21
|
-
end
|
65
|
+
lines
|
22
66
|
end
|
23
67
|
end
|
24
68
|
end
|
data/test/lib.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
unless defined? Todidnt
|
2
|
+
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'todidnt'
|
4
|
+
end
|
5
|
+
|
1
6
|
require 'minitest/spec'
|
2
7
|
require 'minitest/autorun'
|
3
8
|
require 'mocha/setup'
|
4
9
|
|
5
|
-
require_relative '../lib/todidnt'
|
6
|
-
|
7
10
|
class Test < MiniTest::Spec
|
8
11
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'lib'
|
2
|
+
|
3
|
+
class TestTodoLine < Test
|
4
|
+
before do
|
5
|
+
Todidnt::GitCommand.any_instance.stubs(:run!)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.all' do
|
9
|
+
describe 'unit' do
|
10
|
+
it 'constructs the correct `git grep` command' do
|
11
|
+
grep = mock()
|
12
|
+
grep.stubs(:output_lines => [])
|
13
|
+
|
14
|
+
Todidnt::GitCommand.expects(:new).with(:grep, [['-n'], ['-e', 'hello']]).returns(grep)
|
15
|
+
Todidnt::TodoLine.all(['hello'])
|
16
|
+
|
17
|
+
Todidnt::GitCommand.expects(:new).with(:grep, [['-n'], ['-e', 'hello'], ['-e', 'goodbye']]).returns(grep)
|
18
|
+
Todidnt::TodoLine.all(['hello', 'goodbye'])
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a TodoLine object for each result line properly' do
|
22
|
+
Todidnt::GitCommand.any_instance.expects(:output_lines).returns(
|
23
|
+
[
|
24
|
+
'filename.rb:12: content',
|
25
|
+
'other_filename.rb:643: TODO'
|
26
|
+
]
|
27
|
+
)
|
28
|
+
|
29
|
+
Todidnt::TodoLine.expects(:new).with('filename.rb', 12, 'content')
|
30
|
+
Todidnt::TodoLine.expects(:new).with('other_filename.rb', 643, 'TODO')
|
31
|
+
|
32
|
+
Todidnt::TodoLine.all(['anything'])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'functional' do
|
37
|
+
it 'returns a list of TodoLine objects as matches' do
|
38
|
+
Todidnt::GitCommand.any_instance.expects(:output_lines).returns(
|
39
|
+
[
|
40
|
+
'filename.rb:12: content',
|
41
|
+
'other_filename.rb:643: TODO'
|
42
|
+
]
|
43
|
+
)
|
44
|
+
|
45
|
+
todos = Todidnt::TodoLine.all(['anything'])
|
46
|
+
assert_equal 2, todos.count
|
47
|
+
|
48
|
+
assert_equal 'filename.rb', todos.first.filename
|
49
|
+
assert_equal 12, todos.first.line_number
|
50
|
+
assert_equal 'content', todos.first.content
|
51
|
+
|
52
|
+
assert_equal 'other_filename.rb', todos.last.filename
|
53
|
+
assert_equal 643, todos.last.line_number
|
54
|
+
assert_equal 'TODO', todos.last.content
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'ignores lines matching IGNORE list' do
|
58
|
+
Todidnt::GitCommand.any_instance.expects(:output_lines).returns(
|
59
|
+
[
|
60
|
+
'filename.rb:12: content',
|
61
|
+
'thirdparty/other_filename.rb:643: TODO'
|
62
|
+
]
|
63
|
+
)
|
64
|
+
|
65
|
+
todos = Todidnt::TodoLine.all(['anything'])
|
66
|
+
assert_equal 1, todos.count
|
67
|
+
|
68
|
+
assert_equal 'filename.rb', todos.first.filename
|
69
|
+
assert_equal 12, todos.first.line_number
|
70
|
+
assert_equal 'content', todos.first.content
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#populate_blame' do
|
76
|
+
it 'constructs the correct `git blame` command' do
|
77
|
+
blame = mock()
|
78
|
+
blame.expects(:output_lines).returns([])
|
79
|
+
Todidnt::GitCommand.expects(:new).with(:blame,
|
80
|
+
[
|
81
|
+
['--line-porcelain'],
|
82
|
+
['-L', '50,50'],
|
83
|
+
['filename.rb']
|
84
|
+
]
|
85
|
+
).returns(blame)
|
86
|
+
|
87
|
+
todo_line = Todidnt::TodoLine.new('filename.rb', 50, 'commit message')
|
88
|
+
todo_line.populate_blame
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'sets author, timestamp properties on the TodoLine object' do
|
92
|
+
blame = mock()
|
93
|
+
blame.expects(:output_lines).returns(
|
94
|
+
%w{
|
95
|
+
39efeb14a9 1 1
|
96
|
+
author Amber Feng
|
97
|
+
author-time 1383882788
|
98
|
+
author-mail <amber.feng@gmail.com>,
|
99
|
+
summary Commit message,
|
100
|
+
}
|
101
|
+
)
|
102
|
+
Todidnt::GitCommand.expects(:new).returns(blame)
|
103
|
+
|
104
|
+
todo_line = Todidnt::TodoLine.new('filename.rb', 50, 'commit message')
|
105
|
+
todo_line.populate_blame
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/todidnt.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'todidnt'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.1.0'
|
4
4
|
s.summary = 'Todidnt'
|
5
5
|
s.description = "Todidnt finds and dates todos in your git repository."
|
6
6
|
s.authors = ["Amber Feng"]
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.add_development_dependency('mocha')
|
11
11
|
|
12
12
|
s.files = `git ls-files`.split("\n")
|
13
|
-
s.test_files = `git ls-files -- test
|
13
|
+
s.test_files = `git ls-files -- test/test_*.rb`.split("\n")
|
14
14
|
s.executables = ['todidnt']
|
15
15
|
s.require_paths = %w[lib]
|
16
16
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: todidnt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -52,14 +52,15 @@ extra_rdoc_files: []
|
|
52
52
|
files:
|
53
53
|
- Gemfile
|
54
54
|
- Gemfile.lock
|
55
|
-
- README
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
56
57
|
- bin/todidnt
|
57
58
|
- lib/todidnt.rb
|
58
59
|
- lib/todidnt/git_command.rb
|
59
60
|
- lib/todidnt/git_repo.rb
|
60
61
|
- lib/todidnt/todo_line.rb
|
61
62
|
- test/lib.rb
|
62
|
-
- test/
|
63
|
+
- test/test_todo_line.rb
|
63
64
|
- todidnt.gemspec
|
64
65
|
homepage:
|
65
66
|
licenses: []
|
@@ -86,5 +87,4 @@ signing_key:
|
|
86
87
|
specification_version: 3
|
87
88
|
summary: Todidnt
|
88
89
|
test_files:
|
89
|
-
- test/
|
90
|
-
- test/todo_line.rb
|
90
|
+
- test/test_todo_line.rb
|
data/README
DELETED
data/test/todo_line.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
require_relative 'lib'
|
2
|
-
|
3
|
-
class TestTodoLine < Test
|
4
|
-
before do
|
5
|
-
GitCommand.any_instance.stubs(:run!)
|
6
|
-
end
|
7
|
-
|
8
|
-
describe '.all' do
|
9
|
-
describe 'unit' do
|
10
|
-
it 'constructs the correct `git grep` command' do
|
11
|
-
grep = mock()
|
12
|
-
grep.stubs(:output_lines => [])
|
13
|
-
|
14
|
-
GitCommand.expects(:new).with(:grep, [['-n'], ['-e', 'hello']]).returns(grep)
|
15
|
-
TodoLine.all(['hello'])
|
16
|
-
|
17
|
-
GitCommand.expects(:new).with(:grep, [['-n'], ['-e', 'hello'], ['-e', 'goodbye']]).returns(grep)
|
18
|
-
TodoLine.all(['hello', 'goodbye'])
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'creates a TodoLine object for each result line properly' do
|
22
|
-
GitCommand.any_instance.expects(:output_lines).returns(
|
23
|
-
[
|
24
|
-
'filename.rb:12: content',
|
25
|
-
'other_filename.rb:643: TODO'
|
26
|
-
]
|
27
|
-
)
|
28
|
-
|
29
|
-
TodoLine.expects(:new).with('filename.rb', 12, 'content')
|
30
|
-
TodoLine.expects(:new).with('other_filename.rb', 643, 'TODO')
|
31
|
-
|
32
|
-
TodoLine.all(['anything'])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe 'functional' do
|
37
|
-
it 'returns a list of TodoLine objects as matches' do
|
38
|
-
GitCommand.any_instance.expects(:output_lines).returns(
|
39
|
-
[
|
40
|
-
'filename.rb:12: content',
|
41
|
-
'other_filename.rb:643: TODO'
|
42
|
-
]
|
43
|
-
)
|
44
|
-
|
45
|
-
todos = TodoLine.all(['anything'])
|
46
|
-
assert_equal 2, todos.count
|
47
|
-
|
48
|
-
assert_equal 'filename.rb', todos.first.filename
|
49
|
-
assert_equal 12, todos.first.line_number
|
50
|
-
assert_equal 'content', todos.first.content
|
51
|
-
|
52
|
-
assert_equal 'other_filename.rb', todos.last.filename
|
53
|
-
assert_equal 643, todos.last.line_number
|
54
|
-
assert_equal 'TODO', todos.last.content
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'ignores lines matching IGNORE list' do
|
58
|
-
GitCommand.any_instance.expects(:output_lines).returns(
|
59
|
-
[
|
60
|
-
'filename.rb:12: content',
|
61
|
-
'thirdparty/other_filename.rb:643: TODO'
|
62
|
-
]
|
63
|
-
)
|
64
|
-
|
65
|
-
todos = TodoLine.all(['anything'])
|
66
|
-
assert_equal 1, todos.count
|
67
|
-
|
68
|
-
assert_equal 'filename.rb', todos.first.filename
|
69
|
-
assert_equal 12, todos.first.line_number
|
70
|
-
assert_equal 'content', todos.first.content
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe '#populate_blame' do
|
76
|
-
it 'constructs the correct `git blame` command' do
|
77
|
-
# TODO
|
78
|
-
skip
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'sets author, timestamp properties on the TodoLine object' do
|
82
|
-
# TODO
|
83
|
-
skip
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|