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.

732 lines
29 KiB

  1. #-*- coding: utf-8 -*-
  2. # Copyright 2014 Calculate Ltd. http://www.calculate-linux.org
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from itertools import ifilter
  16. import random
  17. import sys
  18. from os import path
  19. import os
  20. import time
  21. from calculate.core.server.gen_pid import search_worked_process, ProcessStatus
  22. from calculate.lib.cl_template import SystemIni
  23. from calculate.lib.datavars import DataVarsError
  24. from calculate.lib.utils.tools import AddonError
  25. from calculate.lib.utils.colortext.palette import TextState
  26. from calculate.lib.utils.colortext import get_color_print
  27. from calculate.update.emerge_parser import RevdepPercentBlock
  28. import math
  29. from package_tools import Git, Layman,\
  30. EmergeLogNamedTask, EmergeLog, GitError, \
  31. PackageInformation, PackageList, EmergePackage
  32. Colors = TextState.Colors
  33. from calculate.lib.utils.files import (getProgPath, STDOUT, removeDir,
  34. PercentProgress, process, getRunCommands,
  35. readFile, listDirectory)
  36. import emerge_parser
  37. import logging
  38. from emerge_parser import EmergeParser, EmergeCommand, EmergeError, EmergeCache
  39. from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate,
  40. RegexpLocalization, _)
  41. setLocalTranslate('cl_update3', sys.modules[__name__])
  42. __ = getLazyLocalTranslate(_)
  43. class UpdateError(AddonError):
  44. """Update Error"""
  45. class Update:
  46. """Основной объект для выполнения действий связанных с обновлением системы
  47. """
  48. def init(self):
  49. commandLog = path.join(self.clVars.Get('core.cl_log_path'),
  50. 'lastcommand.log')
  51. emerge_parser.CommandExecutor.logfile = commandLog
  52. self.color_print = get_color_print()
  53. self.emerge_cache = EmergeCache()
  54. if self.clVars.Get('cl_env_debug_set') == 'off':
  55. EmergeCache.logger.logger.setLevel(logging.WARNING)
  56. self.emerge_cache.check_list = (
  57. self.emerge_cache.check_list +
  58. map(emerge_parser.GitCheckvalue,
  59. self.clVars.Get('update.cl_update_rep_path')))
  60. self.update_map = {}
  61. def _syncRepository(self, name, url, rpath, revision, branch,
  62. cb_progress=None):
  63. """
  64. Синхронизировать репозитори
  65. """
  66. dv = self.clVars
  67. git = Git()
  68. needMeta = False
  69. if not git.checkExistsRep(rpath):
  70. if revision == "last":
  71. git.cloneRepository(url, rpath, branch,
  72. cb_progress=cb_progress)
  73. else:
  74. git.cloneRevRepository(url, rpath, branch, revision,
  75. cb_progress=cb_progress)
  76. needMeta = True
  77. else:
  78. # если нужно обновиться до конкретной ревизии
  79. if revision != "last":
  80. if revision == git.getCurrentCommit(rpath):
  81. if git.getBranch(rpath) == branch:
  82. return False
  83. # получить изменения из удаленного репозитория
  84. git.fetchRepository(rpath, cb_progress=cb_progress)
  85. # если текущая ветка не соответствует нужной
  86. repInfo = git.getStatusInfo(rpath)
  87. if repInfo['branch'] != branch:
  88. # меняем ветку
  89. needMeta = True
  90. git.checkoutBranch(rpath, branch)
  91. if revision == "last":
  92. if git.resetRepository(rpath, to_origin=True):
  93. # если не удалось сбросить
  94. repInfo = git.getStatusInfo(rpath)
  95. if repInfo.get("files", False):
  96. raise GitError("Failed to reset git")
  97. needMeta = True
  98. else:
  99. git.resetRepository(rpath, to_rev=revision)
  100. needMeta = True
  101. if needMeta:
  102. dv.Set('cl_update_outdate_set', 'on', force=True)
  103. return True
  104. def checkRun(self, wait_update):
  105. """
  106. Проверить повторный запуск
  107. """
  108. update_running = lambda: any(os.getpid() != x
  109. for x in search_worked_process('update', dv))
  110. dv = self.clVars
  111. if update_running():
  112. if not wait_update:
  113. raise UpdateError(_("Update is already running. "
  114. "Try to run later."))
  115. else:
  116. self.startTask(_("Waiting for another update to be complete"))
  117. while update_running():
  118. self.pauseProcess()
  119. while update_running():
  120. time.sleep(0.3)
  121. self.resumeProcess()
  122. time.sleep(random.random()*3)
  123. self.endTask()
  124. emerge_running = lambda: any("/usr/bin/emerge" in x
  125. for x in getRunCommands())
  126. if emerge_running():
  127. if not wait_update:
  128. raise UpdateError(_("Emerge is running. "
  129. "Try to run later."))
  130. else:
  131. self.startTask(_("Waiting for emerge to be complete"))
  132. while emerge_running():
  133. time.sleep(1)
  134. self.endTask()
  135. return True
  136. def syncRepositories(self, repname, clean_on_error=True):
  137. """
  138. Синхронизировать репозитории
  139. """
  140. dv = self.clVars
  141. url, rpath, revision, branch = (
  142. dv.Select(["cl_update_rep_url", "cl_update_rep_path",
  143. "cl_update_rep_rev", "cl_update_branch_name"],
  144. where="cl_update_rep_name", eq=repname, limit=1))
  145. if not url or not rpath:
  146. raise UpdateError(_("Configuration variables for repositories "
  147. "are not setup"))
  148. self.addProgress()
  149. if clean_on_error:
  150. try:
  151. if not self._syncRepository(repname, url, rpath, revision, branch,
  152. cb_progress=self.setProgress):
  153. return "skip"
  154. layman = Layman(dv.Get('cl_update_layman_installed'),
  155. dv.Get('cl_update_layman_make'))
  156. if repname != "portage":
  157. layman.add(repname, url, rpath)
  158. return True
  159. except GitError as e:
  160. if e.addon:
  161. self.printWARNING(str(e.addon))
  162. self.printWARNING(str(e))
  163. self.endTask(False)
  164. self.startTask(
  165. _("Re-fetching the {name} repository").format(name=repname))
  166. self.addProgress()
  167. try:
  168. rpath_new = "%s_new" % rpath
  169. self._syncRepository(repname, url, rpath_new, revision,
  170. branch, cb_progress=self.setProgress)
  171. removeDir(rpath)
  172. os.rename(rpath_new, rpath)
  173. except OSError as e:
  174. raise UpdateError(_("Failed to modify the "
  175. "{repname} repository").format(
  176. repname=repname)+":"+str(e))
  177. finally:
  178. if path.exists(rpath_new):
  179. removeDir(rpath_new)
  180. else:
  181. if not self._syncRepository(repname, url, rpath, revision, branch):
  182. return "skip"
  183. layman = Layman(dv.Get('cl_update_layman_installed'),
  184. dv.Get('cl_update_layman_make'))
  185. if repname != "portage":
  186. layman.add(repname, url, rpath)
  187. return True
  188. def syncLaymanRepository(self, repname):
  189. """
  190. Обновить репозиторий через layman
  191. """
  192. layman = getProgPath('/usr/bin/layman')
  193. if not layman:
  194. raise UpdateError(_("The Layman tool is not found"))
  195. rpath = self.clVars.Select('cl_update_other_rep_path',
  196. where='cl_update_other_rep_name', eq=repname,
  197. limit=1)
  198. laymanname = path.basename(rpath)
  199. if Git.is_git(rpath):
  200. self.addProgress()
  201. p = PercentProgress(layman, "-s", laymanname, part=1, atty=True)
  202. for perc in p.progress():
  203. self.setProgress(perc)
  204. else:
  205. p = process(layman, "-s", repname, stderr=STDOUT)
  206. if p.failed():
  207. raise UpdateError(
  208. _("Failed to update the {rname} repository").format(rname=repname),
  209. addon=p.read())
  210. return True
  211. def regenCache(self, repname):
  212. """
  213. Обновить кэш метаданных репозитория
  214. """
  215. egenCache = getProgPath('/usr/bin/egencache')
  216. if not egenCache:
  217. raise UpdateError(_("The Portage tool is not found"))
  218. if repname in self.clVars.Get('cl_update_rep_name'):
  219. path_rep = self.clVars.Select('cl_update_rep_path',
  220. where='cl_update_rep_name',
  221. eq=repname, limit=1)
  222. repo_name = readFile(
  223. path.join(path_rep,"profiles/repo_name")).strip()
  224. if repo_name != repname:
  225. self.printWARNING(
  226. _("Repository '{repo_name}' called '{repname}'"
  227. " in cl_update_rep_name").format(
  228. repo_name=repo_name, repname=repname))
  229. raise UpdateError(_("Failed to update the cache of the {rname} "
  230. "repository").format(rname=repname))
  231. cpu_num = self.clVars.Get('hr_cpu_num')
  232. p = process(egenCache, "--repo=%s" % repname, "--update",
  233. "--jobs=%s" % cpu_num, stderr=STDOUT)
  234. if p.failed():
  235. raise UpdateError(_("Failed to update the cache of the {rname} "
  236. "repository").format(rname=repname),
  237. addon=p.read())
  238. return True
  239. def emergeMetadata(self):
  240. """
  241. Выполнить egencache и emerge --metadata
  242. """
  243. emerge = getProgPath("/usr/bin/emerge")
  244. if not emerge:
  245. raise UpdateError(_("The Emerge tool is not found"))
  246. self.addProgress()
  247. p = PercentProgress(emerge, "--ask=n", "--metadata", part=1, atty=True)
  248. for perc in p.progress():
  249. self.setProgress(perc)
  250. if p.failed():
  251. data = p.read()
  252. with open('/var/log/calculate/failed-metadata-%d.log' % time.time(),
  253. 'w') as f:
  254. f.write(data+p.alldata)
  255. raise UpdateError(_("Failed to update metadata"), addon=data)
  256. return True
  257. def eixUpdate(self):
  258. """
  259. Выполенине eix-update для репозиторием
  260. eix-update выполнятется только для тех репозиториев, которые
  261. обновлялись, если cl_update_eixsync_force==auto, либо
  262. все, если cl_update_eixupdate_force==force
  263. """
  264. eixupdate = getProgPath("/usr/bin/eix-update")
  265. if not eixupdate:
  266. raise UpdateError(_("The Eix tool is not found"))
  267. self.addProgress()
  268. countRep = len(self.clVars.Get('main.cl_portdir_overlay'))+1
  269. p = PercentProgress(eixupdate, "-F", part=countRep or 1, atty=True)
  270. for perc in p.progress():
  271. self.setProgress(perc)
  272. if p.failed():
  273. raise UpdateError(_("Failed to update eix cache"), addon=p.read())
  274. return True
  275. def is_binary_pkg(self, pkg, binary=None):
  276. """
  277. Является ли пакет бинарным
  278. """
  279. if binary:
  280. return True
  281. if 'PN' in pkg and pkg['PN'].endswith('-bin'):
  282. return True
  283. if binary is not None:
  284. return binary
  285. if "binary" in pkg and pkg['binary']:
  286. return True
  287. return False
  288. def _printEmergePackage(self, pkg, binary=False, num=1, max_num=1):
  289. """
  290. Вывод сообщения сборки пакета
  291. """
  292. self.endTask()
  293. _print = self.color_print
  294. one = _print("{0}", num)
  295. two = _print("{0}", max_num)
  296. part = _("({current} of {maximum})").format(current=one,
  297. maximum=two)
  298. _print = _print.foreground(Colors.DEFAULT)
  299. if self.is_binary_pkg(pkg,binary):
  300. _colorprint = _print.foreground(Colors.PURPLE)
  301. else:
  302. _colorprint = _print.foreground(Colors.GREEN)
  303. PackageInformation.add_info(pkg)
  304. name = ""
  305. if pkg.info['DESCRIPTION']:
  306. name = _(pkg.info['DESCRIPTION'])
  307. name = name[:1].upper() + name[1:]
  308. if not name:
  309. name = str(pkg)
  310. self.printSUCCESS(
  311. _("{part} {package}").format(part=part, package=name))
  312. self.startTask(
  313. _("Emerging {package}").format(package=_colorprint(str(pkg))))
  314. def _printInstallPackage(self, pkg, binary=False):
  315. """
  316. Вывод сообщения установки пакета
  317. """
  318. self.endTask()
  319. _print = self.color_print
  320. if self.is_binary_pkg(pkg,binary):
  321. _print = _print.foreground(Colors.PURPLE)
  322. else:
  323. _print = _print.foreground(Colors.GREEN)
  324. #print listDirectory('/var/db/pkg/%s' % pkg['CATEGORY'])
  325. pkg_key = "{CATEGORY}/{PF}".format(**pkg)
  326. if pkg_key in self.update_map:
  327. self.startTask(_("Installing {pkg} [{oldver}]").format(
  328. pkg=_print(str(pkg)), oldver=self.update_map[ pkg_key]))
  329. else:
  330. self.startTask(_("Installing %s") % (_print(str(pkg))))
  331. def _printFetching(self, fn):
  332. """
  333. Вывод сообщения о скачивании
  334. """
  335. self.endTask()
  336. self.startTask(_("Fetching binary packages"))
  337. def _printUninstallPackage(self, pkg, num=1, max_num=1):
  338. """
  339. Вывод сообщения удаления пакета
  340. """
  341. self.endTask()
  342. _print = self.color_print
  343. one = _print("{0}", num)
  344. two = _print("{0}", max_num)
  345. part = _(" ({current} of {maximum})").format(current=one,
  346. maximum=two)
  347. _print = _print.foreground(Colors.LIGHT_RED)
  348. self.startTask(
  349. _("Unmerging{part} {package}").format(part=part,
  350. package=_print(str(pkg))))
  351. def emergelike(self, cmd, *params):
  352. """
  353. Запуск команды, которая подразумевает выполнение emerge
  354. """
  355. cmd_path = getProgPath(cmd)
  356. if not cmd_path:
  357. raise UpdateError(_("Failed to find the %s command") % cmd)
  358. with EmergeParser(
  359. emerge_parser.CommandExecutor(cmd_path, params)) as emerge:
  360. self._startEmerging(emerge)
  361. return True
  362. def revdep_rebuild(self, cmd, *params):
  363. """
  364. Запуск revdep-rebulid
  365. """
  366. cmd_path = getProgPath(cmd)
  367. if not cmd_path:
  368. raise UpdateError(_("Failed to find the %s command") % cmd)
  369. with EmergeParser(
  370. emerge_parser.CommandExecutor(cmd_path, params)) as emerge:
  371. revdep = RevdepPercentBlock(emerge)
  372. self.addProgress()
  373. revdep.add_observer(self.setProgress)
  374. revdep.action = lambda x: (
  375. self.endTask(), self.startTask(_("Assigning files to packages"))
  376. if "Assign" in revdep else None)
  377. self._startEmerging(emerge)
  378. return True
  379. def _display_pretty_package_list(self, pkglist, remove_list=False):
  380. """
  381. Отобразить список пакетов в "удобочитаемом" виде
  382. """
  383. _print = self.color_print
  384. ebuild_color = TextState.Colors.GREEN
  385. binary_color = TextState.Colors.PURPLE
  386. remove_color = TextState.Colors.LIGHT_RED
  387. flag_map = {"updating":
  388. _print.foreground(TextState.Colors.LIGHT_CYAN)("U"),
  389. "reinstall":
  390. _print.foreground(TextState.Colors.YELLOW)("rR"),
  391. "new":
  392. _print.foreground(TextState.Colors.LIGHT_GREEN)("N"),
  393. "newslot":
  394. _print.foreground(TextState.Colors.LIGHT_GREEN)("NS"),
  395. "downgrading": (
  396. _print.foreground(TextState.Colors.LIGHT_CYAN)("U") +
  397. _print.foreground(TextState.Colors.LIGHT_BLUE)("D"))}
  398. for pkg in sorted([PackageInformation.add_info(x) for x in
  399. pkglist],
  400. key=lambda y: y['CATEGORY/PN']):
  401. install_flag = ""
  402. if remove_list:
  403. pkgcolor = _print.foreground(remove_color)
  404. else:
  405. for flag in flag_map:
  406. if pkg[flag]:
  407. install_flag = "(%s) " % flag_map[flag]
  408. break
  409. if self.is_binary_pkg(pkg):
  410. pkgcolor = _print.foreground(binary_color)
  411. else:
  412. pkgcolor = _print.foreground(ebuild_color)
  413. if pkg.info['DESCRIPTION']:
  414. fullname = "%s " % _(pkg.info['DESCRIPTION'])
  415. fullname = fullname[:1].upper()+fullname[1:]
  416. else:
  417. fullname = ""
  418. shortname = pkgcolor("%s-%s" % (pkg["CATEGORY/PN"], pkg["PVR"]))
  419. if "SIZE" in pkg and pkg['SIZE'] and pkg["SIZE"] != "0 kB":
  420. size = " (%s)" % pkg["SIZE"]
  421. else:
  422. size = ""
  423. mult = _print.bold("*")
  424. self.printDefault(
  425. " {mult} {fullname}{flag}{shortname}{size}".format(
  426. mult=mult, fullname=fullname, shortname=shortname, size=size,
  427. flag=install_flag))
  428. def _display_install_package(self, emerge):
  429. """
  430. Отобразить список устанавливаемых пакетов
  431. """
  432. # подробный список пакетов
  433. _print = self.color_print
  434. if self.clVars.Get('cl_verbose_set') == 'on':
  435. self.printPre(str(emerge.install_packages))
  436. else:
  437. pkglist = emerge.install_packages.list
  438. self.printSUCCESS(_print(
  439. _("Listing packages for installation")))
  440. self._display_pretty_package_list(pkglist)
  441. if emerge.install_packages.remove_list:
  442. self.printSUCCESS(_print(
  443. _("Listing packages for removal")))
  444. self._display_pretty_package_list(
  445. emerge.install_packages.remove_list, remove_list=True)
  446. if str(emerge.download_size) != "0 kB":
  447. self.printSUCCESS(_("{size} will be downloaded").format(
  448. size=str(emerge.download_size)))
  449. def _display_remove_list(self, emerge):
  450. """
  451. Отобразить список удаляемых пакетов
  452. """
  453. # подробный список пакетов
  454. if self.clVars.Get('cl_verbose_set') == 'on':
  455. self.printPre(self._emerge_translate(
  456. emerge.uninstall_packages.verbose_result))
  457. else:
  458. _print = self.color_print
  459. pkglist = emerge.uninstall_packages.list
  460. self.printSUCCESS(_print.bold(
  461. _("Listing packages for removal")))
  462. self._display_pretty_package_list(pkglist, remove_list=True)
  463. def getCacheOnWorld(self, params, packages, check=False):
  464. """
  465. Получить список обновляемых пакетов @world из кэша
  466. """
  467. if "@world" in packages:
  468. from calculate.update.utils.cl_update import ClUpdateAction
  469. elog = EmergeLog(
  470. EmergeLogNamedTask(ClUpdateAction.log_names['premerge']))
  471. if check and (elog.list or elog.remove_list):
  472. self.emerge_cache.drop_cache(
  473. "Some packages was installed or removed")
  474. return params, packages
  475. installed_pkgs = elog.list
  476. new_packages = self.emerge_cache.get_cached_package_list()
  477. if new_packages is not None:
  478. return "-1O", ["=%s" % x for x in new_packages
  479. if not str(x) in installed_pkgs]
  480. return params, packages
  481. def updateCache(self, pkg_list):
  482. """
  483. Обновить кэш. Оставить отметку в emerge.log о том, выполнено действие
  484. premerge
  485. """
  486. self.emerge_cache.set_cache(pkg_list)
  487. from calculate.update.utils.cl_update import ClUpdateAction
  488. elog = EmergeLog(
  489. EmergeLogNamedTask(ClUpdateAction.log_names['premerge']))
  490. elog.mark_end_task(),
  491. def premerge(self, param, *packages):
  492. """
  493. Вывести информацию об обновлении
  494. """
  495. param, packages = self.getCacheOnWorld(param, packages, check=True)
  496. param = [param, "-pv"]
  497. if not packages:
  498. self.printSUCCESS(_("Installed packages are up to date"))
  499. self.set_need_update(False)
  500. return True
  501. with EmergeParser(EmergeCommand(list(packages),
  502. extra_params=param)) as emerge:
  503. try:
  504. emerge.run()
  505. if "@world" in packages:
  506. if emerge.install_packages.remove_list:
  507. self.emerge_cache.drop_cache(
  508. "List has packages for remove")
  509. else:
  510. self.updateCache(emerge.install_packages.list)
  511. if not emerge.install_packages.list:
  512. self.printSUCCESS(_("The system is up to date"))
  513. self.set_need_update(False)
  514. return True
  515. self._display_install_package(emerge)
  516. except EmergeError:
  517. self.set_need_update(False)
  518. self.emerge_cache.drop_cache("Emerge error")
  519. self.printPre(self._emerge_translate(emerge.prepare_error))
  520. raise
  521. if self.clVars.Get('cl_update_pretend_set') == 'on':
  522. # установить кэш: есть обновления
  523. self.set_need_update()
  524. return True
  525. self.set_need_update(False)
  526. answer = self.askConfirm(
  527. _("Would you like to merge these packages?"), "yes")
  528. if answer == "no":
  529. raise KeyboardInterrupt
  530. return "yes"
  531. return True
  532. def set_need_update(self, val=True):
  533. """
  534. Установить флаг: есть обновления
  535. """
  536. val = "on" if val else "off"
  537. SystemIni().setVar('update', {'packages': val})
  538. return True
  539. def _emerge_translate(self, s):
  540. """
  541. Перевести текст из emerge
  542. """
  543. return RegexpLocalization('cl_emerge').translate(str(s))
  544. def setUpToDateCache(self):
  545. """
  546. Установить кэш - "нет пакетов для обновления"
  547. """
  548. self.updateCache(PackageList([]))
  549. return True
  550. def _startEmerging(self, emerge):
  551. """
  552. Настроить и выполнить emerge
  553. """
  554. if emerge.install_packages and emerge.install_packages.list:
  555. for pkg in emerge.install_packages.list:
  556. rv = pkg.get('REPLACING_VERSIONS', '')
  557. if rv:
  558. self.update_map["{CATEGORY}/{PF}".format(**pkg)] = \
  559. rv.partition(":")[0]
  560. emerge.command.send("yes\n")
  561. emerge.emerging.add_observer(self._printEmergePackage)
  562. emerge.installing.add_observer(self._printInstallPackage)
  563. emerge.uninstalling.add_observer(self._printUninstallPackage)
  564. emerge.fetching.add_observer(self._printFetching)
  565. try:
  566. emerge.run()
  567. except EmergeError:
  568. self.emerge_cache.drop_cache("Emerge error")
  569. if emerge.emerging_error:
  570. self.printPre(
  571. self._emerge_translate(emerge.emerging_error.log))
  572. else:
  573. self.printPre(self._emerge_translate(emerge.prepare_error))
  574. raise
  575. def emerge(self, param, *packages):
  576. """
  577. Выполнить сборку пакета
  578. """
  579. if not packages:
  580. packages = [param]
  581. extra_params = None
  582. else:
  583. param, packages = self.getCacheOnWorld(param, packages)
  584. if not packages:
  585. return True
  586. extra_params = [param]
  587. with EmergeParser(EmergeCommand(list(packages),
  588. extra_params=extra_params)) as emerge:
  589. try:
  590. emerge.question.action = lambda x: False
  591. emerge.run()
  592. if not emerge.install_packages.list:
  593. return True
  594. except EmergeError:
  595. self.emerge_cache.drop_cache("Emerge error")
  596. self.printPre(self._emerge_translate(emerge.prepare_error))
  597. raise
  598. self._startEmerging(emerge)
  599. return True
  600. def depclean(self):
  601. """
  602. Выполнить очистку системы от лишних пакетов
  603. """
  604. with EmergeParser(EmergeCommand(["--depclean"])) as emerge:
  605. try:
  606. emerge.question.action = lambda x: False
  607. emerge.run()
  608. if not emerge.uninstall_packages.list:
  609. return True
  610. self._display_remove_list(emerge)
  611. except EmergeError:
  612. self.printPre(self._emerge_translate(emerge.prepare_error))
  613. raise
  614. if (self.askConfirm(
  615. _("Would you like to unmerge these packages?")) != 'yes'):
  616. return False
  617. self._startEmerging(emerge)
  618. return True
  619. def update_task(self, task_name):
  620. """
  621. Декоратор для добавления меток запуска и останова задачи
  622. """
  623. def decor(f):
  624. def wrapper(*args, **kwargs):
  625. logger = EmergeLog(EmergeLogNamedTask(task_name))
  626. logger.mark_begin_task()
  627. ret = f(*args, **kwargs)
  628. if ret:
  629. logger.mark_end_task()
  630. return ret
  631. return wrapper
  632. return decor
  633. def migrateCacheRepository(self, url, branch):
  634. rep_set = self.clVars.Get('cl_update_profile_storage')
  635. rep = rep_set.get_repository(url, branch)
  636. if rep:
  637. rep.storage = rep_set.storages[0]
  638. self.clVars.Invalidate('cl_update_profile_storage')
  639. return True
  640. def reconfigureProfileVars(self):
  641. """
  642. Синхронизировать репозитории
  643. """
  644. dv = self.clVars
  645. profile_dv = dv.Get('cl_update_profile_datavars')
  646. try:
  647. for var_name in ('cl_update_rep_rev',
  648. 'cl_update_rep_path',
  649. 'cl_update_rep_url',
  650. 'cl_update_rep_name',
  651. 'cl_update_branch_name',
  652. 'cl_profile_system',
  653. 'cl_update_layman_storage',
  654. 'cl_update_rep'):
  655. dv.Set(var_name, profile_dv.Get(var_name), force=True)
  656. except DataVarsError:
  657. raise UpdateError(_("Wrong profile"))
  658. return True
  659. def setProfile(self):
  660. profile = self.clVars.Select('cl_profile_path',
  661. where='cl_profile_shortname',
  662. eq=self.clVars.Get('cl_update_profile_system'), limit=1)
  663. if not profile:
  664. raise UpdateError(_("Failed to determine profile %s") %
  665. self.clVars.Get('cl_update_profile_system'))
  666. profile_path = path.relpath(profile, '/etc/portage')
  667. try:
  668. for rm_fn in filter(path.exists,
  669. ('/etc/make.profile', '/etc/portage/make.profile')):
  670. os.unlink(rm_fn)
  671. os.symlink(profile_path, '/etc/portage/make.profile')
  672. except (OSError,IOError) as e:
  673. raise UpdateError(_("Failed to set profile: %s")%str(e))
  674. return True