def link_meta_folder(self, spec): src = spack.store.layout.metadata_path(spec) tgt = self.get_path_meta_folder(spec) tree = LinkTree(src) # there should be no conflicts when linking the meta folder tree.merge(tgt, link=self.link)
def merge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate( self.layout.hidden_file_paths, ignore) # check for dir conflicts conflicts = tree.find_dir_conflicts(view_dst, ignore_file) merge_map = tree.get_file_map(view_dst, ignore_file) if not self.ignore_conflicts: conflicts.extend(pkg.view_file_conflicts(self, merge_map)) if conflicts: raise MergeConflictError(conflicts[0]) # merge directories with the tree tree.merge_directories(view_dst, ignore_file) pkg.add_files_to_view(self, merge_map)
def add_standalone(self, spec): if spec.package.is_extension: tty.error(self._croot + 'Package %s is an extension.' % spec.name) return False if spec.external: tty.warn(self._croot + 'Skipping external package: %s' % colorize_spec(spec)) return True if self.check_added(spec): tty.warn(self._croot + 'Skipping already linked package: %s' % colorize_spec(spec)) return True if spec.package.extendable: # Check for globally activated extensions in the extendee that # we're looking at. activated = [ p.spec for p in spack.store.db.activated_extensions_for(spec) ] if activated: tty.error("Globally activated extensions cannot be used in " "conjunction with filesystem views. " "Please deactivate the following specs: ") spack.cmd.display_specs(activated, flags=True, variants=True, long=False) return False tree = LinkTree(spec.prefix) if not self.ignore_conflicts: conflict = tree.find_conflict(self.root) if conflict is not None: tty.error(self._croot + "Cannot link package %s, file already exists: %s" % (spec.name, conflict)) return False conflicts = tree.merge(self.root, link=self.link, ignore=ignore_metadata_dir, ignore_conflicts=self.ignore_conflicts) self.link_meta_folder(spec) if self.ignore_conflicts: for c in conflicts: tty.warn(self._croot + "Could not link: %s" % c) if self.verbose: tty.info(self._croot + 'Linked package: %s' % colorize_spec(spec)) return True
def setUp(self): self.stage = Stage('link-tree-test') with working_dir(self.stage.path): touchp('source/1') touchp('source/a/b/2') touchp('source/a/b/3') touchp('source/c/4') touchp('source/c/d/5') touchp('source/c/d/6') touchp('source/c/d/e/7') source_path = os.path.join(self.stage.path, 'source') self.link_tree = LinkTree(source_path)
def unmerge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate(self.layout.hidden_file_regexes, ignore) merge_map = tree.get_file_map(view_dst, ignore_file) pkg.remove_files_from_view(self, merge_map) # now unmerge the directory tree tree.unmerge_directories(view_dst, ignore_file)
def remove_standalone(self, spec): """ Remove (unlink) a standalone package from this view. """ if not self.check_added(spec): tty.warn(self._croot + 'Skipping package not linked in view: %s' % spec.name) return tree = LinkTree(spec.prefix) tree.unmerge(self.root, ignore=ignore_metadata_dir) self.unlink_meta_folder(spec) if self.verbose: tty.info(self._croot + 'Removed package: %s' % colorize_spec(spec))
def unmerge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate( self.layout.hidden_file_paths, ignore) merge_map = tree.get_file_map(view_dst, ignore_file) pkg.remove_files_from_view(self, merge_map) # now unmerge the directory tree tree.unmerge_directories(view_dst, ignore_file)
def deactivate(self, extension, **kwargs): extensions_layout = kwargs.get("extensions_layout", spack.store.extensions) if extensions_layout is not spack.store.extensions: raise ExtensionError( 'aspell does not support non-global extensions') aspell = which(self.prefix.bin.aspell) dest_dir = aspell('dump', 'config', 'dict-dir', output=str).strip() def ignore(filename): return (filename in spack.store.layout.hidden_file_paths or kwargs.get('ignore', lambda f: False)(filename)) tree = LinkTree(extension.prefix.lib) tree.unmerge(dest_dir, ignore=ignore)
def link(src, dest): abs_src = os.path.abspath(src) conf_py = os.path.join(abs_src, 'conf.py') if not os.path.exists(conf_py): tty.die("Not a Sphinx docs directory: %s" % src) fs.mkdirp(dest) with fs.working_dir(dest): rel_src = os.path.relpath(abs_src) lt = LinkTree(rel_src) lt.merge('.', relative=True, ignore=lambda f: '_spack_root' in f) for f in copy_files: os.remove(f) shutil.copy(os.path.join(abs_src, f), f)
def link_tree(stage): """Return a properly initialized LinkTree instance.""" source_path = os.path.join(stage.path, 'source') return LinkTree(source_path)
class LinkTreeTest(unittest.TestCase): """Tests Spack's LinkTree class.""" def setUp(self): self.stage = Stage('link-tree-test') with working_dir(self.stage.path): touchp('source/1') touchp('source/a/b/2') touchp('source/a/b/3') touchp('source/c/4') touchp('source/c/d/5') touchp('source/c/d/6') touchp('source/c/d/e/7') source_path = os.path.join(self.stage.path, 'source') self.link_tree = LinkTree(source_path) def tearDown(self): if self.stage: self.stage.destroy() def check_file_link(self, filename): self.assertTrue(os.path.isfile(filename)) self.assertTrue(os.path.islink(filename)) def check_dir(self, filename): self.assertTrue(os.path.isdir(filename)) def test_merge_to_new_directory(self): with working_dir(self.stage.path): self.link_tree.merge('dest') self.check_file_link('dest/1') self.check_file_link('dest/a/b/2') self.check_file_link('dest/a/b/3') self.check_file_link('dest/c/4') self.check_file_link('dest/c/d/5') self.check_file_link('dest/c/d/6') self.check_file_link('dest/c/d/e/7') self.link_tree.unmerge('dest') self.assertFalse(os.path.exists('dest')) def test_merge_to_existing_directory(self): with working_dir(self.stage.path): touchp('dest/x') touchp('dest/a/b/y') self.link_tree.merge('dest') self.check_file_link('dest/1') self.check_file_link('dest/a/b/2') self.check_file_link('dest/a/b/3') self.check_file_link('dest/c/4') self.check_file_link('dest/c/d/5') self.check_file_link('dest/c/d/6') self.check_file_link('dest/c/d/e/7') self.assertTrue(os.path.isfile('dest/x')) self.assertTrue(os.path.isfile('dest/a/b/y')) self.link_tree.unmerge('dest') self.assertTrue(os.path.isfile('dest/x')) self.assertTrue(os.path.isfile('dest/a/b/y')) self.assertFalse(os.path.isfile('dest/1')) self.assertFalse(os.path.isfile('dest/a/b/2')) self.assertFalse(os.path.isfile('dest/a/b/3')) self.assertFalse(os.path.isfile('dest/c/4')) self.assertFalse(os.path.isfile('dest/c/d/5')) self.assertFalse(os.path.isfile('dest/c/d/6')) self.assertFalse(os.path.isfile('dest/c/d/e/7')) def test_merge_with_empty_directories(self): with working_dir(self.stage.path): mkdirp('dest/f/g') mkdirp('dest/a/b/h') self.link_tree.merge('dest') self.link_tree.unmerge('dest') self.assertFalse(os.path.exists('dest/1')) self.assertFalse(os.path.exists('dest/a/b/2')) self.assertFalse(os.path.exists('dest/a/b/3')) self.assertFalse(os.path.exists('dest/c/4')) self.assertFalse(os.path.exists('dest/c/d/5')) self.assertFalse(os.path.exists('dest/c/d/6')) self.assertFalse(os.path.exists('dest/c/d/e/7')) self.assertTrue(os.path.isdir('dest/a/b/h')) self.assertTrue(os.path.isdir('dest/f/g')) def test_ignore(self): with working_dir(self.stage.path): touchp('source/.spec') touchp('dest/.spec') self.link_tree.merge('dest', ignore=lambda x: x == '.spec') self.link_tree.unmerge('dest', ignore=lambda x: x == '.spec') self.assertFalse(os.path.exists('dest/1')) self.assertFalse(os.path.exists('dest/a')) self.assertFalse(os.path.exists('dest/c')) self.assertTrue(os.path.isfile('source/.spec')) self.assertTrue(os.path.isfile('dest/.spec'))