Commit 3034291f authored by Seblu's avatar Seblu
Browse files

Rework config/cache files

Static files are now under a directory in xdg directories (config or cache)

New paths:
$XDG_CONFIG/packages.conf
$XDG_CONFIG/sendmail.conf
$XDG_CACHE/packages.conf
parent 2ac8472a
......@@ -22,7 +22,7 @@ It can also be used by AUR maintainers to track update for their packages.
HOW TO USE IT
=============
The first thing to do is to define a list of packages to track by creating a file
~/.config/archversion.conf. The file content looks like an old fashioned INI file.
~/.config/archversion/packages.conf. The file content looks like an old fashioned INI file.
The following example allow to check the last version of acpid against archlinux
official repositories
......@@ -34,8 +34,8 @@ You can find more complete examples in the misc/ directory.
Basically, you can run:
*archversion sync* to fetch last versions from upstream and downstream.
*archversion report -n* to display new verions.
*archversion report -S acpid* to sync and display version report of the acpid package.
*archversion report --new* to display new verions.
*archversion report --sync acpid* to sync and display version report of the acpid package.
*archversion update* to update the current PKGBUILD to the last upstream version.
You can use systemd timers to get a report of packages which need updates:
......
......@@ -10,4 +10,4 @@ do_substitution = sed -e 's,[@]pythondir[@],$(pythondir),g' \
PKGBUILD: PKGBUILD.in
$(do_substitution) < $(srcdir)/$< > $@
dist_doc_DATA = example*.conf
dist_doc_DATA = *.conf.example
[ARCHVERSION]
# Options in this section are option to archversion
# Mail report address
# mailto = archversion@gmail.com
# Mail report subject
# mailsubject = Archversion report
# SMTP server
# smtp = smtp.honeypot.org
[DEFAULT]
# Options in this section will be applied on all others
# unless they are defined.
......
[sendmail]
# Options in this section are about sendmail command
# Mail address
# to = archversion@gmail.com
# Mail subject
# subject = Archversion report
# SMTP server
# smtp = smtp.honeypot.org
\ No newline at end of file
......@@ -20,9 +20,8 @@
'''Archlinux Version Controller'''
from archversion import VERSION, DEFAULT_CONFIG_FILENAME, DEFAULT_CACHE_FILENAME
from archversion import VERSION, CONFIG_SENDMAIL
from archversion.config import BaseConfigFile
from archversion.database import JsonDatabase
from archversion.error import BaseError, MissingConfigFile, NoSuchFile
from archversion.error import ERR_FATAL, ERR_ABORT, ERR_UNKNOWN
from archversion.pacman import parse_pkgbuild, pkgbuild_set_version, pkgbuild_update_checksums
......@@ -42,10 +41,6 @@ def parse_argv():
version="%(prog)s version " + VERSION)
p_main.add_argument("--debug", action="store_true",
help="debug mode")
p_main.add_argument("-c", "--config", default=None,
help="config file path")
p_main.add_argument("-C", "--cache", default=None,
help="cache file path")
sp_main = p_main.add_subparsers()
# config parser
p_conf = sp_main.add_parser("config",
......@@ -151,13 +146,15 @@ def command_report(args, vctrl):
def command_sendmail(args, vctrl):
'''Handle sendmail command call'''
# load sendmail config
config = BaseConfigFile(CONFIG_SENDMAIL)
# check args
try:
to = vctrl.packages["ARCHVERSION"]["mailto"]
subject = vctrl.packages["ARCHVERSION"]["mailsubject"]
smtp = vctrl.packages["ARCHVERSION"]["smtp"]
except KeyError:
logging.error("Invalid sendmail config in section [ARCHVERSION]")
to = config["mail"]["to"]
subject = config["mail"]["subject"]
smtp = config["smtp"]["host"]
except KeyError as exp:
logging.error("Invalid sendmail config: %s" % exp)
exit(1)
# capture a report
stdout = StringIO()
......@@ -229,13 +226,8 @@ def main():
# set global debug mode
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
# load configuration
packages = BaseConfigFile(args.config, DEFAULT_CONFIG_FILENAME)
# load cache database
cachedb = JsonDatabase()
cachedb.load(args.cache, DEFAULT_CACHE_FILENAME)
# load checking controller
vctrl = VersionController(packages, cachedb)
# load controller
vctrl = VersionController()
# call command function
return args.func(args, vctrl)
except KeyboardInterrupt:
......
......@@ -24,11 +24,17 @@ import logging
# Init log systems
logging.basicConfig(format="%(levelname)s: %(message)s")
# xdg config directory
XDG_DIRECTORY = "archversion"
# Stored list of packagas we want to track
DEFAULT_CONFIG_FILENAME = "archversion.conf"
CONFIG_PACKAGES = "packages.conf"
# Configuration for sendmail command
CONFIG_SENDMAIL = "sendmail.conf"
# Cache is stored package versions
DEFAULT_CACHE_FILENAME = "archversion.cache"
CACHE_PACKAGES = "packages.cache"
# Annouced version (from autoconf)
VERSION = "@VERSION@"
......
......@@ -19,30 +19,30 @@
'''Configuration Module'''
from archversion import XDG_DIRECTORY
from archversion.error import MissingConfigFile
from collections import OrderedDict
from configparser import RawConfigParser
from xdg.BaseDirectory import load_first_config
import logging
import os
from logging import debug
from os.path import join, exists
from xdg.BaseDirectory import save_config_path
class BaseConfigFile(OrderedDict):
'''Base config file class'''
def __init__(self, path, default_filename):
def __init__(self, filename):
'''Initialize config object'''
assert(default_filename is not None)
assert(filename is not None)
OrderedDict.__init__(self)
self.path = path
if path is None:
self.path = load_first_config(default_filename)
if not isinstance(self.path, str) or not os.path.exists(self.path):
path = save_config_path(XDG_DIRECTORY)
self.path = join(path, filename)
if not isinstance(self.path, str) or not exists(self.path):
raise MissingConfigFile(self.path)
self.load()
def load(self):
'''Load configuration'''
logging.debug("loading config file at: %s" % self.path)
debug("loading config file at: %s" % self.path)
self._configparser = RawConfigParser()
self._configparser.read(self.path)
for name in self._configparser.sections():
......
......@@ -19,11 +19,13 @@
'''Database Module'''
from archversion import XDG_DIRECTORY
from archversion.error import BaseError
from xdg.BaseDirectory import xdg_cache_home
from os.path import join
from xdg.BaseDirectory import save_cache_path
import json
import logging
import os
class JsonDatabase(dict):
'''Json database'''
......@@ -34,39 +36,24 @@ class JsonDatabase(dict):
if self._path is not None:
self.save()
def _get_path(self, path, default_filename, create=False):
'''Get a path and ensure its exists if create is True'''
if path is None:
if self._path is not None:
path = self._path
else:
path = os.path.join(xdg_cache_home, "archversion", default_filename)
if create and not os.path.exists(path):
directory = os.path.split(path)[0]
if directory != "" and not os.path.isdir(directory):
try:
os.makedirs(directory)
except (IOError, OSError) as exp:
raise BaseError("Create database path failed: %s" % exp)
try:
open(path, "a")
except (IOError, OSError) as exp:
raise BaseError("Create database filename failed; %s" % exp)
return path
def load(self, path, default_filename):
def load(self, filename):
'''Load registered version database into this database'''
assert(default_filename is not None)
# find the right path
self._path = self._get_path(path, default_filename)
if self._path is not None and os.path.isfile(self._path):
logging.debug("Loading database %s" % self._path)
try:
fileobj = open(self._path, "r")
dico = json.load(fileobj)
self.update(dico)
except Exception as exp:
logging.error("Unable to load database %s: %s" % (self._path, exp))
assert(filename is not None)
path = join(save_cache_path(XDG_DIRECTORY), filename)
try:
open(path, "a")
except (IOError, OSError) as exp:
raise BaseError("Create database filename failed; %s" % exp)
logging.debug("Loading database %s" % path)
try:
fileobj = open(path, "r")
dico = json.load(fileobj)
self.update(dico)
except Exception as exp:
logging.error("Unable to load database %s: %s" % (path, exp))
# because we use self._path is __del__, this should be done when
# we are sure that db is loaded
self._path = path
def save(self, save_empty=False):
'''Save current version database into a file'''
......
......@@ -48,8 +48,7 @@ class MissingConfigFile(NoSuchFile):
'''Config file is missing'''
def __str__(self):
logging.debug("No such config file: %s" % self.filename)
return "Missing configuration file. Please create it before!"
return "Missing configuration file: %s.\nPlease create it before!" % self.filename
class InvalidConfigFile(BaseError):
'''Config file is bad formatted'''
......
......@@ -20,12 +20,14 @@
'''Version Module'''
from archversion import USER_AGENT
from archversion.pacman import parse_pkgbuild, Pacman
from archversion import USER_AGENT, CONFIG_PACKAGES, CACHE_PACKAGES
from archversion.config import BaseConfigFile
from archversion.database import JsonDatabase
from archversion.error import InvalidConfigFile, VersionNotFound
from archversion.pacman import parse_pkgbuild, Pacman
from collections import OrderedDict
from urllib.request import urlopen, Request
from time import time
from urllib.request import urlopen, Request
import fnmatch
import json
import logging
......@@ -39,16 +41,19 @@ class VersionController(object):
Handle version detection of packages
'''
def __init__(self, packages, cache):
self.packages = packages
def __init__(self):
# load packages configuration
self.packages = BaseConfigFile(CONFIG_PACKAGES)
# load cache database
self.cache = JsonDatabase()
self.cache.load(CACHE_PACKAGES)
# set cache
if set(cache.keys()) != set(("downstream", "compare", "upstream")):
if set(self.cache.keys()) != set(("downstream", "compare", "upstream")):
logging.debug("Invalid cache, purging it")
cache.clear()
cache["upstream"] = {}
cache["downstream"] = {}
cache["compare"] = {}
self.cache = cache
self.cache.clear()
self.cache["upstream"] = {}
self.cache["downstream"] = {}
self.cache["compare"] = {}
def reduce_packages(self, packages):
'''Keep only the give packages list'''
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment