You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by Sam Ruby <ru...@apache.org> on 2016/03/09 13:21:46 UTC

[whimsy.git] [1/1] Commit 6f93a52: a proper podling class

Commit 6f93a5273fec0706433531a9406ca040cfc0e77d:
    a proper podling class


Branch: refs/heads/master
Author: Sam Ruby <ru...@intertwingly.net>
Committer: Sam Ruby <ru...@intertwingly.net>
Pusher: rubys <ru...@apache.org>

------------------------------------------------------------
lib/whimsy/asf/podlings.rb                                   | +++++++ --
tools/collate_minutes.rb                                     | ++++++ -------
www/classic/roster/main.rb                                   | + -
www/incubator/maillist.cgi                                   | ++++++++ -------
www/roster/main.rb                                           | +++ ---
www/roster/public_nonldap_groups.rb                          | + -
www/roster/views/groups.html.rb                              | ++ --
www/roster/views/index.html.rb                               | + -
www/roster/views/podlings.html.rb                            | +++++++ -------
------------------------------------------------------------
219 changes: 148 additions, 71 deletions.
------------------------------------------------------------


diff --git a/lib/whimsy/asf/podlings.rb b/lib/whimsy/asf/podlings.rb
index 8186836..7858ac7 100644
--- a/lib/whimsy/asf/podlings.rb
+++ b/lib/whimsy/asf/podlings.rb
@@ -1,11 +1,14 @@
 require 'nokogiri'
+require 'date'
 require_relative '../asf'
 
 module ASF
-  class Podlings
+  class Podling
     include Enumerable
+    attr_accessor :name, :status, :description, :mentors, :champion, :reporting
 
-    def self.quarter
+    # three consecutive months, starting with this one
+    def quarter
       [
         Date.today.strftime('%B'),
         Date.today.next_month.strftime('%B'),
@@ -13,41 +16,116 @@ def self.quarter
       ]
     end
 
-    def self.each
-      incubator_content = ASF::SVN['asf/incubator/public/trunk/content']
-      podlings = Nokogiri::XML(File.read("#{incubator_content}/podlings.xml"))
-      podlings.search('podling').map do |node|
-
-        reporting = node.at('reporting')
-        if reporting
-          group = reporting['group']
-          monthly = reporting.text.split(/,\s*/) if reporting['monthly']
-          reporting = %w(January April July October) if group == '1'
-          reporting = %w(February May August November) if group == '2'
-          reporting = %w(March June September December) if group == '3'
-          reporting.rotate! until quarter.include? reporting.first
-
-          if monthly
-            monthly.shift until monthly.empty? or quarter.include? monthly.first
-            reporting = (monthly + reporting).uniq
-          end
+    # create a podling from a Nokogiri node built from podlings.xml
+    def initialize(node)
+      @name = node['name']
+      @resource = node['resource']
+      @status = node['status']
+      @enddate = node['enddate']
+      @startdate = node['startdate']
+      @description = node.at('description').text
+      @mentors = node.search('mentor').map {|mentor| mentor['username']}
+      @champion = node.at('champion')['availid'] if node.at('champion')
+
+      @reporting = node.at('reporting')
+    end
+
+    # map resource to name
+    def name
+      @resource
+    end
+
+    # also map resource to id
+    def id
+      @resource
+    end
+
+    # map name to display_name
+    def display_name
+      @name || @resource
+    end
+
+    # parse startdate
+    def startdate
+      return unless @startdate
+      return Date.parse("#@startdate-15") if @startdate.length < 8
+      Date.parse(@startdate)
+    rescue ArgumentError
+      nil
+    end
+
+    # parse enddate
+    def enddate
+      return unless @enddate
+      return Date.parse("#@enddate-15") if @enddate.length < 8
+      Date.parse(@enddate)
+    rescue ArgumentError
+      nil
+    end
+
+    # lazy evaluation of reporting
+    def reporting
+      if @reporting.instance_of? Nokogiri::XML::Element
+        group = @reporting['group']
+        monthly = @reporting.text.split(/,\s*/) if @reporting['monthly']
+        @reporting = %w(January April July October) if group == '1'
+        @reporting = %w(February May August November) if group == '2'
+        @reporting = %w(March June September December) if group == '3'
+        @reporting.rotate! until quarter.include? @reporting.first
+
+        if monthly
+          monthly.shift until monthly.empty? or quarter.include? monthly.first
+          @reporting = (monthly + @reporting).uniq
         end
+      end
 
-        data = {
-          name: node['name'],
-          status: node['status'],
-          reporting: reporting,
-          description: node.at('description').text,
-          mentors: node.search('mentor').map {|mentor| mentor['username']}
-        }
-        data[:champion] = node.at('champion')['availid'] if node.at('champion')
-        yield node['resource'], data
+      @reporting
+    end
+
+    # list of podlings
+    def self.list
+      incubator_content = ASF::SVN['asf/incubator/public/trunk/content']
+      podlings_xml = "#{incubator_content}/podlings.xml"
+
+      if @mtime != File.mtime(podlings_xml)
+        @list = []
+        podlings = Nokogiri::XML(File.read(podlings_xml))
+        podlings.search('podling').map do |node|
+          @list << new(node)
+        end
       end
+
+      @list
+    end
+
+    # find a podling by name
+    def self.find(name)
+      list.find {|podling| podling.name == name}
+    end
+
+    # below is for backwards compatibility
+
+    # make class itself enumerable
+    class << self
+      include Enumerable
     end
 
     # return the entire list as a hash
     def self.to_h
       Hash[self.to_a]
     end
+
+    # provide a list of podling names and descriptions
+    def self.each(&block)
+      list.each {|podling| block.call podling.name, podling}
+    end
+
+    # allow attributes to be accessed as hash
+    def [](name)
+      return self.send name if self.respond_to? name
+    end
   end
+
+  # more backwards compatibility
+  Podlings = Podling
 end
diff --git a/tools/collate_minutes.rb b/tools/collate_minutes.rb
index e9345cf..ebff9f8 100755
--- a/tools/collate_minutes.rb
+++ b/tools/collate_minutes.rb
@@ -55,24 +55,22 @@
     'security team'               => 'security',
     'c++ standard library'        => 'stdcxx'
 
-# parse podling information
+# extract podling information
 site = {}
-podlings = Nokogiri::XML(File.read("#{INCUBATOR_SITE_AUTHOR}/podlings.xml"))
-podlings.search('podling').each do |podling|
-  if podling['name'].downcase != podling['resource']
-    canonical[podling['name'].downcase] = podling['resource']
+ASF::Podling.list.each do |podling|
+  if podling.display_name.downcase != podling.name
+    canonical[podling.display_name.downcase] = podling.name
   end
 
-  if podling['status'] == 'graduated' and podling['enddate']
-    next if podling['enddate'].length < 10
-    next if Date.today - Date.parse(podling['enddate']) > 90
+  if podling.status == 'graduated' and podling.enddate
+    next if Date.today - podling.enddate > 90
   end
 
-  site[podling["resource"]] = {
-    :name => podling["name"],
-    :status => podling["status"],
-    :link => incubator + "projects/#{podling["resource"]}.html",
-    :text => podling.at('description').text
+  site[podling.name] = {
+    name:   podling.display_name,
+    status: podling.status,
+    link:   incubator + "projects/#{podling.name}.html",
+    text:   podling.description
   }
 end
 
diff --git a/www/classic/roster/main.rb b/www/classic/roster/main.rb
index 396f530..e67c58d 100755
--- a/www/classic/roster/main.rb
+++ b/www/classic/roster/main.rb
@@ -79,7 +79,7 @@
 
 get '/json/podlings' do
   _json do
-    _! ASF::Podlings.to_h
+    _! ASF::Podling.to_h
   end
 end
 
diff --git a/www/incubator/maillist.cgi b/www/incubator/maillist.cgi
index 27a3075..44d6063 100755
--- a/www/incubator/maillist.cgi
+++ b/www/incubator/maillist.cgi
@@ -15,18 +15,19 @@ _html do
       _th 'mailing lists'
     end
 
-    ASF::Podlings.to_enum.sort.each do |name, description|
-      next if description[:status] == 'retired'
-      next if description[:status] == 'graduated'
+    ASF::Podling.list.sort_by {|podling| podling.name}.each do |podling|
+      next if podling.status == 'retired'
+      next if podling.status == 'graduated'
 
       _tr_ do
         _td! do
-          _a name, href: "http://incubator.apache.org/projects/#{name}.html"
+          _a podling.display_name, 
+            href: "http://incubator.apache.org/projects/#{podling.name}.html"
         end
 
-        _td description[:status]
-        _td description[:reporting].join(', ')
-        _td lists.select {|list| list.start_with? "#{name}-"}.join(', ')
+        _td podling.status
+        _td podling.reporting.join(', ')
+        _td lists.select {|list| list.start_with? "#{podling.name}-"}.join(', ')
       end
     end
   end
diff --git a/www/roster/main.rb b/www/roster/main.rb
index ec7fc64..0259ca7 100755
--- a/www/roster/main.rb
+++ b/www/roster/main.rb
@@ -28,7 +28,7 @@
     @committees = ASF::Committee.list
     @members = ASF::Member.list.keys - ASF::Member.status.keys
     @groups = Group.list
-    @podlings = ASF::Podlings.to_h.values
+    @podlings = ASF::Podling.to_h.values
     _html :index
   else
     redirect to('/')
@@ -105,7 +105,7 @@
 
 get '/group/' do
   @groups = Group.list
-  @podlings = ASF::Podlings.to_h
+  @podlings = ASF::Podling.to_h
   _html :groups
 end
 
@@ -123,7 +123,7 @@
   attic = ASF::SVN['asf/attic/site/xdocs/projects']
   @attic = Dir["#{attic}/*.xml"].map {|file| File.basename(file, '.xml')}
   @committees = ASF::Committee.list.map(&:id)
-  @podlings = ASF::Podlings.to_enum.map {|id, hash| hash.merge id: id}
+  @podlings = ASF::Podling.list
 
   _html :podlings
 end
diff --git a/www/roster/public_nonldap_groups.rb b/www/roster/public_nonldap_groups.rb
index 9741cb5..7189fd4 100644
--- a/www/roster/public_nonldap_groups.rb
+++ b/www/roster/public_nonldap_groups.rb
@@ -23,7 +23,7 @@
 require_relative 'public_json_common'
 
 require 'net/http'
-pods = Hash[ASF::Podlings.to_enum.map {|podling, definition| [podling, definition[:status]]}]
+pods = Hash[ASF::Podlings.list.map {|podling| [podling.name, podling.status]}]
 
 file = '/apache/infrastructure-puppet/deployment/modules/subversion_server/files/authorization/asf-authorization-template'
 http = Net::HTTP.new('raw.githubusercontent.com', 443)
diff --git a/www/roster/views/groups.html.rb b/www/roster/views/groups.html.rb
index cd1607d..6b3be34 100644
--- a/www/roster/views/groups.html.rb
+++ b/www/roster/views/groups.html.rb
@@ -51,10 +51,10 @@
           _td type
 
           if @podlings[name]
-            if @podlings[name][:status] == 'retired'
+            if @podlings[name].status == 'retired'
               _td.issue "retired podling"
             else
-              _td "#{@podlings[name][:status]} podling"
+              _td "#{@podlings[name].status} podling"
             end
           else
             _td
diff --git a/www/roster/views/index.html.rb b/www/roster/views/index.html.rb
index cde3c63..128c3cd 100644
--- a/www/roster/views/index.html.rb
+++ b/www/roster/views/index.html.rb
@@ -60,7 +60,7 @@
 
     _tr do
       _td do
-        _a @podlings.select {|podling| podling[:status] == 'current'}.length,
+        _a @podlings.select {|podling| podling.status == 'current'}.length,
           href: 'podlings'
       end
 
diff --git a/www/roster/views/podlings.html.rb b/www/roster/views/podlings.html.rb
index 76f5c41..88b3cd8 100644
--- a/www/roster/views/podlings.html.rb
+++ b/www/roster/views/podlings.html.rb
@@ -21,7 +21,7 @@
   _h1_ 'Summary'
  
   _table.counts do
-    @podlings.group_by {|podling| podling[:status]}.sort.each do |status, list|
+    @podlings.group_by {|podling| podling.status}.sort.each do |status, list|
       _tr do
         _td list.count
         _td do
@@ -67,29 +67,29 @@
     end
 
     _tbody do
-      @podlings.sort_by {|podling| podling[:name].downcase}.each do |podling|
-        status = (@attic.include?(podling[:id]) ? 'attic' : podling[:status])
+      @podlings.sort_by {|podling| podling.name.downcase}.each do |podling|
+        status = (@attic.include?(podling.name) ? 'attic' : podling.status)
 
         _tr_ class: color[status] do
           _td do
-            _a podling[:name], href:
-              "http://incubator.apache.org/projects/#{podling[:id]}.html"
+            _a podling.display_name, href:
+              "http://incubator.apache.org/projects/#{podling.name}.html"
           end
 
-          if @committees.include? podling[:id]
-            _td data_sort_value: "#{podling[:status]} - pmc" do
-              _a podling[:status], href: "committee/#{podling[:id]}"
+          if @committees.include? podling.name
+            _td data_sort_value: "#{podling.status} - pmc" do
+              _a podling.status, href: "committee/#{podling.name}"
             end
-          elsif @attic.include? podling[:id]
-            _td data_sort_value: "#{podling[:status]} - attic" do
-              _a podling[:status], href:
-                "http://attic.apache.org/projects/#{podling[:id]}.html"
+          elsif @attic.include? podling.name
+            _td data_sort_value: "#{podling.status} - attic" do
+              _a podling.status, href:
+                "http://attic.apache.org/projects/#{podling.name}.html"
             end
           else
-            _td podling[:status]
+            _td podling.status
           end
 
-          _td podling[:description]
+          _td podling.description
         end
       end
     end