twdeps 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65c4a0831441f978b94e806b7492a4cfb34ce0f7
4
+ data.tar.gz: c2ea1deb638801eac176a4c70663aef572c994fc
5
+ SHA512:
6
+ metadata.gz: c034226377e9a2707b0225729dbe3ca383e321ced8e4cfdc7d63a786ddf712783b20fa0a3b371985a9c4c7dff29fe398ae60708893c5189b570d24304d982bad
7
+ data.tar.gz: 5bd6d1f659ef348eeb503f69cdc1278432036116474a5bc349c39b0b529576cb92b0fb142c0ad17db8ba619c84efca0dee42015d8717a8a478410fe0d8bce30d
data/.travis.yml CHANGED
@@ -6,7 +6,6 @@ rvm:
6
6
  before_script:
7
7
  - mkdir ~/.task
8
8
  - echo data.location=~/.task > ~/.taskrc
9
- - task count
10
9
 
11
10
  before_install:
12
11
  - echo | sudo add-apt-repository ppa:ultrafredde/ppa
data/README.md CHANGED
@@ -14,7 +14,7 @@ Given a set of interdependent tasks described in the TaskWarrior [tutorial](http
14
14
 
15
15
  Result:
16
16
 
17
- ![party](/nerab/twdeps/raw/master/examples/party.png)
17
+ ![party](https://raw.github.com/nerab/twdeps/master/examples/party.png)
18
18
 
19
19
  ## Installation
20
20
 
@@ -26,16 +26,16 @@ Result:
26
26
  # See [Limitations](Limitations) below for why we need the extra task parms
27
27
  task export rc.json.array=on rc.verbose=nothing | twdeps > deps.png
28
28
 
29
- # Same but spefify output format
30
- task export | twdeps --format svg > deps.svg
29
+ # Same but specify output format
30
+ task export rc.json.array=on rc.verbose=nothing | twdeps --format svg > deps.svg
31
31
 
32
32
  # Create a graph from a previously exported file
33
- task export > tasks.json
33
+ task export rc.json.array=on rc.verbose=nothing > tasks.json
34
34
  cat tasks.json | twdeps > deps.png
35
35
 
36
36
  # Display graph in browser without creating an intermediate file
37
37
  # Requires bcat to be installed
38
- task export | twdeps --format svg | bcat
38
+ task export rc.json.array=on rc.verbose=nothing | twdeps --format svg | bcat
39
39
 
40
40
  ## Dependencies
41
41
 
@@ -45,7 +45,7 @@ The graph is generated with [ruby-graphviz](https://github.com/glejeune/Ruby-Gra
45
45
 
46
46
  ## Limitations
47
47
 
48
- Due to [two](http://taskwarrior.org/issues/1017) [bugs](http://taskwarrior.org/issues/1013) in JSON export, TaskWarrior 2.0 needs the command line options `rc.json.array=on` and `rc.verbose=nothing`.
48
+ Due to [two](http://taskwarrior.org/issues/1017) [bugs](http://taskwarrior.org/issues/1013) in JSON export, TaskWarrior versions before 2.1 need the additional command line options `rc.json.array=on` and `rc.verbose=nothing`.
49
49
 
50
50
  ## Contributing
51
51
 
data/bin/twdeps CHANGED
@@ -26,6 +26,7 @@ where [options] are:
26
26
 
27
27
  EOS
28
28
  opt :format, "Specify output format", :default => 'svg'
29
+ opt :title, "Specify title", :default => 'Task Dependencies'
29
30
  opt :trace, "Enable trace output", :default => false
30
31
  end
31
32
 
@@ -36,7 +37,7 @@ Trollop::die :format, "must be one of #{Graph.formats.join(', ')}" unless Graph.
36
37
 
37
38
  begin
38
39
  repo = Repository.new(ARGF.read)
39
- master = Graph.new(File.basename($0)) # TODO Move this to a CommandlinePresenter
40
+ master = Graph.new(Presenter.new(opts[:title]))
40
41
 
41
42
  # Add all projects (will add their tasks and dependencies recursively)
42
43
  repo.projects.each do |project|
data/examples/party.png CHANGED
Binary file
data/lib/twdeps/graph.rb CHANGED
@@ -1,15 +1,5 @@
1
1
  module TaskWarrior
2
2
  module Dependencies
3
- class NullPresenter
4
- def attributes
5
- {:label => 'Unknown', :fontcolor => 'red'}
6
- end
7
-
8
- def id
9
- 'null'
10
- end
11
- end
12
-
13
3
  # Builds a dependency graph
14
4
  #
15
5
  # +thing+ is added as node with all of its dependencies. A presenter is used to present the task as node label.
@@ -29,9 +19,14 @@ module TaskWarrior
29
19
 
30
20
  #
31
21
  # Build a new Graph for +thing+
32
- # # TODO Accept a presenter that would default to GlobalPresenter with {:rankdir => 'BT'}
33
- def initialize(name = :G, attributes = [])
34
- @graph = GraphViz::new(name, attributes)
22
+ #
23
+ def initialize(presenter_or_id)
24
+ if presenter_or_id.respond_to?(:attributes)
25
+ @graph = GraphViz::new(presenter_or_id.id, presenter_or_id.attributes)
26
+ else
27
+ @graph = GraphViz::new(presenter_or_id)
28
+ end
29
+
35
30
  @dependencies = []
36
31
  @edges = []
37
32
  end
@@ -52,7 +47,7 @@ module TaskWarrior
52
47
  else
53
48
  # it's a project
54
49
  project = task_or_project
55
- cluster = Graph.new(presenter(project).id, presenter(project).attributes)
50
+ cluster = Graph.new(presenter(project))
56
51
 
57
52
  project.tasks.each do |task|
58
53
  cluster << task
@@ -74,7 +69,7 @@ module TaskWarrior
74
69
  def create_edges(nodeA, nodes)
75
70
  nodes.each do |node|
76
71
  nodeB = find_or_create_node(node)
77
- create_edge(nodeA, nodeB)
72
+ create_edge(nodeB, nodeA)
78
73
  end
79
74
  end
80
75
 
@@ -90,7 +85,9 @@ module TaskWarrior
90
85
  edge = [nodeA, nodeB]
91
86
  unless @edges.include?(edge) # GraphViz lacks get_edge, so we need to track existing edges ourselfes
92
87
  @edges << edge
93
- @graph.add_edges(nodeA, nodeB)
88
+
89
+ # We present the edges in the sense of "nodeB depends on nodeA"
90
+ @graph.add_edges(nodeA, nodeB, :dir => 'back', :tooltip => "#{nodeB['label']} depends on #{nodeA['label']}")
94
91
  end
95
92
  end
96
93
 
@@ -0,0 +1,11 @@
1
+ module TaskWarrior
2
+ module Dependencies
3
+ class NullPresenter < Presenter
4
+ def initialize
5
+ super('null')
6
+ self.attributes = {:label => 'Unknown', :fontcolor => 'red'}
7
+ end
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,25 @@
1
+ module TaskWarrior
2
+ module Dependencies
3
+ #
4
+ # Presents a thing to the graph
5
+ #
6
+ class Presenter
7
+ def initialize(id)
8
+ @id = id
9
+ @attributes = {:label => id, :labelloc => 'top'}
10
+ end
11
+
12
+ def attributes
13
+ @attributes
14
+ end
15
+
16
+ def id
17
+ @id
18
+ end
19
+
20
+ protected
21
+ attr_writer :id, :attributes
22
+ end
23
+ end
24
+ end
25
+
@@ -3,17 +3,10 @@ module TaskWarrior
3
3
  #
4
4
  # Presents a project's attributes suitable for a GraphViz cluster
5
5
  #
6
- class ProjectPresenter
6
+ class ProjectPresenter < Presenter
7
7
  def initialize(project)
8
- @project = project
9
- end
10
-
11
- def attributes
12
- {:label => @project.name}
13
- end
14
-
15
- def id
16
- "cluster_#{@project.name}"
8
+ self.id = "cluster_#{project.name}"
9
+ self.attributes = {:label => project.name}
17
10
  end
18
11
  end
19
12
  end
@@ -3,25 +3,17 @@ module TaskWarrior
3
3
  #
4
4
  # Presents a task's attributes suitable for a GraphViz node
5
5
  #
6
- class TaskPresenter
6
+ class TaskPresenter < Presenter
7
7
  def initialize(task)
8
- @task = task
9
- end
10
-
11
- def attributes
12
- attrs = {:label => @task.description}
13
- attrs.merge!({:tooltip => "Status: #{@task.status}"})
14
-
15
- # TODO Once we see the urgency in the JSON export, we can color-code the nodes
16
- # http://taskwarrior.org/issues/973
17
- # attrs.merge!({:fillcolor => 'red', :style => 'filled'})
8
+ self.id = task.uuid
9
+ self.attributes = {
10
+ :label => task.description,
11
+ :tooltip => "Status: #{task.status}"
12
+ }
18
13
 
19
- attrs.merge!({:fontcolor => 'gray', :color => 'gray'}) if :completed == @task.status
20
- attrs
21
- end
22
-
23
- def id
24
- @task.uuid
14
+ if :completed == task.status
15
+ self.attributes.merge!({:fontcolor => 'gray', :color => 'gray'})
16
+ end
25
17
  end
26
18
  end
27
19
  end
@@ -1,5 +1,5 @@
1
1
  module TaskWarrior
2
2
  module Dependencies
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
data/lib/twdeps.rb CHANGED
@@ -1,17 +1,13 @@
1
- require "twdeps/version"
2
-
3
- require "twdeps/task"
4
- require "twdeps/project"
5
- require "twdeps/tag"
6
-
7
- require "twdeps/task_mapper"
8
- require "twdeps/priority_mapper"
9
- require "twdeps/task_repository"
1
+ require "taskwarrior"
10
2
 
3
+ require "twdeps/version"
11
4
  require "twdeps/graph"
5
+ require "twdeps/presenter"
12
6
  require "twdeps/task_presenter"
13
7
  require "twdeps/project_presenter"
8
+ require "twdeps/null_presenter"
14
9
 
10
+ # dependencies
15
11
  require "graphviz"
16
12
  require "json"
17
13
 
@@ -8,7 +8,7 @@ module TaskWarrior
8
8
  def setup
9
9
  repo = TaskWarrior::Repository.new(File.read(fixture('party_taxes.json')))
10
10
 
11
- plain = TaskWarrior::Dependencies::Graph.new
11
+ plain = TaskWarrior::Dependencies::Graph.new(self.class.name)
12
12
 
13
13
  repo.tasks.each do |task|
14
14
  plain << task
@@ -31,12 +31,12 @@ module TaskWarrior
31
31
 
32
32
  def test_edges
33
33
  assert_equal(6, @graph.edges.size)
34
- assert_not_nil(@graph.edge('c992448a-f1ea-4982-8461-47f0705ff509', '6fd0ba4a-ab67-49cd-ac69-64aa999aff8a'))
35
- assert_not_nil(@graph.edge('3b53178e-d5a4-45e0-afc2-1292db58a59a', '9f6f3738-1c08-4f45-8eb4-1e90864c7588'))
36
- assert_not_nil(@graph.edge('9f6f3738-1c08-4f45-8eb4-1e90864c7588', 'e5a867b7-0116-457d-ba43-9ac2bee6ad2a'))
37
- assert_not_nil(@graph.edge('e5a867b7-0116-457d-ba43-9ac2bee6ad2a', 'c992448a-f1ea-4982-8461-47f0705ff509'))
38
- assert_not_nil(@graph.edge('c590941b-eb10-4569-bdc9-0e339f79305e', '6fd0ba4a-ab67-49cd-ac69-64aa999aff8a'))
39
- assert_not_nil(@graph.edge('c590941b-eb10-4569-bdc9-0e339f79305e', 'c992448a-f1ea-4982-8461-47f0705ff509'))
34
+ assert_not_nil(@graph.edge('6fd0ba4a-ab67-49cd-ac69-64aa999aff8a', 'c992448a-f1ea-4982-8461-47f0705ff509'))
35
+ assert_not_nil(@graph.edge('9f6f3738-1c08-4f45-8eb4-1e90864c7588', '3b53178e-d5a4-45e0-afc2-1292db58a59a'))
36
+ assert_not_nil(@graph.edge('e5a867b7-0116-457d-ba43-9ac2bee6ad2a', '9f6f3738-1c08-4f45-8eb4-1e90864c7588'))
37
+ assert_not_nil(@graph.edge('c992448a-f1ea-4982-8461-47f0705ff509', 'e5a867b7-0116-457d-ba43-9ac2bee6ad2a'))
38
+ assert_not_nil(@graph.edge('6fd0ba4a-ab67-49cd-ac69-64aa999aff8a', 'c590941b-eb10-4569-bdc9-0e339f79305e'))
39
+ assert_not_nil(@graph.edge('c992448a-f1ea-4982-8461-47f0705ff509', 'c590941b-eb10-4569-bdc9-0e339f79305e'))
40
40
  end
41
41
 
42
42
  private
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ module TaskWarrior
4
+ module Test
5
+ class TestPresenters < ::Test::Unit::TestCase
6
+ include TaskWarrior::Dependencies
7
+ include TaskWarrior::Test::Fixtures
8
+
9
+ def setup
10
+ @repo = TaskWarrior::Repository.new(File.read(fixture('party_taxes.json')))
11
+ end
12
+
13
+ def test_string_presentation
14
+ foo = 'foo'
15
+ p = Presenter.new(foo)
16
+ assert_equal(foo, p.id)
17
+ assert_not_nil(p.attributes)
18
+ assert_equal({:label=>"foo", :labelloc=>"top"}, p.attributes)
19
+ end
20
+
21
+ def test_null_presentation
22
+ p = NullPresenter.new
23
+ assert_equal('null', p.id)
24
+ assert_equal({:label => 'Unknown', :fontcolor => 'red'}, p.attributes)
25
+ end
26
+
27
+ def test_project_presentation
28
+ p = ProjectPresenter.new(@repo.project('party'))
29
+ assert_equal('cluster_party', p.id)
30
+ assert_equal({:label => 'party'}, p.attributes)
31
+ end
32
+
33
+ def test_task_presentation
34
+ uuid = '67aafe0b-ddd7-482b-9cfa-ac42c43e7559'
35
+ p = TaskPresenter.new(@repo[uuid])
36
+ assert_equal(uuid, p.id)
37
+ assert_equal({:label => 'Get cash from ATM', :tooltip => 'Status: pending'}, p.attributes)
38
+ end
39
+ end
40
+ end
41
+ end
data/twdeps.gemspec CHANGED
@@ -16,13 +16,10 @@ Gem::Specification.new do |gem|
16
16
  gem.version = TaskWarrior::Dependencies::VERSION
17
17
 
18
18
  gem.add_dependency 'ruby-graphviz', '~> 1.0.7'
19
- gem.add_dependency 'activemodel', '~> 3.2'
20
19
  gem.add_dependency 'trollop', '~> 1'
21
- gem.add_development_dependency 'activesupport', '~> 3.2'
22
- gem.add_development_dependency 'twtest', '~> 0.0.4'
20
+ gem.add_dependency 'taskwarrior', '~> 0.0.6'
21
+ gem.add_development_dependency 'twtest', '~> 0.0.6'
23
22
  gem.add_development_dependency 'guard-test', '~> 0.5'
24
23
  gem.add_development_dependency 'guard-bundler', '~> 1.0'
25
24
  gem.add_development_dependency 'rake', '~> 0.9'
26
-
27
- gem.add_development_dependency 'pry'
28
25
  end
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twdeps
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nicholas E. Rabenau
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-06 00:00:00.000000000 Z
11
+ date: 2013-07-21 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: ruby-graphviz
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,31 +20,13 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.0.7
30
- - !ruby/object:Gem::Dependency
31
- name: activemodel
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '3.2'
38
- type: :runtime
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ~>
44
- - !ruby/object:Gem::Version
45
- version: '3.2'
46
27
  - !ruby/object:Gem::Dependency
47
28
  name: trollop
48
29
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
30
  requirements:
51
31
  - - ~>
52
32
  - !ruby/object:Gem::Version
@@ -54,47 +34,41 @@ dependencies:
54
34
  type: :runtime
55
35
  prerelease: false
56
36
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
37
  requirements:
59
38
  - - ~>
60
39
  - !ruby/object:Gem::Version
61
40
  version: '1'
62
41
  - !ruby/object:Gem::Dependency
63
- name: activesupport
42
+ name: taskwarrior
64
43
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
44
  requirements:
67
45
  - - ~>
68
46
  - !ruby/object:Gem::Version
69
- version: '3.2'
70
- type: :development
47
+ version: 0.0.6
48
+ type: :runtime
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
51
  requirements:
75
52
  - - ~>
76
53
  - !ruby/object:Gem::Version
77
- version: '3.2'
54
+ version: 0.0.6
78
55
  - !ruby/object:Gem::Dependency
79
56
  name: twtest
80
57
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
58
  requirements:
83
59
  - - ~>
84
60
  - !ruby/object:Gem::Version
85
- version: 0.0.4
61
+ version: 0.0.6
86
62
  type: :development
87
63
  prerelease: false
88
64
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
65
  requirements:
91
66
  - - ~>
92
67
  - !ruby/object:Gem::Version
93
- version: 0.0.4
68
+ version: 0.0.6
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: guard-test
96
71
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
72
  requirements:
99
73
  - - ~>
100
74
  - !ruby/object:Gem::Version
@@ -102,7 +76,6 @@ dependencies:
102
76
  type: :development
103
77
  prerelease: false
104
78
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
79
  requirements:
107
80
  - - ~>
108
81
  - !ruby/object:Gem::Version
@@ -110,7 +83,6 @@ dependencies:
110
83
  - !ruby/object:Gem::Dependency
111
84
  name: guard-bundler
112
85
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
86
  requirements:
115
87
  - - ~>
116
88
  - !ruby/object:Gem::Version
@@ -118,7 +90,6 @@ dependencies:
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
93
  requirements:
123
94
  - - ~>
124
95
  - !ruby/object:Gem::Version
@@ -126,7 +97,6 @@ dependencies:
126
97
  - !ruby/object:Gem::Dependency
127
98
  name: rake
128
99
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
100
  requirements:
131
101
  - - ~>
132
102
  - !ruby/object:Gem::Version
@@ -134,27 +104,10 @@ dependencies:
134
104
  type: :development
135
105
  prerelease: false
136
106
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
107
  requirements:
139
108
  - - ~>
140
109
  - !ruby/object:Gem::Version
141
110
  version: '0.9'
142
- - !ruby/object:Gem::Dependency
143
- name: pry
144
- requirement: !ruby/object:Gem::Requirement
145
- none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
150
- type: :development
151
- prerelease: false
152
- version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
155
- - - ! '>='
156
- - !ruby/object:Gem::Version
157
- version: '0'
158
111
  description: Takes a TaskWarrior export and emits a graph that visualizes the dependencies
159
112
  between tasks.
160
113
  email:
@@ -175,14 +128,10 @@ files:
175
128
  - examples/party.png
176
129
  - lib/twdeps.rb
177
130
  - lib/twdeps/graph.rb
178
- - lib/twdeps/priority_mapper.rb
179
- - lib/twdeps/project.rb
131
+ - lib/twdeps/null_presenter.rb
132
+ - lib/twdeps/presenter.rb
180
133
  - lib/twdeps/project_presenter.rb
181
- - lib/twdeps/tag.rb
182
- - lib/twdeps/task.rb
183
- - lib/twdeps/task_mapper.rb
184
134
  - lib/twdeps/task_presenter.rb
185
- - lib/twdeps/task_repository.rb
186
135
  - lib/twdeps/version.rb
187
136
  - test/fixtures/no_deps.json
188
137
  - test/fixtures/party.json
@@ -192,36 +141,30 @@ files:
192
141
  - test/integration/test_dependencies.rb
193
142
  - test/test_helper.rb
194
143
  - test/unit/test_graph.rb
195
- - test/unit/test_priority_mapper.rb
196
- - test/unit/test_project.rb
197
- - test/unit/test_repository.rb
198
- - test/unit/test_tag.rb
199
- - test/unit/test_tag_habtm.rb
200
- - test/unit/test_task.rb
144
+ - test/unit/test_presenters.rb
201
145
  - twdeps.gemspec
202
146
  homepage: ''
203
147
  licenses: []
148
+ metadata: {}
204
149
  post_install_message:
205
150
  rdoc_options: []
206
151
  require_paths:
207
152
  - lib
208
153
  required_ruby_version: !ruby/object:Gem::Requirement
209
- none: false
210
154
  requirements:
211
- - - ! '>='
155
+ - - '>='
212
156
  - !ruby/object:Gem::Version
213
157
  version: '0'
214
158
  required_rubygems_version: !ruby/object:Gem::Requirement
215
- none: false
216
159
  requirements:
217
- - - ! '>='
160
+ - - '>='
218
161
  - !ruby/object:Gem::Version
219
162
  version: '0'
220
163
  requirements: []
221
164
  rubyforge_project:
222
- rubygems_version: 1.8.24
165
+ rubygems_version: 2.0.3
223
166
  signing_key:
224
- specification_version: 3
167
+ specification_version: 4
225
168
  summary: Visualizes dependencies between TaskWarrior tasks.
226
169
  test_files:
227
170
  - test/fixtures/no_deps.json
@@ -232,9 +175,4 @@ test_files:
232
175
  - test/integration/test_dependencies.rb
233
176
  - test/test_helper.rb
234
177
  - test/unit/test_graph.rb
235
- - test/unit/test_priority_mapper.rb
236
- - test/unit/test_project.rb
237
- - test/unit/test_repository.rb
238
- - test/unit/test_tag.rb
239
- - test/unit/test_tag_habtm.rb
240
- - test/unit/test_task.rb
178
+ - test/unit/test_presenters.rb
@@ -1,9 +0,0 @@
1
- module TaskWarrior
2
- class PriorityMapper
3
- class << self
4
- def map(json)
5
- {'H' => :high, 'M' => :medium, 'L' => :low}[json]
6
- end
7
- end
8
- end
9
- end
@@ -1,33 +0,0 @@
1
- require 'active_model'
2
-
3
- module TaskWarrior
4
- class Project
5
- attr_reader :name, :tasks
6
-
7
- include ActiveModel::Validations
8
- validates :name, :presence => true
9
- validate :name_may_not_contain_spaces
10
-
11
- def initialize(name, tasks = [])
12
- @name = name
13
- @tasks = tasks
14
- @tasks.each{|t| t.project = self}
15
- end
16
-
17
- def <<(task)
18
- @tasks << task
19
- task.project = self
20
- end
21
-
22
- def to_s
23
- "Project #{name} (#{@tasks.size} tasks)"
24
- end
25
-
26
- private
27
- def name_may_not_contain_spaces
28
- if !name.blank? and name[/\s/]
29
- errors.add(:name, "may not contain spaces")
30
- end
31
- end
32
- end
33
- end
data/lib/twdeps/tag.rb DELETED
@@ -1,48 +0,0 @@
1
- require 'active_model'
2
-
3
- module TaskWarrior
4
- class Tag
5
- attr_reader :name
6
-
7
- include ActiveModel::Validations
8
- validates :name, :presence => true
9
- validate :name_may_not_contain_spaces
10
-
11
- def initialize(tag_or_name, tasks = [])
12
- if tag_or_name.respond_to?(:name)
13
- @name = tag_or_name.name
14
- @tasks = tag_or_name.tasks
15
- else
16
- @name = tag_or_name
17
- @tasks = []
18
- end
19
-
20
- tasks.each{|task|
21
- self << task
22
- }
23
- end
24
-
25
- def <<(task)
26
- @tasks << task unless @tasks.include?(task)
27
- end
28
-
29
- def tasks
30
- @tasks #.dup
31
- end
32
-
33
- def to_s
34
- "Tag: #{name} (#{@tasks.size} tasks)"
35
- end
36
-
37
- def ==(other)
38
- name == other.name
39
- end
40
-
41
- private
42
- def name_may_not_contain_spaces
43
- if !name.blank? and name[/\s/]
44
- errors.add(:name, "may not contain spaces")
45
- end
46
- end
47
- end
48
- end
data/lib/twdeps/task.rb DELETED
@@ -1,52 +0,0 @@
1
- require 'active_model'
2
-
3
- module TaskWarrior
4
- class Task
5
- attr_accessor :description, :id, :entry, :status, :uuid, :project, :dependencies, :parent, :children, :priority
6
-
7
- include ActiveModel::Validations
8
- validates :description, :id, :entry, :status, :uuid, :presence => true
9
-
10
- validates :id, :numericality => { :only_integer => true, :greater_than => 0}
11
-
12
- validates :uuid, :format => {:with => /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/,
13
- :message => "'%{value}' does not match the expected format of a UUID"}
14
-
15
- validates :status, :inclusion => {:in => [:pending, :waiting, :complete], :message => "%{value} is not a valid status"}
16
-
17
- validates :priority, :inclusion => {
18
- :in => [:high, :medium, :low],
19
- :allow_nil => true,
20
- :allow_blank => true,
21
- :message => "%{value} is not a valid priority"
22
- }
23
-
24
- validate :entry_cannot_be_in_the_future
25
-
26
- def initialize(description)
27
- @description = description
28
- @dependencies = []
29
- @children = []
30
- @tags = []
31
- end
32
-
33
- def tags
34
- @tags
35
- end
36
-
37
- def to_s
38
- "Task '#{description}'".tap{|result| result << " <#{uuid}>" if uuid}
39
- end
40
-
41
- private
42
- def entry_cannot_be_in_the_future
43
- begin
44
- if !entry.blank? and entry > DateTime.now
45
- errors.add(:entry, "can't be in the future")
46
- end
47
- rescue
48
- errors.add(:entry, "must be comparable to DateTime")
49
- end
50
- end
51
- end
52
- end
@@ -1,30 +0,0 @@
1
- module TaskWarrior
2
- #
3
- # A DataMapper that makes new Tasks from a JSON representation
4
- #
5
- class TaskMapper
6
- class << self
7
- def map(json)
8
- Task.new(json['description']).tap{|t|
9
- t.id = json['id'].to_i
10
- t.uuid = json['uuid']
11
- t.entry = DateTime.parse(json['entry'])
12
- t.status = json['status'].to_sym
13
- t.project = json['project']
14
-
15
- if json['depends']
16
- if json['depends'].respond_to?(:split)
17
- t.dependencies = json['depends'].split(',')
18
- else
19
- t.dependencies = json['depends']
20
- end
21
- end
22
-
23
- t.parent = json['parent'] # Children will be cross-indexed in the repository
24
- t.priority = PriorityMapper.map(json['priority'])
25
- json['tags'].each{|tag| t.tags << tag} if json['tags']
26
- }
27
- end
28
- end
29
- end
30
- end
@@ -1,77 +0,0 @@
1
- require 'json'
2
-
3
- module TaskWarrior
4
- class SimpleTag
5
- attr_reader :name, :tasks
6
-
7
- def initialize(name)
8
- @name = name
9
- @tasks = []
10
- end
11
-
12
- def <<(task)
13
- @tasks << task unless @tasks.include?(task)
14
- end
15
- end
16
-
17
- class Repository
18
- def initialize(input)
19
- @tasks = {}
20
- @projects = Hash.new{|hash, key| hash[key] = Project.new(key)}
21
- @tags = Hash.new{|hash, key| hash[key] = Tag.new(key)}
22
-
23
- JSON.parse(input).each{|json|
24
- task = TaskWarrior::TaskMapper.map(json)
25
- @tasks[task.uuid] = task
26
- @projects[task.project].tasks << task if task.project
27
-
28
- # Create a new Tag object in @tags that is the value for each tag name
29
- task.tags.each{|tag_name| @tags[tag_name] << task}
30
- }
31
-
32
- # Replace the uuid of each dependency with the real task
33
- @tasks.each_value{|task| task.dependencies.map!{|uuid| @tasks[uuid]}}
34
-
35
- # Replace the project property of each task with a proper Project object carrying a name and all of the project's tasks
36
- @tasks.each_value{|task| task.project = @projects[task.project] if task.project}
37
-
38
- # Add child tasks to their parent, but keep them in the global index
39
- @tasks.each_value do |task|
40
- if task.parent
41
- parent = @tasks[task.parent]
42
-
43
- if parent # we know the parent
44
- parent.children << task
45
- task.parent = parent
46
- end
47
- end
48
- end
49
- end
50
-
51
- def tasks
52
- # Do not expose child tasks directly
53
- @tasks.values.reject{|t| t.parent}
54
- end
55
-
56
- # direct lookup by uuid
57
- def [](uuid)
58
- @tasks[uuid]
59
- end
60
-
61
- def projects
62
- @projects.values
63
- end
64
-
65
- def project(name)
66
- @projects[name] if @projects.has_key?(name)
67
- end
68
-
69
- def tags
70
- @tags.values
71
- end
72
-
73
- def tag(name)
74
- @tags[name] if @tags.has_key?(name)
75
- end
76
- end
77
- end
@@ -1,27 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestPriorityMapper < Test::Unit::TestCase
4
- def test_nil
5
- assert_nil(TaskWarrior::PriorityMapper.map(nil))
6
- end
7
-
8
- def test_empty
9
- assert_nil(TaskWarrior::PriorityMapper.map(''))
10
- end
11
-
12
- def test_low
13
- assert_equal(:low, TaskWarrior::PriorityMapper.map('L'))
14
- end
15
-
16
- def test_medium
17
- assert_equal(:medium, TaskWarrior::PriorityMapper.map('M'))
18
- end
19
-
20
- def test_high
21
- assert_equal(:high, TaskWarrior::PriorityMapper.map('H'))
22
- end
23
-
24
- def test_unknown
25
- assert_nil(TaskWarrior::PriorityMapper.map('crap'))
26
- end
27
- end
@@ -1,55 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestProject < Test::Unit::TestCase
4
- include TaskWarrior::Test::Validations
5
-
6
- def test_name
7
- project = TaskWarrior::Project.new('foo')
8
- assert_valid(project)
9
- assert_empty(project.tasks)
10
- end
11
-
12
- def test_empty_tasks
13
- project = TaskWarrior::Project.new('foo', [])
14
- assert_valid(project)
15
- assert_empty(project.tasks)
16
- end
17
-
18
- def test_with_tasks
19
- project = TaskWarrior::Project.new('foo', [TaskWarrior::Task.new('foobar')])
20
- assert_valid(project)
21
- assert_equal(1, project.tasks.size)
22
- end
23
-
24
- def test_name_nil
25
- project = TaskWarrior::Project.new(nil)
26
- assert_invalid(project)
27
- end
28
-
29
- def test_name_empty
30
- project = TaskWarrior::Project.new('')
31
- assert_invalid(project)
32
- end
33
-
34
- def test_name_with_space
35
- project = TaskWarrior::Project.new('foo bar')
36
- assert_invalid(project)
37
- end
38
-
39
- def test_name_just_space
40
- project = TaskWarrior::Project.new(' ')
41
- assert_invalid(project)
42
- end
43
-
44
- def test_add_task
45
- project = TaskWarrior::Project.new('foo')
46
- assert_empty(project.tasks)
47
- t1 = TaskWarrior::Task.new('foobar')
48
- t2 = TaskWarrior::Task.new('foobaz')
49
- project << t1
50
- project << t2
51
- assert_equal(2, project.tasks.size)
52
- assert_equal(project, t1.project)
53
- assert_equal(project, t2.project)
54
- end
55
- end
@@ -1,64 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestRepository < Test::Unit::TestCase
4
- include TaskWarrior
5
- include TaskWarrior::Test::Fixtures
6
-
7
- def setup
8
- @repo = Repository.new(File.read(fixture('party_taxes.json')))
9
- end
10
-
11
- def test_tags_of_task
12
- atm = @repo['67aafe0b-ddd7-482b-9cfa-ac42c43e7559']
13
- assert_not_nil(atm)
14
- assert_equal(2, atm.tags.size)
15
- end
16
-
17
- def test_all
18
- assert_equal(8, @repo.tasks.size)
19
-
20
- one = @repo['6fd0ba4a-ab67-49cd-ac69-64aa999aff8a']
21
- assert_equal('Select a free weekend in November', one.description)
22
- assert_equal(:high, one.priority)
23
- assert_equal('party', one.project.name)
24
- assert_equal(:pending, one.status)
25
-
26
- # assert_equal(1, one.annotations.size)
27
- # assert_equal(DateTime.new('20120629T191534Z'), one.annotations.first.entry)
28
- # assert_equal('the 13th looks good', one.annotations.first.entry.description)
29
- end
30
-
31
- def test_child
32
- assert_equal(1, @repo['b587f364-c68e-4438-b4d6-f2af6ad62518'].children.size)
33
- end
34
-
35
- def test_parent
36
- assert_equal(@repo['b587f364-c68e-4438-b4d6-f2af6ad62518'], @repo['99c9e1bb-ed75-4525-b05d-cf153a7ee1a1'].parent)
37
- end
38
-
39
- def test_projects
40
- party = @repo.project('party')
41
- assert_not_nil(party)
42
- assert_equal(6, party.tasks.size)
43
- end
44
-
45
- def test_tags
46
- tags = @repo.tags
47
- assert_not_nil(tags)
48
- assert_equal(2, tags.size)
49
- assert(tags.include?(Tag.new('finance')))
50
- assert(tags.include?(Tag.new('mall')))
51
- end
52
-
53
- def test_tasks_of_tag_finance
54
- finance = @repo.tag('finance')
55
- assert_not_nil(finance)
56
- assert_equal(2, finance.tasks.size)
57
- end
58
-
59
- def test_tasks_of_tag_mall
60
- mall = @repo.tag('mall')
61
- assert_not_nil(mall)
62
- assert_equal(3, mall.tasks.size)
63
- end
64
- end
@@ -1,57 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestTag < Test::Unit::TestCase
4
- include TaskWarrior
5
- include TaskWarrior::Test::Validations
6
-
7
- def test_name
8
- tag = Tag.new('foo')
9
- assert_valid(tag)
10
- assert_empty(tag.tasks)
11
- end
12
-
13
- def test_empty_tasks
14
- tag = Tag.new('foo', [])
15
- assert_valid(tag)
16
- assert_empty(tag.tasks)
17
- end
18
-
19
- def test_with_tasks
20
- tag = Tag.new('foo', [Task.new('foobar')])
21
- assert_valid(tag)
22
- assert_equal(1, tag.tasks.size)
23
- end
24
-
25
- def test_name_nil
26
- tag = Tag.new(nil)
27
- assert_invalid(tag)
28
- end
29
-
30
- def test_name_empty
31
- tag = Tag.new('')
32
- assert_invalid(tag)
33
- end
34
-
35
- def test_name_with_space
36
- tag = Tag.new('foo bar')
37
- assert_invalid(tag)
38
- end
39
-
40
- def test_name_just_space
41
- tag = Tag.new(' ')
42
- assert_invalid(tag)
43
- end
44
-
45
- def test_construction
46
- foo = Tag.new('foo')
47
- assert_equal(foo, Tag.new(foo))
48
- assert_equal(Tag.new(foo), foo)
49
- end
50
-
51
- def test_value_object
52
- f1 = Tag.new('foo')
53
- f2 = Tag.new('foo')
54
- assert_not_equal(f1.object_id, f2.object_id)
55
- assert_equal(f1, f2)
56
- end
57
- end
@@ -1,69 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestTagHasAndBelongsToMany < Test::Unit::TestCase
4
- include TaskWarrior::Test::Validations
5
-
6
- def setup
7
- @lookup_foo = TaskWarrior::Task.new('Lookup foo in Wikipedia')
8
- @lookup_deadbeef = TaskWarrior::Task.new('Lookup deadbeef in Wikipedia')
9
-
10
- @foo = TaskWarrior::Tag.new('foo')
11
- @deadbeef = TaskWarrior::Tag.new('deadbeef')
12
- @metasyntactic = TaskWarrior::Tag.new('metasyntactic')
13
-
14
- # We need to do what the repo does - cross-reference manually.
15
- @foo << @lookup_foo
16
- @lookup_foo.tags << @foo
17
- @lookup_foo.tags << @metasyntactic
18
-
19
- @deadbeef << @lookup_deadbeef
20
- @lookup_deadbeef.tags << @deadbeef
21
- @lookup_deadbeef.tags << @metasyntactic
22
-
23
- @metasyntactic << @lookup_foo
24
- @metasyntactic << @lookup_deadbeef
25
- end
26
-
27
- def test_task_tagged
28
- assert_equal(2, @lookup_foo.tags.size)
29
- assert_equal(2, @lookup_deadbeef.tags.size)
30
-
31
- assert_tagged_with(@lookup_foo, @foo)
32
- assert_tagged_with(@lookup_foo, @metasyntactic)
33
- assert_not_tagged_with(@lookup_foo, @deadbeef)
34
-
35
- assert_not_tagged_with(@lookup_deadbeef, @foo)
36
- assert_tagged_with(@lookup_deadbeef, @metasyntactic)
37
- assert_tagged_with(@lookup_deadbeef, @deadbeef)
38
- end
39
-
40
- def test_tag_has_tasks
41
- assert_equal(1, @foo.tasks.size)
42
- assert_equal(1, @deadbeef.tasks.size)
43
- assert_equal(2, @metasyntactic.tasks.size)
44
-
45
- assert_contains_task(@deadbeef, @lookup_deadbeef)
46
- assert_not_contains_task(@deadbeef, @lookup_foo)
47
- assert_not_contains_task(@foo, @lookup_deadbeef)
48
- assert_contains_task(@foo, @lookup_foo)
49
-
50
- assert_contains_task(@metasyntactic, @lookup_deadbeef)
51
- assert_contains_task(@metasyntactic, @lookup_foo)
52
- end
53
-
54
- def assert_tagged_with(task, tag)
55
- assert(task.tags.include?(tag), "#{task} expected to be tagged with #{tag}, but it isn't.'")
56
- end
57
-
58
- def assert_not_tagged_with(task, tag)
59
- assert(!task.tags.include?(tag), "#{task} expected not to be tagged with #{tag}, but it actually is.")
60
- end
61
-
62
- def assert_contains_task(tag, task)
63
- assert(tag.tasks.include?(task), "#{tag} expected to contain #{task}, but it doesn't.")
64
- end
65
-
66
- def assert_not_contains_task(tag, task)
67
- assert(!tag.tasks.include?(task), "#{tag} expected to not contain #{task}, but it actually does.")
68
- end
69
- end
@@ -1,121 +0,0 @@
1
- require 'test_helper'
2
- require 'date'
3
- require 'active_support/core_ext'
4
-
5
- # TODO Add tests for dependencies
6
-
7
- class TestTask < Test::Unit::TestCase
8
- include TaskWarrior::Test::Validations
9
-
10
- def setup
11
- @task = TaskWarrior::Task.new('foobar')
12
- @task.id = 1
13
- @task.uuid = '66465716-b08d-41ea-8567-91b988a2bcbf'
14
- @task.entry = DateTime.now
15
- @task.status = :pending
16
- end
17
-
18
- def test_task_id_nil
19
- @task.id = nil
20
- assert_invalid(@task)
21
- end
22
-
23
- def test_task_id_0
24
- @task.id = 0
25
- assert_invalid(@task)
26
- end
27
-
28
- def test_task_uuid_nil
29
- @task.uuid = nil
30
- assert_invalid(@task)
31
- end
32
-
33
- def test_task_uuid_empty
34
- @task.uuid = ''
35
- assert_invalid(@task)
36
- end
37
-
38
- def test_task_uuid_wrong_format
39
- @task.uuid = 'abcdefg'
40
- assert_invalid(@task)
41
- end
42
-
43
- def test_task_entry_nil
44
- @task.entry = nil
45
- assert_invalid(@task)
46
- end
47
-
48
- def test_task_entry_empty
49
- @task.entry = ''
50
- assert_invalid(@task)
51
- end
52
-
53
- def test_task_entry_wrong_format
54
- @task.entry = "foobar"
55
- assert_invalid(@task)
56
- end
57
-
58
- def test_task_entry_future
59
- @task.entry = DateTime.now.advance(:days => 1)
60
- assert_invalid(@task)
61
- end
62
-
63
- def test_task_status_nil
64
- @task.status = nil
65
- assert_invalid(@task)
66
- end
67
-
68
- def test_task_status_empty
69
- @task.status = ''
70
- assert_invalid(@task)
71
- end
72
-
73
- def test_task_status_unknown_string
74
- @task.status = "foobar"
75
- assert_invalid(@task)
76
- end
77
-
78
- def test_task_status_unknown_symbol
79
- @task.status = :foobar
80
- assert_invalid(@task)
81
- end
82
-
83
- def test_task_priority_nil
84
- @task.priority = nil
85
- assert_valid(@task)
86
- end
87
-
88
- def test_task_priority_empty
89
- @task.priority = ''
90
- assert_valid(@task)
91
- end
92
-
93
- def test_task_priority_unknown_string
94
- @task.priority = "foobar"
95
- assert_invalid(@task)
96
- end
97
-
98
- def test_task_priority_unknown_symbol
99
- @task.priority = :foobar
100
- assert_invalid(@task)
101
- end
102
-
103
- def test_task_priority_high
104
- @task.priority = :high
105
- assert_valid(@task)
106
- end
107
-
108
- def test_task_priority_medium
109
- @task.priority = :medium
110
- assert_valid(@task)
111
- end
112
-
113
- def test_task_priority_low
114
- @task.priority = :low
115
- assert_valid(@task)
116
- end
117
-
118
- def test_task_valid
119
- assert_valid(@task)
120
- end
121
- end