ohac-ditz 0.5.1 → 0.5.2

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/Changelog CHANGED
@@ -1,4 +1,4 @@
1
- == ohac-ditz 0.5.1 / 2010-01-16
1
+ == ohac-ditz 0.5.2 / 2010-01-16
2
2
  * add ditz shell (bin/coditz.rb)
3
3
  * performance hack (disabled issue name interpolation)
4
4
  * performance hack (call unchanged! when save)
@@ -40,7 +40,6 @@ share/ditz/yellow-bar.png
40
40
  man/man1/ditz.1
41
41
  setup.rb
42
42
  bin/coditz.rb
43
- bin/coditz_for_0.5.rb
44
43
  contrib/bookmarklet.js
45
44
  lib/ditz/plugins/icalendar.rb
46
45
  lib/ditz/plugins/mercurial.rb
data/Rakefile CHANGED
@@ -8,15 +8,15 @@ class Hoe
8
8
  def extra_dev_deps; @extra_dev_deps.reject { |x| x[0] == "hoe" } end
9
9
  end
10
10
 
11
- Hoe.new('ditz', Ditz::VERSION) do |p|
11
+ Hoe.new('ohac-ditz', Ditz::VERSION) do |p|
12
12
  p.rubyforge_name = 'ditz'
13
- p.author = "William Morgan"
13
+ p.author = "OHASHI Hideya"
14
14
  p.summary = "A simple issue tracker designed to integrate well with distributed version control systems like git and darcs. State is saved to a YAML file kept under version control, allowing issues to be closed/added/modified as part of a commit."
15
15
 
16
16
  p.description = p.paragraphs_of('README.txt', 4..11).join("\n\n").gsub(/== SYNOPSIS/, "Synopsis:")
17
17
  p.url = "http://ditz.rubyforge.org"
18
18
  p.changes = p.paragraphs_of('Changelog', 0..0).join("\n\n")
19
- p.email = "wmorgan-ditz@masanjin.net"
19
+ p.email = "ohachige@gmail.com"
20
20
  p.extra_deps = [['trollop', '>= 1.9'], ['yaml_waml', '>= 0.3']]
21
21
  end
22
22
 
@@ -1,3 +1,8 @@
1
+ 0.5.2 / ohac-ditz
2
+ ---
3
+
4
+ see Changelog
5
+
1
6
  0.5
2
7
  ---
3
8
 
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ self_file =
5
+ if File.symlink?(__FILE__)
6
+ require 'pathname'
7
+ Pathname.new(__FILE__).realpath
8
+ else
9
+ __FILE__
10
+ end
11
+ $:.unshift(File.dirname(self_file) + "/../lib")
12
+
13
+ require 'rubygems'
14
+ require 'ditz'
15
+ require 'cinatra'
16
+
17
+ # FIXME see http://github.com/jugyo/cinatra/issues/#issue/4
18
+ begin
19
+
20
+ CONFIG_FN = ".ditz-config"
21
+ PLUGIN_FN = ".ditz-plugins"
22
+
23
+ def ditz_plugin_file
24
+ plugin_dir = Ditz::find_dir_containing PLUGIN_FN
25
+ File.join(plugin_dir || ".", PLUGIN_FN)
26
+ end
27
+
28
+ def ditz_config_file
29
+ config_dir = Ditz::find_dir_containing CONFIG_FN
30
+ File.join(config_dir || ".", CONFIG_FN)
31
+ end
32
+
33
+ def ditz_op(cmd, opts = [], project = nil)
34
+ config_file = ditz_config_file
35
+ unless File.exist?(config_file)
36
+ puts 'do init first.'
37
+ return
38
+ end
39
+ config = Ditz::Config.from config_file
40
+ config.use_editor_if_possible = false # overwrite
41
+ config.paginate = "never" # overwrite
42
+ issue_dir = Pathname.new(config.issue_dir)
43
+ unless issue_dir.exist?
44
+ puts 'something wrong.'
45
+ return
46
+ end
47
+ storage = Ditz::FileStorage.new issue_dir
48
+ project = storage.load if project.nil?
49
+ op = Ditz::Operator.new
50
+ op.do cmd, project, config, opts.clone
51
+ storage.save project
52
+ project
53
+ end
54
+
55
+ def get_name_from_mercurial
56
+ path = Ditz.find_dir_containing(".hg")
57
+ len = path ? path.to_s.size : 100
58
+ username = `hg show ui.username` || ''
59
+ username.chomp!
60
+ if username.size > 0
61
+ a = username.split(" ")
62
+ email = a.pop
63
+ email = email[1..-2]
64
+ name = a.join(" ")
65
+ [len, name, email]
66
+ end
67
+ end
68
+
69
+ def get_name_from_git
70
+ path = Ditz.find_dir_containing(".git")
71
+ len = path ? path.to_s.size : 100
72
+ [len, `git config user.name`.chomp, `git config user.email`.chomp]
73
+ end
74
+
75
+ def get_name
76
+ as = [get_name_from_mercurial, get_name_from_git].select{|a|!a.nil?}
77
+ as.min_by{|a|a[0]}
78
+ end
79
+
80
+ command 'ditz_help' do |arg|
81
+ ditz_op 'help'
82
+ end
83
+
84
+ command 'init' do |arg|
85
+ config_file = ditz_config_file
86
+ len, name, email = get_name
87
+ unless File.exist?(config_file)
88
+ config = Ditz::Config.create(
89
+ :name => name,
90
+ :email => email,
91
+ :issue_dir => ".ditz",
92
+ :use_editor_if_possible => false,
93
+ :paginate => "never"
94
+ )
95
+ config.save! config_file
96
+ issue_dir = Pathname.new(config.issue_dir)
97
+ issue_dir.mkdir
98
+ fn = issue_dir + Ditz::FileStorage::PROJECT_FN
99
+ project = Ditz::Project.create(
100
+ :name => "myproject",
101
+ :components => [ Ditz::Component.create(:name => "mycomponent") ]
102
+ )
103
+ project.save! fn
104
+ end
105
+ end
106
+
107
+ command 'todo' do |arg|
108
+ ditz_op 'todo'
109
+ end
110
+
111
+ command 'add' do |arg|
112
+ ditz_op 'add', ['-q', arg]
113
+ end
114
+
115
+ command 'bench' do |arg|
116
+ prj = nil
117
+ 10000.times do |i|
118
+ prj = ditz_op 'add', ['-q', "foo#{i}"], prj
119
+ end
120
+ end
121
+
122
+ command 'close' do |arg|
123
+ ditz_op 'close', ['-n', arg] # TODO select 1,2,3
124
+ end
125
+
126
+ command 'comment' do |arg|
127
+ args = arg.split(' ')
128
+ issue = args.shift
129
+ ditz_op 'comment', [issue, '-m', args.join(' ')]
130
+ end
131
+
132
+ command 'drop' do |arg|
133
+ ditz_op 'drop', [arg]
134
+ end
135
+
136
+ command 'show' do |arg|
137
+ ditz_op 'show', [arg]
138
+ end
139
+
140
+ command 'changelog' do |arg|
141
+ ditz_op 'changelog', [arg]
142
+ end
143
+
144
+ command 'log' do
145
+ ditz_op 'log'
146
+ end
147
+
148
+ command 'shortlog' do
149
+ ditz_op 'shortlog'
150
+ end
151
+
152
+ command 'html' do |arg|
153
+ opts = []
154
+ opts << arg if arg
155
+ ditz_op 'html', opts
156
+ end
157
+
158
+ command 'grep' do |arg|
159
+ opts = []
160
+ opts << arg if arg
161
+ ditz_op 'grep', opts # TODO support ignore case
162
+ end
163
+
164
+ command 'status' do |arg|
165
+ opts = []
166
+ opts << arg if arg
167
+ ditz_op 'status', opts
168
+ end
169
+
170
+ command 'releases' do
171
+ ditz_op 'releases'
172
+ end
173
+
174
+ command 'validate' do
175
+ ditz_op 'validate'
176
+ end
177
+
178
+ command 'release' do |arg|
179
+ opts = []
180
+ opts << arg if arg
181
+ ditz_op 'release', opts
182
+ end
183
+
184
+ command 'reconfigure' do
185
+ # TODO
186
+ end
187
+
188
+ command 'edit' do
189
+ # TODO
190
+ end
191
+
192
+ command 'add-reference' do |arg|
193
+ # TODO interactive only!
194
+ args = arg.split(' ')
195
+ issue = args.shift
196
+ comment = args.join(' ')
197
+ comment = nil if comment.size == 0
198
+ ditz_op 'add-reference', [issue] + (comment ? ['-m', comment] : ['-n'])
199
+ end
200
+
201
+ command 'add-component' do |arg|
202
+ # TODO interactive only!
203
+ ditz_op 'add-component'
204
+ end
205
+
206
+ command 'set-component' do |arg|
207
+ args = arg.split(' ')
208
+ issue = args.shift
209
+ component = args.shift
210
+ comment = args.join(' ')
211
+ comment = nil if comment.size == 0
212
+ ditz_op 'set-component', [issue, component] +
213
+ (comment ? ['-m', comment] : ['-n'])
214
+ end
215
+
216
+ command 'add-release' do |arg|
217
+ args = arg.split(' ')
218
+ name = args.shift
219
+ comment = args.join(' ')
220
+ comment = nil if comment.size == 0
221
+ ditz_op 'add-release', [name] + (comment ? ['-m', comment] : ['-n'])
222
+ end
223
+
224
+ command 'drop-release' do |arg|
225
+ ditz_op 'drop-release', [arg]
226
+ end
227
+
228
+ command 'assign' do |arg|
229
+ args = arg.split(' ')
230
+ issue = args.shift
231
+ release = args.shift
232
+ comment = args.join(' ')
233
+ comment = nil if comment.size == 0
234
+ ditz_op 'assign', [issue, release] + (comment ? ['-m', comment] : ['-n'])
235
+ end
236
+
237
+ command 'unassign' do |arg|
238
+ args = arg.split(' ')
239
+ issue = args.shift
240
+ comment = args.join(' ')
241
+ comment = nil if comment.size == 0
242
+ ditz_op 'unassign', [issue] + (comment ? ['-m', comment] : ['-n'])
243
+ end
244
+
245
+ command 'start' do |arg|
246
+ args = arg.split(' ')
247
+ issue = args.shift
248
+ comment = args.join(' ')
249
+ comment = nil if comment.size == 0
250
+ ditz_op 'start', [issue] + (comment ? ['-m', comment] : ['-n'])
251
+ end
252
+
253
+ command 'stop' do |arg|
254
+ args = arg.split(' ')
255
+ issue = args.shift
256
+ comment = args.join(' ')
257
+ comment = nil if comment.size == 0
258
+ ditz_op 'stop', [issue] + (comment ? ['-m', comment] : ['-n'])
259
+ end
260
+
261
+ =begin
262
+ bin/ditz
263
+ lib/ditz.rb
264
+ lib/ditz/operator.rb
265
+ lib/ditz/model-objects.rb
266
+ lib/ditz/model.rb
267
+ =end
268
+
269
+ command 'print_hooks' do |arg|
270
+ Ditz::HookManager.print_hooks
271
+ end
272
+
273
+ # FIXME see http://github.com/jugyo/cinatra/issues/#issue/4
274
+ rescue => x
275
+ puts x.backtrace
276
+ end
@@ -0,0 +1 @@
1
+ javascript:var%20d=document,w=window,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),f='http://localhost:1234/new',l=d.location,e=encodeURIComponent,p='?u='+e(l.href)%20+'&t='+e(d.title)%20+'&s='+e(s)+'&y=task&r='+e('First%20Last%20<foo@example.com>')+'&R=2010&c=idea',u=f+p;l.href=u;
@@ -3,7 +3,7 @@ require 'trollop'
3
3
 
4
4
  module Ditz
5
5
 
6
- VERSION = "0.5"
6
+ VERSION = "0.5.2"
7
7
  attr_accessor :verbose
8
8
  module_function :verbose, :verbose=
9
9
 
@@ -0,0 +1,64 @@
1
+ ## icalendar ditz plugin
2
+ ##
3
+ ## This plugin adds ability to export full todo list in iCalendar (RFC 2445) format.
4
+ ## It is useful for integration with different pim software like KOrganizer.
5
+ ##
6
+ ## Issues are converted to VTODO entries with completion status set to 50 if
7
+ ## its state is :in_progress, 100 if it's closed and 0 otherwise.
8
+ ## Progress for release is 100 if it's released otherwise it's 99 * closed/all
9
+ ## issues. So maximum for active release is 99 and it's not shown as done until
10
+ ## released.
11
+ ##
12
+ ## Commands added:
13
+ ## ditz todo-ics: generate full todo list in iCalendar format
14
+ ##
15
+ ## Usage:
16
+ ## 1. add a line "- icalendar" to the .ditz-plugins file in the project root
17
+
18
+ require 'vpim/icalendar'
19
+
20
+ module Ditz
21
+
22
+ class Operator
23
+ operation :todo_ics, "Generate full todo list in iCalendar format", :maybe_release
24
+ def todo_ics project, config, releases
25
+ cal = Vpim::Icalendar.create
26
+ releases ||= project.releases + [:unassigned]
27
+ releases = [*releases]
28
+ releases.each do |r|
29
+ issues = project.issues_for_release r
30
+ done = 0
31
+ done = (99 * (issues.select { |i| i.closed? }).length / issues.length).to_int if issues.length != 0
32
+ if r != :unassigned
33
+ done = 100 if r.released?
34
+ parent = "release-#{r.hash}"
35
+ title = "Release #{r.name} (#{r.status})"
36
+ else
37
+ parent = "release-unassigned"
38
+ title = "Unassigned"
39
+ end
40
+ cal.push Vpim::Icalendar::Vtodo.create("SUMMARY" => title, "UID" => parent, "PERCENT-COMPLETE" => "#{done}")
41
+ issues.each do |i|
42
+ cal.push todo2vtodo(i, parent)
43
+ end
44
+ end
45
+ puts cal.encode
46
+ end
47
+
48
+ def todo2vtodo todo, parent
49
+ h = {"SUMMARY" => "#{todo.title}", "UID" => "#{todo.type}-#{todo.id}"}
50
+ h["RELATED-TO"] = parent if parent
51
+ h["PRIORITY"] = "3" if todo.type == :bugfix
52
+ h["PERCENT-COMPLETE"] = case todo.status
53
+ when :closed
54
+ "100"
55
+ when :in_progress
56
+ "50"
57
+ else
58
+ "0"
59
+ end
60
+ return Vpim::Icalendar::Vtodo.create(h)
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,52 @@
1
+ module Ditz
2
+
3
+ class Issue
4
+ alias :old_start_work :start_work
5
+ alias :old_stop_work :stop_work
6
+ field :time_spent, :generator => :get_time_spent
7
+ field :mark_time, :generator => :get_mark_time
8
+ def get_time_spent(config, project)
9
+ time_spent || 0
10
+ end
11
+ def get_mark_time(config, project)
12
+ self.mark_time || 0
13
+ end
14
+ def start_work(who, comment)
15
+ self.mark_time = Time.now
16
+ old_start_work(who, comment)
17
+ end
18
+ def stop_work(who, comment)
19
+ self.time_spent += Time.now - self.mark_time
20
+ self.mark_time = Time.now
21
+ old_stop_work(who, comment)
22
+ end
23
+ end
24
+
25
+ class ScreenView
26
+ def self.modulo(seconds, quotient)
27
+ result, remainder = seconds / quotient, seconds % quotient
28
+ end
29
+ def self.humanize(seconds)
30
+ result = ""
31
+ %w[year month day hour minute second].zip([3600*24*30*365, 3600*24*30, 3600*24, 3600, 60, 1]).inject(seconds) do |seconds, item|
32
+ num, seconds = modulo(seconds, item[1])
33
+ result << "#{item[0].pluralize(num)} " unless num == 0
34
+ seconds
35
+ end
36
+ result
37
+ end
38
+ def self.get_time_spent(issue)
39
+ if issue.status == :paused
40
+ issue.time_spent
41
+ elsif issue.time_spent && issue.mark_time
42
+ issue.time_spent + (Time.now - issue.mark_time)
43
+ else
44
+ 0
45
+ end
46
+ end
47
+ add_to_view :issue_summary do |issue, config|
48
+ " Time spent: #{humanize(get_time_spent(issue).to_i)}\n"
49
+ end
50
+ end
51
+
52
+ end