You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-toolkit/cl-check-templates

156 lines
5.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Copyright 2015-2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import sys
import re
import os
from os import path
from itertools import chain
from calculate.lib.datavars import DataVars
from calculate.lib.cl_template import templateFunction
from calculate.lib.utils.files import readFile, listDirectory, readLinesFile
from calculate.core.result_viewer import ResultViewer
get_pkgname_by_filename = templateFunction.get_pkgname_by_filename
re_pkgname = templateFunction.reData
class ArgumentParserCheck(argparse.ArgumentParser):
def __init__(self):
super(ArgumentParserCheck, self).__init__(
description="Check templates (check pkg and merge function)")
class PackageDb(object):
def __init__(self, reps, installed_db):
self.installed_db = installed_db
self.reps = reps
self.packages = {}
self.renames = None
def __contains__(self, key):
if self.renames is None:
self.load_renames()
category, op, name = key.partition('/')
if category not in self.packages:
self.packages[category] = set()
self.load_pkg_db(category)
self.load_repos(category)
return name in self.packages[category] or key in self.renames
def get_newname(self, key):
return self.renames.get(key,'')
def load_pkg_db(self, category):
packages = self.packages[category]
for pkgname in listDirectory(path.join(self.installed_db,category)):
pkg = re_pkgname.search(pkgname).group(1)
packages.add(pkg)
self.packages[category] = packages
def load_repos(self, category):
packages = self.packages[category]
for rep_dn in self.reps:
for pkgname in listDirectory(path.join(rep_dn,category)):
if "." not in pkgname:
packages.add(pkgname)
self.packages[category] = packages
def load_renames(self):
self.renames = {}
for rep_dn in self.reps:
for fn in listDirectory(path.join(rep_dn,"profiles/updates"),
fullPath=True):
for line in (x for x in readLinesFile(fn) if x.startswith("move ")):
words = [x for x in line.split() if x]
if len(words) == 3:
self.renames[words[1]] = words[2]
class ScanTemplates(object):
reMerge = re.compile("(merge|pkg)\(([-\w/]*)(?::[^)]+?)?(?:\[[^\]]\])?\)[-!=<>]")
CLT_SUFFIX = ".clt"
def __init__(self, dv=None):
if dv is None:
dv = DataVars()
dv.importData()
dv.flIniFile()
self.dv = dv
dbpkg = '/var/db/pkg'
reps = self.dv.Get('cl_repository_location')
self.db = PackageDb(reps, dbpkg)
self.rv = ResultViewer()
def scan(self,dn):
"""
Сканировать директорию с шаблонами
"""
patch_dirs = []
for root, dirs, files in os.walk(dn):
for fn in (path.join(root,x) for x in files):
data = readFile(fn, binary=True)
try:
data_decoded = data.decode("UTF-8")
except UnicodeDecodeError as e:
continue
for fname, pkg in self.reMerge.findall(data_decoded):
pkg = pkg or get_pkgname_by_filename(fn)
if pkg not in self.db:
self._check_pkg(pkg, fname, fn)
def _check_pkg(self, pkg, fname, fn):
if pkg not in self.db:
self.rv.printERROR(
"Package '{pkgname}' specified in "
"the {funcname}() into "
"'{tempname}' template is not found".format(pkgname=pkg,
funcname=fname, tempname=fn))
elif self.db.get_newname(pkg):
self.rv.printERROR(
"Package '{pkgname}' specified in "
"the {funcname}() into "
"'{tempname}' template is renamed to {newname}".format(
pkgname=pkg, funcname=fname, tempname=fn,
newname=self.get_newname(pkg)))
def scan_clt(self, dn):
"""
Сканировать clt шаблоны
"""
for root, dirs, files in os.walk(dn):
for fn in (path.join(root,x) for x in files
if x.endswith(self.CLT_SUFFIX)):
data = readFile(fn, binary=True)
try:
data_decoded = data.decode("UTF-8")
except UnicodeDecodeError as e:
continue
for fname, pkg in self.reMerge.findall(data_decoded):
pkg = pkg or get_pkgname_by_filename(fn)
self._check_pkg(pkg, fname, fn)
def scan_all(self):
template_path = self.dv.Get('main.cl_template_path')
for dn in template_path:
self.scan(dn)
self.scan_clt('/etc')
if __name__=='__main__':
apv = ArgumentParserCheck()
args = apv.parse_args()
ScanTemplates().scan_all()