blob: 73493c5a1bda78706b3a82c550d09f124e43a08f [file] [log] [blame]
# Copyright 2013-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
import errno
import logging
from portage import os
from portage.package.ebuild.fetch import ContentHashLayout
from portage.util._async.FileCopier import FileCopier
from _emerge.CompositeTask import CompositeTask
class DeletionTask(CompositeTask):
__slots__ = ('distfile', 'distfile_path', 'config')
def _start(self):
if self.config.options.recycle_dir is not None:
recycle_path = os.path.join(
self.config.options.recycle_dir, self.distfile)
if self.config.options.dry_run:
logging.info(("dry-run: move '%s' from "
"distfiles to recycle") % self.distfile)
else:
logging.debug(("move '%s' from "
"distfiles to recycle") % self.distfile)
try:
# note: distfile_path can be a symlink here
os.rename(os.path.realpath(self.distfile_path),
recycle_path)
except OSError as e:
if e.errno != errno.EXDEV:
logging.error(("rename %s from distfiles to "
"recycle failed: %s") % (self.distfile, e))
else:
self._delete_links()
self._async_wait()
return
self._start_task(
FileCopier(src_path=self.distfile_path,
dest_path=recycle_path,
background=False),
self._recycle_copier_exit)
return
success = True
if self.config.options.dry_run:
logging.info(("dry-run: delete '%s' from "
"distfiles") % self.distfile)
else:
logging.debug(("delete '%s' from "
"distfiles") % self.distfile)
try:
os.unlink(self.distfile_path)
except OSError as e:
if e.errno not in (errno.ENOENT, errno.ESTALE):
logging.error("%s unlink failed in distfiles: %s" %
(self.distfile, e))
success = False
if success:
self._delete_links()
else:
self.returncode = 1
self._async_wait()
def _recycle_copier_exit(self, copier):
self._assert_current(copier)
if self._was_cancelled():
self.wait()
return
success = True
if copier.returncode == os.EX_OK:
try:
os.unlink(copier.src_path)
except OSError as e:
if e.errno not in (errno.ENOENT, errno.ESTALE):
logging.error("%s unlink failed in distfiles: %s" %
(self.distfile, e))
success = False
else:
logging.error(("%s copy from distfiles "
"to recycle failed: %s") % (self.distfile, copier.future.exception()))
success = False
if success:
self._delete_links()
else:
self.returncode = 1
self._current_task = None
self.wait()
def _delete_links(self):
success = True
for layout in self.config.layouts:
if isinstance(layout, ContentHashLayout) and not self.distfile.digests:
logging.debug(("_delete_links: '%s' has "
"no digests") % self.distfile)
continue
distfile_path = os.path.join(
self.config.options.distfiles,
layout.get_path(self.distfile))
try:
os.unlink(distfile_path)
except OSError as e:
if e.errno not in (errno.ENOENT, errno.ESTALE):
logging.error("%s unlink failed in distfiles: %s" %
(self.distfile, e))
success = False
if success:
self._success()
self.returncode = os.EX_OK
else:
self.returncode = 1
def _success(self):
cpv = "unknown"
if self.config.distfiles_db is not None:
cpv = self.config.distfiles_db.get(self.distfile, cpv)
self.config.delete_count += 1
self.config.log_success("%s\t%s\tremoved" % (cpv, self.distfile))
if self.config.distfiles_db is not None:
try:
del self.config.distfiles_db[self.distfile]
except KeyError:
pass
else:
logging.debug(("drop '%s' from "
"distfiles db") % self.distfile)
if self.config.content_db is not None:
self.config.content_db.remove(self.distfile)
if self.config.deletion_db is not None:
try:
del self.config.deletion_db[self.distfile]
except KeyError:
pass
else:
logging.debug(("drop '%s' from "
"deletion db") % self.distfile)