From 4f082dfce96d7b1100046003907f3e84eaec85b4 Mon Sep 17 00:00:00 2001 From: Marcus Stoegbauer Date: Sat, 12 Jan 2013 23:21:20 +0000 Subject: [PATCH] Erste feature-komplette Alpha --- Tools.py | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ userconfig.py | 143 +++++++++++++++--------------------------------- 2 files changed, 189 insertions(+), 101 deletions(-) create mode 100644 Tools.py diff --git a/Tools.py b/Tools.py new file mode 100644 index 0000000..f71ffee --- /dev/null +++ b/Tools.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# encoding: utf-8 +# $Id$ +# $URL$ + +""" +Tools.py + +Created by Marcus Stoegbauer on 2013-01-12. +Copyright (c) 2013 __MyCompanyName__. All rights reserved. +""" + +import sys +import os +import cfgfile +import filecmp +import re +import time +import shutil + +class Debug(object): + verbose = 0 + + def __init__(self, verbose=0): + self.setverbose(verbose) + # def __init__ + + def setverbose(self, verbose): + """docstring for setverbose""" + self.verbose = verbose + # def setverbose + + def debug(self, out, level=0): + """docstring for debug""" + if self.verbose: + if level > 0: + print "*"*level,out + else: + print out + # if verbose + # def debug +# class Debug + +def error(out): + """Print error on stderr""" + print >> sys.stderr, str(out)+"\n" +# def error + +def getConfig(filename): + """reads filename as config, checks for DEST parameter and returns cfgfile object""" + try: + ret = cfgfile.Conf(filename) + except: + error("Error reading config file %s" % filename) + return False + # try + + # check for DEST parameter + if not ret.check("Main", "DEST"): + error("No DEST in config file %s" % filename) + return False + # if no DEST + + # replace $HOME with real home directory + if ret.get("Main", "DEST") == "$HOME": + ret.set("Main", "DEST", os.environ['HOME']) + # if $HOME + + # make sure DEST ends with / + if not ret.get("Main", "DEST").endswith("/"): + ret.set("Main", "DEST", ret.get("Main", "DEST")+"/") + # if not / + + return ret +# def getConfig + +def diff(destfile, tempfile, commentstring, debug): + """diff destfile and tempfile, returns True if files differ, False if they are the same""" + # FIXME: filter out comments? + debug.debug("Diffing %s and %s" % (destfile, tempfile)) + if not os.path.isfile(destfile): + debug.debug("Destfile %s does not exist, returning True." % destfile) + # destfile does not exist -> copy tempfile over + return True + # if not destfile + if not os.path.isfile(tempfile): + # tempfile does not exist, this should never happen + error("Temporary file %s does not exist, this should not happen." % tempfile) + sys.exit(1) + # if not tempfile + return not filecmp.cmp(tempfile, destfile) + +# def diff + +def userConfigGenerated(filename, cfg): + """returns True if filename has been generated by userconfig, False else""" + + if not os.path.isfile(filename): + # filename does not exist, so it was not generated by userconfig + return False + # if not filename + + if not cfg.check("Main","STAMP"): + # no STAMP in userconfig.cfg, so no way to check if file was generated by userconfig + return False + # no STAMP + + fp = open(filename, "r") + + for line in fp: + if re.search(re.escape(cfg.get("Main","STAMP")), line): + return True + # if search + # for line + return False +# def userConfigGenerated + +def backupFile(filename, debug): + """make backup of filename, returns True if backup is successful, False else""" + if os.path.isfile(filename): + backupname = filename+".userconfig."+time.strftime("%F") + testbackupname = backupname + counter = 0 + while os.path.isfile(testbackupname): + counter+=1 + testbackupname=backupname+"."+str(counter) + # while + debug.debug("Renaming %s to %s" % (filename, testbackupname)) + os.rename(filename, testbackupname) + return True + # if filename + return False +# def backupFile + +def copyFile(sourcefile, destfile, debug): + """copy sourcefile to destfile, returns True if successful, False else""" + + if os.path.isfile(sourcefile): + # sourcefile exists + if os.access(destfile, os.W_OK): + debug.debug("Copying %s to %s" % (sourcefile, destfile)) + shutil.copy(sourcefile, destfile) + return True + # destfile is writable + # if write ok + return False +# def copyFile diff --git a/userconfig.py b/userconfig.py index 8e4e77a..5aa994c 100755 --- a/userconfig.py +++ b/userconfig.py @@ -19,66 +19,25 @@ import getopt # import cfgfile from checks import checks +import Tools + +debug = Tools.Debug() classchecks = checks() cfg = cfgfile.Conf() -verbose = 0 hostclasses = classchecks.__classesForHost__() class Usage(Exception): def __init__(self, msg): self.msg = msg - - -help_message = """ + # def __init__ + help_message = """ -h help -d debug -c userconfig.cfg config file """ - -def debug(out, level=0): - """docstring for debug""" - if verbose: - if level > 0: - print "*"*level,out - else: - print out - # if verbose -# def debug - -def error(out): - """Print error on stderr""" - print >> sys.stderr, str(out)+"\n" -# def error - -def getConfig(filename): - """reads filename as config, checks for DEST parameter and returns cfgfile object""" - try: - ret = cfgfile.Conf(filename) - except: - error("Error reading config file %s" % filename) - return False - # try - - # check for DEST parameter - if not ret.check("Main", "DEST"): - error("No DEST in config file %s" % filename) - return False - # if no DEST - - # replace $HOME with real home directory - if ret.get("Main", "DEST") == "$HOME": - ret.set("Main", "DEST", os.environ['HOME']) - # if $HOME - - # make sure DEST ends with / - if not ret.get("Main", "DEST").endswith("/"): - ret.set("Main", "DEST", ret.get("Main", "DEST")+"/") - # if not / - - return ret -# def getConfig +# class Usage def workconf(directory, depth=2): """walks through directory, collecting all filenames, returns list of all filenames""" @@ -91,7 +50,7 @@ def workconf(directory, depth=2): workconf(name, depth+1) # if dir ret.append(name) - debug("workconf: found file %s" % name, depth) + debug.debug("workconf: found file %s" % name, depth) # for d return ret # def workconf @@ -101,19 +60,19 @@ def workdir(directory): then collect all filenames within this directory and return a dict of all files for this directory """ - debug("===============================", 1) + debug.debug("===============================", 1) # skip directory if no CONFIGFILE present if not os.path.isfile(directory+"/"+cfg.get("Main", "CONFIGFILE")): - debug("No %s in %s, skipping." % (cfg.get("Main", "CONFIGFILE"), directory), 1) - return {} + debug.debug("No %s in %s, skipping." % (cfg.get("Main", "CONFIGFILE"), directory), 1) + return ({},{}) # if not DEST # get config file for directory - dirConfig = getConfig(directory+"/"+cfg.get("Main", "CONFIGFILE")) + dirConfig = Tools.getConfig(directory+"/"+cfg.get("Main", "CONFIGFILE")) if not dirConfig: - debug("Cannot read %s in %s, skipping." % (cfg.get("Main", "CONFIGFILE"), directory), 1) - return {} + debug.debug("Cannot read %s in %s, skipping." % (cfg.get("Main", "CONFIGFILE"), directory), 1) + return ({},{}) # if not dirConfig destdir = dirConfig.get("Main","DEST") @@ -133,7 +92,7 @@ def workdir(directory): # if class directory exists if os.path.isdir(classdir): - debug("workdir: %s" % classdir, 1) + debug.debug("workdir: %s" % classdir, 1) # get list of files within this class directory tempfiles = workconf(classdir) @@ -148,9 +107,9 @@ def workdir(directory): # if classdir # for hostclasses - debug("workdir: %s, Files: %s" % (directory, str(destfiles))) - debug("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", 1) - return destfiles + debug.debug("workdir: %s, Files: %s" % (directory, str(destfiles))) + debug.debug("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", 1) + return (destfiles, dirConfig) # def work def buildFile(classfiles, destfile): @@ -175,7 +134,7 @@ def buildFile(classfiles, destfile): try: fp = os.fdopen(tempfd, "w") except: - error("Cannot write to temporary file %s" % tempfilename) + Tools.error("Cannot write to temporary file %s" % tempfilename) os.remove(tempfilename) return False # try @@ -189,52 +148,34 @@ def buildFile(classfiles, destfile): return tempfilename # def buildFile -def diff(fileA, fileB): - """diff fileA and fileB, returns True if files differ, False if they are the same""" - # FIXME: write - # FIXME: filter out comments? - # FIXME: COMMENTSTRING in config? - return False -# def diff - -def userConfigGenerated(filename): - """returns True if filename has been generated by userconfig, False else""" - # FIXME: write - return True -# def userConfigGenerated - -def backupFile(filename): - """make backup of filename, returns True if backup is successful, False else""" - # FIXME: write - return True -# def backupFile - -def copyFile(sourcefile, destfile): - """copy sourcefile to destfile, returns True if successful, False else""" - return True -# def copyFile - -def processAllFiles(destfiles): +def processAllFiles(destfiles, dirConfig): """processes all files in destfiles, generate files from classes, compare and copy if necessary""" for df in destfiles.keys(): # assemble file to tmp tempfilename = buildFile(destfiles[df], df) if not tempfilename: - debug("Error while creating temp file for %s, skipping." % df) + debug.debug("Error while creating temp file for %s, skipping." % df) continue # if not tempfilename + commentstring = "" + if dirConfig.check("Main", "COMMENSTRING"): + commentstring = dirConfig.get("Main", "COMMENTSTRING") + # if COMMENTSTRNIG + # diff assembled file and config file - if diff(df, tempfilename): - if not userConfigGenerated(df): + if Tools.diff(df, tempfilename, commentstring, debug): + debug.debug("%s changed." % df) + if not Tools.userConfigGenerated(df, cfg): + debug.debug("%s not generated by userconfig, backing up." % df) # file not generated from userconfig -> back up - backupFile(df) + Tools.backupFile(df, debug) # if not userConfigGenerated # copy tmp file to real location - copyFile(tempfilename, df) - # remove tmp - os.remove(tempfilename) + Tools.copyFile(tempfilename, df, debug) # if diff + # remove tmp + os.remove(tempfilename) # for df # def buildAllFiles @@ -251,28 +192,28 @@ def main(): for option, value in opts: if option == "-v": - verbose = 1 + debug.setverbose(1) if option in ("-h", "--help"): raise Usage(help_message) - if option in ("-d", "--debug"): + if option in ("-d", "--debug.debug"): pass if option in ("-c", "--config"): configfile = value # if # for option, value except Usage, err: - error(sys.argv[0].split("/")[-1] + ": " + str(err.msg)) - error("\t for help use --help") + Tools.error(sys.argv[0].split("/")[-1] + ": " + str(err.msg)) + Tools.error("\t for help use --help") return 2 # try if configfile == "": - error( "No config file specified.") + Tools.error( "No config file specified.") return 2 # if configfile cfg.setfilename(configfile) - debug("Classes for host: %s" % hostclasses) + debug.debug("Classes for host: %s" % hostclasses) configdir = cfg.get("Main", "CONFIGDIR") for d in os.listdir(configdir): name = configdir+d @@ -283,9 +224,9 @@ def main(): elif os.path.isfile(name+"/.ignore"): continue else: - debug("main: %s" % name) - destfiles = workdir(name) - processAllFiles(destfiles) + debug.debug("main: %s" % name) + (destfiles, dirConfig) = workdir(name) + processAllFiles(destfiles, dirConfig) # if # for d # def main