Bug 1275419 - Add support for the --option=+a,-b kind of options in python configure. r=chmanchester
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 25 May 2016 15:55:03 +0900
changeset 340182 429f5a3ae4badce551053d5697914d710301233e
parent 340181 83a0dff3856c57b1124da4df3d69c535bcdcfd83
child 340183 27108dad917e666a72ba384ac2311217158aa0c2
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschmanchester
bugs1275419
milestone49.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1275419 - Add support for the --option=+a,-b kind of options in python configure. r=chmanchester
python/mozbuild/mozbuild/configure/options.py
python/mozbuild/mozbuild/test/configure/test_options.py
--- a/python/mozbuild/mozbuild/configure/options.py
+++ b/python/mozbuild/mozbuild/configure/options.py
@@ -338,22 +338,41 @@ class Option(object):
                     '*': '0 or more',
                     '+': '1 or more',
                 }.get(self.nargs, str(self.nargs)),
                 's' if (not isinstance(self.nargs, int) or
                         self.nargs != 1) else ''
             ))
 
         if len(values) and self.choices:
+            relative_result = None
             for val in values:
+                if self.nargs in ('+', '*'):
+                    if val.startswith(('+', '-')):
+                        if relative_result is None:
+                            relative_result = list(self.default)
+                        sign = val[0]
+                        val = val[1:]
+                        if sign == '+':
+                            if val not in relative_result:
+                                relative_result.append(val)
+                        else:
+                            try:
+                                relative_result.remove(val)
+                            except ValueError:
+                                pass
+
                 if val not in self.choices:
                     raise InvalidOptionError(
                         "'%s' is not one of %s"
                         % (val, ', '.join("'%s'" % c for c in self.choices)))
 
+            if relative_result is not None:
+                values = PositiveOptionValue(relative_result, origin=origin)
+
         return values
 
 
 class CommandLineHelper(object):
     '''Helper class to handle the various ways options can be given either
     on the command line of through the environment.
 
     For instance, an Option('--foo', env='FOO') can be passed as --foo on the
--- a/python/mozbuild/mozbuild/test/configure/test_options.py
+++ b/python/mozbuild/mozbuild/test/configure/test_options.py
@@ -233,16 +233,54 @@ class TestOption(unittest.TestCase):
         value = option.get_value('--with-option=b,a')
         self.assertTrue(value)
         self.assertEquals(PositiveOptionValue(('b', 'a')), value)
 
         # Test nargs inference from choices
         option = Option('--with-option', choices=('a', 'b'))
         self.assertEqual(option.nargs, 1)
 
+        # Test "relative" values
+        option = Option('--with-option', nargs='*', default=('b', 'c'),
+                        choices=('a', 'b', 'c', 'd'))
+
+        value = option.get_value('--with-option=+d')
+        self.assertEquals(PositiveOptionValue(('b', 'c', 'd')), value)
+
+        value = option.get_value('--with-option=-b')
+        self.assertEquals(PositiveOptionValue(('c',)), value)
+
+        value = option.get_value('--with-option=-b,+d')
+        self.assertEquals(PositiveOptionValue(('c','d')), value)
+
+        # Adding something that is in the default is fine
+        value = option.get_value('--with-option=+b')
+        self.assertEquals(PositiveOptionValue(('b', 'c')), value)
+
+        # Removing something that is not in the default is fine, as long as it
+        # is one of the choices
+        value = option.get_value('--with-option=-a')
+        self.assertEquals(PositiveOptionValue(('b', 'c')), value)
+
+        with self.assertRaises(InvalidOptionError) as e:
+            option.get_value('--with-option=-e')
+        self.assertEquals(e.exception.message,
+                          "'e' is not one of 'a', 'b', 'c', 'd'")
+
+        # Other "not a choice" errors.
+        with self.assertRaises(InvalidOptionError) as e:
+            option.get_value('--with-option=+e')
+        self.assertEquals(e.exception.message,
+                          "'e' is not one of 'a', 'b', 'c', 'd'")
+
+        with self.assertRaises(InvalidOptionError) as e:
+            option.get_value('--with-option=e')
+        self.assertEquals(e.exception.message,
+                          "'e' is not one of 'a', 'b', 'c', 'd'")
+
     def test_option_value_format(self):
         val = PositiveOptionValue()
         self.assertEquals('--with-value', val.format('--with-value'))
         self.assertEquals('--with-value', val.format('--without-value'))
         self.assertEquals('--enable-value', val.format('--enable-value'))
         self.assertEquals('--enable-value', val.format('--disable-value'))
         self.assertEquals('--value', val.format('--value'))
         self.assertEquals('VALUE=1', val.format('VALUE'))