todidnt 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|