def execute(self): node_paths = self.context.products.get_data(NodePaths) runtime_classpath_product = self.context.products.get_data( 'runtime_classpath', init_func=ClasspathProducts.init_func(self.get_options().pants_workdir)) bundleable_js_product = self.context.products.get_data( 'bundleable_js', init_func=lambda: defaultdict(MultipleRootedProducts)) targets = self.context.targets(predicate=self.is_node_module) with self.invalidated(targets, invalidate_dependents=True) as invalidation_check: for vt in invalidation_check.all_vts: target = vt.target node_installed_path = node_paths.node_path(target) with pushd(node_installed_path): if not vt.valid: self._run_build_script( target, vt.results_dir, node_installed_path, node_paths.all_node_paths) if not target.payload.dev_dependency: output_dir = self._get_output_dir(target, node_installed_path) # Make sure that there is output generated. if not os.path.exists(output_dir): raise TaskError( 'Target {} has build script {} specified, but did not generate any output ' 'at {}.\n'.format( target.address.reference(), target.payload.build_script, output_dir)) absolute_symlink(output_dir, os.path.join(vt.results_dir, target.address.target_name)) bundleable_js_product[target].add_abs_paths(output_dir, [output_dir]) runtime_classpath_product.add_for_target(target, [('default', vt.results_dir)])
def execute(self): node_paths = self.context.products.get_data(NodePaths) runtime_classpath_product = self.context.products.get_data( 'runtime_classpath', init_func=ClasspathProducts.init_func(self.get_options().pants_workdir)) bundleable_js_product = self.context.products.get_data( 'bundleable_js', init_func=lambda: defaultdict(MultipleRootedProducts)) targets = self.context.targets(predicate=self.is_node_module) with self.invalidated(targets, invalidate_dependents=True) as invalidation_check: for vt in invalidation_check.all_vts: target = vt.target node_installed_path = node_paths.node_path(target) with pushd(node_installed_path): if not vt.valid: self._run_build_script(target, vt.results_dir, node_installed_path) if not target.payload.dev_dependency: output_dir = self._get_output_dir(target, node_installed_path) # Make sure that there is output generated. if not os.path.exists(output_dir): raise TaskError( 'Target {} has build script {} specified, but did not generate any output ' 'at {}.\n'.format( target.address.reference(), target.payload.build_script, output_dir)) absolute_symlink(output_dir, os.path.join(vt.results_dir, target.address.target_name)) bundleable_js_product[target].add_abs_paths(output_dir, [output_dir]) runtime_classpath_product.add_for_target(target, [('default', vt.results_dir)])
async def export( console: Console, targets: Targets, export_subsystem: ExportSubsystem, workspace: Workspace, union_membership: UnionMembership, build_root: BuildRoot, dist_dir: DistDir, ) -> Export: request_types = cast("Iterable[type[ExportableDataRequest]]", union_membership.get(ExportableDataRequest)) requests = tuple(request_type(targets) for request_type in request_types) exportables = await MultiGet( Get(ExportableData, ExportableDataRequest, request) for request in requests) prefixed_digests = await MultiGet( Get(Digest, AddPrefix(exp.digest, exp.reldir)) for exp in exportables) output_dir = os.path.join(str(dist_dir.relpath), "export") merged_digest = await Get(Digest, MergeDigests(prefixed_digests)) dist_digest = await Get(Digest, AddPrefix(merged_digest, output_dir)) workspace.write_digest(dist_digest) for exp in exportables: for symlink in exp.symlinks: # Note that if symlink.source_path is an abspath, join returns it unchanged. source_abspath = os.path.join(build_root.path, symlink.source_path) link_abspath = os.path.abspath( os.path.join(output_dir, exp.reldir, symlink.link_rel_path)) absolute_symlink(source_abspath, link_abspath) console.print_stdout( f"Wrote {exp.description} to {os.path.join(output_dir, exp.reldir)}" ) return Export(exit_code=0)
def create_symlink_to_clean_workdir(): # Executed when no link exists. We treat this as equivalent to a request to have deleted # this state. Operations like `clean-all` will already have purged the destination, but in # cases like manual removal of the symlink, we want to treat the case as equivalent. safe_mkdir(workdir_dst, clean=True) absolute_symlink(workdir_dst, workdir_src) maybe_create_source_control_symlink()
def execute(self): targets = self.context.targets(predicate=self.is_node_module) if not targets: return node_paths = self.context.products.get_data(NodePaths) # This is required even if node does not need `compile_classpaths` because certain downstream # tasks require `runtime_classpath` to be initialized correctly with `compile_classpaths` compile_classpath = self.context.products.get_data( "compile_classpath", init_func=ClasspathProducts.init_func( self.get_options().pants_workdir), ) runtime_classpath = self.context.products.get_data( "runtime_classpath", compile_classpath.copy) bundleable_js_product = self.context.products.get_data( "bundleable_js", init_func=lambda: defaultdict(MultipleRootedProducts)) with self.invalidated( targets, invalidate_dependents=True) as invalidation_check: for vt in invalidation_check.all_vts: target = vt.target node_installed_path = node_paths.node_path(target) with pushd(node_installed_path): if not vt.valid: self._run_build_script(target, vt.results_dir, node_installed_path, node_paths.all_node_paths) if not target.payload.dev_dependency: output_dir = self._get_output_dir( target, node_installed_path) # Make sure that there is output generated. if not os.path.exists(output_dir): raise TaskError( "Target {} has build script {} specified, but did not generate any output " "at {}.\n".format( target.address.reference(), target.payload.build_script, output_dir, )) absolute_symlink( output_dir, os.path.join(vt.results_dir, target.address.target_name)) bundleable_js_product[target].add_abs_paths( output_dir, [output_dir]) runtime_classpath.add_for_target( target, [("default", self._snapshotted_classpath(vt.results_dir))])
def publish_results(self, dist_dir, use_basename_prefix, vt, bundle_dir, archivepath, id, archive_ext): """Publish a copy of the bundle and archive from the results dir in dist.""" # TODO (from mateor) move distdir management somewhere more general purpose. name = vt.target.basename if use_basename_prefix else id bundle_copy = os.path.join(dist_dir, '{}-bundle'.format(name)) absolute_symlink(bundle_dir, bundle_copy) self.context.log.info( 'created bundle copy {}'.format(os.path.relpath(bundle_copy, get_buildroot()))) if archivepath: ext = archive.archive_extensions.get(archive_ext, archive_ext) archive_copy = os.path.join(dist_dir,'{}.{}'.format(name, ext)) safe_mkdir_for(archive_copy) # Ensure parent dir exists atomic_copy(archivepath, archive_copy) self.context.log.info( 'created archive copy {}'.format(os.path.relpath(archive_copy, get_buildroot())))
def maybe_create_source_control_symlink(): """If the buildroot we are working in has a source control administrative directory, we need to add a link to it from the physical workdir we create. Tools which run from the physical workdir expect to be able to glean repository information directly. For instance node_binary targets are built using ad-hoc build scripts which can do this. """ # Don't link anything unless this option is enabled. if not global_options.pants_physical_workdir_source_control: return for scm_state_dir in SOURCE_CONTROL_DIRS: scm_source_path = os.path.join(get_buildroot(), scm_state_dir) scm_target_path = os.path.join(workdir_dst, scm_state_dir) if os.path.exists(scm_source_path) and not symlink_is_correct( scm_source_path, scm_target_path): absolute_symlink(scm_source_path, scm_target_path) break
def init_workdir(global_options): """Given the bootstrap options (generally immediately after bootstrap), initialize the workdir. If it is in use, the "physical" workdir is a directory under the `pants_physical_workdir_base` that is unique to each working copy (via including the entire path to the working copy in its name using `safe_filename_from_path`). """ workdir_src = global_options.pants_workdir if not global_options.pants_physical_workdir_base: safe_mkdir(workdir_src) return workdir_src workdir_base = global_options.pants_physical_workdir_base workdir_dst = os.path.join(workdir_base, safe_filename_from_path(workdir_src)) def create_symlink_to_clean_workdir(): # Executed when no link exists. We treat this as equivalent to a request to have deleted # this state. Operations like `clean-all` will already have purged the destination, but in # cases like manual removal of the symlink, we want to treat the case as equivalent. safe_mkdir(workdir_dst, clean=True) absolute_symlink(workdir_dst, workdir_src) if not os.path.lexists(workdir_src): # Does not exist. create_symlink_to_clean_workdir() elif os.path.islink(workdir_src): if os.readlink(workdir_src) != workdir_dst: # Exists but is incorrect. os.unlink(workdir_src) create_symlink_to_clean_workdir() else: # Exists and is correct: ensure that the destination exists. safe_mkdir(workdir_dst) else: safe_rmtree(workdir_src) absolute_symlink(workdir_dst, workdir_src) return workdir_src
def _create_and_check_link(self, source: str, link: str) -> None: absolute_symlink(source, link) self.assertTrue(os.path.islink(link)) self.assertEqual(source, os.readlink(link))
def _create_and_check_link(self, source, link): absolute_symlink(source, link) self.assertTrue(os.path.islink(link)) self.assertEquals(source, os.readlink(link))
def _create_and_check_link(self, source: str, link: str) -> None: absolute_symlink(source, link) assert os.path.islink(link) assert source == os.readlink(link)