From 0e99d3c416723361b0720c5209265d1030225e2a Mon Sep 17 00:00:00 2001 From: Mike khiretskiy Date: Mon, 24 Mar 2014 13:29:41 +0400 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B5=D1=81=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Добавлена пересборка пакетов у которых различаются зависимости в дереве портежей и установленых --- pym/cl_assemble.py | 39 ++++++++++++- pym/tools.py | 141 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 pym/tools.py diff --git a/pym/cl_assemble.py b/pym/cl_assemble.py index ded1c47..a1c8655 100644 --- a/pym/cl_assemble.py +++ b/pym/cl_assemble.py @@ -1,6 +1,6 @@ #-*- coding: utf-8 -*- -# Copyright 2010 Calculate Ltd. http://www.calculate-linux.org +# Copyright 2010-2014 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. @@ -43,6 +43,9 @@ import random from shutil import copyfile import time from itertools import * +from tools import SimpleRepositoryMapper, InstalledPackageInfo, EbuildInfo, \ + EbuildInfoError + def DEBUG(msg): if "DEBUG" in os.environ: @@ -176,6 +179,10 @@ class cl_assemble(color_print): # depclean {'command':'emerge --depclean', 'step':'depclean'}, + # rebuild chanaged packages + {'command':'rebuildChangedPackages()', + 'message':_("Rebuild modified packages"), + 'step':'rebuild_chanaged'}, # module rebuild {'command':'emerge @module-rebuild', 'step':'module', @@ -2054,3 +2061,33 @@ class cl_assemble(color_print): useName): return True return False + + def rebuildChangedPackages(self): + if not self.assemblePath: + self.assemblePath = \ + self.clVars.Get('cl_assemble_path') + + varDbPath = path.join(self.assemblePath, 'var/db/pkg') + InstalledPackageInfo.pkg_dir = varDbPath + EbuildInfo.set_repository_mapper( + SimpleRepositoryMapper(self.assemblePath)) + + def rebuild_generator(): + for pkg in InstalledPackageInfo.get_install_packages(): + try: + if pkg != EbuildInfo(pkg.atom, pkg['repository']): + yield pkg.atom + except EbuildInfoError: + yield pkg.atom + rebuild_list = map(lambda x:"=%s"%x, rebuild_generator()) + print "Package list:", ",".join(rebuild_list) + if rebuild_list: + rebuild_packages = " ".join(rebuild_list) + + cmd = self.runChroot("emerge -1 %s" % rebuild_packages, + showProcess=True) + if cmd.failed(): + raise AssembleError( + _("An error occurred when executing the command")+ + ":\n %s"%self._getCommand(cmd.command)) + return True diff --git a/pym/tools.py b/pym/tools.py new file mode 100644 index 0000000..47e8d09 --- /dev/null +++ b/pym/tools.py @@ -0,0 +1,141 @@ +#-*- coding: utf-8 -*- + +# Copyright 2014 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 collections import Mapping +from functools import total_ordering + +from os import path +import bz2 +import re +try: + from calculate.lib.utils.files import readFile, listDirectory, pathJoin +except ImportError: + from cl_utils import readFile, listDirectory, pathJoin + + +class SimpleRepositoryMapper(Mapping): + """ + Определение пути до репозитория + """ + map_repository = {'gentoo': '/usr/portage', + 'calculate': '/var/lib/layman/calculate'} + layman_path = '/var/lib/layman' + + def __init__(self, prefix='/'): + self.prefix = prefix + + def __getitem__(self, item): + if item in self.map_repository: + return pathJoin(self.prefix, self.map_repository[item]) + return pathJoin(self.prefix, self.layman_path, item) + + def __iter__(self): + return iter(self.map_repository) + + def __len__(self): + return len(self.map_repository) + + +class EbuildInfoError(Exception): + pass + + +class EbuildInfo(object): + """ + Информация о ebuild (DEPEND) из metadata + """ + map_repository = SimpleRepositoryMapper() + meta_suffix_path = 'metadata/md5-cache' + support_keys = ('DEPEND', 'RDEPEND', 'PDEPEND') + + def __init__(self, atom, repository): + meta_path = path.join(self.map_repository[repository], + self.meta_suffix_path) + self._meta_info_path = path.join(meta_path, atom) + if not path.exists(self._meta_info_path): + raise EbuildInfoError("Package is not found") + self._info = self._get_info() + + def _get_info(self): + with open(self._meta_info_path, 'r') as f: + return {k.strip(): v.strip() for k, v in (line.partition('=')[::2] + for line in f.readlines()) + if k in self.support_keys} + + def __getitem__(self, item): + if item in self.support_keys: + return self._info.get(item,'') + raise KeyError(item) + + @classmethod + def set_repository_mapper(cls, mapper): + cls.map_repository = mapper + + def __eq__(self, other): + return all(other[k] == self[k] for k in self.support_keys) + + def __ne__(self, other): + return any(other[k] != self[k] for k in self.support_keys) + + +class InstalledPackageInfoError(Exception): + pass + + +class InstalledPackageInfo(object): + """ + Информация об установленном пакете (DEPEND) из /var/db/pkg + """ + pkg_dir = '/var/db/pkg' + depend_pattern = 'declare (?:-x )?({0})="([^"]+)"' + re_depend = re.compile(depend_pattern.format("RDEPEND|PDEPEND|DEPEND"), + re.DOTALL) + re_multispace = re.compile("\s+", re.DOTALL) + + def __init__(self, atom): + self.atom = atom + self._pkg_path = path.join(self.pkg_dir, atom) + if not path.exists(self._pkg_path): + raise InstalledPackageInfoError("Package is not found") + self._info = self._get_info() + + def _get_info(self): + info = {k: "" for k in ("RDEPEND", "DEPEND", "PDEPEND")} + env_path = path.join(self._pkg_path, 'environment.bz2') + if path.exists(env_path): + with bz2.BZ2File(env_path, 'r') as f: + for r in self.re_depend.finditer(f.read()): + key, value = r.groups() + value = self.re_multispace.sub(" ", value) + info[key] = value.strip() + rep_path = path.join(self._pkg_path, 'repository') + info['repository'] = readFile(rep_path).strip() + return info + + def __getitem__(self, item): + return self._info[item] + + @classmethod + def get_install_packages(cls): + for category in listDirectory(cls.pkg_dir): + for pkg in listDirectory(path.join(cls.pkg_dir, category)): + yield InstalledPackageInfo("%s/%s" % (category, pkg)) + + def __str__(self): + return self.atom + + def __repr__(self): + return "InstalledPackageInfo(%s)" % self.atom