Fix templates

master3.3
Mike Hiretsky 12 years ago
parent 0bdd6a04e8
commit 70b364fb94

@ -662,7 +662,7 @@ class dirHeader(_terms):
"""
# Допустимые параметры заголовка
allowParam = ["append", "chmod", "chown", "name", "path", "autoupdate",
"module","env"]
"module","env","merge"]
# Тип вставки шаблона
typeAppend = ""
@ -2435,7 +2435,7 @@ class _shareTemplate:
return uid, gid, homeDir, groupsNames
return uid, gid, homeDir
class templateFunction(_error, _shareTemplate, _shareTermsFunction):
class templateFunction(_error, _warning, _shareTemplate, _shareTermsFunction):
"""Класс для функций шаблонов"""
# Словарь установленных программ {"имя программы":[версии]}
installProg = {}
@ -2611,7 +2611,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
ret = eval(termTmp)
return ret
def funcSum(self, funArgv, resS, localVars, textTemplateTmp):
def funcSum(self, funArgv, resS, localVars, textTemplateTmp,nameTemp):
"""Функция шаблона, вычисляет функцию sum()"""
terms = funArgv.replace(" ","").split(",")
# Название локальной переменной
@ -2639,7 +2639,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
self.raiseErrTemplate()
return textTemplateTmp
def funcExists(self, funArgv, resS, localVars, textTemplateTmp):
def funcExists(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона exists(),
проверяет существование файла, если существует выдает '1'
если второй параметр root, то проверка осуществляется от корня.
@ -2671,7 +2671,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcLoad(self, funArgv, resS, localVars, textTemplateTmp):
def funcLoad(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона load(),
если файл существует читает из файла локальную переменную
@ -2776,7 +2776,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
else:
return ""
def funcPkg(self, funArgv, resS, localVars, textTemplateTmp):
def funcPkg(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона pkg(), выдает номер версии программы"""
# Название программы
nameProg = funArgv.replace(" ","")
@ -2799,7 +2799,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcRnd(self, funArgv, resS, localVars, textTemplateTmp):
def funcRnd(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона rnd(), выдает строку случайных символов
первый аргумент:
@ -2832,7 +2832,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcCase(self, funArgv, resS, localVars, textTemplateTmp):
def funcCase(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона case(), выдает переменную в определенном регистре
первый аргумент:
@ -2871,7 +2871,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcPush(self, funArgv, resS, localVars, textTemplateTmp):
def funcPush(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""локальная функция записывает значение переменной
в стек глобальных переменных
@ -2912,7 +2912,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcPop(self, funArgv, resS, localVars, textTemplateTmp):
def funcPop(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""локальная функция получает значение
из стека глобальных переменных и присваивает локальной переменной
@ -2965,7 +2965,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
return self.timeConfigsIni[nameEnvFile]
return 0
def funcIni(self, funArgv, resS, localVars, textTemplateTmp):
def funcIni(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""локальная функция записывает и считывает значение переменной
из ini файла ~./calculate/ini.env
@ -3058,7 +3058,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return (textTemplateTmp)
def funcReplace(self, funArgv, resS, localVars, textTemplateTmp):
def funcReplace(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""локальная функция заменяет в значении переменной old на new
replace(old, new, name_var_template)
@ -3109,7 +3109,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcEnv(self, funArgv, resS, localVars, textTemplateTmp):
def funcEnv(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона env(), выдает значение переменной из env файлов
"""
terms = funArgv.replace(" ","").split(",")
@ -3130,7 +3130,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcServer(self, funArgv, resS, localVars, textTemplateTmp):
def funcServer(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона info(), выдает значение опций сервиса
из /var/calculate/remote/calculate.env
@ -3177,7 +3177,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcGroups(self, funArgv, resS, localVars, textTemplateTmp):
def funcGroups(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона groups(),
проверяет нахождение пользователя в группах, если находится выдает '1'
"""
@ -3191,11 +3191,19 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcBelong(self, funArgv, resS, localVars, textTemplateTmp):
def funcBelong(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
#self.setWarning(
# _("Function '{funcname}' used by {template} is depricated"
# " and will be removed at the future").format(
# funcname="belong",template=nameTemp))
return self.funcMerge(funArgv, resS, localVars,
textTemplateTmp, nameTemp)
def funcMerge(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""
Belong function use value in first arg and compare it
for all values in cl_belong_pkg.
If cl_belong_pkg empty or first arg <=cl_belogn_pkg
for all values in cl_merge_pkg.
If cl_merge_pkg empty or first arg <=cl_belogn_pkg
then "1" else ""
"""
terms = funArgv.replace(" ","").split(",")
@ -3206,7 +3214,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
funcPkg = os.path.split(os.path.dirname(self.nameTemplate))[1]
if not funcPkg:
self.raiseErrTemplate(_("incorrect template path"))
pkg = self.objVar.Get("cl_belong_pkg")
pkg = self.objVar.Get("cl_merge_pkg")
replace = ""
if pkg:
if funcPkg in pkg:
@ -3217,7 +3225,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcList(self, funArgv, resS, localVars, textTemplateTmp):
def funcList(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона list().
Если первый аргумент является именем локальной или глобальной
переменной и значение переменной является списком, выдает
@ -3264,7 +3272,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcDisk(self, funArgv, resS, localVars, textTemplateTmp):
def funcDisk(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона disk().
Первый аргумент ищется в значении переменной os_disk_install
(значение os_install_disk_mount -
@ -3333,7 +3341,7 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
textTemplateTmp[resS.end():]
return textTemplateTmp
def funcModule(self, funArgv, resS, localVars, textTemplateTmp):
def funcModule(self, funArgv, resS, localVars, textTemplateTmp, nameTemp):
"""Функция шаблона module(), выдает значение аттрибута api.
аргумент:
@ -3399,7 +3407,8 @@ class templateFunction(_error, _shareTemplate, _shareTermsFunction):
# вызов функции шаблона
textTemplateTmp = self.templateFunction[funcName](self, funArgv,
resS, localVars,
textTemplateTmp)
textTemplateTmp,
nameTemplate)
resS = reFunc.search(textTemplateTmp)
if funcName == "ini":
flagIniFunc = True
@ -3478,7 +3487,7 @@ class Template(_file,_terms,_warning,xmlShare,templateFormat,_shareTemplate):
self.cltObj = None
self.functObj = None
# Предупреждения
self.warning = []
#self.warning = []
# Печатать ли предупреждения о корневых шаблонах без cl_name==pkg
self.printWarning = printWarning
# Необрабатываемые директории
@ -3804,6 +3813,25 @@ re.M|re.S)
"""
return True
def fixNameFileConfig(self,origfilename):
"""Support ._cfg0000 files for postinst"""
if self.objVar.Get('cl_ebuild_phase') != 'postinst':
return origfilename
directory,filename = os.path.split(origfilename)
i = 0
for i in range(0,9999):
if not os.path.exists(os.path.join(directory,
"._cfg%04d_%s"%(i,filename))):
if i:
filename = os.path.join(directory,
"._cfg%04d_%s"%(i-1,filename))
origstat = os.stat(origfilename)[stat.ST_CTIME]
newstat = os.stat(filename)[stat.ST_CTIME]
if newstat > origstat:
return filename
return origfilename
return origfilename
def getHeaderText(self, text):
textLines = text.splitlines()
paramLine = ""
@ -3916,6 +3944,7 @@ re.M|re.S)
return dictTemplates
self.clearErrors()
self.clearWarnings()
if not self.objVar.defined("cl_template_path"):
self.setError(_("undefined variable: ") + "cl_template_path")
return False
@ -4004,20 +4033,20 @@ re.M|re.S)
self.dictProcessedTemplates.keys())
if not self.cltObj.applyTemplates():
return False
if self.objVar.Get('cl_belong_pkg') and \
self.objVar.Get('cl_belong_pkg_new'):
if self.objVar.Get('cl_merge_pkg') and \
self.objVar.Get('cl_merge_pkg_new'):
self.objVar.Set('cl_root_path',
self.objVar.Get('cl_root_path_next'),force=True)
self.recalculateBaseDir()
self.objVar.Set('cl_belong_pkg_pass',list(
set(self.objVar.Get('cl_belong_pkg_pass'))|
set(self.objVar.Get('cl_belong_pkg_new'))),force=True)
self.objVar.Set('cl_belong_pkg',
self.objVar.Get('cl_belong_pkg_new'),force=True)
self.objVar.Set('cl_belong_pkg_new',[],force=True)
self.objVar.Set('cl_merge_pkg_pass',list(
set(self.objVar.Get('cl_merge_pkg_pass'))|
set(self.objVar.Get('cl_merge_pkg_new'))),force=True)
self.objVar.Set('cl_merge_pkg',
self.objVar.Get('cl_merge_pkg_new'),force=True)
self.objVar.Set('cl_merge_pkg_new',[],force=True)
createdDirs = self.createdDirs
filesApply = self.filesApply
self.changeMergePackage(self.objVar.Get('cl_belong_pkg'))
self.changeMergePackage(self.objVar.Get('cl_merge_pkg'))
self.applyTemplates()
createdDirs.extend(self.createdDirs)
filesApply.extend(self.filesApply)
@ -4390,7 +4419,7 @@ re.M|re.S)
applyDir = ""
if applyDir:
if ("autoupdate" in optDir or "autoupdate" in objHead.params ) and \
not self.objVar.Get('cl_belong_pkg_pass'):
not self.objVar.Get('cl_merge_pkg_pass'):
self.autoUpdateDirs.append(applyDir)
return (applyDir, objHead, createdDirs)
@ -4516,9 +4545,9 @@ re.M|re.S)
wrongPkg + ": " + nameFileTemplate)
return ([], False)
for pkg in mergePkgs:
if not pkg in self.objVar.Get('cl_belong_pkg_new') and \
not pkg in self.objVar.Get('cl_belong_pkg_pass'):
self.objVar.Get('cl_belong_pkg_new').append(pkg)
if not pkg in self.objVar.Get('cl_merge_pkg_new') and \
not pkg in self.objVar.Get('cl_merge_pkg_pass'):
self.objVar.Get('cl_merge_pkg_new').append(pkg)
# Родительская директория
path = optFile["path"]
@ -4547,6 +4576,7 @@ re.M|re.S)
pathOldFile = pathJoin(path,nameFile)
else:
pathOldFile = pathJoin(path,os.path.split(nameFileConfig)[1])
pathOldFile = self.fixNameFileConfig(pathOldFile)
applyFiles = [pathOldFile]
# Фильтрация шаблонов по названию файла
realPath = os.path.join("/",pathOldFile.partition(self._baseDir)[2])
@ -4844,7 +4874,7 @@ re.M|re.S)
self.dictProcessedTemplates[pathOldFile].append(nameFileTemplate)
preReturn(pathProg)
if ( "autoupdate" in optFile or "autoupdate" in objHeadNew.params ) \
and not self.objVar.Get('cl_belong_pkg_pass'):
and not self.objVar.Get('cl_merge_pkg_pass'):
self.autoUpdateFiles += applyFiles
return (applyFiles, objHeadNew)

@ -606,6 +606,17 @@ class ReadonlyVariable(Variable):
"""
mode = READONLY
class ActionVariable(ReadonlyVariable):
nonchroot = False
postinst = False
def get(self):
if self.nonchroot and self.Get('cl_chroot_status') == "on":
return "off"
if self.postinst and not self.Get('cl_ebuild_phase') in ('','postinst'):
return "off"
return self.action(self.Get('cl_action'))
class FieldValue:
"""
Table column variable

@ -1,475 +0,0 @@
#-*- coding: utf-8 -*-
# Copyright 2008-2012 Calculate Ltd. 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.
__version__ = "3.0.2"
__app__ = "calculate-lib"
import sys, os, stat, re
from shutil import copy2
from cl_log import log
from calculate.lib import datavars
from calculate.lib import cl_template
from calculate.lib.cl_print import color_print as old_color_print
from calculate.lib.utils.files import (runOsCommand, scanDirectory, pathJoin,
listDirectory)
from calculate.lib.utils.common import getPasswdUsers
import pwd
from os import path
from calculate.lib import cl_overriding
from calculate.lib.utils.files import getModeFile
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_lib3',sys.modules[__name__])
cl_overriding.printERROR = lambda x:filter(lambda y:color_print().printERROR(y),
str(x).splitlines())
class writeLog:
"""Класс логгирования"""
logger = log("apply-templates",
filename="/var/log/calculate/update_config.log",
formatter="%(asctime)s - %(levelname)s - %(message)s")
class DataVars(datavars.DataVars):
flagNotFoundVar = False
def Get(self, *args, **kwargs):
try:
valVars = cl_datavars.DataVars.Get(self, *args, **kwargs)
except self.DataVarsError, e:
valVars = ""
self.flagNotFoundVar = True
return valVars
def Set(self, *args, **kwargs):
try:
valVars = datavars.DataVars.Set(self, *args, **kwargs)
except self.DataVarsError, e:
valVars = ""
self.flagNotFoundVar = True
return valVars
class template(cl_template.template):
def getApplyHeadTemplate(self, *args, **kwargs):
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ([], False)
filesApply, objHeadNew =\
cl_template.template.getApplyHeadTemplate(self, *args, **kwargs)
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ([], False)
else:
return filesApply, objHeadNew
def getApplyHeadDir(self, *args, **kwargs):
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ("", False, [])
pathDir, objHeadDir, createdDirs =\
cl_template.template.getApplyHeadDir(self, *args, **kwargs)
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ("", False, [])
else:
return pathDir, objHeadDir, createdDirs
class templateClt(cl_template.templateClt):
def getApplyHeadTemplate(self, *args, **kwargs):
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ([], False)
filesApply, objHeadNew =\
cl_template.templateClt.getApplyHeadTemplate(self, *args, **kwargs)
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ([], False)
else:
return filesApply, objHeadNew
def getApplyHeadDir(self, *args, **kwargs):
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ("", False, [])
pathDir, objHeadDir, createdDirs =\
cl_template.templateClt.getApplyHeadDir(self, *args, **kwargs)
if self.objVar.flagNotFoundVar:
self.objVar.flagNotFoundVar = False
return ("", False, [])
else:
return pathDir, objHeadDir, createdDirs
class color_print(old_color_print, writeLog):
"""Класс для переопределения печати сообщений"""
_printObj = old_color_print()
def printERROR(self, *arg, **argv):
"""Вывод на печать ошибки"""
# Запись в log ошибки
self.logger.error(arg[0])
self._printObj.printERROR(*arg, **argv)
def printSUCCESS(self, *arg, **argv):
"""Вывод на печать в случае успеха без [ok] справа"""
# Запись в log информации
self.logger.info(arg[0])
self._printObj.printSUCCESS(*arg, **argv)
def printWARNING(self, *arg, **argv):
"""Вывод на печать предупреждения"""
# Запись в log предупреждения
self.logger.warn(arg[0])
self._printObj.printWARNING(*arg, **argv)
def printOK(self, *arg, **argv):
"""Вывод на печать в случае успеха с [ok] справа"""
# Запись в log информации
self.logger.info(arg[0])
self._printObj.printOK(*arg, **argv)
def printNotOK(self, *arg, **argv):
"""Вывод на печать в случае сбоя"""
# Запись в log предупреждения
self.logger.error(arg[0])
self._printObj.printNotOK(*arg, **argv)
class DataVarsObject(DataVars):
"""Класс переменных для десктопа"""
packagePath = "/usr/lib/calculate-2.2"
def __init__(self, nameProgram):
DataVars.__init__(self)
self.nameProgram = nameProgram
def findPathVars(self):
pymPath = os.path.join(self.packagePath, self.nameProgram, "pym")
if os.path.isdir(pymPath) and\
len(filter(lambda x:x.startswith("cl_vars_") and\
x.endswith(".py") or x.startswith("cl_fill_") and\
x.endswith(".py"), os.listdir(pymPath)))==2:
importPath = os.path.abspath(pymPath)
if not importPath in sys.path:
sys.path.insert(0, importPath)
return True
return False
def importDataObject(self, **args):
'''Заполнить конфигурацию переменных, для десктопа'''
# заполнить переменные окружения алгоритмом по умолнанию
sectName = self.nameProgram.rpartition("-")[2]
self.importData(sectName, ('cl_vars_%s' %sectName,
'cl_fill_%s' %sectName))
self.flIniFile()
class shareUpdateConfigs(color_print, writeLog):
"""Общие методы для обновления конфигурационных файлов"""
_tupleOn = ("on","On","oN","ON")
def getFlagUpdAndInstPrograms(self):
"""Получаем флаг обновления и
установленные программы работающие с шаблонами"""
clVars = DataVars()
clVars.flIniFile()
flagUpdate = clVars.Get("cl_autoupdate_set") in self._tupleOn
return flagUpdate, clVars.GetList("cl_merges")
class updateUserConfigs(shareUpdateConfigs):
"""Обновление пользовательских конфигурационных файлов"""
def getXUsers(self):
"""Имена пользователей в X сессии"""
xSession = 0
foundTwoSession = False
retCode, resWho = runOsCommand("who")
xUsers = []
if retCode==0:
if resWho:
listProcessing = lambda x: (x[0], x[1], x[4])\
if len(x)==5 else []
xUsers = list(set(filter(lambda x: x!="root",
map(lambda x: x[0],
filter(lambda x: x and\
(x[2].startswith("(:") or \
x[1].startswith(":")),
map(lambda x: listProcessing(\
filter(lambda y: y, x.split(" "))),
resWho))))))
else:
self.printERROR(_("Failed to execute 'who'"))
return False
return xUsers
def getConfiguredPasswdUsers(self):
"""
Get users from passwd and discard users which has not
.calculate/ini.env.
"""
USER,DIR = 0,1
iniEnv = ".calculate/ini.env"
return map(lambda x:x[USER],
filter(lambda x:path.exists(path.join(x[DIR],iniEnv)),
map(lambda x:(x,pwd.getpwnam(x).pw_dir),
getPasswdUsers())))
def updateConfig(self, nameProgram, category, version):
"""Обновление конфигурационных файлов у пользователей"""
# флаг обновления и программы используемые для наложения шаблонов
flagUpdate, mergePrograms = self.getFlagUpdAndInstPrograms()
# X session user + configured local users (if user profile was not
# configured then there is no need setup package for this user
xUsers = filter(lambda x:not "(unknown)" in x,
list((set(self.getXUsers()) |
set(self.getConfiguredPasswdUsers()))))
if not xUsers:
self.logger.info(_("Package %s") %nameProgram)
self.logger.warn(_("X sessions users not found"))
return True
self.logger.info(_("Package %s") %nameProgram)
self.logger.info(_("Update desktop configuration files"))
if "calculate-desktop" in mergePrograms:
mergePrograms = ["calculate-desktop"]
else:
mergePrograms = []
dictPakkages = {}
listIndex = []
# Добавление условия, что программа category/nameProgram
# установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
for mergeProgram in mergePrograms:
for userName in xUsers:
clVars = DataVarsObject(mergeProgram)
if not clVars.findPathVars():
continue
clVars.importDataObject()
clVars.Set("ur_login", userName, True)
clVars.Set("cl_action", "desktop", True)
clVars.Set("cl_belong_pkg", nameProgram, True)
clTempl = template(clVars, printWarning=False)
dirsFiles = clTempl.applyTemplates()
if dirsFiles is False:
self.printERROR(\
_("Error using templates for user %s")\
%userName)
for errMess in clTempl.getError().splitlines():
self.printERROR(errMess)
return False
if dirsFiles and dirsFiles[1]:
nameAndVerPkg = clVars.Get("cl_name")+"-"+\
clVars.Get("cl_ver")
if not nameAndVerPkg in dictPakkages:
listIndex.append(nameAndVerPkg)
dictPakkages[nameAndVerPkg] = []
dictPakkages[nameAndVerPkg].append((userName,
sorted(list(set(dirsFiles[1])))))
if dictPakkages:
for calcPkg in listIndex:
self.printWARNING(
_("Package %s has changed the following files")\
%calcPkg+":")
for userName, configFiles in dictPakkages[calcPkg]:
self.printWARNING(" "*2 + _("User %s")%userName + ":")
for nameConfigFile in configFiles:
self.printWARNING(" "*5 + nameConfigFile)
if not dictPakkages:
self.logger.warn(_("Templates not found"))
return True
class updateSystemConfigs(shareUpdateConfigs):
"""Обновление системных конфигурационных файлов"""
def isExistsProtectFiles(self, configPath):
"""Есть ли в защищенных директориях конфигурационные файлы"""
if not "CONFIG_PROTECT" in os.environ:
self.printERROR(_("Missing environment variable CONFIG_PROTECT"))
exit(1)
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
flagFoundProtect = False
for pPath in protectPaths:
fPath = os.path.join(configPath, pPath[1:])
if os.path.exists(fPath) and os.listdir(fPath):
flagFoundProtect = True
break
if not flagFoundProtect:
return False
return True
def scanProtectDirs(self, configPath):
configFiles = []
scanObj = scanDirectory()
scanObj.processingFile = lambda path,prefix:configFiles.append(path) or\
True
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
configPath = os.path.realpath(configPath)
for pPath in protectPaths:
realPath = pathJoin(configPath, pPath)
if os.path.exists(realPath):
scanObj.scanningDirectory(realPath)
configFiles = map(lambda x: x.partition(configPath)[2], configFiles)
configFiles = map(lambda x: pathJoin('/',x), configFiles)
return configFiles
def createDir(self, configPath, dstDir):
"""Создание директории в случае необходимости"""
if os.path.exists(dstDir):
return True
def splPath(path):
listPath = []
if path in ("","/"):
return []
base, p = os.path.split(path)
listPath.append(p)
while(not base in ("","/")):
base, p = os.path.split(base)
listPath.append(p)
listPath.reverse()
return listPath
notFoundPaths = []
path = "/"
for p in splPath(dstDir):
path = os.path.join(path,p)
if not os.path.exists(path):
notFoundPaths.append(path)
for mkPath in notFoundPaths:
srcPath = pathJoin(configPath, mkPath)
dMode, dUid, dGid = getModeFile(srcPath)
os.mkdir(mkPath, dMode)
os.chown(mkPath, dUid, dGid)
return True
def copyConfigFiles(self, configPath):
"""Копирование конфигурационных файлов"""
configDstFiles = self.scanProtectDirs(configPath)
if configDstFiles:
self.logger.warn(_("Replaced files:"))
for dst in configDstFiles:
src = pathJoin(configPath, dst)
if src != dst:
dstDir = os.path.dirname(dst)
self.createDir(configPath, dstDir)
copy2(src, dst)
sMode, sUid, sGid = getModeFile(src)
os.chown(dst, sUid, sGid)
os.chmod(dst, sMode)
self.logger.warn(" "*5 + dst)
return True
def copyDirOrFile(self, src, dst, configPath):
if src != dst:
if os.path.isfile(src):
dstDir = os.path.dirname(dst)
self.createDir(configPath, dstDir)
copy2(src, dst)
sMode, sUid, sGid = getModeFile(src)
os.chown(dst, sUid, sGid)
os.chmod(dst, sMode)
elif os.path.isdir(src):
self.createDir(configPath, dst)
sMode, sUid, sGid = getModeFile(src)
os.chown(dst, sUid, sGid)
os.chmod(dst, sMode)
def updateConfig(self, nameProgram, category, version, configPath):
"""Обновление системных конфигурационных файлов"""
# флаг обновления и программы используемые для наложения шаблонов
flagUpdate, mergePrograms = self.getFlagUpdAndInstPrograms()
self.logger.info(_("Package %s") %nameProgram)
self.logger.info(_("Update system cofiguration files"))
if not os.path.exists(configPath):
self.printERROR(_("Path '%s' does not exist")%configPath)
return False
dictPakkages = {}
listIndex = []
# Добавление условия, что программа category/nameProgram установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
clTempl = False
for mergeProgram in mergePrograms:
clVars = DataVarsObject(mergeProgram)
if not clVars.findPathVars():
continue
clVars.importDataObject()
clVars.Set("cl_root_path", configPath, True)
clVars.Set("cl_belong_pkg", nameProgram, True)
clVars.Set("cl_action", 'merge', True)
configFiles = []
nameProg = clVars.Get("cl_name")
if nameProg == "calculate-install":
configFiles = self.scanProtectDirs(configPath)
if configFiles:
cltObject = templateClt(clVars)
cltObject.filterApplyTemplates = configFiles
clTempl = template(clVars, cltObj=cltObject,
printWarning=False)
else:
clTempl = template(clVars, cltObj=False,
printWarning=False)
dirsFiles = clTempl.applyTemplates()
nameAndVerPkg = nameProg + "-"+clVars.Get("cl_ver")
if dirsFiles is False:
self.printERROR(_("Template error in package %s")\
%nameAndVerPkg)
for errMess in clTempl.getError().splitlines():
self.printERROR(errMess)
return False
copyFiles = clTempl.autoUpdateFiles
copyDirs = clTempl.autoUpdateDirs
allCopyAutoupdateFiles = copyDirs + copyFiles
for fileOrDir in allCopyAutoupdateFiles:
dst = "/" + fileOrDir.partition(configPath)[2]
self.copyDirOrFile(fileOrDir, dst, configPath)
if dirsFiles and dirsFiles[1]:
if not nameAndVerPkg in listIndex:
listIndex.append(nameAndVerPkg)
dictPakkages[nameAndVerPkg] =\
sorted(list(set(dirsFiles[1])))
if dictPakkages:
for calcPkg in listIndex:
self.printWARNING(
_("Package %s has changed the following files")%calcPkg+":")
for nameF in dictPakkages[calcPkg]:
nameFile = nameF.partition(configPath)[2]
if nameFile:
if nameFile[:1] != "/":
nameFile = "/" + nameFile
else:
nameFile = nameF
self.printWARNING(" "*5 + nameFile)
else:
self.logger.warn(_("Templates not found"))
if flagUpdate:
self.copyConfigFiles(configPath)
if clTempl and clTempl.getWarning():
cl_overriding.printSUCCESS("")
for warn in clTempl.getWarning().split("\n"):
self.printWARNING(warn)
cl_overriding.printSUCCESS("")
return True

@ -1,118 +0,0 @@
#-*- coding: utf-8 -*-
# Copyright 2008-2012 Calculate Ltd. 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.
from cl_update_config import __app__, __version__,\
updateSystemConfigs, updateUserConfigs
from calculate.lib.cl_print import color_print as old_color_print
from calculate.lib.cl_opt import opt
import sys
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_lib3',sys.modules[__name__])
# Использование программы
USAGE = _("%prog [options] package_name")
# Коментарии к использованию программы
COMMENT_EXAMPLES = _("Update configuration files of package nss_ldap")
# Пример использования программы
EXAMPLES = _(r"%prog --system --pkg_category net-nds --pkg_version 2.4.19\
--path / openldap")
# Описание программы (что делает программа)
DESCRIPTION = _("Update configuration files of the installed package")
# Опции командной строки
CMD_OPTIONS=[{'longOption':"system",
'help':_("update system configuration files")},
{'longOption':"desktop",
'help':_("update desktop (user) configuration files")},
{'longOption':"path",
'optVal':"PATH",
'help':_("root path for saving the updated configuration files")},
{'longOption':"pkg_category",
'optVal':"CATEGORY",
'help':_("package category name")},
{'longOption':"pkg_version",
'optVal':"VERSION",
'help':_("package version number without the revision")}]
class update_cmd:
def __init__(self):
# Объект опций командной строки
self.optobj = opt(\
package=__app__,
version=__version__,
usage=USAGE,
examples=EXAMPLES,
comment_examples=COMMENT_EXAMPLES,
description=DESCRIPTION,
option_list=CMD_OPTIONS + opt.color_control,
check_values=self.checkOpts)
# Создаем объекты логики
self.logicSystemObj = updateSystemConfigs()
self.logicUserObj = updateUserConfigs()
def setPrintNoColor(self, optObj):
"""Установка печати сообщений без цвета"""
if optObj.color and optObj.color=="never":
old_color_print.colorPrint = lambda *arg: \
sys.stdout.write(arg[-1]) or\
sys.stdout.flush()
def checkOpts(self, optObj, args):
"""Проверка опций командной строки"""
if not args:
errMsg = _("no such argument") + ":" + " %s" %USAGE.split(" ")[-1]
self.optobj.error(errMsg)
return False
if len(args)>1:
errMsg = _("wrong argument") + ":" + " %s" %" ".join(args)
self.optobj.error(errMsg)
return False
if optObj.system and not optObj.path:
errMsg = _("no such option") + ":" + " --path"
self.optobj.error(errMsg)
return False
if not optObj.pkg_category:
errMsg = _("no such option") + ":" + " --pkg_category"
self.optobj.error(errMsg)
return False
if not optObj.pkg_version:
errMsg = _("no such option") + ":" + " --pkg_version"
self.optobj.error(errMsg)
return False
if not filter(lambda x: x, [optObj.system, optObj.desktop]):
errMsg = _("no such options") + ":" + " --system " + _("or") +\
" --desktop"
self.optobj.error(errMsg)
return False
return optObj, args
def updateSystemConfig(self, nameProgram, category, version, configPath):
"""Обновление системных конфигурационных файлов"""
if not self.logicSystemObj.updateConfig(nameProgram, category, version,
configPath):
return False
return True
def updateUserConfig(self, nameProgram, category, version):
"""Обновление конфигурационных файлов для пользователей в X сеансах"""
if not self.logicUserObj.updateConfig(nameProgram, category, version):
return False
return True

@ -25,4 +25,4 @@ class VariableClVer(ReadonlyVariable):
"""
Package version
"""
value = "3.1.0"
value = "3.1.1"

@ -128,7 +128,7 @@ class VariableClPassFile(Variable):
Template file performed at now
"""
class VariableClBelongPkg(ReadonlyVariable):
class VariableClMergePkg(ReadonlyVariable):
"""
This variable work with template function belong(package_name)
if the variable is defined then will use only template, which
@ -137,19 +137,27 @@ class VariableClBelongPkg(ReadonlyVariable):
(package_name == value of cl_belong_pkg)
"""
type = "list"
def get(self):
return self.Get('cl_belong_pkg')
class VariableClBelongPkgNew(ReadonlyVariable):
class VariableClMergePkgNew(ReadonlyVariable):
"""
New variable value for cl_belong_pkg
New variable value for cl_merge_pkg
"""
type = "list"
class VariableClBelongPkgPass(ReadonlyVariable):
class VariableClMergePkgPass(ReadonlyVariable):
"""
Performed packages
"""
type = "list"
class VariableClBelongPkg(ReadonlyVariable):
"""
Depricated by cl_merge_pkg
"""
type = "list"
class VariableClAction(ReadonlyVariable):
"""
Program action
@ -237,3 +245,10 @@ class VariableClVerboseSet(Variable):
def init(self):
self.help = _("verbosity output")
self.label = _("Verbosity output")
class VariableClEbuildPhase(ReadonlyVariable):
"""
Current ebuild phase
"""
def get(self):
return os.environ.get("EBUILD_PHASE","")

@ -20,7 +20,7 @@ import re
import platform
from calculate.lib.datavars import Variable,ReadonlyVariable,SimpleDataVars
from calculate.lib.utils.portage import isPkgInstalled
from calculate.lib.utils.files import countFiles
from calculate.lib.utils.files import countFiles,readFile
import calculate.lib.cl_template as cl_template
class Linux:
@ -86,6 +86,14 @@ class Linux:
return "Linux"
return None
def getVersionFromOverlay(self,systemroot):
"""
Get version from overlay calculate-release
"""
overlayPath = 'var/lib/layman/calculate'
releaseFile = 'profiles/calculate-release'
return readFile(path.join(systemroot,overlayPath,releaseFile))
def getVersionFromMetapackage(self,systemroot,shortname):
"""Get version from meta package"""
for pkg in ("app-misc/calculate-meta","app-misc/%s-meta"%shortname):
@ -184,7 +192,8 @@ class VariableOsLinuxVer(ReadonlyVariable,Linux):
def get(self):
"""Get system version"""
linuxShortName = self.Get("os_linux_shortname")
return self.getVersionFromMetapackage(self.systemRoot,
return self.getVersionFromOverlay(self.systemRoot) or \
self.getVersionFromMetapackage(self.systemRoot,
linuxShortName) or \
self.getVersionFromCalculateIni(self.systemRoot) or \
self.getVersionFromGentooFiles(self.systemRoot) or \

@ -22,7 +22,7 @@ from distutils.core import setup
from distutils.command.build_scripts import build_scripts
from distutils.command.install_scripts import install_scripts
__version__ = "3.0.0"
__version__ = "3.1.1"
__app__ = "calculate-lib"
module_name = "calculate.lib"
@ -30,7 +30,7 @@ module_name = "calculate.lib"
setup(
name = __app__,
version = __version__,
description = "The library for Calculate 2",
description = "The library for Calculate 3",
author = "Mir Calculate Ltd.",
author_email = "support@calculate.ru",
url = "http://calculate-linux.org",
@ -43,7 +43,6 @@ setup(
module_name + '.server',
module_name + '.variables',
module_name + '.mod',
module_name + '.update_config',
module_name + '.utils'],
data_files = [("/etc/calculate", []),
("/var/calculate/remote", []),

Loading…
Cancel
Save