From 22f68cd2e05c67512157913f2afc45c2e69cff11 Mon Sep 17 00:00:00 2001 From: jgoerzen Date: Mon, 7 Oct 2002 22:30:35 +0100 Subject: [PATCH] /offlineimap/head: changeset 262 Final prep for 3.99.0 --- offlineimap/head/bin/offlineimap | 5 +- offlineimap/head/debian/changelog | 2 + offlineimap/head/offlineimap.1 | 2 +- offlineimap/head/offlineimap.py | 311 +----------------------- offlineimap/head/offlineimap/init.py | 4 +- offlineimap/head/offlineimap/version.py | 6 +- 6 files changed, 13 insertions(+), 317 deletions(-) diff --git a/offlineimap/head/bin/offlineimap b/offlineimap/head/bin/offlineimap index a9d534e..220965c 100644 --- a/offlineimap/head/bin/offlineimap +++ b/offlineimap/head/bin/offlineimap @@ -1,5 +1,5 @@ #!/usr/bin/env python2.2 - +# Startup from system-wide installation # Copyright (C) 2002 John Goerzen # # @@ -17,6 +17,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -revno = long('$Rev: 252 $'[6:-2]) from offlineimap import init -init.startup(revno) +init.startup('3.99.0') diff --git a/offlineimap/head/debian/changelog b/offlineimap/head/debian/changelog index ece3d4f..e3478d0 100644 --- a/offlineimap/head/debian/changelog +++ b/offlineimap/head/debian/changelog @@ -21,6 +21,8 @@ offlineimap (3.99.0) unstable; urgency=low performs different functions. * Moved threadexited from offlineimap/init.py to offlineimap/threadutil.py. + * offlineimap.py is back to ease the use of OfflineIMAP in single-user + installations. -- John Goerzen Mon, 30 Sep 2002 12:08:08 -0500 diff --git a/offlineimap/head/offlineimap.1 b/offlineimap/head/offlineimap.1 index de6e1d7..ab58832 100644 --- a/offlineimap/head/offlineimap.1 +++ b/offlineimap/head/offlineimap.1 @@ -187,7 +187,7 @@ When you want to run you will issue the .B cd command as above and then type -.B PYTHONPATH=. bin/offlineimap; +.B ./offlineimap.py; there is no installation step necessary. .\"################################################## .SH CONFIGURATION diff --git a/offlineimap/head/offlineimap.py b/offlineimap/head/offlineimap.py index 36b19e1..a765bb4 100644 --- a/offlineimap/head/offlineimap.py +++ b/offlineimap/head/offlineimap.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2.2 - +# Startup from single-user installation # Copyright (C) 2002 John Goerzen # # @@ -17,310 +17,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -from offlineimap import imaplib, imaputil, imapserver, repository, folder, mbnames, threadutil, version, localeval -from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread -from offlineimap.ui import UIBase -import re, os, os.path, offlineimap, sys -from ConfigParser import ConfigParser -from threading import * -from getopt import getopt - -options = {} -if '--help' in sys.argv[1:]: - sys.stdout.write(version.cmdhelp + "\n") - sys.exit(0) - -for optlist in getopt(sys.argv[1:], 'P:1oa:c:d:u:h')[0]: - options[optlist[0]] = optlist[1] - -if '-h' in options: - sys.stdout.write(version.cmdhelp) - sys.stdout.write("\n") - sys.exit(0) -configfilename = os.path.expanduser("~/.offlineimaprc") -if '-c' in options: - configfilename = options['-c'] -if '-P' in options: - if not '-1' in options: - sys.stderr.write("FATAL: profile mode REQUIRES -1\n") - sys.exit(100) - profiledir = options['-P'] - os.mkdir(profiledir) - threadutil.setprofiledir(profiledir) - sys.stderr.write("WARNING: profile mode engaged;\nPotentially large data will be created in " + profiledir + "\n") - - - -config = ConfigParser() -if not os.path.exists(configfilename): - sys.stderr.write(" *** Config file %s does not exist; aborting!\n" % configfilename) - sys.exit(1) - -config.read(configfilename) - -if config.has_option("general", "pythonfile"): - path=os.path.expanduser(config.get("general", "pythonfile")) -else: - path=None -localeval = localeval.LocalEval(path) - -ui = offlineimap.ui.detector.findUI(config, localeval, options.get('-u')) -ui.init_banner() - -if '-d' in options: - for debugtype in options['-d'].split(','): - ui.add_debug(debugtype.strip()) - if debugtype == 'imap': - imaplib.Debug = 5 - -if '-o' in options and config.has_option("general", "autorefresh"): - config.remove_option("general", "autorefresh") - -metadatadir = os.path.expanduser(config.get("general", "metadata")) -if not os.path.exists(metadatadir): - os.mkdir(metadatadir, 0700) - -accounts = config.get("general", "accounts") -if '-a' in options: - accounts = options['-a'] -accounts = accounts.replace(" ", "") -accounts = accounts.split(",") - -server = None -remoterepos = None -localrepos = None -passwords = {} -tunnels = {} - -if '-1' in options: - threadutil.initInstanceLimit("ACCOUNTLIMIT", 1) -else: - threadutil.initInstanceLimit("ACCOUNTLIMIT", - config.getint("general", "maxsyncaccounts")) - -# We have to gather passwords here -- don't want to have two threads -# asking for passwords simultaneously. - -for account in accounts: - #if '.' in account: - # raise ValueError, "Account '%s' contains a dot; dots are not " \ - # "allowed in account names." % account - if config.has_option(account, "preauthtunnel"): - tunnels[account] = config.get(account, "preauthtunnel") - elif config.has_option(account, "remotepass"): - passwords[account] = config.get(account, "remotepass") - elif config.has_option(account, "remotepassfile"): - passfile = open(os.path.expanduser(config.get(account, "remotepassfile"))) - passwords[account] = passfile.readline().strip() - passfile.close() - else: - passwords[account] = ui.getpass(account, config) - for instancename in ["FOLDER_" + account, "MSGCOPY_" + account]: - if '-1' in options: - threadutil.initInstanceLimit(instancename, 1) - else: - threadutil.initInstanceLimit(instancename, - config.getint(account, "maxconnections")) - -mailboxes = [] -servers = {} - -def syncaccount(accountname, *args): - # We don't need an account lock because syncitall() goes through - # each account once, then waits for all to finish. - try: - ui.acct(accountname) - accountmetadata = os.path.join(metadatadir, accountname) - if not os.path.exists(accountmetadata): - os.mkdir(accountmetadata, 0700) - - server = None - if accountname in servers: - server = servers[accountname] - else: - server = imapserver.ConfigedIMAPServer(config, accountname, passwords) - servers[accountname] = server - - remoterepos = repository.IMAP.IMAPRepository(config, localeval, accountname, server) - - # Connect to the Maildirs. - localrepos = repository.Maildir.MaildirRepository(os.path.expanduser(config.get(accountname, "localfolders")), accountname, config) - - # Connect to the local cache. - statusrepos = repository.LocalStatus.LocalStatusRepository(accountmetadata) - - ui.syncfolders(remoterepos, localrepos) - remoterepos.syncfoldersto(localrepos) - ui.acct(accountname) - - folderthreads = [] - for remotefolder in remoterepos.getfolders(): - thread = InstanceLimitedThread(\ - instancename = 'FOLDER_' + accountname, - target = syncfolder, - name = "Folder sync %s[%s]" % \ - (accountname, remotefolder.getvisiblename()), - args = (accountname, remoterepos, remotefolder, localrepos, - statusrepos)) - thread.setDaemon(1) - thread.start() - folderthreads.append(thread) - threadutil.threadsreset(folderthreads) - if not (config.has_option(accountname, 'holdconnectionopen') and \ - config.getboolean(accountname, 'holdconnectionopen')): - server.close() - finally: - pass - -def syncfolder(accountname, remoterepos, remotefolder, localrepos, - statusrepos): - # Load local folder. - localfolder = localrepos.\ - getfolder(remotefolder.getvisiblename().\ - replace(remoterepos.getsep(), localrepos.getsep())) - # Write the mailboxes - mailboxes.append({'accountname': accountname, - 'foldername': localfolder.getvisiblename()}) - # Load local folder - ui.syncingfolder(remoterepos, remotefolder, localrepos, localfolder) - ui.loadmessagelist(localrepos, localfolder) - localfolder.cachemessagelist() - ui.messagelistloaded(localrepos, localfolder, len(localfolder.getmessagelist().keys())) - - - # Load status folder. - statusfolder = statusrepos.getfolder(remotefolder.getvisiblename().\ - replace(remoterepos.getsep(), - statusrepos.getsep())) - if localfolder.getuidvalidity() == None: - # This is a new folder, so delete the status cache to be sure - # we don't have a conflict. - statusfolder.deletemessagelist() - - statusfolder.cachemessagelist() - - - # If either the local or the status folder has messages and - # there is a UID validity problem, warn and abort. - # If there are no messages, UW IMAPd loses UIDVALIDITY. - # But we don't really need it if both local folders are empty. - # So, in that case, save it off. - if (len(localfolder.getmessagelist()) or \ - len(statusfolder.getmessagelist())) and \ - not localfolder.isuidvalidityok(remotefolder): - ui.validityproblem(remotefolder) - return - else: - localfolder.saveuidvalidity(remotefolder.getuidvalidity()) - - # Load remote folder. - ui.loadmessagelist(remoterepos, remotefolder) - remotefolder.cachemessagelist() - ui.messagelistloaded(remoterepos, remotefolder, - len(remotefolder.getmessagelist().keys())) - - - # - - if not statusfolder.isnewfolder(): - # Delete local copies of remote messages. This way, - # if a message's flag is modified locally but it has been - # deleted remotely, we'll delete it locally. Otherwise, we - # try to modify a deleted message's flags! This step - # need only be taken if a statusfolder is present; otherwise, - # there is no action taken *to* the remote repository. - - remotefolder.syncmessagesto_delete(localfolder, [localfolder, - statusfolder]) - ui.syncingmessages(localrepos, localfolder, remoterepos, remotefolder) - localfolder.syncmessagesto(statusfolder, [remotefolder, statusfolder]) - - # Synchronize remote changes. - ui.syncingmessages(remoterepos, remotefolder, localrepos, localfolder) - remotefolder.syncmessagesto(localfolder) - - # Make sure the status folder is up-to-date. - ui.syncingmessages(localrepos, localfolder, statusrepos, statusfolder) - localfolder.syncmessagesto(statusfolder) - statusfolder.save() - - -def syncitall(): - global mailboxes - mailboxes = [] # Reset. - threads = [] - for accountname in accounts: - thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT', - target = syncaccount, - name = "Account sync %s" % accountname, - args = (accountname,)) - thread.setDaemon(1) - thread.start() - threads.append(thread) - # Wait for the threads to finish. - threadutil.threadsreset(threads) - mbnames.genmbnames(config, localeval, mailboxes) - -def sync_with_timer(): - currentThread().setExitMessage('SYNC_WITH_TIMER_TERMINATE') - syncitall() - if config.has_option('general', 'autorefresh'): - refreshperiod = config.getint('general', 'autorefresh') * 60 - while 1: - # Set up keep-alives. - kaevents = {} - kathreads = {} - for accountname in accounts: - if config.has_option(accountname, 'holdconnectionopen') and \ - config.getboolean(accountname, 'holdconnectionopen') and \ - config.has_option(accountname, 'keepalive'): - event = Event() - kaevents[accountname] = event - thread = ExitNotifyThread(target = servers[accountname].keepalive, - name = "Keep alive " + accountname, - args = (config.getint(accountname, 'keepalive'), event)) - thread.setDaemon(1) - thread.start() - kathreads[accountname] = thread - if ui.sleep(refreshperiod) == 2: - # Cancel keep-alives, but don't bother terminating threads - for event in kaevents.values(): - event.set() - break - else: - # Cancel keep-alives and wait for threads to terminate. - for event in kaevents.values(): - event.set() - for thread in kathreads.values(): - thread.join() - syncitall() - -def threadexited(thread): - if thread.getExitCause() == 'EXCEPTION': - if isinstance(thread.getExitException(), SystemExit): - # Bring a SystemExit into the main thread. - # Do not send it back to UI layer right now. - # Maybe later send it to ui.terminate? - raise SystemExit - ui.threadException(thread) # Expected to terminate - sys.exit(100) # Just in case... - os._exit(100) - elif thread.getExitMessage() == 'SYNC_WITH_TIMER_TERMINATE': - ui.terminate() - # Just in case... - sys.exit(100) - os._exit(100) - else: - ui.threadExited(thread) - -threadutil.initexitnotify() -t = ExitNotifyThread(target=sync_with_timer, - name='Sync Runner') -t.setDaemon(1) -t.start() -try: - threadutil.exitnotifymonitorloop(threadexited) -except SystemExit: - raise -except: - ui.mainException() # Also expected to terminate. +from offlineimap import init +init.startup('3.99.0') diff --git a/offlineimap/head/offlineimap/init.py b/offlineimap/head/offlineimap/init.py index 4352f34..485811a 100644 --- a/offlineimap/head/offlineimap/init.py +++ b/offlineimap/head/offlineimap/init.py @@ -25,8 +25,8 @@ from ConfigParser import ConfigParser from threading import * from getopt import getopt -def startup(revno): - assert revno == version.revno, "Revision of main program (%d) does not match that of library (%d). Please double-check your PYTHONPATH and installation locations." % (revno, version.revno) +def startup(versionno): + assert versionno == version.versionstr, "Revision of main program (%d) does not match that of library (%d). Please double-check your PYTHONPATH and installation locations." % (revno, version.revno) options = {} if '--help' in sys.argv[1:]: sys.stdout.write(version.cmdhelp + "\n") diff --git a/offlineimap/head/offlineimap/version.py b/offlineimap/head/offlineimap/version.py index 0062423..cfe813d 100644 --- a/offlineimap/head/offlineimap/version.py +++ b/offlineimap/head/offlineimap/version.py @@ -1,8 +1,8 @@ productname = 'OfflineIMAP' -versionstr = "3.2.8" -revno = long('$Rev: 252 $'[6:-2]) +versionstr = "3.99.0" +revno = long('$Rev: 262 $'[6:-2]) revstr = "Rev %d" % revno -datestr = '$Date: 2002-09-30 10:48:45 -0500 (Mon, 30 Sep 2002) $' +datestr = '$Date: 2002-10-07 11:30:35 -0500 (Mon, 07 Oct 2002) $' versionlist = versionstr.split(".") major = versionlist[0]