From 45ebfe3d8d887313a4a19210bd8d35d768b3a53e Mon Sep 17 00:00:00 2001 From: Mike Khiretskiy Date: Thu, 11 Sep 2014 15:43:00 +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=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=BE?= =?UTF-8?q?=D0=B5=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20egencache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- update/package_tools.py | 2 + update/update.py | 211 +++++++++++++++++++++++++++++--------- update/utils/cl_update.py | 2 - 3 files changed, 163 insertions(+), 52 deletions(-) diff --git a/update/package_tools.py b/update/package_tools.py index 7d9b879..c251007 100644 --- a/update/package_tools.py +++ b/update/package_tools.py @@ -141,6 +141,8 @@ class Git: """ Объект для управление git репозиторием """ + skip_files = ["metadata/md5-cache", + "metadata/cache"] def __init__(self): self._git = self.__getGit() diff --git a/update/update.py b/update/update.py index c2eb158..88e7693 100644 --- a/update/update.py +++ b/update/update.py @@ -29,6 +29,7 @@ from calculate.lib.utils.colortext.palette import TextState from calculate.lib.utils.colortext import get_color_print from calculate.update.emerge_parser import RevdepPercentBlock import re +from collections import MutableSet from package_tools import Git, Layman,\ EmergeLogNamedTask, EmergeLog, GitError, \ @@ -51,6 +52,47 @@ __ = getLazyLocalTranslate(_) class UpdateError(AddonError): """Update Error""" +class OverlayOwnCache(MutableSet): + """ + Сет оверлеев с интегрированным кэшем + """ + def __init__(self, initvalue=()): + pass + + def __get_overlays(self): + own_cache_value = SystemIni().getVar('update', 'own_cache') or "" + return [x.strip() for x in own_cache_value.split(',') if x.strip()] + + def __write_overlays(self, overlays): + if not overlays: + SystemIni().delVar('update', 'own_cache') + else: + SystemIni().setVar('update', {'own_cache': ",".join(overlays)}) + + def __contains__(self, item): + return item in self.__get_overlays() + + def __iter__(self): + return iter(self.__get_overlays()) + + def __len__(self): + return len(self.__get_overlays()) + + def __append_value(self, overlays, value): + if value not in overlays: + overlays.append(value) + self.__write_overlays(overlays) + + def add(self, value): + overlays = self.__get_overlays() + self.__append_value(overlays, value) + + def discard(self, value): + overlays = self.__get_overlays() + if value in overlays: + overlays.remove(value) + self.__write_overlays(overlays) + class Update: """Основной объект для выполнения действий связанных с обновлением системы @@ -78,40 +120,44 @@ class Update: dv = self.clVars git = Git() needMeta = False - if not git.checkExistsRep(rpath): - if revision == "last": - git.cloneRepository(url, rpath, branch, - cb_progress=cb_progress) - else: - git.cloneRevRepository(url, rpath, branch, revision, - cb_progress=cb_progress) - needMeta = True - else: - # если нужно обновиться до конкретной ревизии - if revision != "last": - if revision == git.getCurrentCommit(rpath): - if git.getBranch(rpath) == branch: - return False - # получить изменения из удаленного репозитория - git.fetchRepository(rpath, cb_progress=cb_progress) - # если текущая ветка не соответствует нужной - repInfo = git.getStatusInfo(rpath) - if repInfo['branch'] != branch: - # меняем ветку + try: + self.stash_cache(rpath, name) + if not git.checkExistsRep(rpath): + if revision == "last": + git.cloneRepository(url, rpath, branch, + cb_progress=cb_progress) + else: + git.cloneRevRepository(url, rpath, branch, revision, + cb_progress=cb_progress) needMeta = True - git.checkoutBranch(rpath, branch) - if revision == "last": - if git.resetRepository(rpath, to_origin=True): - # если не удалось сбросить - repInfo = git.getStatusInfo(rpath) - if repInfo.get("files", False): - raise GitError("Failed to reset git") - needMeta = True else: - git.resetRepository(rpath, to_rev=revision) - needMeta = True - if needMeta: - dv.Set('cl_update_outdate_set', 'on', force=True) + # если нужно обновиться до конкретной ревизии + if revision != "last": + if revision == git.getCurrentCommit(rpath): + if git.getBranch(rpath) == branch: + return False + # получить изменения из удаленного репозитория + git.fetchRepository(rpath, cb_progress=cb_progress) + # если текущая ветка не соответствует нужной + repInfo = git.getStatusInfo(rpath) + if repInfo['branch'] != branch: + # меняем ветку + needMeta = True + git.checkoutBranch(rpath, branch) + if revision == "last": + if git.resetRepository(rpath, to_origin=True): + # если не удалось сбросить + repInfo = git.getStatusInfo(rpath) + if repInfo.get("files", False): + raise GitError("Failed to reset git") + needMeta = True + else: + git.resetRepository(rpath, to_rev=revision) + needMeta = True + if needMeta: + dv.Set('cl_update_outdate_set', 'on', force=True) + finally: + self.unstash_cache(rpath, name) return True def setAutocheckParams(self, status, interval): @@ -245,6 +291,61 @@ class Update: layman.add(repname, url, rpath) return True + metadata_cache_names = ("metadata/md5-cache", "metadata/cache") + + def stash_cache(self, rpath, name): + """ + Спрятать кэш + """ + if name in ("portage",): + return + if not name in OverlayOwnCache(): + for cachename in self.metadata_cache_names: + cachedir = path.join(rpath, cachename) + if path.exists(cachedir): + try: + cachedir_s = path.join(path.dirname(rpath), + path.basename( + cachename) + ".stash") + if path.exists(cachedir_s): + removeDir(cachedir_s) + os.rename(cachedir, cachedir_s) + except BaseException as e: + pass + + def unstash_cache(self, rpath, name): + """ + Извлеч кэш + """ + if name in ("portage",): + return + cachenames = self.metadata_cache_names + if not name in OverlayOwnCache(): + if any(path.exists(path.join(rpath, x)) for x in cachenames): + for cachename in cachenames: + cachedir_s = path.join(path.dirname(rpath), + path.basename(cachename)+".stash") + if path.exists(cachedir_s): + try: + removeDir(cachedir_s) + except BaseException as e: + pass + OverlayOwnCache().add(name) + else: + for cachename in cachenames: + cachedir = path.join(rpath, cachename) + cachedir_s = path.join(path.dirname(rpath), + path.basename(cachename)+".stash") + if path.exists(cachedir_s): + try: + os.rename(cachedir_s, cachedir) + except BaseException as e: + pass + else: + if all(not path.exists(path.join(rpath, x)) for x in cachenames): + OverlayOwnCache().discard(name) + + def syncLaymanRepository(self, repname): """ Обновить репозиторий через layman @@ -256,17 +357,21 @@ class Update: where='cl_update_other_rep_name', eq=repname, limit=1) laymanname = path.basename(rpath) - if Git.is_git(rpath): - self.addProgress() - p = PercentProgress(layman, "-s", laymanname, part=1, atty=True) - for perc in p.progress(): - self.setProgress(perc) - else: - p = process(layman, "-s", repname, stderr=STDOUT) - if p.failed(): - raise UpdateError( - _("Failed to update the {rname} repository").format(rname=repname), - addon=p.read()) + self.stash_cache(rpath, laymanname) + try: + if Git.is_git(rpath): + self.addProgress() + p = PercentProgress(layman, "-s", laymanname, part=1, atty=True) + for perc in p.progress(): + self.setProgress(perc) + else: + p = process(layman, "-s", repname, stderr=STDOUT) + if p.failed(): + raise UpdateError( + _("Failed to update the {rname} repository").format(rname=repname), + addon=p.read()) + finally: + self.unstash_cache(rpath, laymanname) return True def regenCache(self, repname): @@ -281,7 +386,7 @@ class Update: where='cl_update_rep_name', eq=repname, limit=1) repo_name = readFile( - path.join(path_rep,"profiles/repo_name")).strip() + path.join(path_rep, "profiles/repo_name")).strip() if repo_name != repname: self.printWARNING( _("Repository '{repo_name}' called '{repname}'" @@ -290,12 +395,18 @@ class Update: raise UpdateError(_("Failed to update the cache of the {rname} " "repository").format(rname=repname)) cpu_num = self.clVars.Get('hr_cpu_num') - p = process(egenCache, "--repo=%s" % repname, "--update", - "--jobs=%s" % cpu_num, stderr=STDOUT) - if p.failed(): - raise UpdateError(_("Failed to update the cache of the {rname} " - "repository").format(rname=repname), - addon=p.read()) + if repname in OverlayOwnCache(): + self.printWARNING( + _("Repository %s has own cache") % repname.capitalize()) + else: + self.startTask(_("Updating the %s repository cache") % + repname.capitalize()) + p = process(egenCache, "--repo=%s" % repname, "--update", + "--jobs=%s" % cpu_num, stderr=STDOUT) + if p.failed(): + raise UpdateError(_("Failed to update the cache of the {rname} " + "repository").format(rname=repname), + addon=p.read()) return True def emergeMetadata(self): diff --git a/update/utils/cl_update.py b/update/utils/cl_update.py index 5204e61..8bf3abc 100644 --- a/update/utils/cl_update.py +++ b/update/utils/cl_update.py @@ -234,7 +234,6 @@ class ClUpdateAction(Action): }, {'name': 'sync_reps:regen_cache', 'foreach': 'cl_update_sync_overlay_rep', - 'message': __("Updating the {eachvar:capitalize} repository cache"), 'essential': False, 'method': 'Update.regenCache(eachvar)', 'condition': ( @@ -244,7 +243,6 @@ class ClUpdateAction(Action): }, {'name': 'sync_other_reps:regen_other_cache', 'foreach': 'cl_update_other_rep_name', - 'message': __("Updating the {eachvar:capitalize} repository cache"), 'method': 'Update.regenCache(eachvar)', 'essential': False, },