This is an automated email from the ASF dual-hosted git repository.

sebb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git


The following commit(s) were added to refs/heads/master by this push:
     new ebc9a6c4 Allow for potential duplicates; return Set
ebc9a6c4 is described below

commit ebc9a6c45c4d5fa516b45433bbce6b3aea175e2c
Author: Sebb <[email protected]>
AuthorDate: Fri Mar 13 23:11:34 2026 +0000

    Allow for potential duplicates; return Set
---
 lib/whimsy/asf/mail.rb             | 36 ++++++++++++++++++++++--------------
 www/board/subscriptions.cgi        | 19 +++++++++++--------
 www/members/moderator_checks.cgi   |  7 ++-----
 www/members/subscriptions.cgi      | 20 +++++++++++---------
 www/members/subscriptions2.cgi     | 19 +++++++++++--------
 www/officers/subscriptioncheck.cgi | 23 +++++++++++++----------
 6 files changed, 70 insertions(+), 54 deletions(-)

diff --git a/lib/whimsy/asf/mail.rb b/lib/whimsy/asf/mail.rb
index ac523500..eb8bde6d 100644
--- a/lib/whimsy/asf/mail.rb
+++ b/lib/whimsy/asf/mail.rb
@@ -3,28 +3,26 @@ require 'weakref'
 module ASF
   # Convenience functions related to emails or mailing lists.
   class Mail
-    # return a Hash containing complete list of all known emails, and the
-    # ASF::Person that is associated with that email.
-    def self.list
-      begin
-        return @list.to_h if @list
-      rescue NoMethodError, WeakRef::RefError
-      end
+    # return a hash containing down-cased email names, together with a Set of 
people with whom
+    # they are associated. In almost all cases there is only a single 
associated person.
+    # The emails are sourced from LDAP, and optionally members.txt and 
iclas.txt
+    def self.listall
+      # Note: no point currently caching the list in memory, as this method is 
only used by cgi scripts
 
-      list = {}
+      list = Hash.new{|h,k| h[k] = Set.new} # this creates a default Proc, 
which we remove later
 
       # load info from LDAP
-      people = ASF::Person.preload(['mail', 'asf-altEmail'])
+      people = ASF::Person.preload(['mail', 'asf-altEmail', 'cn'])
       people.each do |person|
         (person.mail + person.alt_email).each do |mail|
-          list[mail.downcase] = person
+          list[mail.downcase] << person # there may be more that one person 
associated with a single email
         end
       end
 
       # load all member emails in one pass
       ASF::Member.each do |id, text|
         Member.emails(text).each do |mail|
-          list[mail.downcase] ||= Person.find(id)
+          list[mail.downcase] << Person.find(id) # this should find one of the 
pre-loads
         end
       end
 
@@ -32,17 +30,27 @@ module ASF
       ASF::ICLA.each do |icla|
         person = Person.find(icla.id)
         icla.emails.each do |email|
-          list[email.downcase] ||= person
+          list[email.downcase] << person
         end
         next if icla.noId?
 
-        list["#{icla.id.downcase}@apache.org"] ||= person
+        list["#{icla.id.downcase}@apache.org"] << person # is this needed?
       end
 
-      @list = WeakRef.new(list)
+      list.default_proc = nil # no longer create an empty set when a key is 
missing
       list
     end
 
+    # Allow for trailing +- suffix in emails.
+    # e.g.
+    # [email protected] => [email protected]
+    # [email protected] => [email protected]
+    def self.remove_email_suffix(email)
+      # TODO: may need to tighten this to avoid ambiguities
+      # e.g. selectively apply '-xxx' or '+xxx' removal, depending on domain
+      email.downcase.sub(/[-+]\w+@/,'@') # drop suffix
+    end
+
     # return a list of people ids, their public-name, whether they are an ASF 
member, and email addresses
     def self.people_mails
       member_statuses = ASF::Member.member_statuses # cache the statuses. 
TODO: should be done in ASF.Member
diff --git a/www/board/subscriptions.cgi b/www/board/subscriptions.cgi
index 0740aca5..dfd512ad 100755
--- a/www/board/subscriptions.cgi
+++ b/www/board/subscriptions.cgi
@@ -65,18 +65,21 @@ _html do
       end
 
       ids = []
-      maillist = ASF::Mail.list
-      subscribers.each do |line|
-        person = maillist[line.downcase]
-        person ||= maillist[line.downcase.sub(/\+\w+@/,'@')]
-        if person
-          id = person.id
-          id = '*notinavail*' if id == 'notinavail'
+      maillist = ASF::Mail.listall
+      subscribers.each do |email|
+        people = maillist[email.downcase] # email may match more than one 
person
+        people ||= maillist[ASF::Mail.remove_email_suffix(email)]
+        if people
+          people.each do |person|
+            id = person.id
+            id = '*notinavail*' if id == 'notinavail'
+            ids << [id, person, email]
+          end
         else
           person = ASF::Person.find('notinavail')
           id = '*missing*'
+          ids << [id, person, email]
         end
-        ids << [id, person, line]
       end
 
       _table_.table do
diff --git a/www/members/moderator_checks.cgi b/www/members/moderator_checks.cgi
index 8335174b..cd050c1d 100755
--- a/www/members/moderator_checks.cgi
+++ b/www/members/moderator_checks.cgi
@@ -34,17 +34,14 @@ _html do
         _h2 'DRAFT - List moderators whose email addresses are not recognised'
         _p 'If the domain is @apache.org, the email is most likely a typo'
         _p 'In other cases, perhaps the email is not registered'
-        _p do
-          _b 'Emails are matched exactly - case is treated significant, even 
for domains'
-        end
       }
     ) do
       lists, _time = ASF::MLIST.list_moderators(nil)
-      emails = ASF::Mail.list
+      emails = ASF::Mail.listall
       unknown = Hash.new { |h, k| h[k] = []}
       lists.each do |lid, mods|
         mods.each do |mod|
-          unknown[mod] << lid unless MODERATORS.include? mod or emails[mod] or 
private_mod(lid, mod)
+          unknown[mod] << lid unless MODERATORS.include? mod or 
emails[mod.downcase] or private_mod(lid, mod)
         end
       end
 
diff --git a/www/members/subscriptions.cgi b/www/members/subscriptions.cgi
index aaa622c1..cc913df9 100755
--- a/www/members/subscriptions.cgi
+++ b/www/members/subscriptions.cgi
@@ -62,20 +62,22 @@ _html do
 
     members = ASF::Member.new.map {|id, text| ASF::Person.find(id)}
     ASF::Person.preload('cn', members)
-    maillist = ASF::Mail.list
-
+    maillist = ASF::Mail.listall
     subscriptions = []
-    subscribers.each do |line|
-      person = maillist[line.downcase]
-      person ||= maillist[line.downcase.sub(/[-+]\w+@/,'@')] # allow for 
trailing +- suffix
-      if person
-        id = person.id
-        id = '*notinavail*' if id == 'notinavail'
+    subscribers.each do |email|
+      people = maillist[email.downcase]
+      people ||= maillist[ASF::Mail.remove_email_suffix(email)]
+      if people
+        people.each do |person|  # email may match more than one person
+          id = person.id
+          id = '*notinavail*' if id == 'notinavail'
+          subscriptions << [id, person, email]
+        end
       else
         person = ASF::Person.find('notinavail')
         id = '*missing*'
+        subscriptions << [id, person, email]
       end
-      subscriptions << [id, person, line]
     end
 
     _table.table do
diff --git a/www/members/subscriptions2.cgi b/www/members/subscriptions2.cgi
index e28f6788..62009f35 100755
--- a/www/members/subscriptions2.cgi
+++ b/www/members/subscriptions2.cgi
@@ -68,20 +68,23 @@ _html do
     nonASFemails = []
     members = ASF::Member.new.map {|id, _text| ASF::Person.find(id)}
     ASF::Person.preload('cn', members)
-    maillist = ASF::Mail.list
+    maillist = ASF::Mail.listall
 
     subscriptions = []
-    subscribers.each do |line|
-      person = maillist[line.downcase]
-      person ||= maillist[line.downcase.sub(/[-+]\w+@/, '@')] # allow for 
trailing +- suffix
-      if person
-        id = person.id
-        id = '*notinavail*' if id == 'notinavail'
+    subscribers.each do |email|
+      people = maillist[email.downcase]
+      people ||= maillist[ASF::Mail.remove_email_suffix(email)]
+      if people
+        people.each do |person|  # email may match more than one person
+          id = person.id
+          id = '*notinavail*' if id == 'notinavail'
+          subscriptions << [id, person, email]
+        end
       else
         person = ASF::Person.find('notinavail')
         id = '*missing*'
+        subscriptions << [id, person, email]
       end
-      subscriptions << [id, person, line]
     end
 
     _table.table do
diff --git a/www/officers/subscriptioncheck.cgi 
b/www/officers/subscriptioncheck.cgi
index 30b33f6b..09eab509 100755
--- a/www/officers/subscriptioncheck.cgi
+++ b/www/officers/subscriptioncheck.cgi
@@ -19,7 +19,7 @@ MEMBER_ANNOUNCE_OK = %w([email protected] 
[email protected])
 
 DEFAULT_LISTS = 
'board,markpub,members,members-announce,members-notify,operations,press,trademarks,[email protected]'
 listnames = ENV['QUERY_STRING']
-listnames = DEFAULT_LISTS if listnames == ''
+listnames = DEFAULT_LISTS if listnames == '' or listnames.nil?
 
 info_chairs = ASF::Committee.load_committee_info.group_by(&:chair)
 ldap_chairs = ASF.pmc_chairs
@@ -93,19 +93,22 @@ _html do
           _ "(updated #{modtime})"
         end
         subscribers -= MEMBER_ANNOUNCE_OK if listid == 
'[email protected]'
-        subscribers -= ['[email protected]'] if listid = 
'[email protected]'
-        maillist = ASF::Mail.list
-        subscribers.each do |line|
-          person = maillist[line.downcase]
-          person ||= maillist[line.downcase.sub(/\+\w+@/,'@')]
-          if person
-            id = person.id
-            id = '*notinavail*' if id == 'notinavail'
+        subscribers -= ['[email protected]'] if listid == 
'[email protected]'
+        maillist = ASF::Mail.listall
+        subscribers.each do |email|
+          people = maillist[email.downcase]
+          people ||= maillist[ASF::Mail.remove_email_suffix(email)]
+          if people
+            people.each do |person|
+              id = person.id
+              id = '*notinavail*' if id == 'notinavail'
+              ids << [id, person, email]
+            end
           else
             person = ASF::Person.find('notinavail')
             id = '*missing*'
+            ids << [id, person, email]
           end
-          ids << [id, person, line]
         end
       end
 

Reply via email to