slotmove: fix handling for EAPI 4-slot-abi v2.2.0_alpha118
authorZac Medico <zmedico@gentoo.org>
Fri, 13 Jul 2012 23:33:49 +0000 (16:33 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 13 Jul 2012 23:33:49 +0000 (16:33 -0700)
This is just a really minimal fix, in order to prevent slotmove from
behaving incorrectly with packages that use EAPI 4-slot-abi. Any
slotmove commands that try so specify a sub-slot are treated as invalid
for now, since that will required additional EAPI conditional logic, as
reported in bug #426476.

pym/portage/_global_updates.py
pym/portage/dbapi/__init__.py
pym/portage/tests/emerge/test_global_updates.py
pym/portage/tests/update/__init__.py [new file with mode: 0644]
pym/portage/tests/update/__test__ [new file with mode: 0644]
pym/portage/tests/update/test_move_slot_ent.py [new file with mode: 0644]
pym/portage/update.py

index 51750431d9c5079a064b0fff7d3720e40a603c55..c0f3df0b669d6f70a57fd654e7314f9920b00e92 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2010 Gentoo Foundation
+# Copyright 2010-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import print_function
@@ -32,11 +32,15 @@ def _global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
        """
        # only do this if we're root and not running repoman/ebuild digest
 
-       retupd = False
        if secpass < 2 or \
                "SANDBOX_ACTIVE" in os.environ or \
                len(trees) != 1:
-               return retupd
+               return False
+
+       return _do_global_updates(trees, prev_mtimes,
+               quiet=quiet, if_mtime_changed=if_mtime_changed)
+
+def _do_global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
        root = trees._running_eroot
        mysettings = trees[root]["vartree"].settings
        portdb = trees[root]["porttree"].dbapi
@@ -61,6 +65,7 @@ def _global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
        repo_map = {}
        timestamps = {}
 
+       retupd = False
        update_notice_printed = False
        for repo_name in portdb.getRepositories():
                repo = portdb.getRepositoryPath(repo_name)
@@ -237,8 +242,7 @@ def _global_updates(trees, prev_mtimes, quiet=False, if_mtime_changed=True):
                        # Update progress above is indicated by characters written to stdout so
                        # we print a couple new lines here to separate the progress output from
                        # what follows.
-                       print()
-                       print()
+                       writemsg_stdout("\n\n")
 
                        if do_upgrade_packagesmessage and bindb and \
                                bindb.cpv_all():
index 34b1d470560b66ff0a96554e7b290419dd5f08ec..ac8d31169858b1ac262578bd7f7044a4f3a28603 100644 (file)
@@ -8,7 +8,7 @@ import re
 import portage
 portage.proxy.lazyimport.lazyimport(globals(),
        'portage.dbapi.dep_expand:dep_expand@_dep_expand',
-       'portage.dep:match_from_list,_match_slot',
+       'portage.dep:Atom,match_from_list,_match_slot',
        'portage.output:colorize',
        'portage.util:cmp_sort_key,writemsg',
        'portage.versions:catsplit,catpkgsplit,vercmp,_pkg_str',
@@ -312,27 +312,39 @@ class dbapi(object):
        def move_slot_ent(self, mylist, repo_match=None):
                """This function takes a sequence:
                Args:
-                       mylist: a sequence of (package, originalslot, newslot)
+                       mylist: a sequence of (atom, originalslot, newslot)
                        repo_match: callable that takes single repo_name argument
                                and returns True if the update should be applied
                Returns:
                        The number of slotmoves this function did
                """
-               pkg = mylist[1]
+               atom = mylist[1]
                origslot = mylist[2]
                newslot = mylist[3]
-               origmatches = self.match(pkg)
+
+               try:
+                       atom.with_slot
+               except AttributeError:
+                       atom = Atom(atom).with_slot(origslot)
+               else:
+                       atom = atom.with_slot(origslot)
+
+               origmatches = self.match(atom)
                moves = 0
                if not origmatches:
                        return moves
                for mycpv in origmatches:
-                       slot = self.aux_get(mycpv, ["SLOT"])[0]
-                       if slot != origslot:
+                       try:
+                               mycpv = self._pkg_str(mycpv, atom.repo)
+                       except (KeyError, InvalidData):
                                continue
-                       if repo_match is not None \
-                               and not repo_match(self.aux_get(mycpv, ['repository'])[0]):
+                       if repo_match is not None and not repo_match(mycpv.repo):
                                continue
                        moves += 1
+                       if "/" not in newslot and \
+                               mycpv.slot_abi and \
+                               mycpv.slot_abi not in (mycpv.slot, newslot):
+                               newslot = "%s/%s" % (newslot, mycpv.slot_abi)
                        mydata = {"SLOT": newslot+"\n"}
                        self.aux_update(mycpv, mydata)
                return moves
index 73556210016915a0cfc541217c18aa1c5dc4695d..eb54310593f647ae1c94d82cce0caa93aa9233f8 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 Gentoo Foundation
+# Copyright 2011-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
@@ -15,6 +15,8 @@ slotmove invalid_atom 0 3
 slotmove !=invalid/blocker-3* 0 3
 slotmove =valid/atom-3* 0 3 invalid_extra_token
 slotmove =valid/atom-3* 0 3
+slotmove =valid/atom-3* 0 3/3.1
+slotmove =valid/atom-3* 0/0 3
 move valid/atom1 valid/atom2 invalid_extra_token
 move valid/atom1 invalid_atom2
 move invalid_atom1 valid/atom2
@@ -28,7 +30,7 @@ move valid/atom1 valid/atom2
                                ['slotmove', Atom('=valid/atom-3*'), '0', '3'],
                                ['move', Atom('valid/atom1'), Atom('valid/atom2')],
                        ],
-                       10,
+                       12,
                ),
 
                )
diff --git a/pym/portage/tests/update/__init__.py b/pym/portage/tests/update/__init__.py
new file mode 100644 (file)
index 0000000..418ad86
--- /dev/null
@@ -0,0 +1,2 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
diff --git a/pym/portage/tests/update/__test__ b/pym/portage/tests/update/__test__
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pym/portage/tests/update/test_move_slot_ent.py b/pym/portage/tests/update/test_move_slot_ent.py
new file mode 100644 (file)
index 0000000..64475bc
--- /dev/null
@@ -0,0 +1,149 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import textwrap
+
+import portage
+from portage import os
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+from portage._global_updates import _do_global_updates
+
+class MoveSlotEntTestCase(TestCase):
+
+       def testMoveSlotEnt(self):
+
+               ebuilds = {
+       
+                       "dev-libs/A-2::dont_apply_updates" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.30",
+                       },
+
+                       "dev-libs/B-2::dont_apply_updates" : {
+                               "SLOT": "0",
+                       },
+
+                       "dev-libs/C-2.1::dont_apply_updates" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.1",
+                       },
+
+               }
+
+               installed = {
+
+                       "dev-libs/A-1::test_repo" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.30",
+                       },
+
+                       "dev-libs/B-1::test_repo" : {
+                               "SLOT": "0",
+                       },
+
+                       "dev-libs/C-1::test_repo" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/1",
+                       },
+
+               }
+
+               binpkgs = {
+       
+                       "dev-libs/A-1::test_repo" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.30",
+                       },
+
+                       "dev-libs/A-2::dont_apply_updates" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.30",
+                       },
+
+                       "dev-libs/B-1::test_repo" : {
+                               "SLOT": "0",
+                       },
+
+                       "dev-libs/B-2::dont_apply_updates" : {
+                               "SLOT": "0",
+                       },
+
+                       "dev-libs/C-1::test_repo" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/1",
+                       },
+
+                       "dev-libs/C-2.1::dont_apply_updates" : {
+                               "EAPI": "4-slot-abi",
+                               "SLOT": "0/2.1",
+                       },
+
+               }
+
+               updates = textwrap.dedent("""
+                       slotmove dev-libs/A 0 2
+                       slotmove dev-libs/B 0 1
+                       slotmove dev-libs/C 0 1
+               """)
+
+               playground = ResolverPlayground(binpkgs=binpkgs,
+                       ebuilds=ebuilds, installed=installed)
+
+               settings = playground.settings
+               trees = playground.trees
+               eroot = settings["EROOT"]
+               portdir = settings["PORTDIR"]
+               portdb = trees[eroot]["porttree"].dbapi
+               vardb = trees[eroot]["vartree"].dbapi
+               bindb = trees[eroot]["bintree"].dbapi
+
+               updates_dir = os.path.join(portdir, "profiles", "updates")
+
+               try:
+                       ensure_dirs(updates_dir)
+                       with open(os.path.join(updates_dir, "1Q-2010"), 'w') as f:
+                               f.write(updates)
+
+                       # Create an empty updates directory, so that this
+                       # repo doesn't inherit updates from the main repo.
+                       ensure_dirs(os.path.join(
+                               portdb.getRepositoryPath("dont_apply_updates"),
+                               "profiles", "updates"))
+
+                       global_noiselimit = portage.util.noiselimit
+                       portage.util.noiselimit = -2
+                       try:
+                               _do_global_updates(trees, {})
+                       finally:
+                               portage.util.noiselimit = global_noiselimit
+
+                       # 0/2.30 -> 2/2.30
+                       self.assertEqual("2/2.30",
+                               vardb.aux_get("dev-libs/A-1", ["SLOT"])[0])
+                       self.assertEqual("2/2.30",
+                               bindb.aux_get("dev-libs/A-1", ["SLOT"])[0])
+
+                       # 0 -> 1
+                       self.assertEqual("1",
+                               vardb.aux_get("dev-libs/B-1", ["SLOT"])[0])
+                       self.assertEqual("1",
+                               bindb.aux_get("dev-libs/B-1", ["SLOT"])[0])
+
+                       # 0/1 -> 1 (equivalent to 1/1)
+                       self.assertEqual("1",
+                               vardb.aux_get("dev-libs/C-1", ["SLOT"])[0])
+                       self.assertEqual("1",
+                               bindb.aux_get("dev-libs/C-1", ["SLOT"])[0])
+
+                       # dont_apply_updates
+                       self.assertEqual("0/2.30",
+                               bindb.aux_get("dev-libs/A-2", ["SLOT"])[0])
+                       self.assertEqual("0",
+                               bindb.aux_get("dev-libs/B-2", ["SLOT"])[0])
+                       self.assertEqual("0/2.1",
+                               bindb.aux_get("dev-libs/C-2.1", ["SLOT"])[0])
+
+               finally:
+                       playground.cleanup()
index 34e466366e3be3709a990438c80097ffcb5e0d9a..a5cb92edada054695131d6661a3a2c810ee99f38 100644 (file)
@@ -22,6 +22,8 @@ portage.proxy.lazyimport.lazyimport(globals(),
 )
 
 from portage.const import USER_CONFIG_PATH
+from portage.dep import _get_slot_re
+from portage.eapi import _get_eapi_attrs
 from portage.exception import DirectoryNotFound, InvalidAtom, PortageException
 from portage.localization import _
 
@@ -30,7 +32,7 @@ if sys.hexversion >= 0x3000000:
 
 ignored_dbentries = ("CONTENTS", "environment.bz2")
 
-def update_dbentry(update_cmd, mycontent):
+def update_dbentry(update_cmd, mycontent, eapi=None):
        if update_cmd[0] == "move":
                old_value = str(update_cmd[1])
                if old_value in mycontent:
@@ -143,6 +145,8 @@ def grab_updates(updpath, prev_mtimes=None):
 
 def parse_updates(mycontent):
        """Valid updates are returned as a list of split update commands."""
+       eapi_attrs = _get_eapi_attrs(None)
+       slot_re = _get_slot_re(eapi_attrs)
        myupd = []
        errors = []
        mylines = mycontent.splitlines()
@@ -194,6 +198,23 @@ def parse_updates(mycontent):
                                errors.append(_("ERROR: Malformed update entry '%s'") % myline)
                                continue
 
+                       invalid_slot = False
+                       for slot in (origslot, newslot):
+                               m = slot_re.match(slot)
+                               if m is None:
+                                       invalid_slot = True
+                                       break
+                               if "/" in slot:
+                                       # Don't support EAPI 4-slot-abi style SLOT in slotmove
+                                       # yet, since the relevant code isn't aware of EAPI yet
+                                       # (see bug #426476).
+                                       invalid_slot = True
+                                       break
+
+                       if invalid_slot:
+                               errors.append(_("ERROR: Malformed update entry '%s'") % myline)
+                               continue
+
                # The list of valid updates is filtered by continue statements above.
                myupd.append(mysplit)
        return myupd, errors