|
|
|
@ -19,74 +19,29 @@ import re
|
|
|
|
|
import sys
|
|
|
|
|
import time
|
|
|
|
|
from os import path
|
|
|
|
|
from subprocess import Popen
|
|
|
|
|
from calculate.lib.utils.files import (process,getProgPath,STDOUT,removeDir,
|
|
|
|
|
processProgress)
|
|
|
|
|
processProgress,PercentProgress,process)
|
|
|
|
|
|
|
|
|
|
class UpdateError(Exception):
|
|
|
|
|
"""Update Error"""
|
|
|
|
|
|
|
|
|
|
class GitError(Exception):
|
|
|
|
|
"""Git Error"""
|
|
|
|
|
class AddonError(Exception):
|
|
|
|
|
"""
|
|
|
|
|
Исключение с добавочным сообщением
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, msg, addon=None):
|
|
|
|
|
self.message = msg
|
|
|
|
|
self.addon = addon
|
|
|
|
|
Exception.__init__(self,msg)
|
|
|
|
|
|
|
|
|
|
class UpdateError(AddonError):
|
|
|
|
|
"""Update Error"""
|
|
|
|
|
|
|
|
|
|
class GitError(AddonError):
|
|
|
|
|
"""Git Error"""
|
|
|
|
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
|
|
|
|
|
setLocalTranslate('cl_update3',sys.modules[__name__])
|
|
|
|
|
__ = getLazyLocalTranslate(_)
|
|
|
|
|
|
|
|
|
|
class PercentProgress(processProgress):
|
|
|
|
|
"""
|
|
|
|
|
Объект выдает прогресс, ища в выводе \d+%
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
part: количество прогрессов в программе
|
|
|
|
|
delimeter: разделители строк по умолчанию \n и \r
|
|
|
|
|
cachefilter: фильтр вывода программы (регулярная строка)
|
|
|
|
|
startpart: используется для вывода процентов прогрессбар
|
|
|
|
|
с определенного места (0 по умолчанию)
|
|
|
|
|
end: конечный прогрессбар (по умолчанию)
|
|
|
|
|
"""
|
|
|
|
|
def init(self,*args,**kwargs):
|
|
|
|
|
self.rePerc = re.compile("(\d+)%",re.S)
|
|
|
|
|
self.part = kwargs.get("part",1)
|
|
|
|
|
self.add_offset = 100 / self.part
|
|
|
|
|
self.offset = 0 + kwargs.get("startpart",0)*self.add_offset
|
|
|
|
|
self.is_end = kwargs.get("end",True)
|
|
|
|
|
self.stderr = STDOUT
|
|
|
|
|
self.delimeter = re.compile("[%s]"%kwargs.get("delimeter","\n\r"))
|
|
|
|
|
self.cachedata = re.compile(kwargs.get("cachefilter",
|
|
|
|
|
"((?:error|warning|fatal):.*)"))
|
|
|
|
|
|
|
|
|
|
def processInit(self):
|
|
|
|
|
self.percent = 0
|
|
|
|
|
self.showval = 0
|
|
|
|
|
if not self.offset:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def processEnd(self):
|
|
|
|
|
if self.is_end:
|
|
|
|
|
self.percent = 100
|
|
|
|
|
return 100
|
|
|
|
|
|
|
|
|
|
def processString(self,strdata):
|
|
|
|
|
match = self.rePerc.search(strdata)
|
|
|
|
|
resSearch = self.cachedata.search(strdata)
|
|
|
|
|
if resSearch:
|
|
|
|
|
self.cacheresult.append(resSearch.group(1))
|
|
|
|
|
if match:
|
|
|
|
|
percent = int(match.group(1))
|
|
|
|
|
if percent < self.percent:
|
|
|
|
|
self.offset = self.offset + self.add_offset
|
|
|
|
|
percent = percent / self.part
|
|
|
|
|
if percent != self.percent:
|
|
|
|
|
self.percent = percent
|
|
|
|
|
showval = min(99,self.percent + self.offset)
|
|
|
|
|
if showval != self.showval:
|
|
|
|
|
self.showval = showval
|
|
|
|
|
return self.showval
|
|
|
|
|
|
|
|
|
|
class Git:
|
|
|
|
|
"""
|
|
|
|
|
Объект для управление git репозиторием
|
|
|
|
@ -163,7 +118,10 @@ class Git:
|
|
|
|
|
Return:
|
|
|
|
|
Возвращает True если клонирование произведено с установкой на
|
|
|
|
|
указанную ревизию. False если клонирование произведено с
|
|
|
|
|
установкой на последнюю ревизию. В остальных случаях GitError
|
|
|
|
|
установкой на последнюю ревизию.
|
|
|
|
|
Raises:
|
|
|
|
|
GitError: Выполнение ключевых команд выполнено с ошибками (не
|
|
|
|
|
удалось скачать и получить данные из удаленного репозитория)
|
|
|
|
|
"""
|
|
|
|
|
git_dir = self.__gitDir(rpath)
|
|
|
|
|
error = []
|
|
|
|
@ -357,10 +315,19 @@ class Git:
|
|
|
|
|
to_origin: откатить все изменения до удаленного репозитория
|
|
|
|
|
to_rev: откатить все изменения до определенной ревизии
|
|
|
|
|
info: использовать уже полученную информация об изменения в репозитории
|
|
|
|
|
Return:
|
|
|
|
|
True - успешное выполнение
|
|
|
|
|
False - нет необходимости выполнять reset
|
|
|
|
|
Raises:
|
|
|
|
|
GitError: выполнение комманд reset и clean прошло с ошибкой
|
|
|
|
|
"""
|
|
|
|
|
git_dir = self.__gitDir(rpath)
|
|
|
|
|
if to_origin and not info:
|
|
|
|
|
if not info:
|
|
|
|
|
info = self._getStatusInfo(rpath)
|
|
|
|
|
if (all(not info[x] for x in ("files","ahead","behind") if x in info)
|
|
|
|
|
and (not info["origin"] or
|
|
|
|
|
"origin/%s"%info["branch"] == info["origin"])):
|
|
|
|
|
return False
|
|
|
|
|
commit = (info['origin'] if to_origin else to_rev) or "HEAD"
|
|
|
|
|
git_reset = process(self._git,"--git-dir",git_dir,"--work-tree",rpath,
|
|
|
|
|
"reset","--hard", commit, stderr=STDOUT)
|
|
|
|
@ -369,6 +336,7 @@ class Git:
|
|
|
|
|
if git_reset.failed() or git_clean.failed():
|
|
|
|
|
raise GitError(_("Failed to clean {rpath} repository").format(
|
|
|
|
|
rpath=rpath))
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def _getBranch(self,rpath):
|
|
|
|
|
"""
|
|
|
|
@ -406,7 +374,9 @@ class Update:
|
|
|
|
|
"""
|
|
|
|
|
Синхронизировать репозиторий
|
|
|
|
|
"""
|
|
|
|
|
dv = self.clVars
|
|
|
|
|
git = Git()
|
|
|
|
|
needMeta = False
|
|
|
|
|
if not git._checkExistsRep(rpath):
|
|
|
|
|
if revision == "last":
|
|
|
|
|
git._cloneRepository(url, rpath, branch,
|
|
|
|
@ -414,6 +384,7 @@ class Update:
|
|
|
|
|
else:
|
|
|
|
|
git._cloneRevRepository(url, rpath, branch, revision,
|
|
|
|
|
cb_progress=cb_progress)
|
|
|
|
|
needMeta = True
|
|
|
|
|
else:
|
|
|
|
|
# если нужно обновиться до конкретной ревизии
|
|
|
|
|
if revision != "last":
|
|
|
|
@ -426,11 +397,16 @@ class Update:
|
|
|
|
|
repInfo = git._getStatusInfo(rpath)
|
|
|
|
|
if repInfo['branch'] != branch:
|
|
|
|
|
# меняем ветку
|
|
|
|
|
needMeta = True
|
|
|
|
|
git._checkoutBranch(rpath,branch)
|
|
|
|
|
if revision == "last":
|
|
|
|
|
git._resetRepository(rpath, to_origin=True)
|
|
|
|
|
if git._resetRepository(rpath, to_origin=True):
|
|
|
|
|
needMeta = True
|
|
|
|
|
else:
|
|
|
|
|
git._resetRepository(rpath, to_rev=revision)
|
|
|
|
|
needMeta = True
|
|
|
|
|
if needMeta:
|
|
|
|
|
dv.Set('cl_update_outdate_set','on',force=True)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def syncRepositories(self,repname,clean_on_error=True):
|
|
|
|
@ -442,6 +418,8 @@ class Update:
|
|
|
|
|
dv.Select(["cl_update_rep_url","cl_update_rep_path",
|
|
|
|
|
"cl_update_rep_rev","cl_update_branch_name"],
|
|
|
|
|
where="cl_update_rep_name",eq=repname,limit=1))
|
|
|
|
|
if not url or not rpath:
|
|
|
|
|
raise UpdateError(_("Repositories variables is not configured"))
|
|
|
|
|
self.addProgress()
|
|
|
|
|
if clean_on_error:
|
|
|
|
|
try:
|
|
|
|
@ -453,7 +431,94 @@ class Update:
|
|
|
|
|
self.printWARNING(str(e.addon))
|
|
|
|
|
self.printWARNING(str(e))
|
|
|
|
|
self.printWARNING(_("Re-fetch {name} repository"
|
|
|
|
|
).format(name=name))
|
|
|
|
|
).format(name=repname))
|
|
|
|
|
removeDir(rpath)
|
|
|
|
|
self._syncRepository(name,url,rpath,revision,branch)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def syncLaymanRepository(self,repname):
|
|
|
|
|
"""
|
|
|
|
|
Обновить репозиторий через layman
|
|
|
|
|
"""
|
|
|
|
|
layman = getProgPath('/usr/bin/layman')
|
|
|
|
|
if not layman:
|
|
|
|
|
raise UpdateError(_("Layman utility is not found"))
|
|
|
|
|
rpath = self.clVars.Select('cl_update_other_rep_path',
|
|
|
|
|
where='cl_update_other_rep_name',eq=repname,limit=1)
|
|
|
|
|
laymanname = path.basename(rpath)
|
|
|
|
|
if path.exists(path.join(rpath,'.git')):
|
|
|
|
|
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 repository {rname}"
|
|
|
|
|
).format(rname=repname),addon=p.read())
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def regenCache(self,repname):
|
|
|
|
|
"""
|
|
|
|
|
Обновить кэш метаданных репозитория
|
|
|
|
|
"""
|
|
|
|
|
egenCache = getProgPath('/usr/bin/egencache')
|
|
|
|
|
if not egenCache:
|
|
|
|
|
raise UpdateError(_("Portage utility is not found"))
|
|
|
|
|
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 cache of {rname} repository"
|
|
|
|
|
).format(rname=repname),addon=p.read())
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def emergeMetadata(self):
|
|
|
|
|
"""
|
|
|
|
|
Выполнить egencache и emerge --metadata
|
|
|
|
|
"""
|
|
|
|
|
emerge = getProgPath("/usr/bin/emerge")
|
|
|
|
|
if not emerge:
|
|
|
|
|
raise UpdateError(_("Emerge utility is not found"))
|
|
|
|
|
self.addProgress()
|
|
|
|
|
p = PercentProgress(emerge,"--metadata",part=1,atty=True)
|
|
|
|
|
for perc in p.progress():
|
|
|
|
|
self.setProgress(perc)
|
|
|
|
|
if p.failed():
|
|
|
|
|
raise UpdateError(_("Failed to update metadata"),addon=p.read())
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def eixUpdate(self):
|
|
|
|
|
"""
|
|
|
|
|
Выполенине eix-update для репозиторием
|
|
|
|
|
|
|
|
|
|
eix-update выполнятется только для тех репозиториев, которые
|
|
|
|
|
обновлялись, если cl_update_eixsync_force==auto, либо
|
|
|
|
|
все, если cl_update_eixupdate_force==force
|
|
|
|
|
"""
|
|
|
|
|
eixupdate = getProgPath("/usr/bin/eix-update")
|
|
|
|
|
if not eixupdate:
|
|
|
|
|
raise UpdateError(_("Eix utility is not found"))
|
|
|
|
|
self.addProgress()
|
|
|
|
|
excludeList = []
|
|
|
|
|
if self.clVars.Get('cl_update_eixupdate_force') == 'force':
|
|
|
|
|
countRep = len(self.clVars.Get('cl_update_rep_name'))
|
|
|
|
|
else:
|
|
|
|
|
for rep in self.clVars.Get('cl_update_rep_name'):
|
|
|
|
|
# подстановка имен
|
|
|
|
|
mapNames = {'portage':'gentoo'}
|
|
|
|
|
if not rep in self.clVars.Get('cl_update_sync_rep'):
|
|
|
|
|
excludeList.extend(["-x",mapNames.get(rep,rep)])
|
|
|
|
|
countRep = len(self.clVars.Get('cl_update_sync_rep'))
|
|
|
|
|
if (self.clVars.Get('cl_update_other_set') == 'on' or
|
|
|
|
|
self.clVars.Get('cl_update_eixupdate_force') == 'force'):
|
|
|
|
|
countRep += len(self.clVars.Get('update.cl_update_other_rep_name'))
|
|
|
|
|
else:
|
|
|
|
|
for rep in self.clVars.Get('update.cl_update_other_rep_name'):
|
|
|
|
|
excludeList.extend(['-x',rep])
|
|
|
|
|
p = PercentProgress(eixupdate,"-F",*excludeList,part=countRep or 1,atty=True)
|
|
|
|
|
for perc in p.progress():
|
|
|
|
|
self.setProgress(perc)
|
|
|
|
|
if p.failed():
|
|
|
|
|
raise UpdateError(_("Failed to update eix cache"),addon=p.read())
|
|
|
|
|
return True
|
|
|
|
|