Example #1
0
 def test_parse_path(self):
     self.assertEqual(BT('macos', '', '10.10', 'x86_64', 'release'),
                      BT.parse_path('macos-10.10/x86_64/release'))
     self.assertEqual(BT('linux', 'ubuntu', '18', 'x86_64', 'release'),
                      BT.parse_path('linux-ubuntu-18/x86_64/release'))
     self.assertEqual(BT('linux', '', '', 'x86_64', 'release'),
                      BT.parse_path('linux/x86_64/release'))
     self.assertEqual(BT('ios', '', '12', 'armv7,arm64', 'release'),
                      BT.parse_path('ios-12/arm64-armv7/release'))
     self.assertEqual(BT('ios', '', '12', 'armv7,arm64', 'debug'),
                      BT.parse_path('ios-12/arm64-armv7/debug'))
Example #2
0
    def test_install_tarball_with_manual_requirements(self):
        foo_recipe = '''
fake_package foo 1.0.0 0 0 linux release x86_64 ubuntu 18
'''
        bar_recipe = '''
fake_package bar 1.0.0 0 0 linux release x86_64 ubuntu 18
  requirements
    foo >= 1.0.0
'''

        baz_recipe = '''
fake_package baz 1.0.0 0 0 linux release x86_64 ubuntu 18
  requirements
    bar >= 1.0.0
'''

        pm = self._make_test_pm_with_am()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
        foo_tarball = FPUT.create_one_package(foo_recipe, mutations)
        bar_tarball = FPUT.create_one_package(bar_recipe, mutations)
        baz_tarball = FPUT.create_one_package(baz_recipe, mutations)

        pm._artifact_manager.publish(foo_tarball, bt, False, None)
        pm._artifact_manager.publish(bar_tarball, bt, False, None)
        pm._artifact_manager.publish(baz_tarball, bt, False, None)

        pm.install_tarball(foo_tarball, ['BUILD', 'RUN'])
        pm.install_tarball(bar_tarball, ['BUILD', 'RUN'])
        pm.install_tarball(baz_tarball, ['BUILD', 'RUN'])
Example #3
0
 def _install_package(self, pm, desc, bt):
     if check.is_string(desc):
         desc = PD.parse(desc)
     check.check_package_descriptor(desc)
     if check.is_string(bt):
         bt = BT.parse_path(bt)
     check.check_build_target(bt)
     pm.install_package(desc, bt, ['RUN'])
Example #4
0
 def _make_two_env_files_pm(self, code1, code2):
     recipe = self.TWO_ENV_FILES_RECIPE % (code1, code2)
     t = AMT(recipes=recipe)
     t.publish('two_env_files;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
     pm = self._make_caca_test_pm(t.am)
     pdesc = PD.parse('two_env_files-1.0.0')
     bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
     pm.install_package(pdesc, bt, ['RUN'])
     return pm
Example #5
0
 def _make_cabbage_pm(self):
     t = AMT(recipes=self.VEGGIES)
     t.publish('cabbage;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
     t.publish('unset;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
     pm = self._make_caca_test_pm(t.am)
     cabbage = PD.parse('cabbage-1.0.0')
     bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
     pm.install_package(cabbage, bt, ['RUN'])
     pm.install_package(PD.parse('unset-1.0.0'), bt, ['RUN'])
     return pm, cabbage
  def test_load_file(self):
    tmp_config_filename = self.__make_test_config(self.TEST_CONFIG_INI)
    config = manager_config()

    config.load_file(tmp_config_filename, build_target.parse_path('macos-10.10/x86_64/release'))
    self.assertEqual( [ 'common1', 'common2', 'common3', 'common4', 'macos1', 'macos2' ], config['project1']['packages'] )
    self.assertEqual( 'project1 config', config['project1']['description'] )

    self.assertEqual( [ 'common10', 'common20' ], config['project2']['packages'] )
    self.assertEqual( 'project2 config', config['project2']['description'] )

    config.load_file(tmp_config_filename, build_target.parse_path('linux-ubuntu-18/x86_64/release'))
    self.assertEqual( [ 'common1', 'common2', 'common3', 'common4', 'linux1', 'linux2' ], config['project1']['packages'] )
    self.assertEqual( 'project1 config', config['project1']['description'] )

    config.load_file(tmp_config_filename, build_target.parse_path('android/armv7/release'))
    self.assertEqual( [ 'common1', 'common2', 'common3', 'common4' ], config['project1']['packages'] )
    self.assertEqual( 'project1 config', config['project1']['description'] )

    config.load_file(tmp_config_filename, build_target.parse_path('ios-12/arm64-armv7/release'))
    self.assertEqual( [ 'common1', 'common2', 'common3', 'common4' ], config['project1']['packages'] )
    self.assertEqual( 'project1 config', config['project1']['description'] )
Example #7
0
 def _parse_exp(self, bt_path, exp):
     return BT.parse_path(bt_path).parse_expression(exp)
Example #8
0
class test_tools_manager(unit_test):

    __unit_test_data_dir__ = '${BES_TEST_DATA_DIR}/rebuilder'
    __script__ = __file__, '../../../../bin/rebuilder.py'

    DEBUG = unit_test.DEBUG
    #DEBUG = True

    TEST_BUILD_TARGET = build_target.parse_path(
        'linux-ubuntu-18/x86_64/release')

    def _make_test_tm(self):
        amt = AMT(recipes=RECIPES.KNIFE, debug=self.DEBUG)
        amt.publish('knife;6.6.6;0;0;linux;release;x86_64;ubuntu;18')
        root_dir = temp_file.make_temp_dir(delete=not self.DEBUG)
        tools_dir = path.join(root_dir, 'tools')
        if self.DEBUG:
            print('\ntools_manager dir:\n%s' % (tools_dir))
        return TM(tools_dir, self.TEST_BUILD_TARGET, amt.am), amt.am, amt

    def test_ensure_tool(self):
        tm, am, amt = self._make_test_tm()
        knife_desc = PD.parse('knife-6.6.6')
        tm.ensure_tools(knife_desc)
        self.assertEqual([
            'knife_6_6_6/linux-ubuntu-18/x86_64/db/packages.db',
            'knife_6_6_6/linux-ubuntu-18/x86_64/env/framework/env/bes_framework.sh',
            'knife_6_6_6/linux-ubuntu-18/x86_64/env/knife_env.sh',
            'knife_6_6_6/linux-ubuntu-18/x86_64/run.sh',
            'knife_6_6_6/linux-ubuntu-18/x86_64/setup.sh',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/bin/cut.exe',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/bin/cut.sh',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/bin/links_with_shared.exe',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/bin/links_with_static.exe',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/include/libfoo_shared.h',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/include/libfoo_static.h',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/lib/libfoo_shared.so',
            'knife_6_6_6/linux-ubuntu-18/x86_64/stuff/lib/libfoo_static.a',
            'knife_6_6_6/run.sh',
            'knife_6_6_6/setup.sh',
        ], file_find.find(tm.root_dir))

    def test_use_shell_tool(self):
        tm, am, amt = self._make_test_tm()
        knife = PD.parse('knife-1.0.0')
        tm.ensure_tools(knife)
        rv = tm.run_tool(knife, ['cut.sh', 'a', 'b', '666'], {})
        self.assertEqual(0, rv.exit_code)
        self.assertEqual('cut.sh: a b 666', rv.stdout.strip())

    def test_use_python_tool(self):
        tm, am, amt = self._make_test_tm()
        amt.add_recipes(self.RECIPES)
        amt.publish(self.DESCRIPTORS)
        cuchillo = PD.parse('cuchillo-1.0.0')
        tm.ensure_tools(cuchillo)
        rv = tm.run_tool(PD.parse('steel-1.0.0'), ['steel_exe.py', '6'], {})
        self.assertEqual(0, rv.exit_code)
        self.assertEqual('steel_exe.py: 16', rv.stdout.strip())

    def test_use_binary_tool_static(self):
        tm, am, amt = self._make_test_tm()
        knife = PD.parse('knife-1.0.0')
        tm.ensure_tools(knife)
        rv = tm.run_tool(knife, ['links_with_static.exe'], {})
        self.assertEqual(0, rv.exit_code)
        self.assertEqual('11', rv.stdout.strip())

    def test_use_binary_tool_shared(self):
        tm, am, amt = self._make_test_tm()
        knife = PD.parse('knife-1.0.0')
        tm.ensure_tools(knife)
        rv = tm.run_tool(knife, ['links_with_shared.exe'], {})
        self.assertEqual(0, rv.exit_code)
        self.assertEqual('22', rv.stdout.strip())

    def test_transform_env(self):
        tm, am, amt = self._make_test_tm()
        amt.add_recipes(self.RECIPES)
        amt.publish(self.DESCRIPTORS)
        cuchillo = PD.parse('cuchillo-1.0.0')
        tm.ensure_tools(cuchillo)
        env = tm.transform_env({}, cuchillo)
        replacements = {tm.root_dir: '$ROOT_DIR'}
        env2 = copy.deepcopy(env)
        dict_util.replace_values(env2, replacements)
        self.assertEqual(
            {
                'WOOD_ENV1':
                'wood_env1',
                'CUCHILLO_ENV1':
                'cuchillo_env1',
                'STEEL_ENV1':
                'steel_env1',
                'IRON_ENV1':
                'iron_env1',
                'CARBON_ENV1':
                'carbon_env1',
                'PATH':
                '/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.:$ROOT_DIR/steel_1_0_0/linux-ubuntu-18/x86_64/stuff/bin:$ROOT_DIR/wood_1_0_0/linux-ubuntu-18/x86_64/stuff/bin:$ROOT_DIR/cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/bin',
                'PYTHONPATH':
                '$ROOT_DIR/steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python:$ROOT_DIR/wood_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python:$ROOT_DIR/cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python',
                'PKG_CONFIG_PATH':
                '$ROOT_DIR/steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/pkgconfig:$ROOT_DIR/steel_1_0_0/linux-ubuntu-18/x86_64/stuff/share/pkgconfig:$ROOT_DIR/wood_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/pkgconfig:$ROOT_DIR/wood_1_0_0/linux-ubuntu-18/x86_64/stuff/share/pkgconfig:$ROOT_DIR/cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/pkgconfig:$ROOT_DIR/cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/share/pkgconfig',
                'LD_LIBRARY_PATH':
                '$ROOT_DIR/steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib:$ROOT_DIR/wood_1_0_0/linux-ubuntu-18/x86_64/stuff/lib:$ROOT_DIR/cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/lib',
            }, env2)

    def test_tool_installed_files(self):
        tm, am, amt = self._make_test_tm()
        amt.add_recipes(self.RECIPES)
        amt.publish(self.DESCRIPTORS)
        cuchillo = PD.parse('cuchillo-1.0.0')
        tm.ensure_tools(cuchillo)
        self.assertEqual([
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/db/packages.db',
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/env/cuchillo_env.sh',
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/env/framework/env/bes_framework.sh',
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/run.sh',
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/setup.sh',
            'cuchillo_1_0_0/linux-ubuntu-18/x86_64/stuff/bin/cuchillo.py',
            'cuchillo_1_0_0/run.sh',
            'cuchillo_1_0_0/setup.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/db/packages.db',
            'steel_1_0_0/linux-ubuntu-18/x86_64/env/carbon_env.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/env/framework/env/bes_framework.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/env/iron_env.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/env/steel_env.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/run.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/setup.sh',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/bin/carbon.py',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/bin/iron.py',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/bin/steel_exe.py',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python/easy-install.pth',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python/site.py',
            'steel_1_0_0/linux-ubuntu-18/x86_64/stuff/lib/python/steel.py',
            'steel_1_0_0/run.sh',
            'steel_1_0_0/setup.sh',
            'wood_1_0_0/linux-ubuntu-18/x86_64/db/packages.db',
            'wood_1_0_0/linux-ubuntu-18/x86_64/env/framework/env/bes_framework.sh',
            'wood_1_0_0/linux-ubuntu-18/x86_64/env/wood_env.sh',
            'wood_1_0_0/linux-ubuntu-18/x86_64/run.sh',
            'wood_1_0_0/linux-ubuntu-18/x86_64/setup.sh',
            'wood_1_0_0/linux-ubuntu-18/x86_64/stuff/bin/wood.py',
            'wood_1_0_0/run.sh',
            'wood_1_0_0/setup.sh',
        ], file_find.find(tm.root_dir))

    RECIPES = '''
fake_package wood 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/wood.py
      \#!/usr/bin/env python
      print('ffoo')
      raise SystemExit(0)

  env_files
    wood_env.sh
      export WOOD_ENV1=wood_env1

fake_package iron 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/iron.py
      \#!/usr/bin/env python
      print('fbar')
      raise SystemExit(0)

  env_files
    iron_env.sh
      export IRON_ENV1=iron_env1

fake_package carbon 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/carbon.py
      \#!/usr/bin/env python
      print('fbar')
      raise SystemExit(0)

  env_files
    carbon_env.sh
      export CARBON_ENV1=carbon_env1

fake_package steel 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/steel_exe.py
      \#!/usr/bin/env python
      import sys
      assert len(sys.argv) == 2
      import steel
      print('steel_exe.py: %d' % (steel.steel_func1(int(sys.argv[1]))))
      raise SystemExit(0)
    lib/python/steel.py
      def steel_func1(x):
        return x + 10

  env_files
    steel_env.sh
      \#@REBUILD_HEAD@
      export STEEL_ENV1=steel_env1
      bes_env_path_append PATH ${REBUILD_STUFF_DIR}/bin
      bes_env_path_append PYTHONPATH ${REBUILD_STUFF_DIR}/lib/python
      \#@REBUILD_TAIL@

  requirements
    all: RUN iron >= 1.0.0
    all: RUN carbon >= 1.0.0

fake_package cuchillo 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/cuchillo.py
      \#!/usr/bin/env python
      print('fbaz')
      raise SystemExit(0)

  env_files
    cuchillo_env.sh
      export CUCHILLO_ENV1=cuchillo_env1

  requirements
    all: TOOL wood >= 1.0.0
    all: TOOL steel >= 1.0.0

'''

    DESCRIPTORS = [
        'carbon;1.0.0;0;0;linux;release;x86_64;ubuntu;18',
        'cuchillo;1.0.0;0;0;linux;release;x86_64;ubuntu;18',
        'iron;1.0.0;0;0;linux;release;x86_64;ubuntu;18',
        'steel;1.0.0;0;0;linux;release;x86_64;ubuntu;18',
        'wood;1.0.0;0;0;linux;release;x86_64;ubuntu;18',
    ]
Example #9
0
class test_remanager(script_unit_test):

    TEST_BUILD_TARGET = BT.parse_path('linux-ubuntu-18/x86_64/release')

    __unit_test_data_dir__ = '${BES_TEST_DATA_DIR}/remanager'
    __script__ = __file__, '../../bin/remanager.py'

    DEBUG = False

    #  DEBUG = True

    def test_simple_config(self):
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: water only
packages: water
[test2]
description: fiber only
packages: fiber
'''
        test = self._setup_test(config)
        args = [
            'packages',
            'update',
            '--artifacts',
            test.artifact_manager.root_dir,
            '--root-dir',
            test.tmp_dir,
            '--system',
            'linux',
            '--distro',
            'ubuntu',
            '--distro-version',
            '18',
            '--level',
            'release',
            'test1',
        ]
        rv = self.run_script(args)
        self.assertEqual(0, rv.exit_code)

        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--system',
            'linux', '--distro', 'ubuntu', '--distro-version', '18', '--level',
            'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual(['water'], rv.stdout.split('\n'))

    def test_update_first_time(self):
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: test1
packages: orange_juice
[test2]
description: test2
packages: apple pear_juice
'''
        test = self._setup_test(config)
        args = [
            'packages', 'update', '--artifacts',
            test.artifact_manager.root_dir, '--root-dir', test.tmp_dir,
            '--system', 'linux', '--distro', 'ubuntu', '--distro-version',
            '18', '--level', 'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual(0, rv.exit_code)

        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--system',
            'linux', '--distro', 'ubuntu', '--distro-version', '18', '--level',
            'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual([
            'citrus', 'fiber', 'fructose', 'fruit', 'orange', 'orange_juice',
            'water'
        ], rv.stdout.split('\n'))

    def test_update_two_times(self):
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: test1
packages: orange_juice
'''
        test = self._setup_test(config)
        args = [
            'packages', 'update', '--artifacts',
            test.artifact_manager.root_dir, '--root-dir', test.tmp_dir,
            '--system', 'linux', '--distro', 'ubuntu', '--distro-version',
            '18', '--level', 'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual(0, rv.exit_code)
        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--system',
            'linux', '--distro', 'ubuntu', '--distro-version', '18', '--level',
            'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual([
            'citrus', 'fiber', 'fructose', 'fruit', 'orange', 'orange_juice',
            'water'
        ], rv.stdout.split('\n'))
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: test1
packages: orange_juice pear_juice
'''
        file_util.save(path.join(test.tmp_dir, 'config'), content=config)
        args = [
            'packages', 'update', '--artifacts',
            test.artifact_manager.root_dir, '--root-dir', test.tmp_dir,
            '--system', 'linux', '--distro', 'ubuntu', '--distro-version',
            '18', '--level', 'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual(0, rv.exit_code)
        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--system',
            'linux', '--distro', 'ubuntu', '--distro-version', '18', '--level',
            'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual([
            'citrus', 'fiber', 'fructose', 'fruit', 'orange', 'orange_juice',
            'pear', 'pear_juice', 'water'
        ], rv.stdout.split('\n'))

    def test_update_script(self):
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: test1
packages: orange_juice
'''
        test = self._setup_test(config)
        args = [
            'packages', 'update', '--artifacts',
            test.artifact_manager.root_dir, '--root-dir', test.tmp_dir,
            '--system', 'linux', '--distro', 'ubuntu', '--distro-version',
            '18', '--level', 'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual(0, rv.exit_code)
        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--system',
            'linux', '--distro', 'ubuntu', '--distro-version', '18', '--level',
            'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual([
            'citrus', 'fiber', 'fructose', 'fruit', 'orange', 'orange_juice',
            'water'
        ], rv.stdout.split('\n'))
        config = '''
[common]
artifacts_dir: /somewhere/not/there
[test1]
description: test1
packages: orange_juice pear_juice
'''
        file_util.save(path.join(test.tmp_dir, 'config'), content=config)
        cmd = [
            path.join(test.tmp_dir,
                      'update.sh'), '--system', 'linux', '--distro', 'ubuntu',
            '--distro-version', '18', '--level', 'release', 'test1'
        ]
        env = os_env.make_clean_env(keep_keys=['PYTHONPATH'],
                                    update={'PATH': path.dirname(self.script)})
        rv = execute.execute(cmd,
                             raise_error=False,
                             env=env,
                             stderr_to_stdout=True)
        if rv.exit_code != 0 or self.DEBUG:
            self.spew(rv.stdout)
        self.assertEqual(0, rv.exit_code)
        args = [
            'packages', 'print', '--root-dir', test.tmp_dir, '--level',
            'release', '--system', 'linux', '--distro', 'ubuntu',
            '--distro-version', '18', '--level', 'release', 'test1'
        ]
        rv = self.run_script(args)
        self.assertEqual([
            'citrus', 'fiber', 'fructose', 'fruit', 'orange', 'orange_juice',
            'pear', 'pear_juice', 'water'
        ], rv.stdout.split('\n'))

    @classmethod
    def _make_temp_dir(clazz):
        tmp_dir = temp_file.make_temp_dir(delete=not clazz.DEBUG)
        if clazz.DEBUG:
            print("tmp_dir: ", tmp_dir)
        return tmp_dir

    @classmethod
    def _make_test_artifact_manager(clazz):
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        return FPUT.make_artifact_manager(debug=clazz.DEBUG,
                                          recipes=RECIPES.FOODS,
                                          build_target=clazz.TEST_BUILD_TARGET,
                                          mutations=mutations)

    _setup = namedtuple('_setup', 'tmp_dir, artifact_manager')

    @classmethod
    def _setup_test(clazz, config):
        tmp_dir = clazz._make_temp_dir()
        am = clazz._make_test_artifact_manager()
        file_util.save(path.join(tmp_dir, 'config'), content=config)
        return clazz._setup(tmp_dir, am)
Example #10
0
class test_package_manager(unit_test):

    DEBUG = unit_test.DEBUG
    #DEBUG = True

    TEST_BUILD_TARGET = BT.parse_path('linux-ubuntu-18/x86_64/release')

    ZLIB_CONTENTS = [
        'include/zconf.h',
        'include/zlib.h',
        'lib/librebbe_z.a',
        'lib/libz.a',
        'lib/pkgconfig/rebbe_zlib.pc',
        'lib/pkgconfig/zlib.pc',
        'share/man/man3/zlib.3',
    ]

    @classmethod
    def _make_test_pm_with_am(clazz):
        root_dir = temp_file.make_temp_dir(delete=not clazz.DEBUG)
        pm_dir = path.join(root_dir, 'package_manager')
        if clazz.DEBUG:
            print("\nroot_dir:\n", root_dir)
        am = clazz._make_test_artifact_manager()
        return package_manager(pm_dir, am)

    @classmethod
    def _make_empty_pm(clazz):
        root_dir = temp_file.make_temp_dir(delete=not clazz.DEBUG)
        pm_dir = path.join(root_dir, 'package_manager')
        am_dir = path.join(root_dir, 'artifact_manager')
        if clazz.DEBUG:
            print("root_dir:\n%s\n" % (root_dir))
        am = artifact_manager_local(am_dir)
        return package_manager(pm_dir, am)

    @classmethod
    def _make_caca_test_pm(clazz, am):
        root_dir = temp_file.make_temp_dir(delete=not clazz.DEBUG)
        pm_dir = path.join(root_dir, 'package_manager')
        if clazz.DEBUG:
            print("\nroot_dir:\n", root_dir)
        return package_manager(pm_dir, am)

    def test_install_tarball_simple(self):
        pm = self._make_empty_pm()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        water_tarball = FPUT.create_one_package(RECIPES.WATER, mutations)
        pm.install_tarball(water_tarball, ['BUILD', 'RUN'])

    def test_install_tarball_pkg_config(self):
        recipe = '''
fake_package libfoo 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    lib/pkgconfig/libfoo.pc
      prefix=${REBUILD_PACKAGE_PREFIX}
      exec_prefix=${prefix}
      libdir=${exec_prefix}/lib
      includedir=${prefix}/include
      
      Name: libfoo
      Description: libfoo
      Version: 1.0.0
      Libs: -L${libdir} -lfoo
      Libs.private: -lfoo-private
      Cflags: -I${includedir}
'''

        self.maxDiff = None
        pm = self._make_test_pm_with_am()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        tarball = FPUT.create_one_package(recipe,
                                          metadata_mutations=mutations,
                                          debug=self.DEBUG)
        pm.install_tarball(tarball, ['BUILD', 'RUN'])
        self.assertEqual(['libfoo-1.0.0'], pm.list_all(include_version=True))

        PKG_CONFIG_PATH = pm.pkg_config_path
        print('PKG_CONFIG_PATH: %s' % (PKG_CONFIG_PATH))

        # list_all
        packages = pkg_config.list_all(PKG_CONFIG_PATH=PKG_CONFIG_PATH)
        # 2 because of the rebbe_ links
        self.assertEqual(1, len(packages))
        self.assertEqual(set(['libfoo']), set([p[0] for p in packages]))

        # cflags
        modules = ['libfoo']
        cflags = pkg_config.cflags(modules, PKG_CONFIG_PATH=PKG_CONFIG_PATH)
        expected_cflags = [
            '-I%s' % (path.join(pm.installation_dir, 'include')),
        ]
        self.assertEqual(expected_cflags, cflags)

        # libs
        modules = ['libfoo']
        libs = pkg_config.libs(modules, PKG_CONFIG_PATH=PKG_CONFIG_PATH)
        expected_libs = [
            '-L%s' % (path.join(pm.installation_dir, 'lib')),
            '-lfoo',
        ]
        self.assertEqual(expected_libs, libs)

    def test_install_tarball_conflicts(self):
        foo_recipe = '''
fake_package foo 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    foo/cellulose.txt
      cellulose
    foo/inulin.txt
      inulin
'''

        bar_recipe = '''
fake_package bar 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    foo/cellulose.txt
      cellulose
    foo/inulin.txt
      inulin
'''

        pm = self._make_empty_pm()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        foo_tarball = FPUT.create_one_package(foo_recipe, mutations)
        bar_tarball = FPUT.create_one_package(bar_recipe, mutations)
        pm.install_tarball(foo_tarball, ['BUILD', 'RUN'])
        with self.assertRaises(PackageFilesConflictError) as context:
            pm.install_tarball(bar_tarball, ['BUILD', 'RUN'])

    def test_install_tarball_already_installed(self):
        pm = self._make_empty_pm()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        tarball = FPUT.create_one_package(RECIPES.WATER, mutations)
        pm.install_tarball(tarball, ['BUILD', 'RUN'])
        with self.assertRaises(AlreadyInstalledError) as context:
            pm.install_tarball(tarball, ['BUILD', 'RUN'])
        self.assertEqual('package water already installed',
                         context.exception.message)

    def test_install_tarball_missing_requirements(self):
        pm = self._make_test_pm_with_am()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        apple_tarball = FPUT.create_one_package(RECIPES.APPLE, mutations)
        with self.assertRaises(PackageMissingRequirementsError) as context:
            pm.install_tarball(apple_tarball, ['BUILD', 'RUN'])
        self.assertEqual(
            'package apple missing requirements: fiber, fructose, water',
            context.exception.message)

    def test_install_tarball_with_manual_requirements(self):
        foo_recipe = '''
fake_package foo 1.0.0 0 0 linux release x86_64 ubuntu 18
'''
        bar_recipe = '''
fake_package bar 1.0.0 0 0 linux release x86_64 ubuntu 18
  requirements
    foo >= 1.0.0
'''

        baz_recipe = '''
fake_package baz 1.0.0 0 0 linux release x86_64 ubuntu 18
  requirements
    bar >= 1.0.0
'''

        pm = self._make_test_pm_with_am()
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
        foo_tarball = FPUT.create_one_package(foo_recipe, mutations)
        bar_tarball = FPUT.create_one_package(bar_recipe, mutations)
        baz_tarball = FPUT.create_one_package(baz_recipe, mutations)

        pm._artifact_manager.publish(foo_tarball, bt, False, None)
        pm._artifact_manager.publish(bar_tarball, bt, False, None)
        pm._artifact_manager.publish(baz_tarball, bt, False, None)

        pm.install_tarball(foo_tarball, ['BUILD', 'RUN'])
        pm.install_tarball(bar_tarball, ['BUILD', 'RUN'])
        pm.install_tarball(baz_tarball, ['BUILD', 'RUN'])

    def test_uninstall(self):
        pm = self._make_test_pm_with_am()
        pi = PD('water', '1.0.0')
        install_rv = pm.install_package(pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertTrue(install_rv)
        self.assertEqual(['water-1.0.0'], pm.list_all(include_version=True))
        pm.uninstall_package('water')
        self.assertEqual([], pm.list_all(include_version=True))

    def test_is_installed(self):
        pm = self._make_empty_pm()
        self.assertFalse(pm.is_installed('water'))
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        tarball = FPUT.create_one_package(RECIPES.WATER, mutations)
        pm.install_tarball(tarball, ['BUILD', 'RUN'])
        self.assertTrue(pm.is_installed('water'))
        self.assertFalse(pm.is_installed('notthere'))

    @classmethod
    def _make_test_artifact_manager(clazz):
        mutations = {
            'system': 'linux',
            'distro': 'ubuntu',
            'distro_version': '18'
        }
        return FPUT.make_artifact_manager(debug=clazz.DEBUG,
                                          recipes=RECIPES.FOODS,
                                          build_target=clazz.TEST_BUILD_TARGET,
                                          mutations=mutations)

    def test_install_package(self):
        pm = self._make_test_pm_with_am()
        pi = PD('water', '1.0.0')
        install_rv = pm.install_package(pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertTrue(install_rv)
        self.assertEqual(['water-1.0.0'], pm.list_all(include_version=True))

    def test_install_package_upgrade(self):
        pm = self._make_test_pm_with_am()

        old_pi = PD('water', '1.0.0')
        install_rv = pm.install_package(old_pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertTrue(install_rv)
        self.assertEqual(['water-1.0.0'], pm.list_all(include_version=True))

        new_pi = PD('water', '1.0.0-1')
        install_rv = pm.install_package(new_pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertTrue(install_rv)
        self.assertEqual(['water-1.0.0-1'], pm.list_all(include_version=True))

    def test_install_package_same_version(self):
        pm = self._make_test_pm_with_am()

        old_pi = PD('water', '1.0.0')
        install_rv = pm.install_package(old_pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertTrue(install_rv)
        self.assertEqual(['water-1.0.0'], pm.list_all(include_version=True))

        new_pi = PD('water', '1.0.0')
        install_rv = pm.install_package(new_pi, self.TEST_BUILD_TARGET,
                                        ['BUILD', 'RUN'])
        self.assertFalse(install_rv)
        self.assertEqual(['water-1.0.0'], pm.list_all(include_version=True))

    def test_install_package_unknown(self):
        pm = self._make_test_pm_with_am()
        pi = PD('notthere', '6.6.6-1')
        with self.assertRaises(NotInstalledError) as context:
            pm.install_package(pi, self.TEST_BUILD_TARGET, ['BUILD', 'RUN'])

    def test_install_packages(self):
        pm = self._make_test_pm_with_am()

        packages = [
            PD.parse('water-1.0.0'),
            PD.parse('mercury-1.2.8'),
            PD.parse('arsenic-1.2.9'),
        ]

        pm.install_packages(packages, self.TEST_BUILD_TARGET, ['BUILD', 'RUN'])

        self.assertEqual(['arsenic-1.2.9', 'mercury-1.2.8', 'water-1.0.0'],
                         pm.list_all(include_version=True))

    def test_dep_map(self):
        pm = self._make_test_pm_with_am()
        packages = [
            PD.parse('water-1.0.0'),
            PD.parse('fiber-1.0.0'),
            PD.parse('fructose-3.4.5-6'),
            PD.parse('fruit-1.0.0'),
            PD.parse('apple-1.2.3-1'),
        ]
        pm.install_packages(packages, self.TEST_BUILD_TARGET, ['RUN'])
        self.assertEqual([
            'apple-1.2.3-1', 'fiber-1.0.0', 'fructose-3.4.5-6', 'fruit-1.0.0',
            'water-1.0.0'
        ], pm.list_all(include_version=True))
        self.assertEqual(
            {
                'apple': set(['fruit']),
                'fiber': set([]),
                'fructose': set([]),
                'fruit': set(['fiber', 'fructose', 'water']),
                'water': set([]),
            }, pm.dep_map())

    def _make_cabbage_pm(self):
        t = AMT(recipes=self.VEGGIES)
        t.publish('cabbage;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        t.publish('unset;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(t.am)
        cabbage = PD.parse('cabbage-1.0.0')
        bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
        pm.install_package(cabbage, bt, ['RUN'])
        pm.install_package(PD.parse('unset-1.0.0'), bt, ['RUN'])
        return pm, cabbage

    def _make_one_env_file_pm(self, code):
        recipe = self.ONE_ENV_FILE_RECIPE % (code)
        t = AMT(recipes=recipe)
        t.publish('one_env_file;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(t.am)
        pdesc = PD.parse('one_env_file-1.0.0')
        bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
        pm.install_package(pdesc, bt, ['RUN'])
        return pm

    def _make_two_env_files_pm(self, code1, code2):
        recipe = self.TWO_ENV_FILES_RECIPE % (code1, code2)
        t = AMT(recipes=recipe)
        t.publish('two_env_files;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(t.am)
        pdesc = PD.parse('two_env_files-1.0.0')
        bt = BT.parse_path('linux-ubuntu-18/x86_64/release')
        pm.install_package(pdesc, bt, ['RUN'])
        return pm

    def test_transform_env_input_not_mutated(self):
        'Check that the environment passed into transform_env() is not mutated.'
        pm, cabbage = self._make_cabbage_pm()
        env1 = {'FOO': 'foo', 'BAR': 'bar'}
        env1_save = copy.deepcopy(env1)
        env2 = pm.transform_env(env1, ['cabbage'])
        self.assert_dict_equal(env1_save, env1)

    def test_transform_env_defaults(self):
        'Check the defaults of transform_env() when the input env is empty.'
        pm, cabbage = self._make_cabbage_pm()
        env1 = {}
        env2 = self._transform_env(pm, env1, ['cabbage'])
        self.assertEqual(
            {
                '$LD_LIBRARY_PATH': '$ROOT_DIR/stuff/lib',
                'PKG_CONFIG_PATH':
                '$ROOT_DIR/stuff/lib/pkgconfig:$ROOT_DIR/stuff/share/pkgconfig',
                'PATH': '$DEFAULT_PATH:$ROOT_DIR/stuff/bin',
                'PYTHONPATH': '$ROOT_DIR/stuff/lib/python',
            }, env2)

    def test_transform_env_append(self):
        code = '''
      bes_env_path_append PATH /zzzz/bin
      bes_env_path_append PYTHONPATH /zzzz/lib/python
      bes_LD_LIBRARY_PATH_append /zzzz/lib
'''
        pm = self._make_one_env_file_pm(code)
        env1 = {
            'PATH': '$DEFAULT_PATH:/p/bin',
            'PYTHONPATH': '/p/lib/python',
            '$LD_LIBRARY_PATH': '/p/lib',
        }
        env2 = self._transform_env(pm, env1, ['one_env_file'])
        expected = {
            'PATH':
            '$DEFAULT_PATH:/p/bin:$ROOT_DIR/stuff/bin:/zzzz/bin',
            'PYTHONPATH':
            '/p/lib/python:$ROOT_DIR/stuff/lib/python:/zzzz/lib/python',
            '$LD_LIBRARY_PATH':
            '/p/lib:$ROOT_DIR/stuff/lib:/zzzz/lib',
            'PKG_CONFIG_PATH':
            '$ROOT_DIR/stuff/lib/pkgconfig:$ROOT_DIR/stuff/share/pkgconfig',
        }
        self.assert_dict_equal(expected, env2)

    def test_transform_env_prepend(self):
        code = '''
      bes_env_path_prepend PATH /zzzz/bin
      bes_env_path_prepend PYTHONPATH /zzzz/lib/python
      bes_LD_LIBRARY_PATH_prepend /zzzz/lib
'''
        pm = self._make_one_env_file_pm(code)
        env1 = {
            'PATH': '$DEFAULT_PATH:/p/bin',
            'PYTHONPATH': '/p/lib/python',
            '$LD_LIBRARY_PATH': '/p/lib',
        }
        env2 = self._transform_env(pm, env1, ['one_env_file'])
        expected = {
            'PATH':
            '/zzzz/bin:$DEFAULT_PATH:/p/bin:$ROOT_DIR/stuff/bin',
            'PYTHONPATH':
            '/zzzz/lib/python:/p/lib/python:$ROOT_DIR/stuff/lib/python',
            '$LD_LIBRARY_PATH':
            '/zzzz/lib:/p/lib:$ROOT_DIR/stuff/lib',
            'PKG_CONFIG_PATH':
            '$ROOT_DIR/stuff/lib/pkgconfig:$ROOT_DIR/stuff/share/pkgconfig',
        }
        self.assert_dict_equal(expected, env2)

    def test_transform_env_unset(self):
        code1 = '''
      export FOO=foo
      export BAR=bar
      export BAZ=baz
'''
        code2 = '''
      unset BAR
'''
        pm = self._make_two_env_files_pm(code1, code2)
        env1 = {}
        env2 = self._transform_env(pm, env1, ['two_env_files'])
        expected = {
            '$LD_LIBRARY_PATH': '$ROOT_DIR/stuff/lib',
            'PKG_CONFIG_PATH':
            '$ROOT_DIR/stuff/lib/pkgconfig:$ROOT_DIR/stuff/share/pkgconfig',
            'PATH': '$DEFAULT_PATH:$ROOT_DIR/stuff/bin',
            'PYTHONPATH': '$ROOT_DIR/stuff/lib/python',
            'FOO': 'foo',
            'BAZ': 'baz',
        }
        self.assert_dict_equal(expected, env2)

    def test_installed_files(self):
        recipe = '''
fake_package files 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/apple.sh
      \#!/bin/bash
      echo apple ; exit 0
    bin/orange.sh
      \#!/bin/bash
      echo orange ; exit 0
  env_files
    foo.sh
      \#@REBUILD_HEAD@
      export FOO=foo
      \#@REBUILD_TAIL@
    bar.sh
      \#@REBUILD_HEAD@
      export BAR=bar
      \#@REBUILD_TAIL@
  '''
        amt = self._make_test_amt(
            recipe, 'files;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(amt.am)
        self._install_package(pm, 'files-1.0.0',
                              'linux-ubuntu-18/x86_64/release')
        self.assertEqual(['files-1.0.0'], pm.list_all(include_version=True))
        expected = [
            'db/packages.db',
            'env/bar.sh',
            'env/foo.sh',
            'env/framework/env/bes_framework.sh',
            'stuff/bin/apple.sh',
            'stuff/bin/orange.sh',
        ]
        self.assertEqual(expected, file_find.find(pm.root_dir, relative=True))

    def test_installed_files_only_files(self):
        recipe = '''
fake_package files 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/apple.sh
      \#!/bin/bash
      echo apple ; exit 0
    bin/orange.sh
      \#!/bin/bash
      echo orange ; exit 0
  '''
        amt = self._make_test_amt(
            recipe, 'files;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(amt.am)
        self._install_package(pm, 'files-1.0.0',
                              'linux-ubuntu-18/x86_64/release')
        self.assertEqual(['files-1.0.0'], pm.list_all(include_version=True))
        expected = [
            'db/packages.db',
            'env/framework/env/bes_framework.sh',
            'stuff/bin/apple.sh',
            'stuff/bin/orange.sh',
        ]
        self.assertEqual(expected, file_find.find(pm.root_dir, relative=True))

    def test_installed_files_only_env_files(self):
        recipe = '''
fake_package files 1.0.0 0 0 linux release x86_64 ubuntu 18
  env_files
    foo.sh
      \#@REBUILD_HEAD@
      export FOO=foo
      \#@REBUILD_TAIL@
    bar.sh
      \#@REBUILD_HEAD@
      export BAR=bar
      \#@REBUILD_TAIL@
  '''
        amt = self._make_test_amt(
            recipe, 'files;1.0.0;0;0;linux;release;x86_64;ubuntu;18')
        pm = self._make_caca_test_pm(amt.am)
        self._install_package(pm, 'files-1.0.0',
                              'linux-ubuntu-18/x86_64/release')
        self.assertEqual(['files-1.0.0'], pm.list_all(include_version=True))
        expected = [
            'db/packages.db',
            'env/bar.sh',
            'env/foo.sh',
            'env/framework/env/bes_framework.sh',
        ]
        self.assertEqual(expected, file_find.find(pm.root_dir, relative=True))

    def _make_test_amt(self, recipes, publish):
        amt = AMT(recipes=recipes)
        publish = object_util.listify(publish)
        check.check_string_seq(publish)
        for p in publish:
            amt.publish(p)
        return amt

    def _install_package(self, pm, desc, bt):
        if check.is_string(desc):
            desc = PD.parse(desc)
        check.check_package_descriptor(desc)
        if check.is_string(bt):
            bt = BT.parse_path(bt)
        check.check_build_target(bt)
        pm.install_package(desc, bt, ['RUN'])

    ONE_ENV_FILE_RECIPE = '''
fake_package one_env_file 1.0.0 0 0 linux release x86_64 ubuntu 18
  env_files
    file1.sh
      \#@REBUILD_HEAD@
      %s
      \#@REBUILD_TAIL@
  '''

    TWO_ENV_FILES_RECIPE = '''
fake_package two_env_files 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/cut.sh
      \#!/bin/bash
      echo cabbage ; exit 0
  env_files
    file1.sh
      \#@REBUILD_HEAD@
      %s
      \#@REBUILD_TAIL@
    file2.sh
      \#@REBUILD_HEAD@
      %s
      \#@REBUILD_TAIL@
  '''

    VEGGIES = '''fake_package cabbage 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/cut.sh
      \#!/bin/bash
      echo cabbage ; exit 0
  env_files
    cabbage_env.sh
      \#@REBUILD_HEAD@
      bes_env_path_append PATH ${REBUILD_STUFF_DIR}/bin
      #bes_env_path_append PYTHONPATH ${REBUILD_STUFF_DIR}/lib/python
      #bes_LD_LIBRARY_PATH_append ${REBUILD_STUFF_DIR}/lib
      \#@REBUILD_TAIL@

fake_package unset 1.0.0 0 0 linux release x86_64 ubuntu 18
  files
    bin/unsetcut.sh
      \#!/bin/bash
      echo cabbage ; exit 0
  env_files
    unset1.sh
      \#@REBUILD_HEAD@
      export FOO=foo
      \#@REBUILD_TAIL@
    unset2.sh
      \#@REBUILD_HEAD@
      export BAR=bar
      \#@REBUILD_TAIL@
    unset3.sh
      \#@REBUILD_HEAD@
      unset FOO
      \#@REBUILD_TAIL@
'''

    @classmethod
    def _replace_input_env(clazz, env):
        result = copy.deepcopy(env)
        if '$LD_LIBRARY_PATH' in result:
            result['LD_LIBRARY_PATH'] = result['$LD_LIBRARY_PATH']
            del result['$LD_LIBRARY_PATH']
        replacements = {
            '$DEFAULT_PATH': os_env.DEFAULT_SYSTEM_PATH,
        }
        dict_util.replace_values(result, replacements)
        return result

    @classmethod
    def _replace_output_env(clazz, pm, env):
        result = copy.deepcopy(env)
        if os_env.LD_LIBRARY_PATH_VAR_NAME in result:
            result['$LD_LIBRARY_PATH'] = result[
                os_env.LD_LIBRARY_PATH_VAR_NAME]
            del result[os_env.LD_LIBRARY_PATH_VAR_NAME]
        replacements = {
            '/private': '',
            pm.root_dir: '$ROOT_DIR',
            os_env.DEFAULT_SYSTEM_PATH: '$DEFAULT_PATH',
        }
        dict_util.replace_values(result, replacements)
        return result

    @classmethod
    def _transform_env(clazz, pm, env, package_names):
        env = clazz._replace_input_env(env)
        result = pm.transform_env(env, package_names)
        return clazz._replace_output_env(pm, result)