bugzyrb 0.1.0 → 0.2.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/CHANGELOG.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ = bugzyrb 0.2.0, 2010-07-08 1
2
+ * added readline support and history for fields being entered
3
+ * optional project, component, version
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/bugzy.cfg CHANGED
@@ -3,9 +3,9 @@
3
3
  # this overrides defaults inside main program
4
4
 
5
5
  $prompt_assigned_to = false
6
- $default_assigned_to = ENV['logname']
6
+ $default_assigned_to = ENV['LOGNAME']
7
7
  $send_email = true
8
- $email_to = ENV['logname']
8
+ $email_to = ENV['LOGNAME']
9
9
  #$app_dir =
10
10
 
11
11
  $default_type = "bug"
@@ -13,6 +13,8 @@ $default_severity = "normal"
13
13
  $default_status = "open"
14
14
  $default_priority = "P3"
15
15
 
16
+ # prompt variables indicate whether you wish to be prompted during add operation
17
+ # if false, then default value will be used
16
18
  $prompt_type = true
17
19
  $prompt_severity = false
18
20
  $prompt_status = false
data/bugzyrb.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bugzyrb}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rahul Kumar"]
12
- s.date = %q{2010-07-07}
12
+ s.date = %q{2010-07-08}
13
13
  s.default_executable = %q{bugzyrb}
14
14
  s.description = %q{basic, easy-to-use command-line issue-tracker using sqlite for ruby 1.9}
15
15
  s.email = %q{sentinel1879@gmail.com}
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.files = [
22
22
  ".document",
23
23
  ".gitignore",
24
+ "CHANGELOG.rdoc",
24
25
  "LICENSE",
25
26
  "README.rdoc",
26
27
  "Rakefile",
data/lib/bugzyrb.rb CHANGED
@@ -101,9 +101,11 @@ class Bugzy
101
101
  $default_severity = "normal"
102
102
  $default_status = "open"
103
103
  $default_priority = "P3"
104
- $default_assigned_to = ""
104
+ $default_assigned_to = "unassigned"
105
105
  $default_due = 5 # how many days in advance due date should be
106
106
  #$bare = @options[:bare]
107
+ $use_readline = true
108
+ $g_row = nil
107
109
  # we need to load the cfg file here, if given # , or else in home dir.
108
110
  if @options[:config]
109
111
  load @options[:config]
@@ -169,11 +171,15 @@ SQL
169
171
  message "#{@file} created." if File.exists? @file
170
172
  text = <<-TEXT
171
173
  If you wish to associate projects and/or components and versions to an issue,
172
- please add the same in the database using:
174
+ please modify bugzyrb.cfg as follows:
175
+
176
+ $use_project = true
177
+ $use_component = true
178
+ $use_version = true
179
+ Also, fill in valid_project=[...], default_project="x" and prompt_project=true.
180
+
181
+ bugzyrb.cfg must be called using -c bugzyrb.cfg if overriding ~/.bugzyrb.cfg
173
182
 
174
- project add <NAME>
175
- component add <PROJECTNAME> <COMPONENT>
176
- version add <PROJECTNAME> <VERSION>
177
183
  TEXT
178
184
  message text
179
185
 
@@ -201,7 +207,7 @@ SQL
201
207
  body['severity'] = @options[:severity] || $default_severity
202
208
  body['status'] = @options[:status] || $default_status
203
209
  body['priority'] = @options[:priority] || $default_priority
204
- body['assigned_to'] = @options[:assigned_to]
210
+ body['assigned_to'] = @options[:assigned_to] || $default_assigned_to
205
211
  #comment_count = 0
206
212
  #body['description = nil
207
213
  #fix = nil
@@ -244,30 +250,30 @@ SQL
244
250
  if $prompt_desc
245
251
  message "Enter a detailed description (. to exit): "
246
252
  desc = get_lines
253
+ #message "You entered #{desc}"
247
254
  end
248
- message "You entered #{desc}"
249
255
  type = $default_type || "bug"
250
256
  severity = $default_severity || "normal"
251
257
  status = $default_status || "open"
252
258
  priority = $default_priority || "P3"
253
259
  if $prompt_type
254
260
  type = _choice("Select type:", %w[bug enhancement feature task] )
255
- message "You selected #{type}"
261
+ #message "You selected #{type}"
256
262
  end
257
263
  if $prompt_severity
258
264
  severity = _choice("Select severity:", %w[normal critical moderate] )
259
- message "You selected #{severity}"
265
+ #message "You selected #{severity}"
260
266
  end
261
267
  if $prompt_status
262
268
  status = _choice("Select status:", %w[open started closed stopped canceled] )
263
- message "You selected #{status}"
269
+ #message "You selected #{status}"
264
270
  end
271
+ assigned_to = $default_assigned_to
265
272
  if $prompt_assigned_to
266
273
  message "Assign to:"
267
- assigned_to = $stdin.gets.chomp
268
- message "You selected #{assigned_to}"
269
- else
270
- assigned_to = $default_assigned_to
274
+ #assigned_to = $stdin.gets.chomp
275
+ assigned_to = _gets "assigned_to", "assigned_to", $default_assigned_to
276
+ #message "You selected #{assigned_to}"
271
277
  end
272
278
  project = component = version = nil
273
279
  # project
@@ -293,6 +299,7 @@ SQL
293
299
  body["title"]=title
294
300
  body["description"]=description
295
301
  body["type"]=type
302
+ body["status"]=status
296
303
  body["start_date"]=start_date.to_s
297
304
  body["due_date"]=due_date.to_s
298
305
  body["priority"]=priority
@@ -308,8 +315,6 @@ SQL
308
315
  rowid = db.table_insert_hash("bugs", body)
309
316
  puts "Issue #{rowid} created"
310
317
  logid = db.sql_logs_insert rowid, "create", "#{rowid} #{type}: #{title}"
311
- # send an email of some sort needs improbement FIXME
312
- #printable = %w[ title description status severity type assigned_to start_date due_date priority fix ]
313
318
  body["id"] = rowid
314
319
  mail_issue body
315
320
 
@@ -328,22 +333,16 @@ SQL
328
333
  Severity : #{row['severity']}
329
334
  Assigned To : #{row['assigned_to']}
330
335
  TEXT
336
+ body << " Project : #{row['project']}\n" if $use_project
337
+ body << " Component : #{row['component']}\n" if $use_component
338
+ body << " Version : #{row['version']}\n" if $use_version
331
339
  title = "#{row['id']}: #{row['title']} "
332
- require 'tempfile'
333
- temp = Tempfile.new "bugzy"
334
- File.open(temp,"w"){ |f| f.write body }
335
-
336
- #cmd = %Q{ echo "#{body}" | mail -s "#{title}" "#{emailid}" }
337
- # cat is not portable please change
338
- cmd = %Q{ cat #{temp.path} | mail -s "#{title}" "#{emailid}" }
339
-
340
- $stderr.puts "executing: #{cmd}"
341
- unless system(cmd)
342
- $stderr.puts "Error executing #{cmd}"
343
- $stderr.puts $?
344
- end
345
340
 
341
+ cmd = %{ mail -s "#{title}" "#{emailid}" }
342
+ #puts cmd
343
+ Cmdapp::pipe_output(cmd, body)
346
344
  end
345
+
347
346
  ##
348
347
  # view details of a single issue/bug
349
348
  # @param [Array] ARGV, first element is issue number
@@ -411,16 +410,21 @@ TEXT
411
410
  row = db.sql_select_rowid "bugs", id
412
411
  die "No data found for #{id}" unless row
413
412
  editable = %w[ status severity type assigned_to start_date due_date priority title description fix ]
413
+ editable << "project" if $use_project
414
+ editable << "component" if $use_component
415
+ editable << "version" if $use_version
414
416
  sel = _choice "Select field to edit", editable
415
417
  print "You chose: #{sel}"
416
418
  old = row[sel]
417
419
  puts " Current value is: #{old}"
420
+ $g_row = row
418
421
  meth = "ask_#{sel}".to_sym
419
422
  if respond_to? "ask_#{sel}".to_sym
420
423
  str = send(meth, old)
421
424
  else
422
- print "Enter value: "
423
- str = $stdin.gets.chomp
425
+ #print "Enter value: "
426
+ #str = $stdin.gets.chomp
427
+ str = _gets sel, sel, old
424
428
  end
425
429
  #str = old if str.nil? or str == ""
426
430
  if str.nil? or str == old
@@ -431,6 +435,7 @@ TEXT
431
435
  message str
432
436
  db.sql_update "bugs", id, sel, str
433
437
  puts "Updated #{id}"
438
+ str = str.to_s
434
439
  rowid = db.sql_logs_insert id, sel, "[#{id}] updated [#{sel}] with #{str[0..50]}"
435
440
  0
436
441
  end
@@ -451,6 +456,25 @@ TEXT
451
456
  end
452
457
  0
453
458
  end
459
+ def copy args
460
+ id = args.shift
461
+ db, row = validate_id id, true
462
+ newrow = row.to_hash
463
+ ret = newrow.delete("id")
464
+ newrow.delete("date_created")
465
+ newrow.delete("date_modified")
466
+ #row.each_pair { |name, val| puts "(#{name}): #{val} " }
467
+ ret = ask_title row['title']
468
+ newrow['title'] = ret.chomp if ret
469
+ rowid = db.table_insert_hash( "bugs", newrow)
470
+
471
+ title = newrow['title']
472
+ type = newrow['type']
473
+
474
+ logid = db.sql_logs_insert rowid, "create", "#{rowid} #{type}: #{title}"
475
+ newrow["id"] = rowid
476
+ mail_issue newrow
477
+ end
454
478
  def viewlogs args
455
479
  db = get_db
456
480
  id = args[0].nil? ? db.max_bug_id : args[0]
@@ -502,7 +526,26 @@ TEXT
502
526
  elsif @options[:long]
503
527
  fields = "id,status,title,severity,priority,due_date,description"
504
528
  end
505
- rows = db.run "select #{fields} from bugs "
529
+ where = nil
530
+ wherestring = ""
531
+ if @options[:overdue]
532
+ #where = %{ where status != 'closed' and due_date <= "#{Date.today}" }
533
+ where ||= []
534
+ where << %{ status != 'closed'}
535
+ where << %{ due_date <= "#{Date.today}" }
536
+ end
537
+ if @options[:unassigned]
538
+ #where = %{ where status != 'closed' and due_date <= "#{Date.today}" }
539
+ where ||= []
540
+ where << %{ (assigned_to = 'unassigned' or assigned_to is null) }
541
+ end
542
+ if where
543
+ wherestring = " where " + where.join(" and ")
544
+ end
545
+ puts wherestring
546
+
547
+ rows = db.run "select #{fields} from bugs #{wherestring} "
548
+ die "No rows" unless rows
506
549
 
507
550
  if incl
508
551
  incl_str = incl.join "|"
@@ -572,6 +615,11 @@ TEXT
572
615
  def ask_description old=nil
573
616
  Cmdapp::edit_text old
574
617
  end
618
+ def ask_title old=nil
619
+ ret = Cmdapp::edit_text old
620
+ return ret.chomp if ret
621
+ ret
622
+ end
575
623
  ##
576
624
  # prompts user for a cooment to be attached to a issue/bug
577
625
  def comment args #id, comment
@@ -711,32 +759,24 @@ TEXT
711
759
  # future_date(1).to_s[0..10]; # => creates a string object with only Date part, no time
712
760
  # Date.parse(future_date(1).to_s[0..10]) # => converts to a Date object
713
761
 
714
- def future_date days=1
715
- Time.now() + (24 * 60 * 60 * days)
716
- #(Time.now() + (24 * 60 * 60) * days).to_s[0..10];
717
- end
718
-
719
- ## prompt user for due date, called from edit
720
- #def ask_due_date
721
- #days = 1
722
- #ask("Enter due date? ", Date) {
723
- #|q| q.default = future_date(days).to_s[0..10];
724
- #q.validate = lambda { |p| Date.parse(p) >= Date.parse(Time.now.to_s) };
725
- #q.responses[:not_valid] = "Enter a date greater than today"
726
- #}
762
+ #def future_date days=1
763
+ #Time.now() + (24 * 60 * 60 * days)
727
764
  #end
765
+
728
766
  # prompt user for due date, called from edit
729
- def ask_due_date
730
- days = 1
767
+ # NOTE: this takes a peek at $g_row to get start_date and validate against that
768
+ def ask_due_date old=nil
769
+ days = $default_due
731
770
  today = Date.today
732
- ask("Enter due date? ", Date) {
733
- |q| q.default = today + days;
734
- q.validate = lambda { |p| Date.parse(p) >= today };
735
- q.responses[:not_valid] = "Enter a date greater than today"
771
+ start = Date.parse($g_row['start_date'].to_s) || today
772
+ ask("Enter due date? (>= #{start}) ", Date) {
773
+ |q| q.default = (today + days).to_s;
774
+ q.validate = lambda { |p| Date.parse(p) >= start };
775
+ q.responses[:not_valid] = "Enter a date >= than #{start}"
736
776
  }
737
777
  end
738
778
 
739
- def ask_start_date
779
+ def ask_start_date old=nil
740
780
  ask("Enter start date? ", Date) {
741
781
  #|q| q.default = Time.now.to_s[0..10];
742
782
  |q| q.default = Date.today
@@ -844,8 +884,9 @@ TEXT
844
884
  end
845
885
  case prompt_flag
846
886
  when :freeform
847
- prompt_text ||= "#{column.capitalize}? "
848
- str = ask(prompt_text){ |q| q.default = default if default }
887
+ prompt_text ||= "#{column.capitalize}"
888
+ #str = ask(prompt_text){ |q| q.default = default if default }
889
+ str = _gets(column, prompt_text, default)
849
890
  return str
850
891
  when :choice
851
892
  prompt_text ||= "Select #{column}:"
@@ -884,8 +925,25 @@ TEXT
884
925
  #puts "Read: #{$_}" # writes to STDOUT
885
926
  end
886
927
  return nil if str == ""
887
- return str
928
+ return str.chomp
929
+ end
930
+ def _gets column, prompt, default=nil
931
+ text = "#{prompt}? "
932
+ text << "|#{default}|" if default
933
+ puts text
934
+ if $use_readline
935
+ Cmdapp::history_read column, default
936
+ str = Readline::readline('>', false)
937
+ Cmdapp::history_save column, str
938
+ str = default if str.nil? or str == ""
939
+ return str
940
+ else
941
+ str = $stdin.gets.chomp
942
+ str = default if str.nil? or str == ""
943
+ return str
944
+ end
888
945
  end
946
+ # ADD here
889
947
 
890
948
  def self.main args
891
949
  ret = nil
@@ -905,6 +963,11 @@ TEXT
905
963
  if plain
906
964
  options[:colorize] = (plain == "0") ? false:true
907
965
  end
966
+ config = File.expand_path "~/.bugzyrb.cfg"
967
+ if File.exists? config
968
+ options[:config] = config
969
+ #puts "found #{config} "
970
+ end
908
971
 
909
972
  Subcommands::global_options do |opts|
910
973
  opts.banner = "Usage: #{APPNAME} [options] [subcommand [options]]"
@@ -1028,6 +1091,10 @@ TEXT
1028
1091
  opts.banner = "Usage: edit [options] ISSUE_NO"
1029
1092
  opts.description = "Edit a given issue"
1030
1093
  end
1094
+ Subcommands::command :copy do |opts|
1095
+ opts.banner = "Usage: copy [options] ISSUE_NO"
1096
+ opts.description = "Copy a given issue"
1097
+ end
1031
1098
  Subcommands::command :comment do |opts|
1032
1099
  opts.banner = "Usage: comment [options] ISSUE_NO TEXT"
1033
1100
  opts.description = "Add comment a given issue"
@@ -1052,6 +1119,12 @@ TEXT
1052
1119
  options[:bare] = v
1053
1120
  $bare = true
1054
1121
  }
1122
+ opts.on("-o","--overdue", "not closed, due date past") { |v|
1123
+ options[:overdue] = v
1124
+ }
1125
+ opts.on("-u","--unassigned", "not assigned") { |v|
1126
+ options[:unassigned] = v
1127
+ }
1055
1128
  end
1056
1129
  Subcommands::command :viewlogs do |opts|
1057
1130
  opts.banner = "Usage: viewlogs [options] ISSUE_NO"
data/lib/common/cmdapp.rb CHANGED
@@ -258,6 +258,24 @@ def edit_text text
258
258
  return newstr
259
259
  end
260
260
 
261
+ # pipes given string to command
262
+ # @param [String] command to pipe data to
263
+ # @param [String] data to pipe to command
264
+ # @example
265
+ # cmd = %{mail -s "my title" rahul}
266
+ # pipe_output(cmd, "some long text")
267
+ # FIXME: not clear how to return error.
268
+ # NOTE: this is obviously more portable than using system echo or system cat.
269
+ def pipe_output (pipeto, str)
270
+ #pipeto = '/usr/sbin/sendmail -t'
271
+ #pipeto = %q{mail -s "my title" rahul}
272
+ if pipeto != nil # i was taking pipeto from a hash, so checking
273
+ proc = IO.popen(pipeto, "w+")
274
+ proc.puts str
275
+ proc.close_write
276
+ #puts proc.gets
277
+ end
278
+ end
261
279
  ##
262
280
  # reads up template, and substirutes values from myhash
263
281
  # @param [String] template text
@@ -274,6 +292,56 @@ def template_replace template, myhash
274
292
  }
275
293
  t
276
294
  end
295
+ #------------------------------------------------------------
296
+ # these 2 methods deal with with maintaining readline history
297
+ # for various columns. _read reads up any earlier values
298
+ # so user can select from them.
299
+ # _save saves the values for future use.
300
+ #------------------------------------------------------------
301
+ # for a given column, check if there's any previous data
302
+ # in our cache, and put in readlines history so user can
303
+ # use or edit. Also put default value in history.
304
+ # @param [String] name of column for maintaining cache
305
+ # @param [String] default data for user to recall, or edit
306
+ def history_read column, default=nil
307
+ values = []
308
+ oldstr = ""
309
+ if !defined? $history_hash
310
+ require 'readline'
311
+ require 'yaml'
312
+ filename = File.expand_path "~/.bugzy_history.yml"
313
+ $history_filename = filename
314
+ # if file exists with values push them into history
315
+ if File.exists? filename
316
+ $history_hash = YAML::load( File.open( filename ) )
317
+ else
318
+ $history_hash = Hash.new
319
+ end
320
+ end
321
+ values.push(*$history_hash[column]) if $history_hash.has_key? column
322
+ # push existing value into history also, so it can be edited
323
+ values.push(default) if default
324
+ values.uniq!
325
+ Readline::HISTORY.clear # else previous values of other fields also come in
326
+ Readline::HISTORY.push(*values) unless values.empty?
327
+ #puts Readline::HISTORY.to_a
328
+ end
329
+ ##
330
+ # update our cache with str if not present in cache already
331
+ # @param [String] name of column for maintaining cache
332
+ # @param [String] str : data just entered by user
333
+ #
334
+ def history_save column, str
335
+ return if str.nil? or str == ""
336
+ if $history_hash.has_key? column
337
+ return if $history_hash[column].include? str
338
+ end
339
+ ($history_hash[column] ||= []) << str
340
+ filename = $history_filename
341
+ File.open( filename, 'w' ) do |f|
342
+ f << $history_hash.to_yaml
343
+ end
344
+ end
277
345
 
278
346
 
279
347
 
data/lib/common/db.rb CHANGED
@@ -118,7 +118,7 @@ module Database
118
118
  str << ") values ("
119
119
  str << qstr.join(",")
120
120
  str << ")"
121
- puts str
121
+ #puts str
122
122
  @db.execute(str, *bind_vars)
123
123
  rowid = @db.get_first_value( "select last_insert_rowid();")
124
124
  return rowid
@@ -150,7 +150,7 @@ module Database
150
150
  # @param [Fixnum] id unique key
151
151
  # @param [String] fieldname
152
152
  # @param [String] value to update
153
- # @example sql_bugs_update 9, :name, "Roger"
153
+ # @example sql_update "bugs", 9, :name, "Roger"
154
154
  def sql_update table, id, field, value
155
155
  @db.execute( "update #{table} set #{field} = ?, date_modified = ? where id = ?", value,$now, id)
156
156
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Rahul Kumar
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-07-07 00:00:00 +05:30
17
+ date: 2010-07-08 00:00:00 +05:30
18
18
  default_executable: bugzyrb
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -112,6 +112,7 @@ extra_rdoc_files:
112
112
  files:
113
113
  - .document
114
114
  - .gitignore
115
+ - CHANGELOG.rdoc
115
116
  - LICENSE
116
117
  - README.rdoc
117
118
  - Rakefile