pyuserconfig/cli/__init__.py

172 lines
6.7 KiB
Python
Executable File

import sys
import os
import tempfile
import re
import argparse
import time
from userconfig.cfgfile import Conf
from userconfig.tools import Debug
from userconfig.checks import classes_for_host
#FIXME: fill in: from userconfig.tools import ...
class Usage(Exception):
def __init__(self, msg):
self.msg = msg
def workconf(directory, depth=2):
"""walks through directory, collecting all filenames, returns list of all filenames"""
dirs = os.listdir(directory)
ret = []
debug.stdout(" ================ workconf ===============", 1)
debug.stdout(" Finding files in directory %s." % directory, 4)
for d in dirs:
name = directory+"/"+d
if os.path.isdir(name):
workconf(name, depth+1)
if name.endswith(".swp"):
continue
if d == ".svn":
continue
ret.append(name)
debug.stdout(" +++ Found file %s in directory %s" % (name, directory), 4)
debug.stdout(" ================ workconf ===============", 1)
return ret
def build_file(classfiles, destfile, commentstring):
"""open all classfiles, assemble them and write the contents into a tempfile
returns the name of tempfile
:param classfiles:
:param destfile:
:param commentstring:
:return: str
"""
content = []
debug.stdout(" ================ build_file ===============", 1)
if commentstring != "":
debug.stdout(" +++ commentstring found, adding header.", 3)
content.append(commentstring + " " + cfg.get("Main","stamp") + " " + time.strftime("%+") + "\n")
for f in classfiles:
debug.stdout(" +++ Merging %s." % f, 4)
fp = open(f, "r")
filecontent = fp.read()
fp.close()
if commentstring == "":
# look for stamp in content, replace with real stamp
if re.search(re.escape(cfg.get("Main","stampreplace")), filecontent):
debug.stdout(" +++ commentstring empty, replacing stamp in file", 3)
filecontent = re.sub(re.escape(cfg.get("Main","stampreplace")), cfg.get("Main","stamp"), filecontent)
content.append(filecontent)
(tempfd, tempfilename) = tempfile.mkstemp(prefix=os.path.basename(destfile), dir="/tmp")
try:
fp = os.fdopen(tempfd, "w")
except:
Tools.error("Cannot write to temporary file %s" % tempfilename)
os.remove(tempfilename)
return False
debug.stdout(" +++ Writing merged files into tempfile %s." % tempfilename, 3)
for block in content:
fp.write(block)
fp.write("\n")
fp.close()
debug.stdout(" ================ build_file ===============", 1)
return tempfilename
def process_all_files(destfiles, dir_config):
"""processes all files in destfiles, generate files from classes, compare and copy if necessary"""
debug.stdout(" ================ process_all_files ===============", 1)
for df in destfiles.keys():
debug.stdout(" ??? Processing source files for %s." % df, 2)
if not os.path.exists(os.path.dirname(df)):
debug.stdout(" +++ Directory %s does not exist, creating" % os.path.dirname(df), 1)
os.mkdir(os.path.dirname(df))
if not os.path.isdir(os.path.dirname(df)):
debug.stdout(" --- Destination directory %s does not exist, skipping." % os.path.dirname(df), 1)
return False
# assemble file to tmp
commentstring = ""
if dir_config.check("Main", "commentstring"):
commentstring = dir_config.get("Main", "commentstring")
debug.stdout(" +++ Found commentstring %s in %s" % (commentstring, df), 3)
tempfilename = build_file(destfiles[df], df, commentstring)
if not tempfilename:
debug.stdout(" --- Error while creating temp file for %s, skipping." % df, 1)
continue
debug.stdout(" +++ Merged files %s for %s into %s" % (str(destfiles[df]), df, tempfilename), 2)
# diff assembled file and config file
if Tools.diff(df, tempfilename, commentstring, debug):
debug.stdout("File %s has changed" % df, 0)
if not Tools.user_config_generated(df, cfg):
debug.stdout(" +++ %s not generated by userconfig, backing up." % df, 2)
# file not generated from userconfig -> back up
Tools.backup_file(df, debug)
# copy tmp file to real location
debug.stdout("Copy %s to %s." % (tempfilename, df), 0)
Tools.copy_file(tempfilename, df, debug)
# remove tmp
debug.stdout(" +++ Removing temporary file %s." % tempfilename, 2)
os.remove(tempfilename)
debug.stdout(" ================ process_all_files ===============", 1)
classchecks = Checks()
def main():
parser = argparse.ArgumentParser(prog='userconfig',
description='Manages configuration files, usually in the user home directory')
parser.add_argument('-v',
help='Verbosity level (multiple v for higher level)',
dest='verbose', action='count', default=0)
parser.add_argument('-f', '--file',
help='userconfig2.cfg config file',
dest='file', action='store')
cmdline = parser.parse_args()
cfg = Conf(cmdline.file)
debug = Debug()
cfg.set_debug(debug)
cfg.debug(f"Verbose level is {cfg.debug._verbose}", 1)
cfg.debug("================ main ===============", 1)
temp_classes = ""
for h in classes_for_host():
temp_classes=temp_classes + str(h) + ","
cfg.debug("+++ Current host is in classes %s" % temp_classes, 1)
configdir = cfg.get("configdir")
for d in os.listdir(configdir):
name = configdir+"/"+d
cfg.debug("+++ Working in %s" % name, 1)
if not os.path.isdir(name):
cfg.debug("--- %s is not a directory, skipping." % name, 3)
continue
elif d.startswith(".svn") or d.startswith(".git"):
cfg.debug("--- %s is .svn or .git, skipping." % name, 3)
continue
elif os.path.isfile(name+"/.ignore"):
cfg.debug("--- %s contains file .ignore, skipping." % name, 3)
continue
else:
cfg.debug("+++ Processing files in %s" % name, 2)
(destfiles, dirConfig) = workdir(name)
if isinstance(destfiles, dict):
if len(destfiles.keys()) > 0:
cfg.debug("+++ Building %d files: %s" % (len(destfiles.keys()), destfiles.keys()), 3)
process_all_files(destfiles, dirConfig)
else:
cfg.debug("--- No files found for %s, skipping." % name, 1)
if __name__ == '__main__':
main()