Ejemplo n.º 1
0
def syncaccount(threads, config, accountname):
    account = SyncableAccount(config, accountname)
    thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT',
                                   target = account.syncrunner,
                                   name = "Account sync %s" % accountname)
    thread.setDaemon(1)
    thread.start()
    threads.add(thread)
Ejemplo n.º 2
0
    def sync(self, siglistener):
        # 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, [statusrepos])

            siglistener.addfolders(remoterepos.getfolders(), bool(self.refreshperiod), quick)

            while True:
                folderthreads = []
                for remotefolder, quick in siglistener.queuedfolders():
                    thread = InstanceLimitedThread(\
                        instancename = 'FOLDER_' + self.remoterepos.getname(),
                        target = syncfolder,
                        name = "Folder sync %s[%s]" % \
                        (self.name, remotefolder.getvisiblename()),
                        args = (self.name, remoterepos, remotefolder, localrepos,
                                statusrepos, quick))
                    thread.setDaemon(1)
                    thread.start()
                    folderthreads.append(thread)
                threadutil.threadsreset(folderthreads)
                if siglistener.clearfolders():
                    break
            mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()
        finally:
            pass

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 3
0
def syncaccount(threads, config, accountname, siglisteners):
    account = SyncableAccount(config, accountname)
    siglistener = SigListener()
    thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT',
                                   target = account.syncrunner,
                                   name = "Account sync %s" % accountname,
                                   kwargs = {'siglistener': siglistener} )
    # the Sync Runner thread is the only one that will mutate siglisteners
    siglisteners.append(siglistener)
    thread.setDaemon(1)
    thread.start()
    threads.add(thread)
Ejemplo n.º 4
0
    def syncmessagesto_copy(self, dest, applyto):
        """Pass 2 of folder synchronization.

        Look for messages present in self but not in dest.  If any, add
        them to dest."""
        threads = []

        dest_messagelist = dest.getmessagelist()
        for uid in self.getmessagelist().keys():
            if uid < 0:  # Ignore messages that pass 1 missed.
                continue
            if not uid in dest_messagelist:
                if self.suggeststhreads():
                    self.waitforthread()
                    thread = InstanceLimitedThread(\
                        self.getcopyinstancelimit(),
                        target = self.copymessageto,
                        name = "Copy message %d from %s" % (uid,
                                                            self.getvisiblename()),
                        args = (uid, applyto))
                    thread.setDaemon(1)
                    thread.start()
                    threads.append(thread)
                else:
                    self.copymessageto(uid, applyto, register=0)
        for thread in threads:
            thread.join()
Ejemplo n.º 5
0
    def syncmessagesto_neguid(self, dest, applyto):
        """Pass 1 of folder synchronization.

        Look for messages in self with a negative uid.  These are messages in
        Maildirs that were not added by us.  Try to add them to the dests,
        and once that succeeds, get the UID, add it to the others for real,
        add it to local for real, and delete the fake one."""

        uidlist = [uid for uid in self.getmessagelist().keys() if uid < 0]
        threads = []

        usethread = None
        if applyto != None:
            usethread = applyto[0]

        for uid in uidlist:
            if usethread and usethread.suggeststhreads():
                usethread.waitforthread()
                thread = InstanceLimitedThread(\
                    usethread.getcopyinstancelimit(),
                    target = self.syncmessagesto_neguid_msg,
                    name = "New msg sync from %s" % self.getvisiblename(),
                    args = (uid, dest, applyto))
                thread.setDaemon(1)
                thread.start()
                threads.append(thread)
            else:
                self.syncmessagesto_neguid_msg(uid, dest, applyto, register=0)
        for thread in threads:
            thread.join()
Ejemplo n.º 6
0
    def syncmessagesto_copy(self, dest, applyto):
        """Pass 2 of folder synchronization.

        Look for messages present in self but not in dest.  If any, add
        them to dest."""
        threads = []
        
	dest_messagelist = dest.getmessagelist()
        for uid in self.getmessagelist().keys():
            if uid < 0:                 # Ignore messages that pass 1 missed.
                continue
            if not uid in dest_messagelist:
                if self.suggeststhreads():
                    self.waitforthread()
                    thread = InstanceLimitedThread(\
                        self.getcopyinstancelimit(),
                        target = self.copymessageto,
                        name = "Copy message %d from %s" % (uid,
                                                            self.getvisiblename()),
                        args = (uid, applyto))
                    thread.setDaemon(1)
                    thread.start()
                    threads.append(thread)
                else:
                    self.copymessageto(uid, applyto, register = 0)
        for thread in threads:
            thread.join()
Ejemplo n.º 7
0
    def syncmessagesto_neguid(self, dest, applyto):
        """Pass 1 of folder synchronization.

        Look for messages in self with a negative uid.  These are messages in
        Maildirs that were not added by us.  Try to add them to the dests,
        and once that succeeds, get the UID, add it to the others for real,
        add it to local for real, and delete the fake one."""

        uidlist = [uid for uid in self.getmessagelist().keys() if uid < 0]
        threads = []

        usethread = None
        if applyto != None:
            usethread = applyto[0]
        
        for uid in uidlist:
            if usethread and usethread.suggeststhreads():
                usethread.waitforthread()
                thread = InstanceLimitedThread(\
                    usethread.getcopyinstancelimit(),
                    target = self.syncmessagesto_neguid_msg,
                    name = "New msg sync from %s" % self.getvisiblename(),
                    args = (uid, dest, applyto))
                thread.setDaemon(1)
                thread.start()
                threads.append(thread)
            else:
                self.syncmessagesto_neguid_msg(uid, dest, applyto, register = 0)
        for thread in threads:
            thread.join()
Ejemplo n.º 8
0
def syncaccount(threads, config, accountname):
    account = SyncableAccount(config, accountname)
    thread = InstanceLimitedThread(instancename='ACCOUNTLIMIT',
                                   target=account.syncrunner,
                                   name="Account sync %s" % accountname)
    thread.setDaemon(True)
    thread.start()
    threads.add(thread)
Ejemplo n.º 9
0
    def sync(self, siglistener):
        # 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, [statusrepos])

            siglistener.addfolders(remoterepos.getfolders(),
                                   bool(self.refreshperiod), quick)

            while True:
                folderthreads = []
                for remotefolder, quick in siglistener.queuedfolders():
                    thread = InstanceLimitedThread(\
                        instancename = 'FOLDER_' + self.remoterepos.getname(),
                        target = syncfolder,
                        name = "Folder sync %s[%s]" % \
                        (self.name, remotefolder.getvisiblename()),
                        args = (self.name, remoterepos, remotefolder, localrepos,
                                statusrepos, quick))
                    thread.setDaemon(1)
                    thread.start()
                    folderthreads.append(thread)
                threadutil.threadsreset(folderthreads)
                if siglistener.clearfolders():
                    break
            mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()
        finally:
            pass

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 10
0
def syncaccount(threads, config, accountname, siglisteners):
    account = SyncableAccount(config, accountname)
    siglistener = SigListener()
    thread = InstanceLimitedThread(instancename='ACCOUNTLIMIT',
                                   target=account.syncrunner,
                                   name="Account sync %s" % accountname,
                                   kwargs={'siglistener': siglistener})
    # the Sync Runner thread is the only one that will mutate siglisteners
    siglisteners.append(siglistener)
    thread.setDaemon(1)
    thread.start()
    threads.add(thread)
Ejemplo n.º 11
0
    def sync(self):
        """Synchronize the account once, then return

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function.
        """
        folderthreads = []

        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

            # init repos with list of folders, so we have them (and the
            # folder delimiter etc)
            remoterepos.getfolders()
            localrepos.getfolders()

            remoterepos.sync_folder_structure(localrepos, statusrepos)
            # replicate the folderstructure between REMOTE to LOCAL
            if not localrepos.getconfboolean('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)

            # iterate through all folders on the remote repo and sync
            for remotefolder in remoterepos.getfolders():
                # check for CTRL-C or SIGTERM
                if Account.abort_NOW_signal.is_set(): break

                if not remotefolder.sync_this:
                    self.ui.debug('', "Not syncing filtered folder '%s'"
                                  "[%s]" % (remotefolder, remoterepos))
                    continue # Ignore filtered folder
                localfolder = self.get_local_folder(remotefolder)
                if not localfolder.sync_this:
                    self.ui.debug('', "Not syncing filtered folder '%s'"
                                 "[%s]" % (localfolder, localfolder.repository))
                    continue # Ignore filtered folder
                thread = InstanceLimitedThread(\
                    instancename = 'FOLDER_' + self.remoterepos.getname(),
                    target = syncfolder,
                    name = "Folder %s [acc: %s]" % (remotefolder, self),
                    args = (self, remotefolder, quick))
                thread.start()
                folderthreads.append(thread)
            # wait for all threads to finish
            for thr in folderthreads:
                thr.join()
            # Write out mailbox names if required and not in dry-run mode
            if not self.dryrun:
                mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            #error while syncing. Drop all connections that we have, they
            #might be bogus by now (e.g. after suspend)
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # sync went fine. Hold or drop depending on config
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 12
0
    def __sync(self):
        """Synchronize the account once, then return.

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function."""

        folderthreads = []

        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

            # Init repos with list of folders, so we have them (and the
            # folder delimiter etc).
            remoterepos.getfolders()
            localrepos.getfolders()

            remoterepos.sync_folder_structure(localrepos, statusrepos)
            # Replicate the folderstructure between REMOTE to LOCAL.
            if not localrepos.getconfboolean('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)

            # Iterate through all folders on the remote repo and sync.
            for remotefolder in remoterepos.getfolders():
                # Check for CTRL-C or SIGTERM.
                if Account.abort_NOW_signal.is_set():
                    break

                if not remotefolder.sync_this:
                    self.ui.debug('', "Not syncing filtered folder '%s'"
                                  "[%s]"% (remotefolder, remoterepos))
                    continue # Ignore filtered folder.

                # The remote folder names must not have the local sep char in
                # their names since this would cause troubles while converting
                # the name back (from local to remote).
                sep = localrepos.getsep()
                if (sep != os.path.sep and
                    sep != remoterepos.getsep() and
                    sep in remotefolder.getname()):
                    self.ui.warn('', "Ignoring folder '%s' due to unsupported "
                        "'%s' character serving as local separator."%
                        (remotefolder.getname(), localrepos.getsep()))
                    continue # Ignore unsupported folder name.

                localfolder = self.get_local_folder(remotefolder)
                if not localfolder.sync_this:
                    self.ui.debug('', "Not syncing filtered folder '%s'"
                                 "[%s]"% (localfolder, localfolder.repository))
                    continue # Ignore filtered folder.

                if not globals.options.singlethreading:
                    thread = InstanceLimitedThread(
                        limitNamespace="%s%s"% (
                            FOLDER_NAMESPACE, self.remoterepos.getname()),
                        target=syncfolder,
                        name="Folder %s [acc: %s]"% (
                            remotefolder.getexplainedname(), self),
                        args=(self, remotefolder, quick)
                    )
                    thread.start()
                    folderthreads.append(thread)
                else:
                    syncfolder(self, remotefolder, quick)
            # Wait for all threads to finish.
            for thr in folderthreads:
                thr.join()
            mbnames.writeIntermediateFile(self.name) # Write out mailbox names.
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            # Error while syncing. Drop all connections that we have, they
            # might be bogus by now (e.g. after suspend).
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # Sync went fine. Hold or drop depending on config.
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 13
0
    def __sync(self):
        """Synchronize the account once, then return.

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function."""

        folderthreads = []

        hook = self.getconf('presynchook', '')
        self.callhook(hook)

        if self.utf_8_support and self.remoterepos.getdecodefoldernames():
            raise OfflineImapError(
                "Configuration mismatch in account " +
                "'%s'. " % self.getname() +
                "\nAccount setting 'utf8foldernames' and repository " +
                "setting 'decodefoldernames'\nmay not be used at the " +
                "same time. This account has not been synchronized.\n" +
                "Please check the configuration and documentation.",
                OfflineImapError.ERROR.REPO)

        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:
            startedThread = False
            remoterepos = self.remoterepos
            localrepos = self.localrepos
            statusrepos = self.statusrepos

            # Init repos with list of folders, so we have them (and the
            # folder delimiter etc).
            remoterepos.getfolders()
            localrepos.getfolders()

            remoterepos.sync_folder_structure(localrepos, statusrepos)
            # Replicate the folderstructure between REMOTE to LOCAL.
            if not localrepos.getconfboolean('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)

            # Iterate through all folders on the remote repo and sync.
            for remotefolder in remoterepos.getfolders():
                # Check for CTRL-C or SIGTERM.
                if Account.abort_NOW_signal.is_set():
                    break

                if not remotefolder.sync_this:
                    self.ui.debug(
                        '', "Not syncing filtered folder '%s'"
                        "[%s]" % (remotefolder.getname(), remoterepos))
                    continue  # Ignore filtered folder.

                # The remote folder names must not have the local sep char in
                # their names since this would cause troubles while converting
                # the name back (from local to remote).
                sep = localrepos.getsep()
                if (sep != os.path.sep and sep != remoterepos.getsep()
                        and sep in remotefolder.getname()):
                    self.ui.warn(
                        '', "Ignoring folder '%s' due to unsupported "
                        "'%s' character serving as local separator." %
                        (remotefolder.getname(), localrepos.getsep()))
                    continue  # Ignore unsupported folder name.

                localfolder = self.get_local_folder(remotefolder)
                if not localfolder.sync_this:
                    self.ui.debug(
                        '', "Not syncing filtered folder '%s'"
                        "[%s]" %
                        (localfolder.getname(), localfolder.repository))
                    continue  # Ignore filtered folder.

                if not globals.options.singlethreading:
                    thread = InstanceLimitedThread(
                        limitNamespace="%s%s" %
                        (FOLDER_NAMESPACE, self.remoterepos.getname()),
                        target=syncfolder,
                        name="Folder %s [acc: %s]" %
                        (remotefolder.getexplainedname(), self),
                        args=(self, remotefolder, quick))
                    thread.start()
                    folderthreads.append(thread)
                else:
                    syncfolder(self, remotefolder, quick)
                startedThread = True
            # Wait for all threads to finish.
            for thr in folderthreads:
                thr.join()
            if startedThread is True:
                mbnames.writeIntermediateFile(
                    self.name)  # Write out mailbox names.
            else:
                msg = "Account {}: no folder to sync (folderfilter issue?)".format(
                    self)
                raise OfflineImapError(msg, OfflineImapError.ERROR.REPO)
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            # Error while syncing. Drop all connections that we have, they
            # might be bogus by now (e.g. after suspend).
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # Sync went fine. Hold or drop depending on config.
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 14
0
    def sync(self):
        """Synchronize the account once, then return

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function.
        """
        folderthreads = []

        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

            # init repos with list of folders, so we have them (and the
            # folder delimiter etc)
            remoterepos.getfolders()
            localrepos.getfolders()

            remoterepos.sync_folder_structure(localrepos, statusrepos)
            # replicate the folderstructure between REMOTE to LOCAL
            if not localrepos.getconfboolean('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)

            # iterate through all folders on the remote repo and sync
            for remotefolder in remoterepos.getfolders():
                # check for CTRL-C or SIGTERM
                if Account.abort_NOW_signal.is_set(): break

                if not remotefolder.sync_this:
                    self.ui.debug(
                        '', "Not syncing filtered folder '%s'"
                        "[%s]" % (remotefolder, remoterepos))
                    continue  # Ignore filtered folder
                localfolder = self.get_local_folder(remotefolder)
                if not localfolder.sync_this:
                    self.ui.debug(
                        '', "Not syncing filtered folder '%s'"
                        "[%s]" % (localfolder, localfolder.repository))
                    continue  # Ignore filtered folder
                if not globals.options.singlethreading:
                    thread = InstanceLimitedThread(\
                        instancename = 'FOLDER_' + self.remoterepos.getname(),
                        target = syncfolder,
                        name = "Folder %s [acc: %s]" % (remotefolder, self),
                        args = (self, remotefolder, quick))
                    thread.start()
                    folderthreads.append(thread)
                else:
                    syncfolder(self, remotefolder, quick)
            # wait for all threads to finish
            for thr in folderthreads:
                thr.join()
            # Write out mailbox names if required and not in dry-run mode
            if not self.dryrun:
                mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            #error while syncing. Drop all connections that we have, they
            #might be bogus by now (e.g. after suspend)
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # sync went fine. Hold or drop depending on config
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 15
0
    def sync(self):
        """Synchronize the account once, then return

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function.
        """
        folderthreads = []

        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
            # replicate the folderstructure from REMOTE to LOCAL
            if not localrepos.getconf('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)
                remoterepos.syncfoldersto(localrepos, [statusrepos])

            # iterate through all folders on the remote repo and sync
            for remotefolder in remoterepos.getfolders():
                thread = InstanceLimitedThread(\
                    instancename = 'FOLDER_' + self.remoterepos.getname(),
                    target = syncfolder,
                    name = "Folder sync [%s]" % self,
                    args = (self.name, remoterepos, remotefolder, localrepos,
                            statusrepos, quick))
                thread.setDaemon(1)
                thread.start()
                folderthreads.append(thread)
            # wait for all threads to finish
            for thr in folderthreads:
                thr.join()
            mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            #error while syncing. Drop all connections that we have, they
            #might be bogus by now (e.g. after suspend)
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # sync went fine. Hold or drop depending on config
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)
Ejemplo n.º 16
0
    def sync(self):
        """Synchronize the account once, then return

        Assumes that `self.remoterepos`, `self.localrepos`, and
        `self.statusrepos` has already been populated, so it should only
        be called from the :meth:`syncrunner` function.
        """
        folderthreads = []

        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
            # replicate the folderstructure from REMOTE to LOCAL
            if not localrepos.getconf('readonly', False):
                self.ui.syncfolders(remoterepos, localrepos)
                remoterepos.syncfoldersto(localrepos, [statusrepos])

            # iterate through all folders on the remote repo and sync
            for remotefolder in remoterepos.getfolders():
                thread = InstanceLimitedThread(\
                    instancename = 'FOLDER_' + self.remoterepos.getname(),
                    target = syncfolder,
                    name = "Folder sync [%s]" % self,
                    args = (self.name, remoterepos, remotefolder, localrepos,
                            statusrepos, quick))
                thread.setDaemon(1)
                thread.start()
                folderthreads.append(thread)
            # wait for all threads to finish
            for thr in folderthreads:
                thr.join()
            mbnames.write()
            localrepos.forgetfolders()
            remoterepos.forgetfolders()
        except:
            #error while syncing. Drop all connections that we have, they
            #might be bogus by now (e.g. after suspend)
            localrepos.dropconnections()
            remoterepos.dropconnections()
            raise
        else:
            # sync went fine. Hold or drop depending on config
            localrepos.holdordropconnections()
            remoterepos.holdordropconnections()

        hook = self.getconf('postsynchook', '')
        self.callhook(hook)