commit:     5f7b4865ecafe4f04a92c5e1158f657b0dcd41d6
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Fri Sep 26 03:02:41 2014 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Sun Oct 19 17:23:07 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=5f7b4865

dblink.mergeme: implement bug #523684

If a CONFIG_PROTECTed file was installed but no longer exists in the
file system, then it may have been deleted or renamed by the admin.
Therefore, force the file to be merged with a ._cfg name, so that the
admin will be prompted for this update.

X-Gentoo-Bug: 523684
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=523684

---
 pym/portage/dbapi/vartree.py            | 32 ++++++++++++++++++++++++--------
 pym/portage/tests/emerge/test_simple.py | 19 +++++++++++++++++--
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index b46ba0b..11384bf 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -4687,10 +4687,7 @@ class dblink(object):
                                zing = "!!!"
                                mymtime = None
                                protected = self.isprotected(mydest)
-                               if mydmode != None:
-                                       # destination file exists
-
-                                       if stat.S_ISDIR(mydmode):
+                               if mydmode is not None and 
stat.S_ISDIR(mydmode):
                                                # install of destination is 
blocked by an existing directory with the same name
                                                newdest = 
self._new_backup_path(mydest)
                                                msg = []
@@ -4703,12 +4700,15 @@ class dblink(object):
                                                self._eerror("preinst", msg)
                                                mydest = newdest
 
-                                       elif stat.S_ISREG(mydmode) or 
(stat.S_ISLNK(mydmode) and os.path.exists(mydest) and 
stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
+                               elif mydmode is None or stat.S_ISREG(mydmode) 
or \
+                                       (stat.S_ISLNK(mydmode) and 
os.path.exists(mydest)
+                                       and 
stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
                                                # install of destination is 
blocked by an existing regular file,
                                                # or by a symlink to an 
existing regular file;
                                                # now, config file management 
may come into play.
                                                # we only need to tweak mydest 
if cfg file management is in play.
-                                               if protected:
+                                               destmd5 = None
+                                               if protected and mydmode is not 
None:
                                                        destmd5 = 
perform_md5(mydest, calc_prelink=calc_prelink)
                                                        if protect_if_modified:
                                                                contents_key = \
@@ -4721,7 +4721,21 @@ class dblink(object):
                                                if protected:
                                                        # we have a protection 
path; enable config file management.
                                                        cfgprot = 0
-                                                       if mymd5 == destmd5:
+                                                       cfgprot_force = False
+                                                       if mydmode is None:
+                                                               if 
self._installed_instance is not None and \
+                                                                       
self._installed_instance._match_contents(
+                                                                       
myrealdest) is not False:
+                                                                       # If 
the file doesn't exist, then it may
+                                                                       # have 
been deleted or renamed by the
+                                                                       # 
admin. Therefore, force the file to be
+                                                                       # 
merged with a ._cfg name, so that the
+                                                                       # admin 
will be prompted for this update
+                                                                       # (see 
bug #523684).
+                                                                       
cfgprot_force = True
+                                                                       moveme 
= True
+                                                                       cfgprot 
= True
+                                                       elif mymd5 == destmd5:
                                                                #file already 
in place; simply update mtimes of destination
                                                                moveme = 1
                                                        else:
@@ -4749,7 +4763,9 @@ class dblink(object):
                                                                del 
cfgfiledict[myrealdest]
 
                                                        if cfgprot:
-                                                               mydest = 
new_protect_filename(mydest, newmd5=mymd5)
+                                                               mydest = 
new_protect_filename(mydest,
+                                                                       
newmd5=mymd5,
+                                                                       
force=cfgprot_force)
 
                                # whether config protection or not, we merge 
the new file the
                                # same way.  Unless moveme=0 (blocking 
directory)

diff --git a/pym/portage/tests/emerge/test_simple.py 
b/pym/portage/tests/emerge/test_simple.py
index 0bb83ae..6fc81ab 100644
--- a/pym/portage/tests/emerge/test_simple.py
+++ b/pym/portage/tests/emerge/test_simple.py
@@ -12,7 +12,8 @@ from portage.const import (BASH_BINARY, PORTAGE_BASE_PATH,
 from portage.process import find_binary
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import ResolverPlayground
-from portage.util import ensure_dirs
+from portage.util import (ensure_dirs, find_updated_config_files,
+       shlex_split)
 
 class SimpleEmergeTestCase(TestCase):
 
@@ -42,6 +43,10 @@ src_install() {
        doins "${T}"/regular-file
        dosym regular-file /usr/lib/${P}/symlink || die
 
+       # Test CONFIG_PROTECT
+       insinto /etc
+       newins "${T}"/regular-file ${PN}-${SLOT%/*}
+
        # Test code for bug #381629, using a copyright symbol encoded with 
latin-1.
        # We use $(printf "\\xa9") rather than $'\\xa9', since printf apparently
        # works in any case, while $'\\xa9' transforms to \\xef\\xbf\\xbd under
@@ -267,8 +272,18 @@ pkg_preinst() {
                        emerge_cmd + ("--pretend", "--depclean", "--verbose", 
"dev-libs/B"),
                        emerge_cmd + ("--pretend", "--depclean",),
                        emerge_cmd + ("--depclean",),
-                       quickpkg_cmd + ("dev-libs/A",),
+                       quickpkg_cmd + ("--include-config", "y", "dev-libs/A",),
+                       # Test bug #523684, where a file renamed or removed by 
the
+                       # admin forces replacement files to be merged with 
config
+                       # protection.
+                       lambda: self.assertEqual(0,
+                               len(list(find_updated_config_files(eroot,
+                               shlex_split(settings["CONFIG_PROTECT"]))))),
+                       lambda: os.unlink(os.path.join(eprefix, "etc", "A-0")),
                        emerge_cmd + ("--usepkgonly", "dev-libs/A"),
+                       lambda: self.assertEqual(1,
+                               len(list(find_updated_config_files(eroot,
+                               shlex_split(settings["CONFIG_PROTECT"]))))),
                        emaint_cmd + ("--check", "all"),
                        emaint_cmd + ("--fix", "all"),
                        fixpackages_cmd,

Reply via email to