|
|
|
@ -0,0 +1,223 @@
|
|
|
|
|
commit 77950c9102160e20fceef81f486d26bc1d26b39a
|
|
|
|
|
Author: Mike khiretskiy <mh@calculate.ru>
|
|
|
|
|
Date: Mon Mar 24 13:29:41 2014 +0400
|
|
|
|
|
|
|
|
|
|
Добавлена пересборка измененных пакетов
|
|
|
|
|
|
|
|
|
|
Добавлена пересборка пакетов у которых различаются зависимости
|
|
|
|
|
в дереве портежей и установленых
|
|
|
|
|
|
|
|
|
|
diff --git pym/cl_assemble.py pym/cl_assemble.py
|
|
|
|
|
index ded1c47..9824d71 100644
|
|
|
|
|
--- pym/cl_assemble.py
|
|
|
|
|
+++ 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:
|
|
|
|
|
@@ -173,6 +176,10 @@ class cl_assemble(color_print):
|
|
|
|
|
# update world
|
|
|
|
|
{'command':'emerge -uDN --with-bdeps=y world',
|
|
|
|
|
'step':'update'},
|
|
|
|
|
+ # rebuild chanaged packages
|
|
|
|
|
+ {'command':'rebuildChangedPackages()',
|
|
|
|
|
+ 'message':_("Rebuild modified packages"),
|
|
|
|
|
+ 'step':'rebuild_chanaged'},
|
|
|
|
|
# depclean
|
|
|
|
|
{'command':'emerge --depclean',
|
|
|
|
|
'step':'depclean'},
|
|
|
|
|
@@ -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 pym/tools.py pym/tools.py
|
|
|
|
|
new file mode 100644
|
|
|
|
|
index 0000000..47e8d09
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ 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
|