diff options
Diffstat (limited to 'bin/arch')
-rw-r--r-- | bin/arch | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/bin/arch b/bin/arch new file mode 100644 index 00000000..be430f68 --- /dev/null +++ b/bin/arch @@ -0,0 +1,187 @@ +#! @PYTHON@ +# +# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +"""Rebuild a list's archive. + +Use this command to rebuild the archives for a mailing list. You may want to +do this if you edit some messages in an archive, or remove some messages from +an archive. + +Usage: %(PROGRAM)s [options] <listname> [<mbox>] + +Where options are: + -h / --help + Print this help message and exit. + + -q / --quiet + Make the archiver output less verbose. + + --wipe + First wipe out the original archive before regenerating. You usually + want to specify this argument unless you're generating the archive in + chunks. + + -s N + --start=N + Start indexing at article N, where article 0 is the first in the mbox. + Defaults to 0. + + -e M + --end=M + End indexing at article M. This script is not very efficient with + respect to memory management, and for large archives, it may not be + possible to index the mbox entirely. For that reason, you can specify + the start and end article numbers. + +Where <mbox> is the path to a list's complete mbox archive. Usually this will +be some path in the archives/private directory. For example: + +%% bin/arch mylist archives/private/mylist.mbox/mylist.mbox + +<mbox> is optional. If it is missing, it is calculated. +""" + +import os +import sys +import getopt +import shutil + +import paths +from Mailman import mm_cfg +from Mailman import Errors + +from Mailman.MailList import MailList +from Mailman.Archiver.HyperArch import HyperArchive +from Mailman.LockFile import LockFile +from Mailman import i18n + +_ = i18n._ + +PROGRAM = sys.argv[0] +i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) + + + +def usage(code, msg=''): + if code: + fd = sys.stderr + else: + fd = sys.stdout + print >> fd, _(__doc__) + if msg: + print >> fd, msg + sys.exit(code) + + + +def main(): + # get command line arguments + try: + opts, args = getopt.getopt( + sys.argv[1:], 'hs:e:q', + ['help', 'start', 'end', 'quiet', 'wipe']) + except getopt.error, msg: + usage(1, msg) + + start = None + end = None + verbose = 1 + wipe = 0 + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-s', '--start'): + try: + start = int(arg) + except ValueError: + usage(1) + elif opt in ('-e', '--end'): + try: + end = int(arg) + except ValueError: + usage(1) + elif opt in ('-q', '--quiet'): + verbose = 0 + elif opt == '--wipe': + wipe = 1 + + # grok arguments + if len(args) < 1: + usage(1, _('listname is required')) + listname = args[0].lower().strip() + + if len(args) < 2: + mbox = None + else: + mbox = args[1] + + if len(args) > 2: + usage(1) + + # open the mailing list object + mlist = None + lock = None + try: + try: + mlist = MailList(listname) + except Errors.MMListError, e: + usage(2, _('No such list "%(listname)s"\n%(e)s')) + if mbox is None: + mbox = mlist.ArchiveFileName() + + i18n.set_language(mlist.preferred_language) + # lay claim to the archive's lock file. this is so no other post can + # mess up the archive while we're glomming it. we pick a suitably + # long period of time for the lock lifetime, however we really don't + # know how long it will take. + # + # XXX: processUnixMailbox() should refresh the lock. + # + # XXX: this may not be necessary because I think we lay claim to the + # list lock up above, although that may be too short to be of use (and + # maybe we don't really want to lock the list anyway). + # + lockfile = os.path.join(mm_cfg.LOCK_DIR, mlist._internal_name) + \ + '.archiver.lock' + # set the lock lifetime to 3 hours. XXX is this reasonable??? + lock = LockFile(lockfile, lifetime=3*60*60) + lock.lock() + # Maybe wipe the old archives + if wipe: + shutil.rmtree(mlist.archive_dir()) + try: + fp = open(mbox) + except IOError, msg: + usage(3, _('Cannot open mbox file %(mbox)s: %(msg)s')) + + archiver = HyperArchive(mlist) + archiver.VERBOSE = verbose + try: + archiver.processUnixMailbox(fp, start, end) + finally: + archiver.close() + fp.close() + finally: + if lock: + lock.unlock() + if mlist: + mlist.Unlock() + + +if __name__ == '__main__': + main() |