#1572 Reuse make_module in mmd resolver tests
Merged 4 years ago by cqi. Opened 4 years ago by cqi.

file modified
+11 -2
@@ -5,6 +5,7 @@ 

  import functools

  import hashlib

  import os

+ import re

  import time

  from traceback import extract_stack

  
@@ -489,10 +490,18 @@ 

      if arches:

          assert store_to_db

  

-     name, stream, version, context = nsvc.split(":")

+     nsvc_regex = re.compile(r"([^:]+):([^:]+):([^:]+)(?::(.+))?")

+ 

+     match = nsvc_regex.match(nsvc)

+     if not match:

+         raise ValueError('Argument nsvc is not in format N:S:V or N:S:V:C')

+ 

+     name, stream, version, context = match.groups()

+ 

      mmd = Modulemd.ModuleStreamV2.new(name, stream)

      mmd.set_version(int(version))

-     mmd.set_context(context)

+     if context:

+         mmd.set_context(context)

      mmd.set_summary("foo")

      # Test unicode in mmd.

      mmd.set_description(u"foo \u2019s")

@@ -6,8 +6,8 @@ 

  import pytest

  import solv

  

- from module_build_service import Modulemd

  from module_build_service.web.mmd_resolver import MMDResolver

+ from tests import make_module

  

  

  class TestMMDResolver:
@@ -17,54 +17,6 @@ 

      def teardown_method(self, test_method):

          pass

  

-     @staticmethod

-     def _make_mmd(nsvc, requires, xmd_buildrequires=None, virtual_streams=None):

-         name, stream, version = nsvc.split(":", 2)

-         mmd = Modulemd.ModuleStreamV2.new(name, stream)

-         mmd.set_summary("foo")

-         mmd.set_description("foo")

-         for license_ in mmd.get_module_licenses():

-             mmd.remove_module_license(license_)

-         mmd.add_module_license("GPL")

- 

-         xmd = mmd.get_xmd()

-         xmd["mbs"] = {}

-         xmd["mbs"]["buildrequires"] = {}

-         if xmd_buildrequires:

-             for ns in xmd_buildrequires:

-                 n, s = ns.split(":")

-                 xmd["mbs"]["buildrequires"][n] = {"stream": s}

-         if virtual_streams:

-             xmd["mbs"]["virtual_streams"] = virtual_streams

-         mmd.set_xmd(xmd)

- 

-         if ":" in version:

-             version, context = version.split(":")

-             mmd.set_context(context)

-             add_requires = Modulemd.Dependencies.add_runtime_stream

-             add_empty_requires = Modulemd.Dependencies.set_empty_runtime_dependencies_for_module

-         else:

-             add_requires = Modulemd.Dependencies.add_buildtime_stream

-             add_empty_requires = Modulemd.Dependencies.set_empty_buildtime_dependencies_for_module

-         mmd.set_version(int(version))

- 

-         if not isinstance(requires, list):

-             requires = [requires]

-         else:

-             requires = requires

- 

-         for reqs in requires:

-             deps = Modulemd.Dependencies()

-             for req_name, req_streams in reqs.items():

-                 if req_streams == []:

-                     add_empty_requires(deps, req_name)

-                 else:

-                     for req_stream in req_streams:

-                         add_requires(deps, req_name, req_stream)

-             mmd.add_dependencies(deps)

- 

-         return mmd

- 

      @pytest.mark.parametrize(

          "deps, expected",

          (
@@ -83,12 +35,25 @@ 

          assert str(reqs) == expected

  

      @pytest.mark.parametrize(

-         "buildrequires, expected",

+         "dependencies, expected",

          (

-             ({"platform": []}, [[["platform:f28:0:c0:x86_64"], ["platform:f29:0:c0:x86_64"]]]),

-             ({"platform": ["f28"]}, [[["platform:f28:0:c0:x86_64"]]]),

              (

-                 {"gtk": [], "qt": []},

+                 [{"buildrequires": {"platform": []}}],

+                 [

+                     [

+                         ["platform:f28:0:c0:x86_64"],

+                         ["platform:f29:0:c0:x86_64"],

+                     ]

+                 ]

+             ),

+             (

+                 [{"buildrequires": {"platform": ["f28"]}}],

+                 [

+                     [["platform:f28:0:c0:x86_64"]]

+                 ]

+             ),

+             (

+                 [{"buildrequires": {"gtk": [], "qt": []}}],

                  [

                      [

                          ["gtk:3:0:c8:x86_64", "qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"],
@@ -99,7 +64,7 @@ 

                  ],

              ),

              (

-                 {"gtk": [], "qt": [], "platform": []},

+                 [{"buildrequires": {"gtk": [], "qt": [], "platform": []}}],

                  [

                      [

                          ["gtk:3:0:c8:x86_64", "qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"],
@@ -114,7 +79,10 @@ 

                  ],

              ),

              (

-                 [{"qt": [], "platform": ["f28"]}, {"gtk": [], "platform": ["f29"]}],

+                 [

+                     {"buildrequires": {"qt": [], "platform": ["f28"]}},

+                     {"buildrequires": {"gtk": [], "platform": ["f29"]}}

+                 ],

                  [

                      [

                          ["qt:4:0:c8:x86_64", "platform:f28:0:c0:x86_64"],
@@ -127,11 +95,11 @@ 

                  ],

              ),

              (

-                 {"mess": []},

+                 [{"buildrequires": {"mess": []}}],

                  [[["mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64", "platform:f28:0:c0:x86_64"]]],

              ),

              (

-                 {"mess": [], "platform": []},

+                 [{"buildrequires": {"mess": [], "platform": []}}],

                  [

                      [

                          ["mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64", "platform:f28:0:c0:x86_64"],
@@ -141,27 +109,31 @@ 

              ),

          ),

      )

-     def test_solve(self, buildrequires, expected):

+     def test_solve(self, dependencies, expected):

          modules = (

-             ("platform:f28:0:c0", {}),

-             ("platform:f29:0:c0", {}),

-             ("gtk:3:0:c8", {"platform": ["f28"]}),

-             ("gtk:3:0:c9", {"platform": ["f29"]}),

-             ("gtk:4:0:c8", {"platform": ["f28"]}),

-             ("gtk:4:0:c9", {"platform": ["f29"]}),

-             ("qt:4:0:c8", {"platform": ["f28"]}),

-             ("qt:4:0:c9", {"platform": ["f29"]}),

-             ("qt:5:0:c8", {"platform": ["f28"]}),

-             ("qt:5:0:c9", {"platform": ["f29"]}),

+             ("platform:f28:0:c0", []),

+             ("platform:f29:0:c0", []),

+             ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}]),

+             ("gtk:3:0:c9", [{"requires": {"platform": ["f29"]}}]),

+             ("gtk:4:0:c8", [{"requires": {"platform": ["f28"]}}]),

+             ("gtk:4:0:c9", [{"requires": {"platform": ["f29"]}}]),

+             ("qt:4:0:c8", [{"requires": {"platform": ["f28"]}}]),

+             ("qt:4:0:c9", [{"requires": {"platform": ["f29"]}}]),

+             ("qt:5:0:c8", [{"requires": {"platform": ["f28"]}}]),

+             ("qt:5:0:c9", [{"requires": {"platform": ["f29"]}}]),

              (

                  "mess:1:0:c0",

-                 [{"gtk": ["3"], "platform": ["f28"]}, {"gtk": ["4"], "platform": ["f29"]}],

+                 [

+                     {"requires": {"gtk": ["3"], "platform": ["f28"]}},

+                     {"requires": {"gtk": ["4"], "platform": ["f29"]}},

+                 ],

              ),

          )

-         for n, req in modules:

-             self.mmd_resolver.add_modules(self._make_mmd(n, req))

+         for nsvc, deps in modules:

+             self.mmd_resolver.add_modules(

+                 make_module(nsvc, dependencies=deps))

  

-         app = self._make_mmd("app:1:0", buildrequires)

+         app = make_module("app:1:0", dependencies=dependencies)

          expanded = self.mmd_resolver.solve(app)

  

          expected = set(
@@ -171,11 +143,11 @@ 

          assert expanded == expected

  

      @pytest.mark.parametrize(

-         "buildrequires, expected",

+         "dependencies, expected",

          (

              # BR all platform streams -> build for all platform streams.

              (

-                 {"platform": []},

+                 [{"buildrequires": {"platform": []}}],

                  [

                      [

                          ["platform:el8.2.0.z:0:c0:x86_64"],
@@ -187,7 +159,7 @@ 

              ),

              # BR "el8" platform stream -> build for all el8 platform streams.

              (

-                 {"platform": ["el8"]},

+                 [{"buildrequires": {"platform": ["el8"]}}],

                  [

                      [

                          ["platform:el8.2.0.z:0:c0:x86_64"],
@@ -197,18 +169,21 @@ 

                  ],

              ),

              # BR "el8.1.0" platform stream -> build just for el8.1.0.

-             ({"platform": ["el8.1.0"]}, [[["platform:el8.1.0:0:c0:x86_64"]]]),

+             (

+                 [{"buildrequires": {"platform": ["el8.1.0"]}}],

+                 [[["platform:el8.1.0:0:c0:x86_64"]]]

+             ),

              # BR platform:el8.1.0 and gtk:3, which is not built against el8.1.0,

              # but it is built only against el8.0.0 -> cherry-pick gtk:3 from el8.0.0

              # and build once against platform:el8.1.0.

              (

-                 {"platform": ["el8.1.0"], "gtk": ["3"]},

+                 [{"buildrequires": {"platform": ["el8.1.0"], "gtk": ["3"]}}],

                  [[["platform:el8.1.0:0:c0:x86_64", "gtk:3:0:c8:x86_64"]]],

              ),

              # BR platform:el8.2.0 and gtk:3, this time gtk:3 build against el8.2.0 exists

              # -> use both platform and gtk from el8.2.0 and build once.

              (

-                 {"platform": ["el8.2.0.z"], "gtk": ["3"]},

+                 [{"buildrequires": {"platform": ["el8.2.0.z"], "gtk": ["3"]}}],

                  [[["platform:el8.2.0.z:0:c0:x86_64", "gtk:3:1:c8:x86_64"]]],

              ),

              # BR platform:el8.2.0 and mess:1 which is built against platform:el8.1.0 and
@@ -217,7 +192,7 @@ 

              # -> cherry-pick mess:1 from el8.1.0 and

              # -> use gtk:3:1 from el8.2.0.

              (

-                 {"platform": ["el8.2.0.z"], "mess": ["1"]},

+                 [{"buildrequires": {"platform": ["el8.2.0.z"], "mess": ["1"]}}],

                  [[["platform:el8.2.0.z:0:c0:x86_64", "mess:1:0:c0:x86_64", "gtk:3:1:c8:x86_64"]]],

              ),

              # BR platform:el8.1.0 and mess:1 which is built against platform:el8.1.0 and
@@ -226,13 +201,13 @@ 

              # -> Used mess:1 from el8.1.0 and

              # -> cherry-pick gtk:3:0 from el8.0.0.

              (

-                 {"platform": ["el8.1.0"], "mess": ["1"]},

+                 [{"buildrequires": {"platform": ["el8.1.0"], "mess": ["1"]}}],

                  [[["platform:el8.1.0:0:c0:x86_64", "mess:1:0:c0:x86_64", "gtk:3:0:c8:x86_64"]]],

              ),

              # BR platform:el8.0.0 and mess:1 which is built against platform:el8.1.0 and

              # requires gtk:3 which is built against platform:el8.2.0 and platform:el8.0.0

              # -> No valid combination, because mess:1 is only available in el8.1.0 and later.

-             ({"platform": ["el8.0.0"], "mess": ["1"]}, []),

+             ([{"buildrequires": {"platform": ["el8.0.0"], "mess": ["1"]}}], []),

              # This is undefined... it might build just once against latest platform or

              # against all the platforms... we don't know

              # ({"platform": ["el8"], "gtk": ["3"]}, {}, [
@@ -240,21 +215,40 @@ 

              # ]),

          ),

      )

-     def test_solve_virtual_streams(self, buildrequires, expected):

+     def test_solve_virtual_streams(self, dependencies, expected):

          modules = (

-             # (nsvc, buildrequires, expanded_buildrequires, virtual_streams)

-             ("platform:el8.0.0:0:c0", {}, {}, ["el8"]),

-             ("platform:el8.1.0:0:c0", {}, {}, ["el8"]),

-             ("platform:el8.2.0.z:0:c0", {}, {}, ["el8"]),

-             ("platform:el7.6.0:0:c0", {}, {}, ["el7"]),

-             ("gtk:3:0:c8", {"platform": ["el8"]}, {"platform:el8.0.0"}, None),

-             ("gtk:3:1:c8", {"platform": ["el8"]}, {"platform:el8.2.0.z"}, None),

-             ("mess:1:0:c0", [{"gtk": ["3"], "platform": ["el8"]}], {"platform:el8.1.0"}, None),

+             # (nsvc, dependencies, xmd_mbs_buildrequires, virtual_streams)

+             ("platform:el8.0.0:0:c0", [], {}, ["el8"]),

+             ("platform:el8.1.0:0:c0", [], {}, ["el8"]),

+             ("platform:el8.2.0.z:0:c0", [], {}, ["el8"]),

+             ("platform:el7.6.0:0:c0", [], {}, ["el7"]),

+             (

+                 "gtk:3:0:c8",

+                 [{"requires": {"platform": ["el8"]}}],

+                 {"platform": {"stream": "el8.0.0"}},

+                 None

+             ),

+             (

+                 "gtk:3:1:c8",

+                 [{"requires": {"platform": ["el8"]}}],

+                 {"platform": {"stream": "el8.2.0.z"}},

+                 None

+             ),

+             (

+                 "mess:1:0:c0",

+                 [{"requires": {"gtk": ["3"], "platform": ["el8"]}}],

+                 {"platform": {"stream": "el8.1.0"}},

+                 None

+             ),

          )

-         for n, req, xmd_br, virtual_streams in modules:

-             self.mmd_resolver.add_modules(self._make_mmd(n, req, xmd_br, virtual_streams))

- 

-         app = self._make_mmd("app:1:0", buildrequires)

+         for nsvc, deps, xmd_mbs_brs, virtual_streams in modules:

+             xmd = {"mbs": {"buildrequires": xmd_mbs_brs}}

+             if virtual_streams:

+                 xmd["mbs"]["virtual_streams"] = virtual_streams

+             self.mmd_resolver.add_modules(

+                 make_module(nsvc, dependencies=deps, xmd=xmd))

+ 

+         app = make_module("app:1:0", dependencies=dependencies)

          if not expected:

              with pytest.raises(RuntimeError):

                  self.mmd_resolver.solve(app)
@@ -268,32 +262,32 @@ 

          assert expanded == expected

  

      @pytest.mark.parametrize(

-         "app_buildrequires, modules, err_msg_regex",

+         "dependencies, modules, err_msg_regex",

          (

              # app --br--> gtk:1 --req--> bar:1* ---req---> platform:f29

              #    \--br--> foo:1 --req--> bar:2* ---req--/

              (

-                 {"gtk": "1", "foo": "1"},

+                 [{"buildrequires": {"gtk": ["1"], "foo": ["1"]}}],

                  (

-                     ("platform:f29:0:c0", {}),

-                     ("gtk:1:1:c01", {"bar": ["1"]}),

-                     ("bar:1:0:c02", {"platform": ["f29"]}),

-                     ("foo:1:1:c03", {"bar": ["2"]}),

-                     ("bar:2:0:c04", {"platform": ["f29"]}),

+                     ("platform:f29:0:c0", []),

+                     ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]),

+                     ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]),

+                     ("foo:1:1:c03", [{"requires": {"bar": ["2"]}}]),

+                     ("bar:2:0:c04", [{"requires": {"platform": ["f29"]}}]),

                  ),

                  "bar:1:0:c02 and bar:2:0:c04",

              ),

              # app --br--> gtk:1 --req--> bar:1* ----------req----------> platform:f29

              #    \--br--> foo:1 --req--> baz:1 --req--> bar:2* --req--/

              (

-                 {"gtk": "1", "foo": "1"},

+                 [{"buildrequires": {"gtk": ["1"], "foo": ["1"]}}],

                  (

-                     ("platform:f29:0:c0", {}),

-                     ("gtk:1:1:c01", {"bar": ["1"]}),

-                     ("bar:1:0:c02", {"platform": ["f29"]}),

-                     ("foo:1:1:c03", {"baz": ["1"]}),

-                     ("baz:1:1:c04", {"bar": ["2"]}),

-                     ("bar:2:0:c05", {"platform": ["f29"]}),

+                     ("platform:f29:0:c0", []),

+                     ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]),

+                     ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]),

+                     ("foo:1:1:c03", [{"requires": {"baz": ["1"]}}]),

+                     ("baz:1:1:c04", [{"requires": {"bar": ["2"]}}]),

+                     ("bar:2:0:c05", [{"requires": {"platform": ["f29"]}}]),

                  ),

                  "bar:1:0:c02 and bar:2:0:c05",

              ),
@@ -303,29 +297,37 @@ 

              #    \--br--> pkga:1 --req--> perl:5' -------req-----------/

              #    \--br--> pkgb:1 --req--> perl:6' -------req-----------/

              (

-                 {"gtk": "1", "foo": "1", "pkga": "1", "pkgb": "1"},

+                 [{

+                     "buildrequires": {

+                         "gtk": ["1"],

+                         "foo": ["1"],

+                         "pkga": ["1"],

+                         "pkgb": ["1"],

+                     }

+                 }],

                  (

                      ("platform:f29:0:c0", {}),

-                     ("gtk:1:1:c01", {"bar": ["1"]}),

-                     ("bar:1:0:c02", {"platform": ["f29"]}),

-                     ("foo:1:1:c03", {"baz": ["1"]}),

-                     ("baz:1:1:c04", {"bar": ["2"]}),

-                     ("bar:2:0:c05", {"platform": ["f29"]}),

-                     ("pkga:1:0:c06", {"perl": ["5"]}),

-                     ("perl:5:0:c07", {"platform": ["f29"]}),

-                     ("pkgb:1:0:c08", {"perl": ["6"]}),

-                     ("perl:6:0:c09", {"platform": ["f29"]}),

+                     ("gtk:1:1:c01", [{"requires": {"bar": ["1"]}}]),

+                     ("bar:1:0:c02", [{"requires": {"platform": ["f29"]}}]),

+                     ("foo:1:1:c03", [{"requires": {"baz": ["1"]}}]),

+                     ("baz:1:1:c04", [{"requires": {"bar": ["2"]}}]),

+                     ("bar:2:0:c05", [{"requires": {"platform": ["f29"]}}]),

+                     ("pkga:1:0:c06", [{"requires": {"perl": ["5"]}}]),

+                     ("perl:5:0:c07", [{"requires": {"platform": ["f29"]}}]),

+                     ("pkgb:1:0:c08", [{"requires": {"perl": ["6"]}}]),

+                     ("perl:6:0:c09", [{"requires": {"platform": ["f29"]}}]),

                  ),

                  # MMD Resolver should still catch a conflict

                  "bar:1:0:c02 and bar:2:0:c05",

              ),

          ),

      )

-     def test_solve_stream_conflicts(self, app_buildrequires, modules, err_msg_regex):

-         for n, req in modules:

-             self.mmd_resolver.add_modules(self._make_mmd(n, req))

+     def test_solve_stream_conflicts(self, dependencies, modules, err_msg_regex):

+         for nsvc, deps in modules:

+             self.mmd_resolver.add_modules(

+                 make_module(nsvc, dependencies=deps))

  

-         app = self._make_mmd("app:1:0", app_buildrequires)

+         app = make_module("app:1:0", dependencies=dependencies)

  

          with pytest.raises(RuntimeError, match=err_msg_regex):

              self.mmd_resolver.solve(app)
@@ -338,16 +340,19 @@ 

          with all available platforms.

          """

          modules = (

-             ("platform:f28:0:c0", {}),

-             ("platform:f29:0:c0", {}),

-             ("platform:f30:0:c0", {}),

-             ("gtk:3:0:c8", {"platform": ["f28"]}),

-             ("gtk:3:0:c9", {"platform": ["f29"]}),

+             ("platform:f28:0:c0", []),

+             ("platform:f29:0:c0", []),

+             ("platform:f30:0:c0", []),

+             ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}]),

+             ("gtk:3:0:c9", [{"requires": {"platform": ["f29"]}}]),

          )

-         for n, req in modules:

-             self.mmd_resolver.add_modules(self._make_mmd(n, req))

+         for nsvc, deps in modules:

+             self.mmd_resolver.add_modules(

+                 make_module(nsvc, dependencies=deps))

  

-         app = self._make_mmd("app:1:0", {"platform": [], "gtk": ["3"]})

+         app = make_module("app:1:0", dependencies=[

+             {"buildrequires": {"platform": [], "gtk": ["3"]}}

+         ])

          expanded = self.mmd_resolver.solve(app)

  

          # Build only against f28 and f29, because "gtk:3" is not built against f30.
@@ -364,15 +369,24 @@ 

          it was built on newer platform stream, but can run on any platform stream.

          """

          modules = (

-             ("platform:f28:0:c0", {}, {}),

-             ("platform:f29:0:c0", {}, {}),

-             ("platform:f30:0:c0", {}, {}),

-             ("foo:1:0:c8", {"platform": []}, ["platform:f29"]),

+             ("platform:f28:0:c0", [], {}),

+             ("platform:f29:0:c0", [], {}),

+             ("platform:f30:0:c0", [], {}),

+             (

+                 "foo:1:0:c8",

+                 [{"requires": {"platform": []}}],

+                 {"platform": {"stream": "f29"}}

+             ),

          )

-         for n, req, xmd_req in modules:

-             self.mmd_resolver.add_modules(self._make_mmd(n, req, xmd_req))

- 

-         app = self._make_mmd("app:1:0", {"platform": ["f28"], "foo": ["1"]})

+         for nsvc, deps, xmd_mbs_brs in modules:

+             mmd = make_module(nsvc, dependencies=deps, xmd={

+                 "mbs": {"buildrequires": xmd_mbs_brs}

+             })

+             self.mmd_resolver.add_modules(mmd)

+ 

+         app = make_module("app:1:0", [

+             {"buildrequires": {"platform": ["f28"], "foo": ["1"]}}

+         ])

          expanded = self.mmd_resolver.solve(app)

  

          expected = {
@@ -382,18 +396,18 @@ 

          assert expanded == expected

  

      @pytest.mark.parametrize(

-         "nsvc, requires, expected",

+         "nsvc, dependencies, expected",

          (

-             ("platform:f28:0:c0", {}, True),

-             ("platform:latest:5:c8", {}, False),

-             ("gtk:3:0:c8", {"platform": ["f28"]}, False)

+             ("platform:f28:0:c0", [], True),

+             ("platform:latest:5:c8", [], False),

+             ("gtk:3:0:c8", [{"requires": {"platform": ["f28"]}}], False)

          ),

      )

-     def test_base_module_stream_version(self, nsvc, requires, expected):

+     def test_base_module_stream_version(self, nsvc, dependencies, expected):

          """

          Tests that add_base_module_provides returns True for base modules with stream versions

          """

-         mmd = self._make_mmd(nsvc, requires)

+         mmd = make_module(nsvc, dependencies=dependencies)

          solvable = self.mmd_resolver.available_repo.add_solvable()

          solvable.name = nsvc

          solvable.evr = str(mmd.get_version())
@@ -408,7 +422,7 @@ 

          ),

      )

      def test_base_module_provides(self, nsvc, expected):

-         self.mmd_resolver.add_modules(self._make_mmd(nsvc, {}))

+         self.mmd_resolver.add_modules(make_module(nsvc))

          ns = nsvc.rsplit(":", 2)[0]

          provides = self.mmd_resolver.solvables[ns][0].lookup_deparray(solv.SOLVABLE_PROVIDES)

          assert {str(provide) for provide in provides} == expected

Signed-off-by: Chenxiong Qi cqi@redhat.com

Build #744 failed (commit: 7c57767cd28fc311c508c756e45628addd78fe11).
Rebase or make new commits to rebuild.

Could you please double quotes here and below to meet the coding standards?

How about the following regex so that you don't capture the colon in context?

([^:]+):([^:]+):([^:]+)(?::(.+))?

@cqi everything else looks good. Thanks for doing this!

rebased onto ed98760

4 years ago

Build #776 failed (commit: ed98760).
Rebase or make new commits to rebuild.

Build #778 failed (commit: ed98760).
Rebase or make new commits to rebuild.

@mprahl The comments are addressed. I'll merge this PR so that I can update my other PRs based on this one. Thanks for your review.

Pull-Request has been merged by cqi

4 years ago

Build #777 failed (commit: ed98760).
Rebase or make new commits to rebuild.