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 CHANGED
@@ -1,6 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
  ruby '1.9.3'
3
3
 
4
+ gem 'chronic'
5
+
4
6
  group 'test' do
5
7
  gem 'minitest'
6
8
  gem 'mocha'
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
@@ -0,0 +1,4 @@
1
+ task :test do
2
+ $LOAD_PATH << './test'
3
+ Dir.glob('test/test_*.rb').each { |t| require File.basename(t) }
4
+ end
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::Runner.start(options)
26
+ Todidnt::CLI.run(command, options)
@@ -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
- require_relative 'todidnt/git_repo'
2
- require_relative 'todidnt/git_command'
3
- require_relative 'todidnt/todo_line'
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 Runner
7
- def self.start(options)
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
- puts "\nResults:"
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.0.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/*`.split("\n")
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.0.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-07 00:00:00.000000000 Z
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/todo_line.rb
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/lib.rb
90
- - test/todo_line.rb
90
+ - test/test_todo_line.rb
data/README DELETED
@@ -1,9 +0,0 @@
1
- TODO:
2
-
3
- - tests
4
- - actual logging that is not putsing
5
- - optimize blames
6
- - html report?
7
- - filter by person or time
8
- - handle FIXME/XXX/custom
9
- - stats
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