]> code.delx.au - offlineimap/blobdiff - offlineimap/accounts.py
New option to only work with subscribed folders
[offlineimap] / offlineimap / accounts.py
index b0f51dc3d4c69e48ddc6a4199b687bdbe8d6e322..36a7665bcfdadb3cfa6dca7d0f7f70ac039804ca 100644 (file)
@@ -1,8 +1,6 @@
 # Copyright (C) 2003 John Goerzen
 # <jgoerzen@complete.org>
 #
-# Portions Copyright (C) 2007 David Favro <offlineimap@meta-dynamic.com>
-#
 #    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
@@ -23,6 +21,7 @@ from offlineimap.ui import UIBase
 from offlineimap.threadutil import InstanceLimitedThread, ExitNotifyThread
 from threading import Event
 import os
+from subprocess import Popen, PIPE
 
 def getaccountlist(customconfig):
     return customconfig.getsectionlist('Account')
@@ -47,6 +46,7 @@ class Account(CustomConfig.ConfigHelperMixin):
         self.localeval = config.getlocaleval()
         self.ui = UIBase.getglobalui()
         self.refreshperiod = self.getconffloat('autorefresh', 0.0)
+        self.quicknum = 0
         if self.refreshperiod == 0.0:
             self.refreshperiod = None
 
@@ -84,16 +84,10 @@ class Account(CustomConfig.ConfigHelperMixin):
         
         refreshperiod = int(self.refreshperiod * 60)
         sleepresult = self.ui.sleep(refreshperiod)
-        if sleepresult == 2:
-            # Cancel keep-alive, but don't bother terminating threads
-            for item in kaobjs:
-                item.stopkeepalive(abrupt = 1)
-            return sleepresult
-        else:
-            # Cancel keep-alive and wait for thread to terminate.
-            for item in kaobjs:
-                item.stopkeepalive(abrupt = 0)
-            return sleepresult
+        # Cancel keepalive
+        for item in kaobjs:
+            item.stopkeepalive()
+        return sleepresult
             
 class AccountSynchronizationMixin:
     def syncrunner(self):
@@ -127,12 +121,29 @@ class AccountSynchronizationMixin:
     def sync(self):
         # We don't need an account lock because syncitall() goes through
         # each account once, then waits for all to finish.
+
+        hook = self.getconf('presynchook', '')
+        self.callhook(hook)
+
+        quickconfig = self.getconfint('quick', 0)
+        if quickconfig < 0:
+            quick = True
+        elif quickconfig > 0:
+            if self.quicknum == 0 or self.quicknum > quickconfig:
+                self.quicknum = 1
+                quick = False
+            else:
+                self.quicknum = self.quicknum + 1
+                quick = True
+        else:
+            quick = False
+
         try:
             remoterepos = self.remoterepos
             localrepos = self.localrepos
             statusrepos = self.statusrepos
             self.ui.syncfolders(remoterepos, localrepos)
-            remoterepos.syncfoldersto(localrepos)
+            remoterepos.syncfoldersto(localrepos, [statusrepos])
 
             folderthreads = []
             for remotefolder in remoterepos.getfolders():
@@ -142,22 +153,41 @@ class AccountSynchronizationMixin:
                     name = "Folder sync %s[%s]" % \
                     (self.name, remotefolder.getvisiblename()),
                     args = (self.name, remoterepos, remotefolder, localrepos,
-                            statusrepos))
+                            statusrepos, quick))
                 thread.setDaemon(1)
                 thread.start()
                 folderthreads.append(thread)
             threadutil.threadsreset(folderthreads)
             mbnames.write()
+            localrepos.forgetfolders()
+            remoterepos.forgetfolders()
             localrepos.holdordropconnections()
             remoterepos.holdordropconnections()
         finally:
             pass
+
+        hook = self.getconf('postsynchook', '')
+        self.callhook(hook)
+
+    def callhook(self, cmd):
+        if not cmd:
+            return
+        try:
+            self.ui.callhook("Calling hook: " + cmd)
+            p = Popen(cmd, shell=True,
+                      stdin=PIPE, stdout=PIPE, stderr=PIPE,
+                      close_fds=True)
+            r = p.communicate()
+            self.ui.callhook("Hook stdout: %s\nHook stderr:%s\n" % r)
+            self.ui.callhook("Hook return code: %d" % p.returncode)
+        except:
+            self.ui.warn("Exception occured while calling hook")
     
 class SyncableAccount(Account, AccountSynchronizationMixin):
     pass
 
 def syncfolder(accountname, remoterepos, remotefolder, localrepos,
-               statusrepos):
+               statusrepos, quick):
     global mailboxes
     ui = UIBase.getglobalui()
     ui.registerthread(accountname)
@@ -167,12 +197,6 @@ def syncfolder(accountname, remoterepos, remotefolder, localrepos,
                             replace(remoterepos.getsep(), localrepos.getsep()))
     # Write the mailboxes
     mbnames.add(accountname, 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().\
@@ -185,6 +209,19 @@ def syncfolder(accountname, remoterepos, remotefolder, localrepos,
         
     statusfolder.cachemessagelist()
 
+    if quick:
+        if not localfolder.quickchanged(statusfolder) \
+               and not remotefolder.quickchanged(statusfolder):
+            ui.skippingfolder(remotefolder)
+            localrepos.restore_atime()
+            return
+
+    # Load local folder
+    ui.syncingfolder(remoterepos, remotefolder, localrepos, localfolder)
+    ui.loadmessagelist(localrepos, localfolder)
+    localfolder.cachemessagelist()
+    ui.messagelistloaded(localrepos, localfolder, len(localfolder.getmessagelist().keys()))
+
     # 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