Bug 1275419 - Add support for the --option=+a,-b kind of options in python configure. r?chmanchester
--- 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 int 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'))