[ditz-talk] [PATCH] Generalize handling of issues to support more types of issue.
Nicolas Pouillard
nicolas.pouillard at gmail.com
Thu Apr 10 08:48:49 EDT 2008
---
lib/lowline.rb | 5 +++-
lib/model-objects.rb | 8 ++++++-
lib/operator.rb | 58 +++++++++++++++++++++++++-------------------------
lib/util.rb | 8 +++++++
4 files changed, 48 insertions(+), 31 deletions(-)
diff --git a/lib/lowline.rb b/lib/lowline.rb
index 74895d6..3d0a781 100644
--- a/lib/lowline.rb
+++ b/lib/lowline.rb
@@ -17,7 +17,10 @@ class String
def blank?; self =~ /\A\s*\z/ end
def underline; self + "\n" + ("-" * self.length) end
def multiline prefix=""; blank? ? "" : "\n" + self.gsub(/^/, prefix) end
- def pluralize n; n.to_pretty_s + " " + (n == 1 ? self : self + "s") end # oh yeah
+ def pluralize n, b=true
+ s = (n == 1 ? self : (self == 'bugfix' ? 'bugfixes' : self + "s")) # oh yeah
+ b ? n.to_pretty_s + " " + s : s
+ end
end
class Array
diff --git a/lib/model-objects.rb b/lib/model-objects.rb
index 5cd3156..e5bf293 100644
--- a/lib/model-objects.rb
+++ b/lib/model-objects.rb
@@ -83,6 +83,10 @@ EOS
issues.select { |i| i.release.nil? }
end
+ def group_issues these_issues=issues
+ these_issues.group_by { |i| i.type }.sort_by { |(t,g)| Issue::TYPE_ORDER[t] }
+ end
+
def assign_issue_names!
prefixes = components.map { |c| [c.name, c.name.gsub(/^\s+/, "-").downcase] }.to_h
ids = components.map { |c| [c.name, 0] }.to_h
@@ -122,6 +126,8 @@ class Issue < ModelObject
STATUS_WIDGET = { :unstarted => "_", :in_progress => ">", :paused => "=", :closed => "x" }
DISPOSITIONS = [ :fixed, :wontfix, :reorg ]
TYPES = [ :bugfix, :feature ]
+ TYPE_ORDER = { :bugfix => 0, :feature => 1 }
+ TYPE_LETTER = { 'b' => :bugfix, 'f' => :feature }
STATUSES = STATUS_WIDGET.keys
STATUS_STRINGS = { :in_progress => "in progress", :wontfix => "won't fix" }
@@ -213,7 +219,7 @@ class Issue < ModelObject
def get_type config, project
type = ask "Is this a (b)ugfix or a (f)eature?", :restrict => /^[bf]$/
- type == "b" ? :bugfix : :feature
+ TYPE_LETTER[type]
end
def get_component config, project
diff --git a/lib/operator.rb b/lib/operator.rb
index 74ce0b0..355b8e2 100644
--- a/lib/operator.rb
+++ b/lib/operator.rb
@@ -35,23 +35,20 @@ class Operator
releases.each do |r|
next if r.released? unless force_show
- bugs = project.issues.
- select { |i| i.type == :bugfix && i.release == r.name }
- feats = project.issues.
- select { |i| i.type == :feature && i.release == r.name }
+ groups = project.group_issues(project.issues_for_release(r))
- #next if bugs.empty? && feats.empty? unless force_show
+ #next if groups.empty? unless force_show
- ret << [r, bugs, feats]
+ ret << [r, groups]
end
return ret unless show_unassigned
- bugs = project.issues.select { |i| i.type == :bugfix && i.release.nil? }
- feats = project.issues.select { |i| i.type == :feature && i.release.nil? }
+ groups = project.group_issues(project.unassigned_issues)
- return ret if bugs.empty? && feats.empty? unless force_show
- ret << [nil, bugs, feats]
+ return ret if groups.empty? unless force_show
+
+ ret << [nil, groups]
end
private :parse_releases_arg
@@ -132,7 +129,7 @@ EOS
puts
end
- operation :add, "Add a bug/feature request"
+ operation :add, "Add an issue"
def add project, config
issue = Issue.create_interactively(:args => [config, project]) or return
comment = ask_multiline "Comments"
@@ -142,7 +139,7 @@ EOS
puts "Added issue #{issue.name}."
end
- operation :drop, "Drop a bug/feature request", :issue
+ operation :drop, "Drop an issue", :issue
def drop project, config, issue
project.drop_issue issue
puts "Dropped #{issue.name}. Note that other issue names may have changed."
@@ -176,26 +173,30 @@ EOS
operation :status, "Show project status", :maybe_release
def status project, config, releases
- releases.each do |r, bugs, feats|
- title, bar = [r ? r.name : "unassigned", status_bar_for(bugs + feats)]
-
- ncbugs = bugs.count_of { |b| b.closed? }
- ncfeats = feats.count_of { |f| f.closed? }
- pcbugs = 100.0 * (bugs.empty? ? 1.0 : ncbugs.to_f / bugs.size)
- pcfeats = 100.0 * (feats.empty? ? 1.0 : ncfeats.to_f / feats.size)
+ releases.each do |r, groups|
+ issues = groups.map { |_,g| g }.flatten
+ title = r ? r.name : "unassigned"
+
+ groups = groups.map do |t,g|
+ nc = g.count_of { |i| i.closed? }
+ pc = 100.0 * (g.empty? ? 1.0 : nc.to_f / g.size)
+ [t, g, nc, pc]
+ end
special = if r && r.released?
"(released)"
- elsif bugs.empty? && feats.empty?
+ elsif groups.empty?
"(no issues)"
- elsif ncbugs == bugs.size && ncfeats == feats.size
+ elsif issues.all? { |i| i.closed? }
"(ready for release)"
else
- bar
+ status_bar_for(issues)
end
- printf "%-10s %2d/%2d (%3.0f%%) bugs, %2d/%2d (%3.0f%%) features %s\n",
- title, ncbugs, bugs.size, pcbugs, ncfeats, feats.size, pcfeats, special
+ middle = groups.map do |(t,g,nc,pc)|
+ "%2d/%2d (%3.0f%%) %s" % [nc, g.size, pc, t.to_s.pluralize(g.size, false)]
+ end.join(', ')
+ printf "%-10s %s %s\n", title, middle, special
end
if project.releases.empty?
@@ -230,13 +231,13 @@ EOS
end
def actually_do_todo project, config, releases, full
- releases.each do |r, bugs, feats|
+ releases.each do |r, groups|
if r
puts "Version #{r.name} (#{r.status}):"
else
puts "Unassigned:"
end
- issues = bugs + feats
+ issues = groups.map { |_,g| g }.flatten
issues = issues.select { |i| i.open? } unless full
puts(todo_list_for(issues.sort_by { |i| i.sort_order }) || "No open issues.")
puts
@@ -347,10 +348,9 @@ EOS
operation :changelog, "Generate a changelog for a release", :release
def changelog project, config, r
- feats, bugs = project.issues_for_release(r).partition { |i| i.feature? }
puts "== #{r.name} / #{r.released? ? r.release_time.pretty_date : 'unreleased'}"
- feats.select { |f| f.closed? }.each { |i| puts "* #{i.title}" }
- bugs.select { |f| f.closed? }.each { |i| puts "* bugfix: #{i.title}" }
+ project.group_issues(project.issues_for_release(r)).
+ each { |t,g| g.select { |i| i.closed? }.each { |i| puts "* #{t}: #{i.title}" } }
end
operation :html, "Generate html status pages", :dir
diff --git a/lib/util.rb b/lib/util.rb
index 7812a1c..03dba7e 100644
--- a/lib/util.rb
+++ b/lib/util.rb
@@ -19,6 +19,14 @@ module Enumerable
each { |e| x = yield(e); return x if x }
nil
end
+
+ def group_by
+ inject({}) do |groups, element|
+ (groups[yield(element)] ||= []) << element
+ groups
+ end
+ end if RUBY_VERSION < '1.9'
+
end
class Array
--
1.5.5.rc3
More information about the ditz-talk
mailing list