update_dbentry: improve slotmove support
authorZac Medico <zmedico@gentoo.org>
Wed, 19 Sep 2012 19:48:24 +0000 (12:48 -0700)
committerZac Medico <zmedico@gentoo.org>
Wed, 19 Sep 2012 19:48:24 +0000 (12:48 -0700)
This could be especially useful for "built" slot operator deps, in
order to avoid having a slotmove trigger unnecessary rebuilds.

pym/portage/tests/update/test_update_dbentry.py
pym/portage/update.py

index e13cfed74bbfc879b96e3c74dcc6910b3169d163..ac16a8ae374deddb5f59117b89efbfd5140aa6a2 100644 (file)
@@ -6,14 +6,40 @@ import textwrap
 
 import portage
 from portage import os
+from portage.dep import Atom
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.update import update_dbentry
 from portage.util import ensure_dirs
 from portage._global_updates import _do_global_updates
 
 class UpdateDbentryTestCase(TestCase):
 
        def testUpdateDbentryTestCase(self):
+               cases = (
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
+                               "  dev-libs/A:0  ", "  dev-libs/A:1  "),
+
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "1",
+                               "  >=dev-libs/A-1:0  ", "  >=dev-libs/A-1:1  "),
+
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "5_pre2",
+                               "  dev-libs/A:0/1=[foo]  ", "  dev-libs/A:1/1=[foo]  "),
+
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "5_pre2",
+                               "  dev-libs/A:0/1[foo]  ", "  dev-libs/A:1/1[foo]  "),
+
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "5_pre2",
+                               "  dev-libs/A:0/0[foo]  ", "  dev-libs/A:1/1[foo]  "),
+
+                       (("slotmove", Atom("dev-libs/A"), "0", "1"), "5_pre2",
+                               "  dev-libs/A:0=[foo]  ", "  dev-libs/A:1=[foo]  "),
+               )
+               for update_cmd, eapi, input_str, output_str in cases:
+                       result = update_dbentry(update_cmd, input_str, eapi=eapi)
+                       self.assertEqual(result, output_str)
+
+       def testUpdateDbentryDbapiTestCase(self):
 
                ebuilds = {
 
index 121e957201c4fef5acaa1c26246d2d36ea0d4100..017f71f62d55134e6526afb189ead8ce1df8449c 100644 (file)
@@ -22,7 +22,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
 )
 
 from portage.const import USER_CONFIG_PATH
-from portage.dep import _get_slot_re
+from portage.dep import Atom, _get_slot_re
 from portage.eapi import _get_eapi_attrs
 from portage.exception import DirectoryNotFound, InvalidAtom, PortageException
 from portage.localization import _
@@ -57,12 +57,44 @@ def update_dbentry(update_cmd, mycontent, eapi=None):
                                        return "".join(matchobj.groups())
                        mycontent = re.sub("(%s-)(\\S*)" % old_value, myreplace, mycontent)
        elif update_cmd[0] == "slotmove" and update_cmd[1].operator is None:
-               pkg, origslot, newslot = update_cmd[1:]
-               old_value = "%s:%s" % (pkg, origslot)
-               if old_value in mycontent:
-                       old_value = re.escape(old_value)
-                       new_value = "%s:%s" % (pkg, newslot)
-                       mycontent = re.sub(old_value+"($|\\s)", new_value+"\\1", mycontent)
+               orig_atom, origslot, newslot = update_cmd[1:]
+               orig_cp = orig_atom.cp
+
+               # We don't support versioned slotmove atoms here, since it can be
+               # difficult to determine if the version constraints really match
+               # the atoms that we're trying to update.
+               if orig_atom.version is None and orig_cp in mycontent:
+                       # this split preserves existing whitespace
+                       split_content = re.split(r'(\s+)', mycontent)
+                       modified = False
+                       for i, token in enumerate(split_content):
+                               if orig_cp not in token:
+                                       continue
+                               try:
+                                       atom = Atom(token, eapi=eapi)
+                               except InvalidAtom:
+                                       continue
+                               if atom.cp != orig_cp:
+                                       continue
+                               if atom.slot is None or atom.slot != origslot:
+                                       continue
+
+                               slot_part = newslot
+                               if atom.sub_slot is not None:
+                                       if atom.sub_slot == origslot:
+                                               sub_slot = newslot
+                                       else:
+                                               sub_slot = atom.sub_slot
+                                       slot_part += "/" + sub_slot
+                               if atom.slot_operator is not None:
+                                       slot_part += atom.slot_operator
+
+                               split_content[i] = atom.with_slot(slot_part)
+                               modified = True
+
+                       if modified:
+                               mycontent = "".join(split_content)
+
        return mycontent
 
 def update_dbentries(update_iter, mydata, eapi=None):