package com.atomist.rug.cli.command.shell; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import com.atomist.project.archive.ResolvedDependency; import com.atomist.project.archive.RugResolver; import com.atomist.rug.cli.Constants; import com.atomist.rug.cli.command.AbstractAnnotationBasedCommand; import com.atomist.rug.cli.command.CommandContext; import com.atomist.rug.cli.command.CommandEventListener; import com.atomist.rug.cli.command.CommandEventListenerAdapter; import com.atomist.rug.cli.command.CommandEventListenerRegistry; import com.atomist.rug.cli.command.annotation.Command; import com.atomist.rug.cli.command.fs.ArtifactSourceFileWatcherFactory; import com.atomist.rug.cli.command.fs.ArtifactSourceFileWatcherFactory.FileWatcher; import com.atomist.rug.cli.output.ProgressReportingOperationRunner; import com.atomist.rug.cli.output.Style; import com.atomist.rug.cli.settings.Settings; import com.atomist.rug.cli.utils.ArtifactDescriptorUtils; import com.atomist.rug.cli.version.VersionUtils; import com.atomist.rug.resolver.ArtifactDescriptor; import com.atomist.rug.resolver.LocalArtifactDescriptor; import com.atomist.rug.resolver.metadata.MetadataWriter; import com.atomist.source.ArtifactSource; import com.atomist.source.FileArtifact; public class ShellCommand extends AbstractAnnotationBasedCommand { private static final String BANNER_CONFIG_KEY = "shell-banner-enable"; private static final String banner = "" + " ____ ____ _ ___ \n" + " | _ \\ _ _ __ _ / ___| | |_ _|\n" + " | |_) | | | |/ _` | | | | | | | \n" + " | _ <| |_| | (_| | | |___| |___ | | \n" + " |_| \\_\\\\__,_|\\__, | \\____|_____|___|\n" + " %s |___/ %s"; @Command public void run(ArtifactSource source, ArtifactDescriptor artifact, ResolvedDependency operations, RugResolver resolver, Settings settings) { new ProgressReportingOperationRunner<Void>(String.format("Initializing shell for %s", ArtifactDescriptorUtils.coordinates(artifact))).run((reporter) -> { registerFileSystemWatcherEventListener(artifact, operations); registerOperationsEventListener(source, artifact, operations, resolver); return null; }); if (!Constants.isShell()) { printBanner(settings); } Constants.setShell(true); } private void registerFileSystemWatcherEventListener(ArtifactDescriptor artifact, ResolvedDependency operations) { if (artifact instanceof LocalArtifactDescriptor && operations != null) { CommandContext.save(FileWatcher.class, ArtifactSourceFileWatcherFactory.create(artifact)); } } private void registerOperationsEventListener(ArtifactSource source, ArtifactDescriptor artifact, ResolvedDependency operations, RugResolver resolver) { CommandEventListener listener = new OperationsLoadedEventListener(source); listener.operationsLoaded(artifact, operations, resolver); CommandEventListenerRegistry.register(listener); } private void printBanner(Settings settings) { if (settings.getConfigValue(BANNER_CONFIG_KEY, true)) { String version = VersionUtils.readVersion().orElse("0.0.0"); log.newline(); log.info(banner, Style.gray("Atomist"), Style.gray(StringUtils.leftPad(version, 18))); } log.newline(); log.info( "Press 'Tab' to complete. Type 'help' and hit 'Return' for help, and 'exit' to quit."); } private static class OperationsLoadedEventListener extends CommandEventListenerAdapter { private ArtifactSource source; public OperationsLoadedEventListener(ArtifactSource source) { this.source = source; } @Override public void operationsLoaded(ArtifactDescriptor artifact, ResolvedDependency operations, RugResolver resolver) { if (artifact != null && operations != null) { FileArtifact file = MetadataWriter.createWithoutExcludes(operations.rugs(), artifact, source, null, Constants.cliClient()); try { FileUtils.write(ShellUtils.SHELL_OPERATIONS, file.content(), StandardCharsets.ISO_8859_1); FileUtils.forceDeleteOnExit(ShellUtils.SHELL_OPERATIONS); } catch (IOException e) { // We can't write the operations out to a file, so what? } } } } }