aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cnf/make.globals2
-rw-r--r--man/make.conf.55
-rw-r--r--pym/portage/const.py1
-rw-r--r--pym/portage/dbapi/vartree.py41
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):