def test_clean_all(self): cmds.clean({}) self.mock_exists.assert_has_calls([ mock.call('partdir1'), mock.call().__bool__(), mock.call('partdir2'), mock.call().__bool__(), mock.call('partdir3'), mock.call().__bool__(), mock.call(common.get_partsdir()), mock.call().__bool__(), mock.call(common.get_stagedir()), mock.call().__bool__(), mock.call(common.get_snapdir()), mock.call().__bool__(), ]) self.mock_rmtree.assert_has_calls([ mock.call('partdir1'), mock.call('partdir2'), mock.call('partdir3'), mock.call(common.get_stagedir()), mock.call(common.get_snapdir()), ]) self.mock_rmdir.assert_called_once_with(common.get_partsdir())
def main(argv=None): argv = argv if argv else [] args = docopt(__doc__, argv=argv) config = snapcraft.yaml.load_config() if args['PART']: config.validate_parts(args['PART']) for part in config.all_parts: if not args['PART'] or part.name in args['PART']: part.clean() # parts dir does not contain only generated code. if (os.path.exists(common.get_partsdir()) and not os.listdir(common.get_partsdir())): os.rmdir(common.get_partsdir()) parts_match = set(config.part_names) == set(args['PART']) # Only clean stage if all the parts were cleaned up. clean_stage = not args['PART'] or parts_match if clean_stage and os.path.exists(common.get_stagedir()): logger.info('Cleaning up staging area') shutil.rmtree(common.get_stagedir()) if os.path.exists(common.get_snapdir()): logger.info('Cleaning up snapping area') shutil.rmtree(common.get_snapdir())
def test_partial_clean(self): parts = self.make_snapcraft_yaml(n=3) main(["clean", "clean0", "clean2"]) for i in [0, 2]: self.assertFalse( os.path.exists(parts[i]["part_dir"]), "Expected for {!r} to be wiped".format(parts[i]["part_dir"]) ) self.assertTrue(os.path.exists(parts[1]["part_dir"]), "Expected a part directory for the clean1 part") self.assertTrue(os.path.exists(common.get_partsdir())) self.assertTrue(os.path.exists(common.get_stagedir())) self.assertTrue(os.path.exists(common.get_snapdir())) # Now clean it the rest of the way main(["clean", "clean1"]) for i in range(0, 3): self.assertFalse( os.path.exists(parts[i]["part_dir"]), "Expected for {!r} to be wiped".format(parts[i]["part_dir"]) ) self.assertFalse(os.path.exists(common.get_partsdir())) self.assertFalse(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def clean(args): config = _load_config() part_names = {part.name for part in config.all_parts} for part_name in args.parts: if part_name not in part_names: logger.error('The part named {!r} is not defined in ' '\'snapcraft.yaml\''.format(part_name)) sys.exit(1) for part in config.all_parts: if not args.parts or part.name in args.parts: part.clean() # parts dir does not contain only generated code. if (os.path.exists(common.get_partsdir()) and not os.listdir(common.get_partsdir())): os.rmdir(common.get_partsdir()) clean_stage = not args.parts or part_names == set(args.parts) if clean_stage and os.path.exists(common.get_stagedir()): logger.info('Cleaning up staging area') shutil.rmtree(common.get_stagedir()) if os.path.exists(common.get_snapdir()): logger.info('Cleaning up snapping area') shutil.rmtree(common.get_snapdir())
def test_clean_stage_after_fileset_change(self): # Create part1 and get it through the "build" step. handler = pluginhandler.load_plugin('part1', 'nil') handler.makedirs() bindir = os.path.join(handler.code.installdir, 'bin') os.makedirs(bindir) open(os.path.join(bindir, '1'), 'w').close() open(os.path.join(bindir, '2'), 'w').close() handler.mark_done('build') handler.stage() # Verify that both files have been staged self.assertTrue( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '1'))) self.assertTrue( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '2'))) # Now update the `stage` fileset to only snap one of these files handler.code.options.stage = ['bin/1'] # Now clean the strip step for part1 handler.clean_stage({}) # Verify that part1's file is no longer staged self.assertFalse( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '1')), 'Expected bin/1 to be cleaned') self.assertFalse( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '2')), 'Expected bin/2 to be cleaned as well, even though the filesets ' 'changed since it was staged.')
def test_build_environment(self): class Options: configflags = [] plugin = cmake.CMakePlugin('test-part', Options()) os.makedirs(plugin.builddir) plugin.build() expected = {} expected['CMAKE_PREFIX_PATH'] = '$CMAKE_PREFIX_PATH:{}'.format( common.get_stagedir()) expected['CMAKE_INCLUDE_PATH'] = '$CMAKE_INCLUDE_PATH:' + ':'.join( ['{0}/include', '{0}/usr/include', '{0}/include/{1}', '{0}/usr/include/{1}']).format(common.get_stagedir(), common.get_arch_triplet()) expected['CMAKE_LIBRARY_PATH'] = '$CMAKE_LIBRARY_PATH:' + ':'.join( ['{0}/lib', '{0}/usr/lib', '{0}/lib/{1}', '{0}/usr/lib/{1}']).format(common.get_stagedir(), common.get_arch_triplet()) self.assertEqual(3, self.run_mock.call_count) for call_args in self.run_mock.call_args_list: environment = call_args[1]['env'] for variable, value in expected.items(): self.assertTrue( variable in environment, 'Expected variable "{}" to be in environment'.format( variable)) self.assertEqual(environment[variable], value, 'Expected ${}={}, but it was {}'.format( variable, value, environment[variable]))
def test_partial_clean(self): parts = self.make_snapcraft_yaml(n=3) clean.main(['clean0', 'clean2']) for i in [0, 2]: self.assertFalse( os.path.exists(parts[i]['part_dir']), 'Expected for {!r} to be wiped'.format(parts[i]['part_dir'])) self.assertTrue(os.path.exists(parts[1]['part_dir']), 'Expected a part directory for the clean1 part') self.assertTrue(os.path.exists(common.get_partsdir())) self.assertTrue(os.path.exists(common.get_stagedir())) self.assertTrue(os.path.exists(common.get_snapdir())) # Now clean it the rest of the way clean.main(['clean1']) for i in range(0, 3): self.assertFalse( os.path.exists(parts[i]['part_dir']), 'Expected for {!r} to be wiped'.format(parts[i]['part_dir'])) self.assertFalse(os.path.exists(common.get_partsdir())) self.assertFalse(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def _cleanup_common_directories(config): _remove_directory_if_empty(common.get_partsdir()) _remove_directory_if_empty(common.get_stagedir()) _remove_directory_if_empty(common.get_snapdir()) max_index = -1 for part in config.all_parts: step = part.last_step() if step: index = common.COMMAND_ORDER.index(step) if index > max_index: max_index = index # If no parts have been pulled, remove the parts directory. In most cases # this directory should have already been cleaned, but this handles the # case of a failed pull. should_remove_partsdir = max_index < common.COMMAND_ORDER.index('pull') if should_remove_partsdir and os.path.exists(common.get_partsdir()): logger.info('Cleaning up parts directory') shutil.rmtree(common.get_partsdir()) # If no parts have been staged, remove staging area. should_remove_stagedir = max_index < common.COMMAND_ORDER.index('stage') if should_remove_stagedir and os.path.exists(common.get_stagedir()): logger.info('Cleaning up staging area') shutil.rmtree(common.get_stagedir()) # If no parts have been stripped, remove snapping area. should_remove_snapdir = max_index < common.COMMAND_ORDER.index('strip') if should_remove_snapdir and os.path.exists(common.get_snapdir()): logger.info('Cleaning up snapping area') shutil.rmtree(common.get_snapdir())
def clear_common_directories(self): if os.path.exists(common.get_partsdir()): shutil.rmtree(common.get_partsdir()) if os.path.exists(common.get_stagedir()): shutil.rmtree(common.get_stagedir()) if os.path.exists(common.get_snapdir()): shutil.rmtree(common.get_snapdir())
def _build_environment(self): env = os.environ.copy() env['CMAKE_PREFIX_PATH'] = '$CMAKE_PREFIX_PATH:{}'.format( common.get_stagedir()) env['CMAKE_INCLUDE_PATH'] = '$CMAKE_INCLUDE_PATH:' + ':'.join([ '{0}/include', '{0}/usr/include', '{0}/include/{1}', '{0}/usr/include/{1}' ]).format(common.get_stagedir(), common.get_arch_triplet()) env['CMAKE_LIBRARY_PATH'] = '$CMAKE_LIBRARY_PATH:' + ':'.join([ '{0}/lib', '{0}/usr/lib', '{0}/lib/{1}', '{0}/usr/lib/{1}' ]).format(common.get_stagedir(), common.get_arch_triplet()) return env
def test_clean_nested_dependent_parts(self): yaml = """name: clean-test version: 1.0 summary: test clean description: test clean parts: main: plugin: nil source: . dependent: plugin: nil source: . after: [main] dependent-dependent: plugin: nil source: . after: [dependent]""" super().make_snapcraft_yaml(yaml) part_dirs = {} for part in ['main', 'dependent', 'dependent-dependent']: part_dirs[part] = os.path.join(common.get_partsdir(), part) os.makedirs(part_dirs[part]) os.makedirs(common.get_stagedir()) os.makedirs(common.get_snapdir()) # Cleaning only `main`. Since `dependent` depends upon main, we expect # that it will be cleaned as well. Otherwise it won't be using the new # `main` when it is built. clean.main(['main']) self.assertFalse(os.path.exists(part_dirs['main']), 'Expected part directory for main to be cleaned') self.assertFalse( os.path.exists(part_dirs['dependent']), 'Expected part directory for dependent to be cleaned as it ' 'depends upon main') self.assertFalse( os.path.exists(part_dirs['dependent-dependent']), 'Expected part directory for dependent-dependent to be cleaned as ' 'it depends upon dependent, which depends upon main') self.assertFalse(os.path.exists(common.get_partsdir())) self.assertFalse(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def _build_environment(self): env = os.environ.copy() env['CMAKE_PREFIX_PATH'] = '$CMAKE_PREFIX_PATH:{}'.format( common.get_stagedir()) env['CMAKE_INCLUDE_PATH'] = '$CMAKE_INCLUDE_PATH:' + ':'.join( ['{0}/include', '{0}/usr/include', '{0}/include/{1}', '{0}/usr/include/{1}']).format(common.get_stagedir(), common.get_arch_triplet()) env['CMAKE_LIBRARY_PATH'] = '$CMAKE_LIBRARY_PATH:' + ':'.join( ['{0}/lib', '{0}/usr/lib', '{0}/lib/{1}', '{0}/usr/lib/{1}']).format(common.get_stagedir(), common.get_arch_triplet()) return env
def test_cleanbuild(self, mock_installed, mock_call): mock_installed.return_value = True fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) self.make_snapcraft_yaml() # simulate build artifacts dirs = [ os.path.join(common.get_partsdir(), 'part1', 'src'), common.get_stagedir(), common.get_snapdir(), os.path.join(common.get_partsdir(), 'plugins'), ] files_tar = [ os.path.join(common.get_partsdir(), 'plugins', 'x-plugin.py'), 'main.c', ] files_no_tar = [ os.path.join(common.get_stagedir(), 'binary'), os.path.join(common.get_snapdir(), 'binary'), 'snap-test.snap', 'snap-test_1.0_source.tar.bz2', ] for d in dirs: os.makedirs(d) for f in files_tar + files_no_tar: open(f, 'w').close() cleanbuild.main() self.assertEqual( 'Setting up container with project assets\n' 'Waiting for a network connection...\n' 'Network connection established\n' 'Retrieved snap-test_1.0_amd64.snap\n', fake_logger.output) with tarfile.open('snap-test_1.0_source.tar.bz2') as tar: tar_members = tar.getnames() for f in files_no_tar: f = os.path.relpath(f) self.assertFalse('./{}'.format(f) in tar_members, '{} should not be in {}'.format(f, tar_members)) for f in files_tar: f = os.path.relpath(f) self.assertTrue('./{}'.format(f) in tar_members, '{} should be in {}'.format(f, tar_members))
def test_clean_stage(self): filesets = { 'all': { 'fileset': ['*'], }, 'no1': { 'fileset': ['-1'], }, 'onlya': { 'fileset': ['a'], }, 'onlybase': { 'fileset': ['*', '-*/*'], }, 'nostara': { 'fileset': ['-*/a'], }, } for key, value in filesets.items(): with self.subTest(key=key): self.clear_common_directories() handler = pluginhandler.load_plugin('test_part', 'nil', { 'stage': value['fileset'] }) handler.makedirs() installdir = handler.code.installdir os.makedirs(installdir + '/1/1a/1b') os.makedirs(installdir + '/2/2a') os.makedirs(installdir + '/3') open(installdir + '/a', mode='w').close() open(installdir + '/b', mode='w').close() open(installdir + '/1/a', mode='w').close() open(installdir + '/3/a', mode='w').close() handler.mark_done('build') # Stage the installed files handler.stage() self.assertTrue(os.listdir(common.get_stagedir())) handler.clean_stage({}) self.assertFalse(os.listdir(common.get_stagedir()), 'Expected snapdir to be completely cleaned')
def test_strip_one_part_only_from_3(self): fake_logger = fixtures.FakeLogger(level=logging.ERROR) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml(n=3) strip.main(['strip1', ]) self.assertFalse( os.path.exists( os.path.join(common.get_snapdir(), 'meta', 'snap.yaml')), 'There should not be a snap.yaml') self.assertTrue(os.path.exists(common.get_snapdir()), 'Expected a snap directory') self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[1]['part_dir']), 'Expected a part directory for the strip1 part') self.assertTrue(os.path.exists(parts[1]['state_file']), 'Expected a state file for the strip1 part') with open(parts[1]['state_file']) as sf: state = sf.readlines() self.assertEqual(len(state), 1, 'Expected only one line in the state ' 'file for the strip1 part') self.assertEqual(state[0], 'strip', "Expected the state file for " " strip1 to be 'strip'") for i in [0, 2]: self.assertFalse(os.path.exists(parts[i]['part_dir']), 'Pulled wrong part') self.assertFalse(os.path.exists(parts[i]['state_file']), 'Expected for only to be a state file for build1')
def test_strip_defaults(self): fake_logger = fixtures.FakeLogger(level=logging.ERROR) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml() strip.main() self.assertTrue(os.path.exists(common.get_snapdir()), 'Expected a snap directory') self.assertTrue( os.path.exists( os.path.join(common.get_snapdir(), 'meta', 'package.yaml')), 'Expected a package.yaml') self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[0]['part_dir']), 'Expected a part directory for the build0 part') self.assertTrue(os.path.exists(parts[0]['state_file']), 'Expected a state file for the build0 part') with open(parts[0]['state_file']) as sf: state = sf.readlines() self.assertEqual( len(state), 1, 'Expected only one line in the state ' 'file for the build0 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "build0 to be 'strip'")
def test_stage_ran_twice_is_a_noop(self): fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml() stage.main() self.assertEqual( 'Pulling stage0 \n' 'Building stage0 \n' 'Staging stage0 \n', fake_logger.output) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[0]['part_dir']), 'Expected a part directory for the build0 part') self.verify_state('build0', parts[0]['state_dir'], 'stage') fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) stage.main() self.assertEqual( 'Skipping pull stage0 (already ran)\n' 'Skipping build stage0 (already ran)\n' 'Skipping stage stage0 (already ran)\n', fake_logger.output)
def test_upload(self): upload.main() self.assertEqual( 'Snap snap-test_1.0_amd64.snap not found. ' 'Running snap step to create it.\n' 'Pulling part1 \n' 'Building part1 \n' 'Staging part1 \n' 'Stripping part1 \n' 'Snapping snap-test_1.0_amd64.snap\n' 'Snapped snap-test_1.0_amd64.snap\n', self.fake_logger.output) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(self.state_file, 'Expected a state file for the part1 part') with open(self.state_file) as sf: state = sf.readlines() self.assertEqual(len(state), 1, 'Expected only one line in the state ' 'file for the part1 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "part1 to be 'strip'") self.mock_upload.assert_called_once_with( 'snap-test_1.0_amd64.snap', 'snap-test', config=self.mock_load_config.return_value)
def test_strip_defaults(self): fake_logger = fixtures.FakeLogger(level=logging.ERROR) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml() strip.main() self.assertTrue(os.path.exists(common.get_snapdir()), 'Expected a snap directory') self.assertTrue( os.path.exists( os.path.join(common.get_snapdir(), 'meta', 'snap.yaml')), 'Expected a snap.yaml') self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[0]['part_dir']), 'Expected a part directory for the build0 part') self.assertTrue(os.path.exists(parts[0]['state_file']), 'Expected a state file for the build0 part') with open(parts[0]['state_file']) as sf: state = sf.readlines() self.assertEqual(len(state), 1, 'Expected only one line in the state ' 'file for the build0 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "build0 to be 'strip'")
def test_string_replacement_with_complex_data(self): stagedir = common.get_stagedir() subject = { 'filesets': { 'files': [ 'somefile', '$SNAPCRAFT_STAGE/file1', 'SNAPCRAFT_STAGE/really', ] }, 'configFlags': [ '--with-python', '--with-swig $SNAPCRAFT_STAGE/swig', ], } expected = { 'filesets': { 'files': [ 'somefile', '{}/file1'.format(stagedir), 'SNAPCRAFT_STAGE/really', ] }, 'configFlags': [ '--with-python', '--with-swig {}/swig'.format(stagedir), ], } self.assertEqual(pluginhandler._expand_env(subject), expected)
def test_upload(self): upload.main() self.assertEqual( 'Snap snap-test_1.0_amd64.snap not found. ' 'Running snap step to create it.\n' 'Pulling part1 \n' 'Building part1 \n' 'Staging part1 \n' 'Stripping part1 \n' 'Snapping snap-test_1.0_amd64.snap\n' 'Snapped snap-test_1.0_amd64.snap\n', self.fake_logger.output) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(self.state_file, 'Expected a state file for the part1 part') with open(self.state_file) as sf: state = sf.readlines() self.assertEqual( len(state), 1, 'Expected only one line in the state ' 'file for the part1 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "part1 to be 'strip'") self.mock_upload.assert_called_once_with( 'snap-test_1.0_amd64.snap', 'snap-test', config=self.mock_load_config.return_value)
def test_stage_one_part_only_from_3(self): fake_logger = fixtures.FakeLogger(level=logging.ERROR) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml(n=3) stage.main([ 'stage1', ]) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[1]['part_dir']), 'Expected a part directory for the stage1 part') self.assertTrue(os.path.exists(parts[1]['state_file']), 'Expected a state file for the stage1 part') with open(parts[1]['state_file']) as sf: state = sf.readlines() self.assertEqual( len(state), 1, 'Expected only one line in the state ' 'file for the stage1 part') self.assertEqual( state[0], 'stage', "Expected the state file for " " stage1 to be 'stage'") for i in [0, 2]: self.assertFalse(os.path.exists(parts[i]['part_dir']), 'Pulled wrong part') self.assertFalse( os.path.exists(parts[i]['state_file']), 'Expected for only to be a state file for build1')
def test_strip_one_part_only_from_3(self): fake_logger = fixtures.FakeLogger(level=logging.ERROR) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml(n=3) main(['strip', 'strip1']) self.assertFalse( os.path.exists( os.path.join(common.get_snapdir(), 'meta', 'snap.yaml')), 'There should not be a snap.yaml') self.assertTrue(os.path.exists(common.get_snapdir()), 'Expected a snap directory') self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[1]['part_dir']), 'Expected a part directory for the strip1 part') self.verify_state('strip1', parts[1]['state_dir'], 'strip') for i in [0, 2]: self.assertFalse(os.path.exists(parts[i]['part_dir']), 'Pulled wrong part') self.assertFalse(os.path.exists(parts[i]['state_dir']), 'Expected for only to be a state file for build1')
def test_snap_defaults(self, mock_call): fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) self.make_snapcraft_yaml() snap.main() self.assertEqual( 'Pulling part1 \n' 'Building part1 \n' 'Staging part1 \n' 'Stripping part1 \n' 'Snapping snap-test_1.0_amd64.snap\n' 'Snapped snap-test_1.0_amd64.snap\n', fake_logger.output) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(self.state_file, 'Expected a state file for the part1 part') with open(self.state_file) as sf: state = sf.readlines() self.assertEqual(len(state), 1, 'Expected only one line in the state ' 'file for the part1 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "part1 to be 'strip'") mock_call.assert_called_once_with([ 'mksquashfs', common.get_snapdir(), 'snap-test_1.0_amd64.snap', '-noappend', '-comp', 'xz'])
def test_clean_all(self): self.make_snapcraft_yaml(n=3) clean.main() self.assertFalse(os.path.exists(common.get_partsdir())) self.assertFalse(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def test_clean_all_when_all_parts_specified(self): self.make_snapcraft_yaml(n=3) clean.main(['clean0', 'clean1', 'clean2']) self.assertFalse(os.path.exists(common.get_partsdir())) self.assertFalse(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def test_clean_stage_multiple_independent_parts(self): # Create part1 and get it through the "build" step. handler1 = pluginhandler.load_plugin('part1', 'nil') handler1.makedirs() bindir = os.path.join(handler1.code.installdir, 'bin') os.makedirs(bindir) open(os.path.join(bindir, '1'), 'w').close() handler1.mark_done('build') # Now create part2 and get it through the "build" step. handler2 = pluginhandler.load_plugin('part2', 'nil') handler2.makedirs() bindir = os.path.join(handler2.code.installdir, 'bin') os.makedirs(bindir) open(os.path.join(bindir, '2'), 'w').close() handler2.mark_done('build') # Now stage both parts handler1.stage() handler2.stage() # Verify that part1's file has been staged self.assertTrue( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '1'))) # Verify that part2's file has been staged self.assertTrue( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '2'))) # Now clean the stage step for part1 handler1.clean_stage({}) # Verify that part1's file is no longer staged self.assertFalse( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '1')), "Expected part1's staged files to be cleaned") # Verify that part2's file is still there self.assertTrue( os.path.exists(os.path.join(common.get_stagedir(), 'bin', '2')), "Expected part2's staged files to be untouched")
def _expand_env(attr): if isinstance(attr, str) and _SNAPCRAFT_STAGE in attr: return attr.replace(_SNAPCRAFT_STAGE, common.get_stagedir()) elif isinstance(attr, list) or isinstance(attr, tuple): return [_expand_env(i) for i in attr] elif isinstance(attr, dict): return {k: _expand_env(attr[k]) for k in attr} return attr
def stage_env(self): stagedir = common.get_stagedir() env = [] env += _runtime_env(stagedir) env += _build_env_for_stage(stagedir) for part in self.all_parts: env += part.env(stagedir) return env
def clean(args): config = _load_config() for part in config.all_parts: logger.info("Cleaning up for part %r", part.name) if os.path.exists(part.partdir): shutil.rmtree(part.partdir) # parts dir does not contain only generated code. if os.path.exists(common.get_partsdir()) and not os.listdir(common.get_partsdir()): os.rmdir(common.get_partsdir()) logger.info("Cleaning up staging area") if os.path.exists(common.get_stagedir()): shutil.rmtree(common.get_stagedir()) logger.info("Cleaning up snapping area") if os.path.exists(common.get_snapdir()): shutil.rmtree(common.get_snapdir())
def stage_env(self): root = common.get_stagedir() env = [] env += self.runtime_env(root) env += self.build_env(root) for part in self.all_parts: env += part.env(root) return env
def test_no_parts_defined(self): self.fake_config.all_parts = [] self.mock_load_config.return_value = self.fake_config cmds.clean({}) self.mock_exists.assert_has_calls([ mock.call(common.get_stagedir()), mock.call().__bool__(), mock.call(common.get_snapdir()), mock.call().__bool__(), ]) self.mock_rmtree.assert_has_calls([ mock.call(common.get_stagedir()), mock.call(common.get_snapdir()), ]) self.mock_rmdir.assert_called_once_with(common.get_partsdir())
def clean(args): config = _load_config() for part in config.all_parts: logger.info('Cleaning up for part %r', part.name) if os.path.exists(part.partdir): shutil.rmtree(part.partdir) # parts dir does not contain only generated code. if (os.path.exists(common.get_partsdir()) and not os.listdir(common.get_partsdir())): os.rmdir(common.get_partsdir()) logger.info('Cleaning up staging area') if os.path.exists(common.get_stagedir()): shutil.rmtree(common.get_stagedir()) logger.info('Cleaning up snapping area') if os.path.exists(common.get_snapdir()): shutil.rmtree(common.get_snapdir())
def test_clean_all_when_all_parts_specified(self): class args: parts = ["part1", "part2", "part3"] cmds.clean(args()) self.mock_exists.assert_has_calls( [ mock.call(common.get_partsdir()), mock.call().__bool__(), mock.call(common.get_stagedir()), mock.call().__bool__(), mock.call(common.get_snapdir()), mock.call().__bool__(), ] ) self.mock_rmtree.assert_has_calls([mock.call(common.get_stagedir()), mock.call(common.get_snapdir())]) self.mock_rmdir.assert_called_once_with(common.get_partsdir()) self.assertEqual(self.clean_calls, ["part1", "part2", "part3"])
def test_clean_all(self): class args: parts = [] cmds.clean(args()) self.mock_exists.assert_has_calls([ mock.call(common.get_partsdir()), mock.call().__bool__(), mock.call(common.get_stagedir()), mock.call().__bool__(), mock.call(common.get_snapdir()), mock.call().__bool__(), ]) self.mock_rmtree.assert_has_calls([ mock.call(common.get_stagedir()), mock.call(common.get_snapdir()), ]) self.mock_rmdir.assert_called_once_with(common.get_partsdir()) self.assertEqual(self.clean_calls, ['part1', 'part2', 'part3'])
def test_just_upload_if_snap_file_exists(self): self.mock_os.path.exists.return_value = True upload.main() # stages are not build if snap file already exists self.assertFalse(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertFalse(os.path.exists(self.state_file)) self.mock_upload.assert_called_once_with( 'snap-test_1.0_amd64.snap', 'snap-test', config=self.mock_load_config.return_value)
def test_everything_is_clean(self): self.mock_exists.return_value = False self.mock_listdir.side_effect = FileNotFoundError() cmds.clean({}) self.mock_exists.assert_has_calls([ mock.call('partdir1'), mock.call('partdir2'), mock.call('partdir3'), mock.call(common.get_partsdir()), mock.call(common.get_stagedir()), mock.call(common.get_snapdir()), ]) self.assertFalse(self.mock_rmdir.called) self.assertFalse(self.mock_rmtree.called)
def build_env_for_part(self, part, root_part=True): """Return a build env of all the part's dependencies.""" env = [] stagedir = common.get_stagedir() for dep_part in part.deps: env += dep_part.env(stagedir) env += self.build_env_for_part(dep_part, root_part=False) if root_part: env += part.env(part.installdir) env += _runtime_env(stagedir) env += _runtime_env(part.installdir) env += _build_env_for_stage(stagedir) else: env += part.env(stagedir) env += _runtime_env(stagedir) return env
def test_dict_with_string_replacements(self): stagedir = common.get_stagedir() replacements = ( ( 'no replacement', { '1': 'snapcraft_stage/usr/bin', '2': '/usr/bin', }, { '1': 'snapcraft_stage/usr/bin', '2': '/usr/bin', }, ), ( 'replaced start', { '1': '$SNAPCRAFT_STAGE/usr/bin', '2': '/usr/bin', }, { '1': '{}/usr/bin'.format(stagedir), '2': '/usr/bin', }, ), ( 'replaced between', { '1': '--without-python', '2': '--with-swig $SNAPCRAFT_STAGE/usr/swig', }, { '1': '--without-python', '2': '--with-swig {}/usr/swig'.format(stagedir), }, ), ) for test_name, subject, expected in replacements: self.subTest(key=test_name) self.assertEqual(pluginhandler._expand_env(subject), expected)
def test_partial_clean(self): parts = self.make_snapcraft_yaml(n=3) clean.main(['clean0', 'clean2', ]) for i in [0, 2]: self.assertFalse( os.path.exists(parts[i]['part_dir']), 'Expected for {!r} to be wiped'.format(parts[i]['part_dir'])) self.assertFalse( os.path.exists(parts[i]['state_file']), 'Expected for {!r} to be wiped'.format(parts[i]['state_file'])) self.assertTrue(os.path.exists(parts[1]['part_dir']), 'Expected a part directory for the clean1 part') self.assertTrue(os.path.exists(parts[1]['state_file']), 'Expected a state file for the clean1 part') self.assertTrue(os.path.exists(common.get_partsdir())) self.assertTrue(os.path.exists(common.get_stagedir())) self.assertFalse(os.path.exists(common.get_snapdir()))
def test_strip_ran_twice_is_a_noop(self): fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) parts = self.make_snapcraft_yaml() strip.main() self.assertEqual( 'Pulling strip0 \n' 'Building strip0 \n' 'Staging strip0 \n' 'Stripping strip0 \n', fake_logger.output) self.assertTrue(os.path.exists(common.get_stagedir()), 'Expected a stage directory') self.assertTrue(os.path.exists(common.get_partsdir()), 'Expected a parts directory') self.assertTrue(os.path.exists(parts[0]['part_dir']), 'Expected a part directory for the build0 part') self.assertTrue(os.path.exists(parts[0]['state_file']), 'Expected a state file for the build0 part') with open(parts[0]['state_file']) as sf: state = sf.readlines() self.assertEqual( len(state), 1, 'Expected only one line in the state ' 'file for the build0 part') self.assertEqual(state[0], 'strip', "Expected the state file for " "build0 to be 'strip'") fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) strip.main() self.assertEqual( 'Skipping pull strip0 (already ran)\n' 'Skipping build strip0 (already ran)\n' 'Skipping stage strip0 (already ran)\n' 'Skipping strip strip0 (already ran)\n', fake_logger.output)
def make_snapcraft_yaml(self, n=1, create=True): parts = '\n'.join([self.yaml_part.format(i) for i in range(n)]) super().make_snapcraft_yaml(self.yaml_template.format(parts=parts)) open('icon.png', 'w').close() parts = [] for i in range(n): part_dir = os.path.join(common.get_partsdir(), 'clean{}'.format(i)) state_file = os.path.join(part_dir, 'state') parts.append({ 'part_dir': part_dir, 'state_file': state_file, }) if create: os.makedirs(part_dir) open(state_file, 'w').close() if create: os.makedirs(common.get_stagedir()) os.makedirs(common.get_snapdir()) return parts
def test_get_stagedir(self): self.assertEqual(os.path.join(self.path, 'stage'), common.get_stagedir())