New option --archive-prefix, alias -p

Technically, this works just like the --suffix option.  This commit also
updates the manpage accordingly.

Currently, the prefix is not checked for slashes, so it could contain path
components.  (The same applies for the suffix, btw).  Since the expanded
string is prepended to the archive base name, this can be used to dynamically
configure the archive directory, depending on the archive cutoff date.  I'm
not sure if this can be considered a reasonable feature, though.
This commit is contained in:
Nikolaus Schulz 2010-07-30 23:26:22 +02:00
parent f22fe4decd
commit b6bc92c34f
4 changed files with 70 additions and 13 deletions

View File

@ -54,6 +54,11 @@ Version 0.8.0 - UNRELEASED
* IMAP servers (Dovecot and UW-IMAP at least) may store mailbox meta data
for mboxes in a pseudo message. Such messages are now detected and never
archived. Obsoletes: patch #2210707. (Thanks, "tlhackque")
* New option --prefix, or short -p, to specify an archive name prefix. Like
a suffix specified with the --suffix option, the prefix is expanded with
strftime(). Specifying this option disables the default archive name
suffix. Obsoletes: feature request #604281. (Thanks Serafeim Zanikolas
for an initial patch)
Version 0.7.2 - 9 November 2007

View File

@ -171,6 +171,7 @@ class StaleFiles:
class Options:
"""Class to store runtime options, including defaults"""
archive_prefix = None
archive_suffix = "_archive"
days_old_max = 180
date_old_max = None
@ -209,12 +210,12 @@ class Options:
"""
try:
opts, args = getopt.getopt(args, '?D:S:Vd:hno:F:P:qs:uv',
opts, args = getopt.getopt(args, '?D:S:Vd:hno:F:P:qs:p:uv',
["date=", "days=", "delete", "dry-run", "help",
"include-flagged", "no-compress", "output-dir=",
"filter-append=", "pwfile=", "dont-mangle",
"preserve-unread", "quiet", "size=", "suffix=",
"verbose", "debug-imap=", "version",
"prefix=", "verbose", "debug-imap=", "version",
"warn-duplicate", "copy", "all"])
except getopt.error, msg:
user_error(msg)
@ -257,6 +258,8 @@ class Options:
self.quiet = True
if o in ('-s', '--suffix'):
self.archive_suffix = a
if o in ('-p', '--prefix'):
self.archive_prefix = a
if o in ('-S', '--size'):
self.min_size = string.atoi(a)
if o in ('-u', '--preserve-unread'):
@ -642,6 +645,7 @@ Options are as follows:
-o, --output-dir=DIR directory to store archives (default: same as original)
-P, --pwfile=FILE file to read imap password from (default: None)
-F, --filter-append=STRING append arbitrary string to the IMAP filter string
-p, --prefix=NAME prefix for archive filename (default: none)
-s, --suffix=NAME suffix for archive filename (default: '%s')
-S, --size=NUM only archive messages NUM bytes or larger
-n, --dry-run don't write to anything - just show what would be done
@ -1626,21 +1630,25 @@ def commit_archive(archive, final_archive_name):
def make_archive_name(mailbox_name):
"""Derive archive name and (relative) path from the mailbox name."""
# allow the user to embed time formats such as '%B' in the suffix string
# allow the user to embed time formats such as '%B' in the prefix or suffix string
if options.date_old_max == None:
parsed_suffix_time = time.time() - options.days_old_max*24*60*60
tm = time.localtime(time.time() - options.days_old_max*24*60*60)
else:
parsed_suffix_time = options.date_old_max
parsed_suffix = time.strftime(options.archive_suffix,
time.localtime(parsed_suffix_time))
tm = time.localtime(options.date_old_max)
prefix = suffix = ""
if options.archive_prefix:
prefix = time.strftime(options.archive_prefix, tm)
if options.archive_suffix:
suffix = time.strftime(options.archive_suffix, tm)
if re.match(r'imaps?://', mailbox_name.lower()):
mailbox_name = mailbox_name.rsplit('/', 1)[-1]
final_archive_name = mailbox_name + parsed_suffix
archive_dir = ""
archive_base = mailbox_name.rsplit('/', 1)[-1]
else:
archive_dir, archive_base = os.path.split(mailbox_name)
if options.output_dir:
final_archive_name = os.path.join(options.output_dir,
os.path.basename(final_archive_name))
return final_archive_name
archive_dir = options.output_dir
archive_name = os.path.join(archive_dir, prefix + archive_base + suffix)
return archive_name
def check_sane_destdir(dir):
"""Do a very primitive check if the given directory looks like a reasonable

View File

@ -223,6 +223,16 @@ cut-off date:
</Para></ListItem>
</VarListEntry>
<VarListEntry>
<Term>
<Option>-p <Replaceable/NAME/, --prefix=<Replaceable/NAME/</Option>
</Term>
<ListItem><Para>Prefix <Replaceable/NAME/ to the archive name.
Like a suffix, this is run through the &python; <application/time.strftime()/
function. The default is not to add a prefix.
</Para></ListItem>
</VarListEntry>
<VarListEntry>
<Term>
<Option>-S <Replaceable/NUM/, --size=<Replaceable/NUM/</Option>

View File

@ -425,6 +425,15 @@ class TestOptionParser(unittest.TestCase):
archivemail.options.parse_args(["-s", suffix], "")
assert archivemail.options.archive_suffix == suffix
def testOptionPrefix(self):
"""--prefix and -p options are parsed correctly"""
for prefix in ("_static_", "_%B_%Y", "-%Y-%m-%d"):
archivemail.options.parse_args(["--prefix="+prefix], "")
assert archivemail.options.archive_prefix == prefix
archivemail.options.prefix = None
archivemail.options.parse_args(["-p", prefix], "")
assert archivemail.options.archive_prefix == prefix
def testOptionDryrun(self):
"""--dry-run option is parsed correctly"""
archivemail.options.parse_args(["--dry-run"], "")
@ -908,6 +917,31 @@ class TestArchiveMboxSuffix(unittest.TestCase):
archivemail.options.quiet = False
archivemail.options.archive_suffix = self.old_suffix
class TestArchiveMboxPrefix(unittest.TestCase):
"""make sure the 'prefix' option works"""
def setUp(self):
self.old_prefix = archivemail.options.archive_prefix
self.old_suffix = archivemail.options.archive_suffix
archivemail.options.archive_suffix = ""
archivemail.options.quiet = True
def testPrefix(self):
"""archiving with specified --prefix arguments"""
for archive_prefix in ("_static_", "_%B_%Y", "-%Y-%m-%d", "%Y/%m/"):
archivemail.options.archive_prefix = archive_prefix
for mbox_name in "foobar", "/tmp/foobar", "schnorchz/foobar":
archive_dir, archive_base = os.path.split(mbox_name)
days = archivemail.options.days_old_max
tm = time.localtime(time.time() - days*24*60*60)
prefix = time.strftime(archive_prefix, tm)
archive_name = os.path.join(archive_dir, prefix + archive_base)
self.assertEqual(archive_name,
archivemail.make_archive_name(mbox_name))
def tearDown(self):
archivemail.options.quiet = False
archivemail.options.archive_prefix = self.old_prefix
archivemail.options.archive_suffix = self.old_suffix
class TestArchiveDryRun(TestArchive):
"""make sure the 'dry-run' option works"""