Raw File
check-for-update
#!/usr/bin/env python

import os
import sys
import popen2
import time
import tempfile
import urllib
import stat
from systemArgs import systemArgs
from systemArgs import ErrorcodeException
from ConfigParser import ConfigParser

(True, False) = (1==1, 0==1)

class Checker:
    def __init__(self, internal):
        self.internal = internal
        self.lockfile = os.path.join(internal, 'lock')
        self.last_check = os.path.join(internal, '.last_check')
        self.load_config()

    def load_config(self):    
        self.config = ConfigParser()
        configfile = open((os.path.join(self.internal, "config")))
        self.config.readfp(configfile)

    def check_update(self):
        check_update = self.config.getint("source", "check_update")
        if check_update < 0:
            # Don't check at all
            return
        try:
            last_checked = os.stat(self.last_check)[stat.ST_MTIME]
        except OSError:
            last_checked = 0 
        # Is it more than check_update minutes?
        if (time.time() - last_checked) > check_update * 60:
            self.check_server()
            # BUG: Naive - even failed checks count as last_check
            open(self.last_check, "w")

    def lock(self):
       # is there some old lock?
       try:
           last_locked = os.stat(self.lockfile)[stat.ST_MTIME]
           if (time.time() - last_locked) > 3600*24: # 1 day
               os.unlink(self.lockfile)
       except OSError:
           # the file might not exist or disappear before unlink 
           pass    
       try:
           os.open(self.lockfile, os.O_CREAT|os.O_EXCL)
           return True
       except OSError:
           return False   
    
    def unlock(self):
        os.unlink(self.lockfile)       
   
    def new_version(self, urlpath, localfile):     
        # Download dotfiles archive
        url = self.config.get("source", "url")

        try:
            server_date = urllib.urlopen(url + urlpath).readline()
        except:
            return False

        my_date = open(localfile).readline()

        # BUG: Stops working in year 2100               
        # MUST be a valid date =)
        if server_date[:2] == "20" and server_date > my_date:
           return True

        return False   

    def check_server(self):
        # First - check if forgetrc it self has # been updated
        if self.new_version('forgetrc.version',
                os.path.join(self.internal, 'forgetrc.version')):
           if not self.lock():
               # Somebody else is fucking up
               print "Should upgrade forgetrc, but lock file exists", self.lockfile
               return
           try:
               print "Upgrading forgetrc"
               program = os.path.join(self.internal, "update-forgetrc")
               # and doing so without output
               try:
                    systemArgs(program, joinStdErr=1)
               except ErrorcodeException, e:
                   print e[1]
               # Don't do anything more here, the new version is taking over
           finally:    
               self.unlock()
           # Don't do anything more, forgetrc will take care    
           return    

        home = os.getenv("HOME")   
        if self.new_version('dotfiles.version',
                            os.path.join(home, '.dotfiles.version')):
           if not self.lock():
               # Somebody else is fucking up
               print "Should upgrade dotfiles, but lock exists"
               return
           try:                  
               print "Upgrading dotfiles"
               program = os.path.join(self.internal, "update-dotfiles")
               # and doing so without output
               try:
                   systemArgs(program, joinStdErr=1)
               except ErrorcodeException, e:
                   print e[1]
           finally:    
               self.unlock()
        
if __name__ == "__main__":
    if sys.argv[1:]:
        help = sys.argv[1]
        if help in "-h --help".split():
            print "Usage: %s" % sys.argv[0]
            print "Downloads new dotfiles and installs them"
            print "If destdir is not given, installs to $HOME"
            sys.exit()
        if sys.argv[1] in "-d --daemon".split():
            if os.fork():
              # We are not the child, so die and make the
              # children an orphan, ie. daemon
              # Works with sys.exit as well, magically enough.., but
              # we'll do it proper with _exit
              # sys.exit()
              os._exit(0)

            # Still here? Then you are the lucky child.
            sys.stdin = open("/dev/null", "r")
            sys.stdout = open("/dev/null", "a")
            sys.stderr = open("/dev/null", "a")
#            for file in (sys.stdin, sys.stderr, sys.stdout):
#                os.close(file.fileno())
#                file.close()        

    internal=os.path.abspath(os.path.dirname(sys.argv[0]))
    checker = Checker(internal)
    checker.check_update()

back to top