From 10b6d0129d062f4d5d8a7611023c3f8cc43f1eab Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 25 Oct 2012 01:35:31 -0700 Subject: Add FEATURES=merge-sync, for bug #439584. --- cnf/make.globals | 2 +- man/make.conf.5 | 5 +++++ pym/portage/const.py | 1 + pym/portage/dbapi/vartree.py | 41 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cnf/make.globals b/cnf/make.globals index e53f1867f..47ee787c6 100644 --- a/cnf/make.globals +++ b/cnf/make.globals @@ -53,7 +53,7 @@ FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${ho # Default user options FEATURES="assume-digests binpkg-logs config-protect-if-modified distlocks ebuild-locks - fixlafiles news parallel-fetch protect-owned + fixlafiles merge-sync news parallel-fetch protect-owned sandbox sfperms strict unknown-features-warn unmerge-logs unmerge-orphans userfetch" diff --git a/man/make.conf.5 b/man/make.conf.5 index 4c86d38e6..9152ab295 100644 --- a/man/make.conf.5 +++ b/man/make.conf.5 @@ -361,6 +361,11 @@ Do \fBNOT\fR use \fIlmirror\fR for clients that need to override \fBRESTRICT\fR when fetching from a local mirror, but instead use a "local" mirror setting in \fI/etc/portage/mirrors\fR, as described in \fBportage\fR(5). .TP +.B merge\-sync +After a package is merged or unmerged, sync relevant files to +disk in order to avoid data\-loss in the event of a power failure. +This feature is enabled by default. +.TP .B metadata\-transfer Automatically perform a metadata transfer when `emerge \-\-sync` is run. In versions of portage >=2.1.5, this feature is disabled by diff --git a/pym/portage/const.py b/pym/portage/const.py index 3242861cf..8c5bbf308 100644 --- a/pym/portage/const.py +++ b/pym/portage/const.py @@ -96,6 +96,7 @@ SUPPORTED_FEATURES = frozenset([ "downgrade-backup", "ebuild-locks", "fakeroot", "fail-clean", "force-mirror", "force-prefix", "getbinpkg", "installsources", "keeptemp", "keepwork", "fixlafiles", "lmirror", + "merge-sync", "metadata-transfer", "mirror", "multilib-strict", "news", "noauto", "noclean", "nodoc", "noinfo", "noman", "nostrip", "notitles", "parallel-fetch", "parallel-install", diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index cb7b39b02..edc477a09 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -30,6 +30,7 @@ portage.proxy.lazyimport.lazyimport(globals(), 'portage.util.env_update:env_update', 'portage.util.listdir:dircache,listdir', 'portage.util.movefile:movefile', + 'portage.util._ctypes:find_library,LoadLibrary', 'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry', 'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap', 'portage.util._async.SchedulerInterface:SchedulerInterface', @@ -73,6 +74,7 @@ import io from itertools import chain import logging import os as _os +import platform import pwd import re import stat @@ -4688,7 +4690,44 @@ class dblink(object): disk and avoid data-loss in the event of a power failure. This method does nothing if FEATURES=merge-sync is disabled. """ - pass + if not self._device_path_map or \ + "merge-sync" not in self.settings.features: + return + + syncfs = self._get_syncfs() + if syncfs is None: + try: + proc = subprocess.Popen(["sync"]) + except EnvironmentError: + pass + else: + proc.wait() + else: + for path in self._device_path_map.values(): + try: + fd = os.open(path, os.O_RDONLY) + except OSError: + pass + else: + try: + syncfs(fd) + except OSError: + pass + finally: + os.close(fd) + + def _get_syncfs(self): + if platform.system() == "Linux": + filename = find_library("c") + if filename is not None: + library = LoadLibrary(filename) + if library is not None: + try: + return library.syncfs + except AttributeError: + pass + + return None def merge(self, mergeroot, inforoot, myroot=None, myebuild=None, cleanup=0, mydbapi=None, prev_mtimes=None, counter=None): -- cgit v1.2.3