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.
 
 

1428 lines
45 KiB

#-*- coding: utf-8 -*-
# Copyright 2008-2013 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.
import os
import sys
import re
from os import path
from calculate.lib.datavars import (Variable, VariableError,
ReadonlyVariable, ReadonlyTableVariable, TableVariable, FieldValue,
SimpleDataVars, DataVarsError)
from calculate.lib.utils.files import readFile, \
listDirectory, process, pathJoin
from calculate.lib.configparser import ConfigParser
from calculate.lib.cl_lang import setLocalTranslate
from calculate.lib.utils.text import simplify_profiles
from calculate.lib.utils.portage import Git, GitError, Layman
from ..profile import RepositoryStorageSet, DEFAULT_BRANCH, \
LocalStorage, ProfileRepository, CacheStorage
from calculate.lib.variables import linux as lib_linux
from calculate.lib.variables import env
from calculate.update.update_info import UpdateInfo
import urllib2
import time
_ = lambda x:x
setLocalTranslate('cl_update3', sys.modules[__name__])
class VariableAcUpdateSync(ReadonlyVariable):
"""
Action variable which has value "up" for package install and
install this package
"""
def get(self):
action = self.Get("cl_action")
if action in ("sync",):
if self.Get('cl_update_world'):
return self.Get('cl_update_world')
return ""
class VariableClUpdateWorld(Variable):
type = "choice"
value = "update"
opt = ["--world"]
syntax = "--{choice}-world"
metavalue = "MODE"
def init(self):
self.help = ("'rebuild' - " + _("rebuild the system packages list") +
",\n'merge' - " + _("append the profile packages list") +
",\n'update' - " + _("update the system packages list"))
self.label = _("System packages list")
def choice(self):
return [("rebuild", _("Rebuild")),
("merge", _("Merge")),
("update", _("Update"))]
class VariableClRebuildWorldSet(Variable):
"""
List of action update world, rebuild world,
"""
type = "bool"
opt = ["--rebuild-world"]
untrusted = True
value = "off"
def init(self):
self.help = _("Rebuild world")
self.label = _("Rebuild world")
class VariableClUpdateRevSet(Variable):
"""
List of action update world, rebuild world,
"""
type = "bool"
opt = ["--update-rev"]
untrusted = True
value = "on"
check_after = ["cl_update_sync_rep",
"cl_update_metadata_force",
"cl_update_other_set",
"cl_update_eixupdate_force"]
def init(self):
self.help = _("make a revision update")
self.label = _("Make a revision update")
class VariableClUpdateRep(Variable):
"""
Обновлять репозитории до конкретной ревизии или до последней
"""
type = "choice"
value = "rev"
def choice(self):
return ["last", "rev"]
class VariableClUpdateRepData(ReadonlyTableVariable):
"""
Информация о репозиториях
"""
source = ['cl_update_rep_name',
'cl_update_rep_url',
'cl_update_rep_path',
'cl_update_rep_rev']
class VariableClUpdateRepName(Variable):
"""
Список имен используемых репозиториев
"""
type = "list"
value = []
class VariableClUpdateRepUrl(Variable):
"""
Список путей до репозиториев
"""
type = "list"
value = []
class VariableClUpdateLaymanConfig(ReadonlyVariable):
"""
Объект конфига layman
"""
type = "object"
def get(self):
chroot = self.Get('cl_chroot_path')
cp = ConfigParser()
cp.read(path.join(chroot, 'etc/layman/layman.cfg'))
return cp
class VariableClUpdateLaymanStorage(Variable):
"""
Путь к репозиториям layman
"""
param_name = "storage"
fallback_value = "var/lib/layman"
def get(self):
cp = self.Get('cl_update_layman_config')
res = cp.get('MAIN', self.param_name, fallback=self.fallback_value)
return pathJoin(self.Get('cl_chroot_path'), res)
class VariableClUpdateRepPath(ReadonlyVariable):
"""
Пути до репозиториев
"""
type = "list"
mapPath = {'portage': 'usr/portage',
'gentoo': '/usr/portage'}
def get(self):
repPath = self.Get('cl_update_layman_storage')
chroot_path = self.Get('cl_chroot_path')
def generatePaths(names):
for name in names:
if name in self.mapPath:
yield path.join(chroot_path, self.mapPath[name])
else:
yield path.join(repPath, name)
return list(generatePaths(self.Get('cl_update_rep_name')))
class VariableClUpdateRepRev(Variable):
"""
Ревизии до которых необходимо обновить репозитории
"""
type = "list"
def get(self):
cp = ConfigParser()
revisions = self.Get('update.cl_update_binhost_revisions')
if revisions:
cp.read_string(unicode(revisions[0]))
branch = self.Get('cl_update_branch')
def generateBranch():
for repname, branchname in zip(
self.Get('cl_update_rep_name'),
self.Get('cl_update_branch_name')):
if branchname == "binhost":
yield cp.get("vcs", repname, fallback=branch)
else:
yield branchname
return list(generateBranch())
class VariableClUpdateBranch(Variable):
"""
Ветка на которую будет обновляться репозиторий если -getbinpkg
"""
value = "master"
class VariableClUpdateBranchData(TableVariable):
"""
Выбор веток репозиториев до которых необходимо обновиться
"""
opt = ["--branch"]
metavalue = 'BRANCHES'
untrusted = True
source = ["cl_update_branch_rep",
"cl_update_branch_name"]
def init(self):
self.help = _("set branches for repository (REPOSITORY:BRANCH)")
self.label = _("Repositories branches")
def raiseReadonlyIndexError(self, fieldname="", variablename="", value=""):
"""
Неизвестный оврелей
"""
raise VariableError(_("Repository %s not found")%value)
class VariableClUpdateBranchRep(ReadonlyVariable):
"""
Список доступных репозиторием
"""
type = "list"
def init(self):
self.label = _("Repositories")
def get(self):
return self.Get('cl_update_rep_name')
class VariableClUpdateBinhostData(ReadonlyTableVariable):
"""
Таблица содержащая
binhost/содержимое файла ревизий/время доступа
"""
source = ["cl_update_binhost_host",
"cl_update_binhost_revisions",
"cl_update_binhost_time"]
def check_binhost(self, binhost):
revision_files = [path.join(binhost, x)
for x in self.Get('cl_update_binhost_revision_path')]
timeout = self.GetInteger('cl_update_binhost_timeout')
try:
data = None
for fn in revision_files:
if data is None:
data = urllib2.urlopen(fn, timeout=timeout).read()
elif data != urllib2.urlopen(fn, timeout=timeout).read():
return ""
return data
except urllib2.URLError:
return ""
re_revison = re.compile("\w+=(\w+)")
def binhost_key(self, data):
host, t = data
try:
cp = ConfigParser()
cp.read_string(data.decode('utf-8'))
data = sum(int(x) for x in cp['vcs'].values())
except (TypeError, KeyError) as e:
data = 0
return (1 if int(time) >= 0 else 0,
data,
-int(time))
def get_timestamp(self, binhost):
DAY = 60 * 60 * 24
timeout = self.GetInteger('cl_update_binhost_timeout')
timestamp_file = path.join(binhost,
self.Get('cl_update_binhost_timestamp_path'))
try:
t = time.time()
data = urllib2.urlopen(timestamp_file, timeout=timeout).read().strip()
if data.isdigit() and t - int(data) < 5 * DAY:
return data, int((time.time() - t)*1000)
except urllib2.URLError as e:
pass
return "", -1
def get(self, hr=False):
binhost = self.Get('cl_update_binhost')
recheck = self.GetBool('cl_update_binhost_recheck_set')
def generate_by_timestamp():
for host in self.Get('cl_update_binhosts'):
if host:
ts_content, duration = self.get_timestamp(host)
if ts_content:
yield host, ts_content, str(duration)
if not recheck and binhost:
ts, t = self.get_timestamp(binhost)
if ts:
data = self.check_binhost(binhost)
if data:
return [[binhost, data, str(t)]]
for host, ts, t in sorted(generate_by_timestamp(),
key=lambda x: (-int(x[1]), int(x[2]))):
data = self.check_binhost(host)
if data:
return [[host, data, str(t)]]
return [[]]
class VariableClUpdateBinhostRecheckSet(Variable):
"""
Принудительно обновить binhost
"""
type = "bool"
value = "off"
opt = ["--recheck-binhost"]
def init(self):
self.help = _("re-check binary hosts")
self.label = _("Re-check binary hosts")
class VariableClUpdateBinhostHost(FieldValue, ReadonlyVariable):
"""
Список имен прочих репозиториев
"""
type = "list"
source_variable = "cl_update_binhost_data"
column = 0
class VariableClUpdateBinhostRevisions(FieldValue,ReadonlyVariable):
"""
Список имен прочих репозиториев
"""
type = "list"
source_variable = "cl_update_binhost_data"
column = 1
class VariableClUpdateBinhostTime(FieldValue,ReadonlyVariable):
"""
Список имен прочих репозиториев
"""
type = "list"
source_variable = "cl_update_binhost_data"
column = 2
class VariableClUpdateBranchName(Variable):
"""
Список доступных репозиторием
"""
type = "choiceedit-list"
def init(self):
self.label = _("Branches")
def choice(self):
return ["master", "develop", "update", "binhost"]
def get(self):
if "getbinpkg" in self.Get('cl_features'):
return ["binhost" for x in self.Get('cl_update_rep_name')]
else:
branch = self.Get('cl_update_branch')
return [branch for x in self.Get('cl_update_rep_name')]
class VariableClUpdateSyncRep(Variable):
"""
Обновляемый репозиторий
"""
type = "choice-list"
element = "selecttable"
opt = ["-r", "--repositories"]
metavalue = "REPOSITORIES"
untrusted = True
@property
def rep_name(self):
return self.Get('update.cl_update_rep_name')
def init(self):
self.help = _("synchronized repositories (all by default)")
self.label = _("Synchronized repositories")
def set(self, value):
orderList = self.rep_name
return sorted(value, key=lambda x:
(orderList.index(x) if x in orderList else -1), reverse=True)
def get(self):
return list(reversed(self.rep_name))
def choice(self):
return self.rep_name
class VariableClUpdateSyncOverlayRep(ReadonlyVariable):
"""
Обновляемые репозитории (исключая portage)
"""
type = "list"
def get(self):
return filter(lambda x: x != "portage", self.Get('cl_update_sync_rep'))
class VariableClUpdateOutdateSet(ReadonlyVariable):
"""
Флаг устанавливаемый в ходе обновления репозиториев,
сообщающий что хотя бы один из запланированных репозиториев
обновлен и следует обновляет различные метаданные
Если обновляются прочие оверлеи - данные считаются что устарели
"""
type = "bool"
def get(self):
if (self.Get('cl_update_other_set') == 'on' and
self.Get('cl_update_other_rep_name')):
return "on"
return "off"
class VariableClUpdateMetadataForce(Variable):
"""
Принудительное действие с метаданными
"""
type = "choice"
value = "auto"
opt = ["--update-metadata"]
syntax = "--{choice}-update-metadata"
metavalue = "MODE"
#untrusted = True
def init(self):
self.help = ("'force' - " + _("force the update ebuilds metadata") +
",\n'skip' - " + _("skip the ebuild metadata update") +
",\n'auto' - " + _("update metadata if it is outdated"))
self.label = _("Update metadata")
def choice(self):
return [("force", _("Force")),
("skip", _("Skip")),
("auto", _("If needed"))]
class VariableClUpdateEgencacheForce(Variable):
"""
Принудительное выполнение egencache
"""
type = "choice"
value = "auto"
opt = ["--egencache"]
syntax = "--{choice}-egencache"
metavalue = "MODE"
#untrusted = True
def init(self):
self.help = ("'force' - " + _("force the update of the overlays cache") +
",\n'skip' - " + _("skip the update of the overlays cache") +
",\n'auto' - " + _("update the overlays cache if outdated"))
self.label = _("Update the overlays cache")
def choice(self):
return [("force", _("Force")),
("skip", _("Skip")),
("auto", _("If needed"))]
class VariableClUpdateEixupdateForce(Variable):
"""
Принудительное действие с eix-update
"""
type = "choice"
value = "auto"
opt = ["--eix-update"]
syntax = "--{choice}-eix-update"
metavalue = "MODE"
#untrusted = True
def init(self):
self.help = ("'force' - " + _("force the eix cache update") +
",\n'skip' - " + _("skip the eix cache update") +
",\n'auto' - " + _("update the eix cache if it "
"is outdated"))
self.label = _("Update the eix cache")
def choice(self):
return [("force", _("Force")),
("skip", _("Skip")),
("auto", _("If needed"))]
class VariableClUpdateOtherSet(Variable):
"""
Обновить остальные оверлеи
"""
type = "bool"
value = "off"
opt = ["-o", "--update-other"]
def init(self):
self.help = _("update other overlays")
self.label = _("Update other overlays")
class VariableClUpdateOtherRepData(ReadonlyTableVariable):
"""
Информация о прочих репозиториях
"""
source = ['cl_update_other_rep_name',
'cl_update_other_rep_path']
portdir_overlay = "main.cl_portdir_overlay"
def generator(self):
repNames = self.Get('update.cl_update_rep_name')
layman = Layman(self.Get('update.cl_update_layman_installed'),
self.Get('update.cl_update_layman_make'),
self.Get('update.cl_update_layman_conf'))
layman_overlays = layman.get_installed()
for rpath in self.Get(self.portdir_overlay):
repo_file = path.join(rpath, "profiles/repo_name")
rname = readFile(repo_file).strip() or path.basename(rpath)
if rname in layman_overlays and rname not in repNames:
yield (rname, rpath)
def get(self):
return list(self.generator())
class VariableClUpdateOtherRepName(FieldValue,ReadonlyVariable):
"""
Список имен прочих репозиториев
"""
type = "list"
source_variable = "cl_update_other_rep_data"
column = 0
class VariableClUpdateOtherRepPath(FieldValue,ReadonlyVariable):
"""
Список путей до прочих репозиториев
"""
type = "list"
source_variable = "cl_update_other_rep_data"
column = 1
class VariableClUpdateLaymanInstalled(VariableClUpdateLaymanStorage):
"""
Путь до файла layman installed.xml
"""
param_name = "installed"
fallback_value = "var/lib/layman/installed.xml"
class VariableClUpdateLaymanMake(VariableClUpdateLaymanStorage):
"""
Путь до файла make.conf изменяемого layman`ом
"""
param_name = "make_conf"
fallback_value = "var/lib/layman/make.conf"
class VariableClUpdateLaymanConf(VariableClUpdateLaymanStorage):
"""
Путь до конфигурационного файла репозиториев для layman
"""
param_name = "repos_conf"
fallback_value = "etc/portage/repos.conf/layman.conf"
class VariableClUpdatePretendSet(Variable):
"""
Запустить предварительную проверку на обновления
"""
type = "bool"
value = "off"
opt = ["-p", "--pretend"]
def init(self):
self.label = _("Pretend a package update")
self.help = _("instead of actually performing the update, "
"simply display the list of packages that "
"will be installed")
class VariableClUpdateSyncOnlySet(Variable):
"""
Не выполнять установку/обновление пакетов при обновлении
"""
type = "bool"
value = "off"
opt = ["-s", "--sync-only"]
def init(self):
self.label = _("Only synchronize repositories")
self.help = _("do not update packages")
def check(self, value):
if (value == "on" and self.Get('cl_rebuild_world_set') != 'on' and
not self.Get('cl_update_sync_rep') and
self.Get('cl_update_other_set') == 'off' and
self.Get('cl_update_rev_set') == 'off' and
self.Get('cl_update_metadata_force') != "force" and
self.Get('cl_update_eixupdate_force') != "force"):
raise VariableError(_("Select at least one sync repository"))
class VariableClUpdateWaitAnotherSet(Variable):
"""
Ждать завершения другого процесса обновления
"""
type = "bool"
value = "on"
opt = ["--wait-another-update"]
def init(self):
self.label = _("Wait for another update to be complete")
self.help = _("wait until the running update is finished")
class VariableClUpdateProfileStorage(ReadonlyVariable):
type = "object"
def get(self):
return RepositoryStorageSet(
LocalStorage('/var/lib/layman'),
CacheStorage('/var/calculate/tmp/update'))
class VariableClUpdateRepHost(Variable):
type = "list"
value = ['calculate']
class VariableClUpdateRepHostUrl(Variable):
type = "list"
value = ['git://git.calculate.ru/calculate/%s.git']
class VariableClUpdateProfileDatavars(ReadonlyVariable):
type = "object"
profile = "cl_update_profile_system"
profiles_path = "cl_update_profile_path"
profiles_shortname = "cl_update_profile_shortname"
def get(self):
profile = self.Get(self.profile)
path_profile = self.Select(self.profiles_path,
where=self.profiles_shortname,
eq=profile, limit=1)
if path_profile:
return DataVarsUpdateProfile(path_profile)
return ""
class VariableClUpdateProfileLinuxFullname(ReadonlyVariable):
"""
Имя системы в профиле
"""
def init(self):
self.label = _("Distribution name")
datavars = "cl_update_profile_datavars"
def get(self):
dv = self.Get(self.datavars)
if dv:
try:
subname = dv.Get('os_linux_subname')
linuxname = dv.Get('os_linux_name')
linuxver = dv.Get('os_linux_ver')
if subname:
return "%s %s %s" % (linuxname, linuxver, subname)
return "%s %s" %(linuxname,linuxver)
except DataVarsError as s:
raise VariableError("Wrong Calculate Linux profile")
return ""
class VariableClUpdateProfileDependData(ReadonlyTableVariable):
"""
Зависимые репозитории
"""
source = ['cl_update_profile_depend_name',
'cl_update_profile_depend_url']
datavars = "cl_update_profile_datavars"
def init(self):
self.label = _("Used repositories")
@staticmethod
def url_like(url1, url2):
match1 = VariableClUpdateProfileUrl.re_url.search(url1)
match2 = VariableClUpdateProfileUrl.re_url.search(url2)
if match1 and match2:
return match1.group(2).lower() == match2.group(2).lower()
return False
def get(self, hr=False):
dv = self.Get(self.datavars)
# TODO: неиспользуемая переменная возможно
# испольуется для инициализации
#url = self.Get('cl_update_profile_url').lower()
if dv:
return reversed(zip(dv.Get('cl_update_rep_name'),
dv.Get('cl_update_rep_url')))
return ""
setValue = Variable.setValue
class VariableClUpdateTemplatesLocate(Variable):
"""
Выбранные типы хранилищ шаблонов
"""
type = "choice-list"
element = "selecttable"
opt = ["-T","--templates"]
metavalue = "TEMPLATES"
untrusted = True
check_after = ['cl_update_profile_system']
profile_datevars = "update.cl_update_profile_datavars"
descriptionMap = {'overlay': _('Overlay templates'),
'local': _('Local templates'),
'calculate': _("Calculate overlay templates"),
'distros': _('Distribution templates'),
'distro': _('Distribution templates'),
'remote': _('Remote templates'),
'clt': _('clt templates')}
def init(self):
self.label = _("Templates location")
self.help = _("select the location for templates %s") \
%",".join(self.get())
def get(self):
dv = self.Get(self.profile_datevars)
if dv:
return dv.Get('cl_template_location') + ['clt']
else:
return self.Get('cl_templates_locate')
def choice(self):
descr = lambda x: self.descriptionMap.get(x,
_("%s overlay templates" % x))
return map(lambda x: (x, descr(x)), self.get())
class VariableClUpdateProfileDependName(FieldValue, ReadonlyVariable):
type = "list"
source_variable = "cl_update_profile_depend_data"
column = 0
def init(self):
self.label = _("Name")
class VariableClUpdateProfileDependUrl(FieldValue, ReadonlyVariable):
type = "list"
source_variable = "cl_update_profile_depend_data"
column = 1
def init(self):
self.label = _("URL")
class VariableClUpdateProfileRepName(ReadonlyVariable):
type = "list"
def get(self):
dv = self.Get('cl_update_profile_datavars')
if dv:
return dv.Get('cl_update_rep_name')
return []
class VariableClUpdateProfileSyncRep(ReadonlyVariable):
type = "list"
def get(self):
return list(reversed(self.Get('cl_update_profile_rep_name')))
class VariableClUpdateProfileRepUrl(ReadonlyVariable):
type = "list"
def get(self):
dv = self.Get('cl_update_profile_datavars')
if dv:
return dv.Get('cl_update_rep_url')
return []
class VariableClUpdateProfileLinuxVer(ReadonlyVariable):
"""
Имя системы в профиле
"""
def init(self):
self.label = _("System profile version")
def get(self):
dv = self.Get('cl_update_profile_datavars')
if dv:
return dv.Get('os_linux_ver')
return ""
class VariableClUpdateProfileLinuxName(ReadonlyVariable):
"""
Имя системы в профиле
"""
def get(self):
dv = self.Get('cl_update_profile_datavars')
if dv:
dv.Get('os_linux_name')
return ""
class VariableClUpdateProfileUrl(Variable):
"""
URL текущего репозитория
"""
untrusted = True
check_after = ["cl_update_profile_branch"]
opt = ["--url"]
metavalue = "URL"
profile = "cl_profile_system"
branch = "cl_update_profile_branch"
storage = "cl_update_profile_storage"
default_url = "git://git.calculate.ru/calculate/distros.git"
profiles_shortname = 'cl_update_profile_shortname'
@property
def current_root(self):
return '/'
def init(self):
self.label = _("Profile repository")
self.help = _("set the profile repository")
re_url = re.compile(
r"^(?:(%s)://)?(\w[\w\./:-]+?\w)(\.git)?$" % "|".join(
["http", "https", "git"]))
re_shortname = re.compile('^(?:([\w\.-]+):)?([\w\.-]+)$')
@classmethod
def normalize_url(cls, url):
match = cls.re_url.match(url)
if not match:
raise VariableError(_("Wrong repository URL"))
url = match.group(2)
url = "%s://%s" % (match.group(1) or "git", url)
url = "%s.git" % url
return url
def url_by_shortname(self, value):
match = self.re_shortname.match(value)
if not match.group(1):
template = self.Get('update.cl_update_rep_host_url')
if template:
template = template[0]
else:
template = self.Select('update.cl_update_rep_host_url',
where='update.cl_update_rep_host',
eq=match.group(1), limit=1)
if not template:
raise VariableError(_("Failed to determine the repository host"))
try:
return template % match.group(2)
except TypeError:
raise VariableError(_("Failed to determine the repository host"))
def set(self, value):
if self.re_shortname.match(value):
value = self.url_by_shortname(value)
return self.normalize_url(value)
def check(self, value):
if not value:
raise VariableError("Need to specify profile repository")
try:
branch = self.Get(self.branch)
self.Get(self.storage).get_profiles(value, branch)
except GitError as e:
raise VariableError(str(e))
if not self.Get(self.profiles_shortname):
raise VariableError(_("Repository %s has no profiles")%value)
def get(self):
try:
profile = self.Get(self.profile)
if profile:
while (profile != self.current_root and
".git" not in listDirectory(profile)):
profile = path.dirname(profile)
if profile == self.current_root:
return ""
git = Git()
return git.get_url(profile, "origin") or ""
except:
pass
return self.default_url
class VariableClUpdateProfileRepoName(ReadonlyVariable):
def init(self):
self.label = _("Repository name")
storage = "cl_update_profile_storage"
url = "cl_update_profile_url"
def get(self):
rep_set = self.Get(self.storage)
url = self.Get(self.url)
rep = rep_set.get_repository(url, branch=None)
if rep:
return rep.repo_name
return ""
class VariableClUpdateProfileBranch(Variable):
"""
Текущий репозиторий
"""
untrusted = True
type = "edit"
opt = ["--branch"]
metavalue = "BRANCH"
storage = "cl_update_profile_storage"
url = "cl_update_profile_url"
value = DEFAULT_BRANCH
def init(self):
self.label = _("Repository branch")
self.help = _("set the repository branch")
def check(self, value):
pass
## TODO: проверка ветки
#try:
# url = self.Get('cl_update_profile_url')
# self.Get('cl_update_profile_storage').get_profiles(url, value)
#except GitError as e:
# raise VariableError(str(e))
class VariableClProfileRepository(ReadonlyVariable):
"""
Репозиторий из которого будут получены профили
"""
type = "object"
def get(self):
try:
profile_dn = self.Get('cl_profile_system')
while profile_dn != '/' and ".git" not in listDirectory(profile_dn):
profile_dn = path.dirname(profile_dn)
if profile_dn == '/':
return ""
ls = LocalStorage(path.dirname(profile_dn))
return ProfileRepository(path.basename(profile_dn), ls)
except:
return ""
class VariableClProfileData(ReadonlyTableVariable):
"""
Таблица данных о текущих профилях системы
"""
source = []
repository = "cl_profile_repository"
def profile_filter(self, profiles):
arch = self.Get('os_arch_machine_gentoo')
return [x for x in profiles if x.arch == arch]
def get(self, hr=False):
rep = self.Get(self.repository)
if not rep:
return [[]]
profiles = rep.get_profiles()
if not profiles:
return [[]]
repo_name = profiles[0].repository.repo_name
filtered_profiles = self.profile_filter(profiles)
full_name = [x.profile for x in filtered_profiles]
profile_path = [x.path for x in filtered_profiles]
profile_arch = [x.arch for x in filtered_profiles]
short_name = simplify_profiles(full_name)
full_name = ["%s:%s" % (repo_name, x) for x in full_name]
return zip(full_name,
short_name,
profile_path,
profile_arch)
setValue = Variable.setValue
class VariableClUpdateProfileRepository(ReadonlyVariable):
"""
Репозиторий из которого будет извлечён список профилей
"""
type = "object"
url = "cl_update_profile_url"
storage = "cl_update_profile_storage"
branch = "cl_update_profile_branch"
sync_set = "update.cl_update_profile_sync_set"
def get(self):
url = self.Get(self.url)
if not url:
return ""
try:
rep_set = self.Get(self.storage)
branch = self.Get(self.branch)
rep = rep_set.get_repository(url, branch)
if rep and self.Get(self.sync_set) == 'on':
rep.sync()
return rep_set.get_repository(url, branch) or ""
except GitError:
return ""
class VariableClUpdateProfileRepositoryName(ReadonlyVariable):
"""
Название репозитория, из которого будут извлечены профили
"""
def get(self):
rep = self.Get('cl_update_profile_repository')
if rep:
return rep.repo_name
return ""
class VariableClUpdateProfileData(VariableClProfileData):
source = ["cl_update_profile_fullname",
"cl_update_profile_shortname",
"cl_update_profile_path",
"cl_update_profile_arch"]
repository = "cl_update_profile_repository"
class VariableClUpdateProfileFullname(FieldValue, ReadonlyVariable):
"""
Полное название профиля
"""
type = "list"
source_variable = "cl_update_profile_data"
column = 0
class VariableClUpdateProfileShortname(FieldValue, ReadonlyVariable):
"""
Упрощенное название профиля
"""
type = "list"
source_variable = "cl_update_profile_data"
column = 1
class VariableClUpdateProfilePath(FieldValue, ReadonlyVariable):
"""
Путь от корня до профиля
"""
type = "list"
source_variable = "cl_update_profile_data"
column = 2
class VariableClUpdateProfileArch(FieldValue, ReadonlyVariable):
"""
Архитектура профиля
"""
type = "list"
source_variable = "cl_update_profile_data"
column = 3
class VariableClUpdateProfileSystem(Variable):
"""
Профиль системы (симлинк /etc/make.profile')
"""
type = "choice"
opt = ["cl_update_profile_system"]
untrusted = True
metavalue = "PROFILE"
profiles_path = "cl_update_profile_path"
profiles_shortname = "cl_update_profile_shortname"
profiles_fullname = "cl_update_profile_fullname"
profiles_arch = "cl_update_profile_arch"
profile = "cl_profile_system"
url = "cl_update_profile_url"
gentoo_arch = 'os_arch_machine_gentoo'
def init(self):
self.label = _("System profile")
self.help = _("set the system profile")
def check(self, profile):
if not profile:
raise VariableError(_("You must specify the profile"))
path_profile = self.Select(self.profiles_path,
where=self.profiles_shortname,
eq=profile, limit=1)
profile_fullname = self.Select(self.profiles_fullname,
where=self.profiles_shortname,
eq=profile, limit=1)
if path_profile:
dv = DataVarsUpdateProfile(path_profile)
if ":" in profile_fullname:
repo_name = profile_fullname.partition(":")[0]
else:
repo_name = ""
try:
if (not dv.Get('cl_update_rep_name') or
not dv.Get('cl_update_rep_url')):
raise VariableError(
_("Repository variables "
"were not configured for the profile"))
if not dv.Get('os_linux_name'):
raise VariableError("")
if repo_name not in list(dv.Get('cl_update_rep_name')):
raise VariableError(
_("Overlay %s is not specified "
"in cl_update_rep_name") % repo_name)
except (DataVarsError,VariableError) as e:
if str(e):
message = ". " + str(e)
else:
message = ""
raise VariableError(_("The selected profile is not Calculate")
+ message)
else:
raise VariableError(_("Wrong Calculate profile"))
def get(self):
try:
profile_system = self.Get(self.profile)
profile = self.Select(self.profiles_shortname,
where=self.profiles_path,
eq=profile_system, limit=1)
if profile:
return profile
except VariableError:
pass
shortname = self.Get(self.profiles_shortname)
if len(shortname) == 1:
return shortname[0]
return ""
def choice(self):
url = self.Get(self.url)
if not url:
return []
arch = self.Get(self.gentoo_arch)
profiles = zip(*self.Select([self.profiles_shortname,
self.profiles_fullname],
where=self.profiles_arch, eq=arch))
if profiles:
short_name, full_name = profiles
return zip(short_name, full_name)
return []
class DataVarsUpdateProfile(SimpleDataVars):
"""
Упрощенная модель переменных для получения данных с удаленного профиля
"""
source = ['cl_update_rep_name',
'cl_update_rep_url',
'cl_update_rep_path',
'cl_update_rep_rev',
'cl_update_branch_name']
def __init__(self, profile, chroot_path='/', recheck=None):
SimpleDataVars.__init__(
self,
lib_linux.VariableOsLinuxName(),
lib_linux.VariableOsLinuxShortname(),
lib_linux.VariableOsLinuxSubname(),
lib_linux.VariableOsLinuxVer(),
lib_linux.VariableClProfileSystem(),
env.VariableClRepositoryData(),
env.VariableClRepositoryName(),
env.VariableClRepositoryLocation(),
env.VariableClChrootPath(),
env.VariableClTemplateLocation(),
env.VariableClTemplatePath(),
env.VariableClEmergeConfig(systemRoot=chroot_path),
env.VariableClFeatures(),
VariableClUpdateRepData(section="update"),
VariableClUpdateRepPath(section="update"),
VariableClUpdateRepRev(section="update"),
VariableClUpdateBranch(section="update"),
VariableClUpdateBranchName(section="update"),
VariableClUpdateLaymanConfig(section="update"),
VariableClUpdateLaymanStorage(section="update"),
VariableClUpdateRepName(section="update"),
VariableClUpdateRep(section="update"),
VariableClUpdateRepUrl(section="update"),
VariableClUpdateBinhost(section="update"),
VariableClUpdateBinhostData(section="update"),
VariableClUpdateBinhostHost(section="update"),
VariableClUpdateBinhostRecheckSet(section="update"),
VariableClUpdateBinhostRevisions(section="update"),
VariableClUpdateBinhostTime(section="update"),
VariableClUpdateBinhostTimeout(section="update"),
VariableClUpdateBinhostTimestampPath(section="update"),
VariableClUpdateBinhosts(section="update"),
VariableClUpdateBinhostRevisionPath(section="update"),
)
# TODO: при переключении профиля использовать master ветки
self.cache['cl_profile_system'] = profile
self.cache['cl_chroot_path'] = chroot_path
if recheck is not None:
self.cache['cl_update_binhost_recheck_set'] = recheck
self.flIniFileFrom(profile)
def __repr__(self):
return "Profile variables"
class VariableClUpdateProfileSyncSet(Variable):
"""
Синхронизировать репозиторий перед сменой профиля
"""
type = "bool"
value = "off"
opt = ["-u", "--update-cache"]
def init(self):
self.label = _("Update the cache")
self.help = _("Update the cache")
class VariableClUpdateAutocheckSet(Variable):
"""
Выполнять/невыполнять автопроверку обновлений
"""
type = "bool"
value = "on"
opt = ["-a", "--autocheck"]
def init(self):
self.label = _("Automatically check updates")
self.help = _("automatically check updates")
class VariableClUpdateAutocheckInterval(Variable):
"""
Интервал выполнения проверки
"""
type = "choiceedit"
opt = ["-I", "--autocheck-interval"]
metavalue = "INTERVAL"
def init(self):
self.label = _("Interval for the updates checking")
self.help = _("set interval for the updates checking")
def choice(self):
return [["6h",_("every six hours")],
["12h",_("every twelve hours")],
["1d",_("daily")]]
class VariableClUpdateAutocheckScheduleSet(Variable):
"""
Запустить проверку только если со времени последнего запуска прошло
необходимое время
"""
type = "bool"
value = "off"
opt = ["--schedule"]
def init(self):
self.label = _("Consider the autocheck schedule")
self.help = _("consider the autocheck schedule")
class VariableClUpdateEmergelistSet(Variable):
"""
Вывести список пакетов в формате emerge
"""
type = "bool"
value = "off"
opt = ["-e","--emergelist"]
def init(self):
self.label = _("Emerge-like packages list")
self.help = _("display the packages list in emerge format")
class VariableClUpdateKernelVersion(ReadonlyVariable):
"""
Текущая версия ядра
"""
def get(self):
return process('/bin/uname','-r').read().strip()
class VariableClUpdateKernelSrcPath(ReadonlyVariable):
"""
Каталог содержащий исходный код текущего ядра
"""
def get(self):
kernel_ver = self.Get('cl_update_kernel_version')
for template_path in ("/lib/modules/%s/build",
"/usr/src/linux-%s"):
src_path = template_path % kernel_ver
if path.exists(src_path):
if path.islink(src_path):
return os.readlink(src_path)
else:
return src_path
else:
return ""
class VariableClUpdateKernelPkg(ReadonlyVariable):
"""
Пакет текущего ядра
"""
def get(self):
src_path = self.Get('cl_update_kernel_src_path')
if src_path:
qfile = process('/usr/bin/qfile', '-vC', src_path)
if qfile.success():
return qfile.read().partition(" ")[0]
return ""
class VariableClUpdateLinesLimit(Variable):
"""
Количество выводимых строк при ошибке
"""
type = "int"
value = "30"
class VariableClUpdateSkipSetupSet(Variable):
"""
Пропустить выполнение cl-setup-system в cl-update-profile
"""
type = "bool"
value = "off"
opt = ["--skip-setup-system"]
def init(self):
self.label = _("Skip the system setup")
self.help = _("skip the system setup")
class VariableClUpdateCleanpkgSet(Variable):
"""
Пропустить выполнение cl-setup-system в cl-update-profile
"""
type = "bool"
value = "off"
opt = ["--clean-pkg"]
def init(self):
self.label = _("Clean obsolete programs archives")
self.help = _("clean obsolete programs archives")
class VariableClUpdateOutdatedKernelPath(Variable):
"""
Файл-флаг наличия устаревшего, неудаленного ядра
"""
value = "/var/lib/calculate/calculate-update/outdated_kernel"
class VariableClUpdateSkipRbSet(Variable):
"""
Пропусить revdep-rebuild
"""
type = "bool"
value = "off"
opt = ["-R", "--skip-revdep-rebuild"]
def init(self):
self.label = _("Skip reverse dependencies check")
self.help = _("skip reverse dependencies check")
class VariableClUpdateOutdatedKernelSet(ReadonlyVariable):
"""
Есть наличие устаревшего ядра
"""
type = "bool"
def get(self):
ui = UpdateInfo(self.parent)
return "on" if ui.outdated_kernel else "off"
class VariableClUpdateBinhosts(Variable):
"""
Список хостов с бинарными обновлениями
"""
type = "list"
value = ["ftp://ftp.calculate.ru/pub/calculate"]
class VariableClUpdateBinhost(Variable):
"""
Хост с бинарными обновлениями
"""
value = ""
class VariableClUpdateBinhostRevisionPath(Variable):
"""
Путь до revisions файлов
"""
type = "list"
value = [
"grp/default/ini.env",
"grp/kde/ini.env",
"grp/server/ini.env",
"grp/x/ini.env"
]
class VariableClUpdateBinhostTimestampPath(Variable):
"""
Путь до файла timestamp
"""
value = "timestamp"
class VariableClUpdateBinhostTimeout(Variable):
"""
Таймаут на проверку одного binhost
"""
type = "int"
value = "5"