2024-03-29 21:48:06 +01:00
|
|
|
import os
|
|
|
|
import argparse
|
|
|
|
from userconfig.cfgfile import Conf
|
2024-03-29 22:36:07 +01:00
|
|
|
from userconfig import Userconfig
|
2024-03-31 22:20:47 +02:00
|
|
|
import sys
|
|
|
|
import subprocess
|
2024-03-29 21:48:06 +01:00
|
|
|
|
2024-03-31 23:28:11 +02:00
|
|
|
|
|
|
|
class Debug:
|
|
|
|
_verbose = 0
|
|
|
|
|
|
|
|
_COLOR_RED = '\033[91m'
|
|
|
|
_COLOR_BLUE = '\33[34m'
|
|
|
|
_COLOR_GREEN = '\33[32m'
|
|
|
|
_COLOR_YELLOW = '\033[93m'
|
|
|
|
_COLOR_END = '\33[0m'
|
|
|
|
|
2024-04-01 00:49:03 +02:00
|
|
|
_FORMAT = {'STANDARD': 'INFO: ',
|
2024-03-31 23:28:11 +02:00
|
|
|
'ERROR': f'{_COLOR_RED}ERROR:{_COLOR_END} ',
|
|
|
|
'NOTICE': f'{_COLOR_BLUE}NOTICE:{_COLOR_END} ',
|
|
|
|
'WARNING': f'{_COLOR_YELLOW}WARNING:{_COLOR_END} ',
|
|
|
|
'SUCCESS': f'{_COLOR_GREEN}SUCCESS:{_COLOR_END} '
|
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self, verbose=0):
|
|
|
|
self.set_verbose(verbose)
|
|
|
|
|
|
|
|
def set_verbose(self, verbose):
|
|
|
|
self._verbose = verbose
|
|
|
|
|
|
|
|
def add_verbose(self):
|
|
|
|
self._verbose += 1
|
|
|
|
|
|
|
|
def get_verbose(self):
|
|
|
|
return self._verbose
|
|
|
|
|
|
|
|
def stdout(self, out, verbose_level=0, category='STANDARD'):
|
2024-04-01 00:49:03 +02:00
|
|
|
spaces = ''
|
|
|
|
if verbose_level > 1:
|
|
|
|
spaces = ' '*(verbose_level-1)
|
|
|
|
|
2024-03-31 23:28:11 +02:00
|
|
|
if self._verbose >= verbose_level:
|
|
|
|
if category in self._FORMAT:
|
2024-04-01 00:49:03 +02:00
|
|
|
print(f'{spaces}{self._FORMAT[category]}{out}')
|
2024-03-31 23:28:11 +02:00
|
|
|
else:
|
2024-04-01 00:49:03 +02:00
|
|
|
print(f'{spaces}[category {category} unknown]:{out}')
|
2024-03-31 23:28:11 +02:00
|
|
|
|
|
|
|
def stderr(self, out, verbose_level=0, category='STANDARD'):
|
|
|
|
if self._verbose >= verbose_level:
|
|
|
|
if category in self._FORMAT:
|
|
|
|
print(f'{self._FORMAT[category]}{out}', file=sys.stderr)
|
|
|
|
else:
|
|
|
|
print(f'[category {category} unknown]:{out}', file=sys.stderr)
|
|
|
|
|
|
|
|
def red(self, out):
|
|
|
|
return f'{self._COLOR_RED}{out}{self._COLOR_END}'
|
|
|
|
|
|
|
|
def green(self, out):
|
|
|
|
return f'{self._COLOR_GREEN}{out}{self._COLOR_END}'
|
|
|
|
|
|
|
|
def blue(self, out):
|
|
|
|
return f'{self._COLOR_BLUE}{out}{self._COLOR_END}'
|
|
|
|
|
|
|
|
def yellow(self, out):
|
|
|
|
return f'{self._COLOR_YELLOW}{out}{self._COLOR_END}'
|
|
|
|
|
2024-03-29 21:48:06 +01:00
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(prog='userconfig',
|
2024-03-29 22:36:07 +01:00
|
|
|
description='Manages configuration files, usually in the user home directory')
|
2024-03-29 21:48:06 +01:00
|
|
|
|
|
|
|
parser.add_argument('-v',
|
2024-03-29 22:36:07 +01:00
|
|
|
help='Verbosity level (multiple v for higher level)',
|
|
|
|
dest='verbose', action='count', default=0)
|
2024-03-29 21:48:06 +01:00
|
|
|
parser.add_argument('-f', '--file',
|
2024-03-29 22:36:07 +01:00
|
|
|
help='userconfig2.cfg config file',
|
|
|
|
dest='file', action='store')
|
2024-03-29 21:48:06 +01:00
|
|
|
cmdline = parser.parse_args()
|
|
|
|
debug = Debug()
|
2024-04-01 01:41:27 +02:00
|
|
|
debug.set_verbose(cmdline.verbose)
|
|
|
|
cfg = Conf(filename=cmdline.file, debug=debug)
|
2024-03-29 22:36:07 +01:00
|
|
|
uc = Userconfig(cfg)
|
2024-03-29 21:48:06 +01:00
|
|
|
|
2024-04-01 00:49:03 +02:00
|
|
|
cfg.debug.stdout(f'Verbose level: {cfg.debug.get_verbose()}', 1)
|
2024-03-31 23:28:11 +02:00
|
|
|
configdir = cfg.get('configdir')
|
2024-03-31 22:20:47 +02:00
|
|
|
# configdir is the root of the userconfig files
|
|
|
|
# Directory structure:
|
|
|
|
# configdir/
|
|
|
|
# |-- userconfig2.conf
|
|
|
|
# |-- package1/
|
|
|
|
# |- package.conf
|
|
|
|
# |- 001_Arch_Linux/
|
|
|
|
# |- file1
|
|
|
|
# |- file2
|
|
|
|
# |- 002_Host_glitters/
|
|
|
|
# |- file1
|
|
|
|
# |- 003_all/
|
|
|
|
# |- file2
|
|
|
|
#
|
|
|
|
# Terminology:
|
|
|
|
# directories below configdir are packages, packages contain directories categorizing for which host/arch they
|
|
|
|
# are fitted, below that are files which are installed at the destination
|
|
|
|
#
|
|
|
|
# directory names in packages:
|
|
|
|
# [Number]_[category]_[value]
|
|
|
|
# Number: can have leading zeros for better sorting in directory structure, will be used for sorting and priority
|
|
|
|
# category: which kind of match we are looking for. currently: Arch for `uname -s`, Host for `hostname -s`
|
2024-03-31 23:28:11 +02:00
|
|
|
# value: optional, if category requires an input value, for example: Arch_Linux
|
2024-03-31 22:20:47 +02:00
|
|
|
# can be empty for example if category is all (no match needed, we want this always to be applied)
|
|
|
|
|
|
|
|
cfg.debug.stdout(f'configdir: {configdir}', 1)
|
|
|
|
for package in os.scandir(configdir):
|
2024-04-01 00:49:03 +02:00
|
|
|
# Skip on non-production files
|
2024-03-31 22:20:47 +02:00
|
|
|
if not package.is_dir():
|
|
|
|
cfg.debug.stdout(f'{package.path} is not a directory, skipping', 2, 'WARNING')
|
2024-03-29 21:48:06 +01:00
|
|
|
continue
|
2024-03-31 22:20:47 +02:00
|
|
|
if package.name in ['.svn', '.git']:
|
|
|
|
cfg.debug.stdout(f'{package.path} is a svn or git data directory, skipping', 2, 'WARNING')
|
2024-04-01 01:41:27 +02:00
|
|
|
continue
|
2024-03-31 22:20:47 +02:00
|
|
|
if os.path.isfile(f'{package.path}/.ignore'):
|
|
|
|
cfg.debug.stdout(f'{package.path} contains .ignore, skipping', 2, 'WARNING')
|
2024-03-29 21:48:06 +01:00
|
|
|
continue
|
2024-04-01 00:49:03 +02:00
|
|
|
# Start processing
|
|
|
|
cfg.debug.stdout(f'Start Package {cfg.debug.green(package.path)}', 1, 'NOTICE')
|
|
|
|
# Get all category directories for package
|
2024-03-31 22:20:47 +02:00
|
|
|
(category_dirs, dir_config) = uc.process_package_dir(package.path)
|
2024-04-01 01:41:27 +02:00
|
|
|
if not category_dirs:
|
|
|
|
cfg.debug.stdout(f'Could not get category_dirs for package {package.name}, skipping package.', 0, 'ERROR')
|
|
|
|
continue
|
|
|
|
if not dir_config:
|
|
|
|
cfg.debug.stdout(f'Could not get dir_config for package {package.name}, skipping package.', 0, 'ERROR')
|
|
|
|
continue
|
2024-03-31 22:20:47 +02:00
|
|
|
cfg.debug.stdout(f'Got categories: {category_dirs}', 2)
|
|
|
|
host_category_dirs = uc.filter_categories(category_dirs)
|
2024-04-01 01:41:27 +02:00
|
|
|
cfg.debug.stdout('Host uses categories: %s' % ", ".join([f'{v[1]}_{v[2]}' for v in host_category_dirs]), 2)
|
2024-03-31 22:20:47 +02:00
|
|
|
file_list = dict()
|
|
|
|
for c in host_category_dirs:
|
|
|
|
file_list = uc.process_category_dir(c, file_list)
|
|
|
|
cfg.debug.stdout(f'Found files: {file_list}', 2)
|
|
|
|
if len(file_list) and os.access(f'{package.path}/install.sh', os.X_OK):
|
|
|
|
cfg.debug.stdout(f'Execute {package.path}/install.sh', 2)
|
|
|
|
subprocess.call([f'{package.path}/install.sh'])
|
|
|
|
for file in file_list:
|
|
|
|
dest = f'{dir_config.get(section="Main", option="dest")}/{file}'
|
2024-04-01 01:41:27 +02:00
|
|
|
cfg.debug.stdout('Generating %s from:\n %s' % (dest, "\n ".join(file_list[file])), 1)
|
2024-04-01 00:49:03 +02:00
|
|
|
|
2024-03-31 22:20:47 +02:00
|
|
|
try:
|
|
|
|
comment_string = dir_config.get(section="Main", option="commentstring")
|
|
|
|
except ValueError:
|
|
|
|
cfg.debug.stdout(f'commentstring does not exist in config file {dir_config._cfgfiles}', 0, 'ERROR')
|
|
|
|
sys.exit(1)
|
|
|
|
# Make sure all directories for destination file exist
|
2024-04-01 00:49:03 +02:00
|
|
|
if uc.create_destination_directories(dir_config.get(section="Main", option="dest")):
|
|
|
|
cfg.debug.stdout(f'Created target directories {cfg.debug.green(dir_config.get(section="Main", option="dest"))}',
|
|
|
|
0, 'SUCCESS')
|
|
|
|
else:
|
|
|
|
cfg.debug.stdout(f'All target directories exist', 2)
|
2024-03-31 22:20:47 +02:00
|
|
|
temp_filename = uc.build_file(file_list[file], dest, comment_string)
|
2024-04-01 00:49:03 +02:00
|
|
|
if uc.diff_and_copy_file(temp_filename, dest, comment_string):
|
|
|
|
cfg.debug.stdout(f'Copy {temp_filename} -> {cfg.debug.green(dest)} (changed)\n', 0, 'SUCCESS')
|
|
|
|
else:
|
|
|
|
cfg.debug.stdout(f'Generated file and destination are the same.\n', 1)
|
|
|
|
|
|
|
|
cfg.debug.stdout(f'End Package {cfg.debug.green(package.path)}\n\n', 1, 'NOTICE')
|
2024-03-31 23:28:11 +02:00
|
|
|
|
2024-03-29 21:48:06 +01:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|