[Mailman-Developers] Newlist/rmlist update

Marc MERLIN marc_news@vasoftware.com
Tue, 1 Jan 2002 20:33:01 +0100


As promised, here's a patch that:
1) Adds the SPLIT_DIRS option which does this:

root@gandalf:/var/local/mailman/lists# l
total 16
drwxrwsr-x    4 root     mailman      4096 Jan  1 20:03 ./
drwxrwsr-x   19 mailman  mailman      4096 Jan  1 09:55 ../
drwxrwsr-x    3 root     mailman      4096 Jan  1 19:46 m/
lrwxrwxrwx    1 root     mailman        43 Jan  1 20:01 mailman-owner -> /var/local/mailman/lists/m/ma/mailman-owner/
drwxrwsr-x    3 root     mailman      4096 Jan  1 12:18 t/
lrwxrwxrwx    1 root     mailman        34 Jan  1 20:02 test -> /var/local/mailman/lists/t/te/test/
lrwxrwxrwx    1 root     mailman        35 Jan  1 20:03 test2 -> /var/local/mailman/lists/t/te/test2/

root@gandalf:/var/local/mailman/archives/private# l
total 16
drwxrws--x    4 root     mailman      4096 Jan  1 20:03 ./
drwxrwsr-x    4 root     mailman      4096 Jan  1 09:55 ../
drwxrwsr-x    3 root     mailman      4096 Jan  1 19:46 m/
lrwxrwxrwx    1 root     mailman        54 Jan  1 20:01 mailman-owner -> /var/local/mailman/archives/private/m/ma/mailman-owner/
lrwxrwxrwx    1 root     mailman        59 Jan  1 20:01 mailman-owner.mbox -> /var/local/mailman/archives/private/m/ma/mailman-owner.mbox/
drwxrwsr-x    3 root     mailman      4096 Jan  1 12:18 t/
lrwxrwxrwx    1 root     mailman        45 Jan  1 20:02 test -> /var/local/mailman/archives/private/t/te/test/
lrwxrwxrwx    1 root     mailman        46 Jan  1 20:03 test2 -> /var/local/mailman/archives/private/t/te/test2/
lrwxrwxrwx    1 root     mailman        51 Jan  1 20:03 test2.mbox -> /var/local/mailman/archives/private/t/te/test2.mbox/
lrwxrwxrwx    1 root     mailman        50 Jan  1 20:02 test.mbox -> /var/local/mailman/archives/private/t/te/test.mbox/

  This gets around the 32K link / directory limit in many filesystems
  (limiting mailman to 16K lists)

2) Creates the pipermail html dir at list creation time so that you don't
   get an http error when you view the archive of a list that doesn't have
   messages yet

3) rmlist now does what it advertises with -a (you couldn't erase archives
   after erasing a list)

   root@gandalf:/var/local/mailman/bin# ./rmlist test2
   Not removing archives.  Reinvoke with -a to remove them.
   Removing list info
   Removing list info
   root@gandalf:/var/local/mailman/bin# ./rmlist -a test2
   List test2 does not exist or was already deleted, trying to remove archives.
   Removing private archives
   Removing private archives
   Removing private archives
   Removing private archives
   Removing public archives
   test2 public archives not found as /var/local/mailman/archives/public/t/te/test2
   Removing public archives
   test2 public archives not found as /var/local/mailman/archives/public/t/te/test2.mbox


If everyone  is cool  with this, I'll  write a tool  to convert  an existing
installation  to  the new  (optional)  directory  layout  (I need  this  for
lists.sourceforge.net)


diff -urN mailman/Mailman/Archiver/Archiver.py mailman.subdirs/Mailman/Archiver/Archiver.py
--- mailman/Mailman/Archiver/Archiver.py	Fri Oct 26 23:57:47 2001
+++ mailman.subdirs/Mailman/Archiver/Archiver.py	Tue Jan  1 11:07:56 2002
@@ -76,6 +76,10 @@
         #             listname.mbox
         #         listname/
         #             lots-of-pipermail-stuff
+	# (note that if mm_cfg.SPLIT_DIRS is set, we create subdirectories and
+	# use symlinks (this gets around a 32k directories limit in some 
+	# filesystems linked to a 32k hardlink limit per inode -- Marc))
+	#
         #     public/
         #         listname.mbox@ -> ../private/listname.mbox
         #         listname@ -> ../private/listname
@@ -89,7 +93,25 @@
         omask = os.umask(0)
         try:
             try:
-                os.mkdir(self.archive_dir()+'.mbox', 02775)
+		listname=self.internal_name();
+		if mm_cfg.SPLIT_DIRS:
+		    archprivdir=os.path.join(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR,
+			    listname[0], listname[0:2], listname + '.mbox')
+		    os.makedirs(archprivdir, 02775)
+		    os.symlink(archprivdir, self.archive_dir()+'.mbox')
+		else:
+		    os.mkdir(self.archive_dir()+'.mbox', 02775)
+                # We also create an empty pipermail archive directory (pipermail
+                # would create it, but in the meantime lists with no archives
+                # return errors when you browse the non existant archive dir)
+		# Besides, pipermail won't know about mm_cfg.SPLIT_DIRS -- Marc
+		if mm_cfg.SPLIT_DIRS:
+		    archprivdir=os.path.join(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR,
+			    listname[0], listname[0:2], listname)
+		    os.makedirs(archprivdir, 02775)
+		    os.symlink(archprivdir, self.archive_dir())
+		else:
+		    os.mkdir(self.archive_dir(), 02775)
             except OSError, e:
                 if e.errno <> errno.EEXIST: raise
         finally:
diff -urN mailman/Mailman/Archiver/pipermail.py mailman.subdirs/Mailman/Archiver/pipermail.py
--- mailman/Mailman/Archiver/pipermail.py	Fri Nov 30 09:07:32 2001
+++ mailman.subdirs/Mailman/Archiver/pipermail.py	Tue Jan  1 11:28:15 2002
@@ -252,6 +252,9 @@
 	self.database = database
 
 	# If the directory doesn't exist, create it
+	# This code shouldn't get run anymore, we create the directory in
+        # Archiver.py. It should only get used  by legacy lists created that
+        # are only receiving their first message in the HTML archive now -- Marc
 	try:
             os.stat(self.basedir)
 	except os.error, errdata:
diff -urN mailman/Mailman/Defaults.py.in mailman.subdirs/Mailman/Defaults.py.in
--- mailman/Mailman/Defaults.py.in	Tue Jan  1 08:29:01 2002
+++ mailman.subdirs/Mailman/Defaults.py.in	Tue Jan  1 12:50:35 2002
@@ -62,6 +62,13 @@
 HOME_PAGE         = 'index.html'
 MAILMAN_SITE_LIST = 'mailman'
 
+# Set to '1' to have mailman start creating lists in directories like
+# ~mailman/lists/l/li/listname/ (same thing for  the archives) to get around
+# the 32K directory limitation in some filesystems.
+# Because this sets symlinks to the  expected positions, it is fully forward
+# and backward compatible -- Marc
+SPLIT_DIRS = 0
+
 
 
 #####
diff -urN mailman/Mailman/MailList.py mailman.subdirs/Mailman/MailList.py
--- mailman/Mailman/MailList.py	Tue Jan  1 08:29:02 2002
+++ mailman.subdirs/Mailman/MailList.py	Tue Jan  1 10:40:25 2002
@@ -388,7 +388,13 @@
         Utils.ValidateEmail(admin)
         omask = os.umask(0)
         try:
-            os.makedirs(os.path.join(mm_cfg.LIST_DATA_DIR, name), 02775)
+	    listdir=os.path.join(mm_cfg.LIST_DATA_DIR, name)
+	    if mm_cfg.SPLIT_DIRS:
+		splitdir=os.path.join(mm_cfg.LIST_DATA_DIR, name[0], name[0:2], name)
+		os.makedirs(splitdir, 02775)
+		os.symlink(splitdir, listdir)
+	    else:
+		os.makedirs(listdir, 02775)
         finally:
             os.umask(omask)
         self._full_path = os.path.join(mm_cfg.LIST_DATA_DIR, name)
diff -urN mailman/bin/rmlist mailman.subdirs/bin/rmlist
--- mailman/bin/rmlist	Sat Sep  8 01:18:47 2001
+++ mailman.subdirs/bin/rmlist	Tue Jan  1 12:35:35 2002
@@ -1,4 +1,4 @@
-#! @PYTHON@
+#! /usr/bin/python
 #
 # Copyright (C) 1998,1999,2000,2001 by the Free Software Foundation, Inc.
 #
@@ -78,11 +78,6 @@
         usage(1)
     listname = args[0].lower().strip()
 
-    if not Utils.list_exists(listname):
-        usage(1, _('No such list: %(listname)s'))
-
-    mlist = MailList.MailList(listname, lock=0)
-
     removeArchives = 0
     for opt, arg in opts:
         if opt in ('-a', '--archives'):
@@ -90,28 +85,57 @@
         elif opt in ('-h', '--help'):
             usage(0)
 
+    if not Utils.list_exists(listname):
+	if not removeArchives:
+	    usage(1, _('No such list (or list already deleted): %(listname)s'))
+	else:
+	    print _('List %(listname)s does not exist or was already deleted, trying to remove archives.')
+
     if not removeArchives:
         print _('Not removing archives.  Reinvoke with -a to remove them.')
 
-    # Do the MTA-specific list deletion tasks
-    if mm_cfg.MTA:
-        modname = 'Mailman.MTA.' + mm_cfg.MTA
-        __import__(modname)
-        sys.modules[modname].remove(mlist)
 
-    REMOVABLES = [('lists/%s', 'list info'),
-                  ]
+    listsplitsubdir = os.path.join(listname[0], listname[0:2], listname)
+    listmboxsplitsubdir = os.path.join(listname[0], listname[0:2], listname + ".mbox")
+    REMOVABLES = [ ]
+    if Utils.list_exists(listname):
+	mlist = MailList.MailList(listname, lock=0)
+
+	# Do the MTA-specific list deletion tasks
+	if mm_cfg.MTA:
+	    modname = 'Mailman.MTA.' + mm_cfg.MTA
+	    __import__(modname)
+	    sys.modules[modname].remove(mlist)
+
+	REMOVABLES = [
+	    (os.path.join('lists', listname), _('list info')),
+	    (os.path.join('lists', listsplitsubdir), _('list info'))
+	]
+
 
     if removeArchives:
-        REMOVABLES.extend(
-            [('archives/private/%s',      _('private archives')),
-             ('archives/private/%s.mbox', _('private archives')),
-             ('archives/public/%s',       _('public archives')),
-             ('archives/public/%s.mbox',  _('public archives')),
-             ])
+        REMOVABLES.extend ([
+	    (os.path.join('archives', 'private', listname), 
+						_('private archives')),
+	    (os.path.join('archives', 'private', listsplitsubdir), 
+						_('private archives')),
+	    (os.path.join('archives', 'private', listname + '.mbox'), 
+						_('private archives')),
+	    (os.path.join('archives', 'private', listmboxsplitsubdir), 
+						_('private archives')),
+
+	    (os.path.join('archives', 'public', listname), 
+						_('public archives')),
+	    (os.path.join('archives', 'public', listsplitsubdir), 
+						_('public archives')),
+	    (os.path.join('archives', 'public', listname + '.mbox'), 
+						_('public archives')),
+	    (os.path.join('archives', 'public', listmboxsplitsubdir), 
+						_('public archives'))
+	 ])
 
     for dirtmpl, msg in REMOVABLES:
-        dir = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl % listname)
+        dir = os.path.join(mm_cfg.VAR_PREFIX, dirtmpl)
         remove_it(listname, dir, msg)
 
 

-- 
Microsoft is to operating systems & security ....
                                      .... what McDonalds is to gourmet cooking
  
Home page: http://marc.merlins.org/   |   Finger marc_f@merlins.org for PGP key