Index: subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy =================================================================== diff -u -N -red32e3402ab4946b789489a4bd44a86f98afca2b -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy (.../DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy) (revision ed32e3402ab4946b789489a4bd44a86f98afca2b) +++ subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/suppliers/DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy (.../DynamicRevisionRemoteResolveWithMetadataSupplierIntegrationTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -16,10 +16,10 @@ package org.gradle.integtests.resolve.suppliers import org.gradle.api.internal.artifacts.ivyservice.CacheLayout -import org.gradle.integtests.fixtures.cache.CachingIntegrationFixture import org.gradle.integtests.fixtures.GradleMetadataResolveRunner import org.gradle.integtests.fixtures.RequiredFeature import org.gradle.integtests.fixtures.RequiredFeatures +import org.gradle.integtests.fixtures.cache.CachingIntegrationFixture import org.gradle.integtests.resolve.AbstractModuleDependencyResolveTest import org.gradle.test.fixtures.HttpModule import org.gradle.test.fixtures.file.TestFile @@ -1040,8 +1040,8 @@ then: noExceptionThrown() - result.assertRawOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" - result.assertRawOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" + result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:2.2" + result.assertOutputContains "Found result for rule [DefaultConfigurableRule{rule=class MP, ruleParams=[]}] and key group:projectB:1.1" } def "changing the implementation of a rule invalidates the cache"() { Index: subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy =================================================================== diff -u -N -r7f4731b7dfb369efe0d7015162ecfb8722606aa3 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy (.../InProcessGradleExecuterIntegrationTest.groovy) (revision 7f4731b7dfb369efe0d7015162ecfb8722606aa3) +++ subprojects/internal-integ-testing/src/integTest/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuterIntegrationTest.groovy (.../InProcessGradleExecuterIntegrationTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -23,8 +23,6 @@ import spock.lang.Specification import spock.lang.Unroll -import static org.gradle.util.TextUtil.normaliseLineSeparators - class InProcessGradleExecuterIntegrationTest extends Specification { @Rule RedirectStdOutAndErr outputs = new RedirectStdOutAndErr() @@ -146,6 +144,6 @@ } def stripped(String output) { - return normaliseLineSeparators(LogContent.stripWorkInProgressArea(output)) + return LogContent.of(output).withNormalizedEol() } } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy =================================================================== diff -u -N -r7f4731b7dfb369efe0d7015162ecfb8722606aa3 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy (.../RichConsoleStyling.groovy) (revision 7f4731b7dfb369efe0d7015162ecfb8722606aa3) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/RichConsoleStyling.groovy (.../RichConsoleStyling.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -15,45 +15,14 @@ */ package org.gradle.integtests.fixtures - -import org.fusesource.jansi.Ansi - /** * A trait for testing console behavior. *

* Note: The console output contains formatting characters. */ trait RichConsoleStyling { public final static String CONTROL_SEQUENCE_START = "\u001B[" - public final static String CONTROL_SEQUENCE_SEPARATOR = ";" - public final static String CONTROL_SEQUENCE_END = "m" - public final static String DEFAULT_TEXT = "0;39" - /** - * Wraps the text in the proper control characters for styled output in the rich console - */ - static String styledText(String plainText, Ansi.Color color, Ansi.Attribute... attributes) { - String styledString = CONTROL_SEQUENCE_START - if (color) { - styledString += color.fg() - } - if (attributes) { - attributes.each { attribute -> - if (styledString.length() > CONTROL_SEQUENCE_START.length()) { - styledString += CONTROL_SEQUENCE_SEPARATOR - } - styledString += attribute.value() - } - } - styledString += CONTROL_SEQUENCE_END + plainText + CONTROL_SEQUENCE_START - if (color) { - styledString += DEFAULT_TEXT - } - styledString += CONTROL_SEQUENCE_END - - return styledString - } - static String workInProgressLine(String plainText) { return boldOn() + plainText + reset() } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy =================================================================== diff -u -N -r0007210d7aae16974d69d402a2ee644d07fe92bd -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy (.../AbstractConsoleGroupedTaskFunctionalTest.groovy) (revision 0007210d7aae16974d69d402a2ee644d07fe92bd) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/console/AbstractConsoleGroupedTaskFunctionalTest.groovy (.../AbstractConsoleGroupedTaskFunctionalTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -38,35 +38,99 @@ } boolean errorsShouldAppearOnStdout() { - // If stderr is attached to the console or if we'll use the fallback console - return (consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached()) || usesFallbackConsole() + // If both stdout and stderr is attached to the console, they are merged together + return consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached() } - boolean usesFallbackConsole() { - return consoleAttachment == ConsoleAttachment.NOT_ATTACHED && (consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose) + boolean stdoutUsesStyledText() { + if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { + // Can currently write rich text to one stream at a time, and we prefer stderr when it is attached to the console and stdout is not + return false + } + return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stdoutAttached } + boolean stderrUsesStyledText() { + // Can currently write rich text to one stream at a time, and we prefer stdout when it is attached to the console + if (!consoleAttachment.stdoutAttached && consoleAttachment.stderrAttached) { + return consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose || consoleType == ConsoleOutput.Auto && consoleAttachment.stderrAttached + } + return false + } + abstract ConsoleOutput getConsoleType() - protected StyledOutput styled(String plainOutput, Ansi.Color color, Ansi.Attribute... attributes) { - return new StyledOutput(plainOutput, color, attributes) + protected StyledOutput styled(Ansi.Color color, Ansi.Attribute attribute) { + return new StyledOutput(null, color, attribute) } - public class StyledOutput { - private final String plainOutput - private final String styledOutput + protected StyledOutput styled(Ansi.Attribute attribute) { + return new StyledOutput(null, null, attribute) + } - StyledOutput(String plainOutput, Ansi.Color color, Ansi.Attribute... attributes) { - this.plainOutput = plainOutput - this.styledOutput = styledText(plainOutput, color, attributes) + class StyledOutput { + final String plainOutput + final String styledOutput + private final Ansi.Color color + private final Ansi.Attribute attribute + + private StyledOutput(StyledOutput previous, Ansi.Color color, Ansi.Attribute attribute) { + if (attribute != Ansi.Attribute.INTENSITY_BOLD && attribute != null) { + throw new UnsupportedOperationException() + } + this.color = color + this.attribute = attribute + def previousColor = null + def previousAttribute = null + def styled = "" + if (previous == null) { + this.plainOutput = "" + } else { + this.plainOutput = previous.plainOutput + previousColor = previous.color + previousAttribute = previous.attribute + styled = previous.styledOutput + } + if (attribute != null && previousAttribute == null) { + styled += "{bold-on}" + } + if (attribute == null && previousAttribute != null) { + styled += "{bold-off}" + } + if (color != null && color != previousColor) { + styled += "{foreground-color " + color.name().toLowerCase() + "}" + } + if (color == null && previousColor != null) { + styled += "{foreground-color default}" + } + this.styledOutput = styled } - public String getOutput() { - return consoleAttachment.stdoutAttached ? styledOutput : plainOutput + private StyledOutput(StyledOutput previous, String text) { + this.color = previous.color + this.attribute = previous.attribute + this.plainOutput = previous.plainOutput + text + this.styledOutput = previous.styledOutput + text } - public String getErrorOutput() { - return consoleAttachment.stderrAttached ? styledOutput : plainOutput + StyledOutput text(String text) { + return new StyledOutput(this, text) } + + StyledOutput styled(Ansi.Attribute attribute) { + return new StyledOutput(this, color, attribute) + } + + StyledOutput off() { + return new StyledOutput(this, null, null) + } + + String getOutput() { + return stdoutUsesStyledText() ? styledOutput : plainOutput + } + + String getErrorOutput() { + return stderrUsesStyledText() ? styledOutput : plainOutput + } } } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java =================================================================== diff -u -N -rb3f9768cce6dd5d3a6a91daeec23998130c43898 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java (.../AbstractGradleExecuter.java) (revision b3f9768cce6dd5d3a6a91daeec23998130c43898) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/AbstractGradleExecuter.java (.../AbstractGradleExecuter.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -76,7 +76,10 @@ import static org.gradle.api.internal.artifacts.BaseRepositoryFactory.PLUGIN_PORTAL_OVERRIDE_URL_PROPERTY; import static org.gradle.integtests.fixtures.RepoScriptBlockUtil.gradlePluginRepositoryMirrorUrl; -import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.*; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.DAEMON; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.FOREGROUND; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.NOT_DEFINED; +import static org.gradle.integtests.fixtures.executer.AbstractGradleExecuter.CliDaemonArgument.NO_DAEMON; import static org.gradle.integtests.fixtures.executer.OutputScrapingExecutionResult.STACK_TRACE_ELEMENT; import static org.gradle.internal.service.scopes.DefaultGradleUserHomeScopeServiceRegistry.REUSE_USER_HOME_SERVICES; import static org.gradle.util.CollectionUtils.collect; @@ -1403,7 +1406,7 @@ } private boolean errorsShouldAppearOnStdout() { - // If stderr is attached to the console or if we'll use the fallback console - return (consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached()) || (consoleAttachment == ConsoleAttachment.NOT_ATTACHED && (consoleType == ConsoleOutput.Rich || consoleType == ConsoleOutput.Verbose)); + // If stdout and stderr are attached to the console + return consoleAttachment.isStderrAttached() && consoleAttachment.isStdoutAttached(); } } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java =================================================================== diff -u -N -rf9b5e7f8a51be4fb585fa4ada0d83c6b7037583f -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java (.../ConsoleAttachment.java) (revision f9b5e7f8a51be4fb585fa4ada0d83c6b7037583f) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ConsoleAttachment.java (.../ConsoleAttachment.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -21,7 +21,6 @@ public enum ConsoleAttachment { NOT_ATTACHED("not attached to a console", null), ATTACHED("console attached to both stdout and stderr", TestConsoleMetadata.BOTH), - ATTACHED_NEITHER("console detected but not attached to either stdout or stderr", TestConsoleMetadata.NEITHER), ATTACHED_STDOUT_ONLY("console attached to stdout only", TestConsoleMetadata.STDOUT_ONLY), ATTACHED_STDERR_ONLY("console attached to stderr only", TestConsoleMetadata.STDERR_ONLY); Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java =================================================================== diff -u -N -rf58120e37e9de2821c7bc216c060a9dbe40fa962 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java (.../ErrorsOnStdoutScrapingExecutionResult.java) (revision f58120e37e9de2821c7bc216c060a9dbe40fa962) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ErrorsOnStdoutScrapingExecutionResult.java (.../ErrorsOnStdoutScrapingExecutionResult.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -60,18 +60,6 @@ } @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - delegate.assertRawOutputContains(expectedOutput); - return this; - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - delegate.assertRawOutputContains(expectedOutput); - return this; - } - - @Override public ExecutionResult assertOutputEquals(String expectedOutput, boolean ignoreExtraLines, boolean ignoreLineOrder) { delegate.assertOutputEquals(expectedOutput, ignoreExtraLines, ignoreLineOrder); return this; Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java =================================================================== diff -u -N -rf58120e37e9de2821c7bc216c060a9dbe40fa962 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java (.../ExecutionResult.java) (revision f58120e37e9de2821c7bc216c060a9dbe40fa962) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/ExecutionResult.java (.../ExecutionResult.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -62,13 +62,6 @@ ExecutionResult assertHasErrorOutput(String expectedOutput); /** - * Asserts that this result includes the given error log message in the raw output (including ANSI characters and build result message). - * - * @param expectedOutput The expected log message, with line endings normalized to a newline character. - */ - ExecutionResult assertHasRawErrorOutput(String expectedOutput); - - /** * Returns true when this result includes the given error log message. Does not consider any text in or following the build result message (use {@link #assertHasPostBuildOutput(String)} instead). * * @param expectedOutput The expected log message, with line endings normalized to a newline character. @@ -85,13 +78,6 @@ ExecutionResult assertOutputContains(String expectedOutput); /** - * Asserts that this result includes the given non-error log message (including ANSI characters and build result message). - * - * @param expectedOutput The expected log message, with line endings normalized to a newline character. - */ - ExecutionResult assertRawOutputContains(String expectedOutput); - - /** * Asserts that the given content includes the given log message. * * @param content The content to check Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java =================================================================== diff -u -N -r42508e2680b93241ded10a0864fd1615c961d397 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java (.../InProcessGradleExecuter.java) (revision 42508e2680b93241ded10a0864fd1615c961d397) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/InProcessGradleExecuter.java (.../InProcessGradleExecuter.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -557,18 +557,6 @@ return this; } - @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - outputResult.assertHasRawErrorOutput(expectedOutput); - return this; - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - outputResult.assertRawOutputContains(expectedOutput); - return this; - } - public String getError() { return outputResult.getError(); } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java =================================================================== diff -u -N -rc1ef580d94d1af17f159badc353544e17141a744 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java (.../LogContent.java) (revision c1ef580d94d1af17f159badc353544e17141a744) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/LogContent.java (.../LogContent.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableList; import net.rubygrapefruit.ansi.AnsiParser; import net.rubygrapefruit.ansi.console.AnsiConsole; +import net.rubygrapefruit.ansi.console.DiagnosticConsole; import net.rubygrapefruit.ansi.token.NewLine; import net.rubygrapefruit.ansi.token.Text; import org.gradle.api.Action; @@ -88,7 +89,7 @@ * Creates a new instance from a sequence of lines (without the line separators). */ public static LogContent of(List lines) { - return new LogContent(ImmutableList.copyOf(lines), false, false,null); + return new LogContent(ImmutableList.copyOf(lines), false, false, null); } public static LogContent empty() { @@ -202,23 +203,14 @@ } /** - * Returns a copy of this log content with ANSI control characters removed. + * Returns a copy of this log content with ANSI control characters interpreted to produce plain text. */ - public LogContent removeAnsiChars() { + public LogContent ansiCharsToPlainText() { if (definitelyNoAnsiChars) { return this; } try { - AnsiConsole console = new AnsiConsole(); - AnsiParser parser = new AnsiParser(); - Writer writer = new OutputStreamWriter(parser.newParser("utf-8", console)); - for (int i = 0; i < lines.size(); i++) { - if (i > 0) { - writer.write("\n"); - } - writer.write(lines.get(i)); - } - writer.flush(); + AnsiConsole console = interpretAnsiChars(); StringBuilder result = new StringBuilder(); console.contents(token -> { if (token instanceof Text) { @@ -233,6 +225,43 @@ } } + /** + * Returns a copy of this log content with ANSI control characters interpreted to produce plain text with text attributes included. + */ + public LogContent ansiCharsToColorText() { + if (definitelyNoAnsiChars) { + return this; + } + try { + AnsiConsole console = interpretAnsiChars(); + DiagnosticConsole diagnosticConsole = new DiagnosticConsole(); + for (int i = 0; i < console.getRows().size(); i++) { + AnsiConsole.Row row = console.getRows().get(i); + if (i > 0) { + diagnosticConsole.visit(NewLine.INSTANCE); + } + row.visit(diagnosticConsole); + } + return new LogContent(toLines(diagnosticConsole.toString()), definitelyNoDebugPrefix, true, rawContent); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private AnsiConsole interpretAnsiChars() throws IOException { + AnsiConsole console = new AnsiConsole(); + AnsiParser parser = new AnsiParser(); + Writer writer = new OutputStreamWriter(parser.newParser("utf-8", console)); + for (int i = 0; i < lines.size(); i++) { + if (i > 0) { + writer.write("\n"); + } + writer.write(lines.get(i)); + } + writer.flush(); + return console; + } + public static String stripJavaIllegalAccessWarnings(String result) { return JAVA_ILLEGAL_ACCESS_WARNING_PATTERN.matcher(result).replaceAll(""); } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java =================================================================== diff -u -N -rbc15470cc8d4bbeca877ec154b4f00e368a43d2f -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java (.../OutputScrapingExecutionFailure.java) (revision bc15470cc8d4bbeca877ec154b4f00e368a43d2f) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailure.java (.../OutputScrapingExecutionFailure.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -63,13 +63,13 @@ protected OutputScrapingExecutionFailure(String output, String error) { super(LogContent.of(output), LogContent.of(error)); - LogContent withoutDebug = LogContent.of(output).removeAnsiChars().removeDebugPrefix(); + LogContent withoutDebug = LogContent.of(output).ansiCharsToPlainText().removeDebugPrefix(); // Find failure section Pair match = withoutDebug.splitOnFirstMatchingLine(FAILURE_PATTERN); if (match == null) { // Not present in output, check error output. - match = LogContent.of(error).removeAnsiChars().removeDebugPrefix().splitOnFirstMatchingLine(FAILURE_PATTERN); + match = LogContent.of(error).ansiCharsToPlainText().removeDebugPrefix().splitOnFirstMatchingLine(FAILURE_PATTERN); if (match != null) { match = Pair.of(withoutDebug, match.getRight()); } else { Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java =================================================================== diff -u -N -rc1ef580d94d1af17f159badc353544e17141a744 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java (.../OutputScrapingExecutionResult.java) (revision c1ef580d94d1af17f159badc353544e17141a744) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionResult.java (.../OutputScrapingExecutionResult.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -83,7 +83,7 @@ this.error = error; // Split out up the output into main content and post build content - LogContent filteredOutput = this.output.removeAnsiChars().removeDebugPrefix(); + LogContent filteredOutput = this.output.ansiCharsToPlainText().removeDebugPrefix(); Pair match = filteredOutput.splitOnFirstMatchingLine(BUILD_RESULT_PATTERN); if (match == null) { this.mainContent = filteredOutput; @@ -92,7 +92,7 @@ this.mainContent = match.getLeft(); this.postBuild = match.getRight().drop(1); } - this.errorContent = error.removeAnsiChars(); + this.errorContent = error.ansiCharsToPlainText(); } public String getOutput() { @@ -193,16 +193,6 @@ return assertContentContains(errorContent.withNormalizedEol(), expectedOutput, "Error output"); } - @Override - public ExecutionResult assertHasRawErrorOutput(String expectedOutput) { - return assertContentContains(getError(), expectedOutput, "Error output"); - } - - @Override - public ExecutionResult assertRawOutputContains(String expectedOutput) { - return assertContentContains(getOutput(), expectedOutput, "Build output"); - } - public String getError() { return error.withNormalizedEol(); } Index: subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java =================================================================== diff -u -N -rc1ef580d94d1af17f159badc353544e17141a744 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java (.../GroupedOutputFixture.java) (revision c1ef580d94d1af17f159badc353544e17141a744) +++ subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixture.java (.../GroupedOutputFixture.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -79,7 +79,7 @@ tasks = new HashMap(); transformations = new HashMap(); - String strippedOutput = output.removeAnsiChars().withNormalizedEol(); + String strippedOutput = output.ansiCharsToPlainText().withNormalizedEol(); findOutputs(strippedOutput, TASK_OUTPUT_PATTERN, this::consumeTaskOutput); findOutputs(strippedOutput, TRANSFORMATION_OUTPUT_PATTERN, this::consumeTransformationOutput); Index: subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy =================================================================== diff -u -N -rbc15470cc8d4bbeca877ec154b4f00e368a43d2f -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy (.../OutputScrapingExecutionFailureTest.groovy) (revision bc15470cc8d4bbeca877ec154b4f00e368a43d2f) +++ subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/executer/OutputScrapingExecutionFailureTest.groovy (.../OutputScrapingExecutionFailureTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -356,6 +356,13 @@ failure.assertOutputContains("Some sort of output") failure.assertOutputContains "Some more output" + and: + !failure.mainContent.withNormalizedEol().contains("INITIALIZING") + !failure.mainContent.withNormalizedEol().contains("IDLE") + + and: + !failure.mainContent.withNormalizedEol().contains("DEBUG") + where: output << [rawOutput, debugOutput] } @@ -393,11 +400,11 @@ def static getRawOutput() { return """ -\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001BSome sort of output\u001B[0K -Some sort of FAILURE: without status bar or work in progress +\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> Evaluating settings\u001B[m\u001B[21D\u001B[1B\u001B[2ASome sort of output\u001B[0K +Some sort of FAILURE: without status bar or work in progress\u001B[0K Some more output -\u001B[2A\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B> IDLE\u001B[6D\u001B[1B\u001B[2AFAILURE: \u001B[39m\u001B[31mBuild failed with an exception. \u001B[39m\u001B[0K - +\u001B[1m<\u001B[0;32;1;0;39;1m-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B> IDLE\u001B[6D\u001B[1B\u001B[2AFAILURE: \u001B[39m\u001B[31mBuild failed with an exception. \u001B[39m\u001B[0K +\u001B[0K * Where: Build file 'build.gradle' line: 4 Index: subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy =================================================================== diff -u -N -r725332bb3e6a12008f8ba7f35a8f16dd36b3ef88 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy (.../GroupedOutputFixtureTest.groovy) (revision 725332bb3e6a12008f8ba7f35a8f16dd36b3ef88) +++ subprojects/internal-integ-testing/src/test/groovy/org/gradle/integtests/fixtures/logging/GroupedOutputFixtureTest.groovy (.../GroupedOutputFixtureTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -16,6 +16,7 @@ package org.gradle.integtests.fixtures.logging +import org.gradle.integtests.fixtures.executer.LogContent import spock.lang.Specification class GroupedOutputFixtureTest extends Specification { @@ -44,7 +45,7 @@ \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -56,21 +57,22 @@ def "parses incremental tasks"() { given: def consoleOutput = """ -\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[0K\u001B[35D\u001B[2B\u001B[1A\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [0s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[1A\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[0K +\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[0K\u001B[35D\u001B[2B\u001B[1A\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [0s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B\u001B[1A\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[0K \u001B[1m> Task :longRunningTask\u001B[m\u001B[0K First incremental output \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B\u001B[2ASecond incremental output\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[6D\u001B[1B\u001B[2A\u001B[0K +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B\u001B[2ASecond incremental output\u001B[0K \u001B[0K +\u001B[0K +\u001B[1A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :longRunningTask\u001B[m\u001B[18D\u001B[1B\u001B[2A\u001B[0K +\u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 9s 1 actionable task: 1 executed \u001B[2K """ when: - GroupedOutputFixture fixture = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture fixture = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: fixture.taskCount == 1 @@ -98,7 +100,7 @@ \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -134,7 +136,7 @@ """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'First line of text\n\n\n\nLast line of text' @@ -155,7 +157,7 @@ \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':1:log').output == "Output from 1" @@ -184,7 +186,7 @@ \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.taskCount == 3 @@ -208,7 +210,7 @@ 3 actionable tasks: 3 executed \u001B[2K """ - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) when: groupedOutput.task(':doesNotExist') @@ -233,45 +235,42 @@ \u001B[2K """ when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'Output from :log' } def "handles output interleaved with end-of-line erasing"() { given: - def consoleOutput = """\u001B[1A\u001B[1m> Connecting to Daemon\u001B[m\u001B[22D\u001B[1B -\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B -\u001B[1A\u001B[1m> root project > Compiling /home/tcagent2/agent/work/1c72cb73edd79150/subprojects/logging/build/tmp/test files/BasicGroupedTaskLoggingFunctionalSpec/long_running_task_o..._5s_delay/m5mh7/build.gradle into local compilation cache\u001B[m\u001B[228D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[35D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [5s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B + def consoleOutput = """\u001B[1A\u001B[1m> Connecting to Daemon\u001B[m\u001B[22D +\u001B[1A\u001B[90m> IDLE\u001B[39m\u001B[0K\u001B[6D +\u001B[1A\u001B[1m<-------------> 0% CONFIGURING [0s]\u001B[m\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D +\u001B[1A\u001B[1m> root project > Compiling /home/tcagent2/agent/work/1c72cb73edd79150/subprojects/logging/build/tmp/test files/BasicGroupedTaskLoggingFunctionalSpec/long_running_task_o..._5s_delay/m5mh7/build.gradle into local compilation cache\u001B[m\u001B[228D +\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[35D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [1s]\u001B[m\u001B[0K\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[0K\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [3s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [4s]\u001B[m\u001B[33D\u001B[1B \u001B[2A\u001B[1m> Task :log\u001B[m\u001B[0K Before\u001B[0K \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[2B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[2B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [6s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [7s]\u001B[m\u001B[33D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B \u001B[2AAfter\u001B[0K -\u001B[1B\u001B[0K -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D\u001B[1B +\u001B[0K +\u001B[0K +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [8s]\u001B[m\u001B[33D\u001B[1B\u001B[1m> :log\u001B[m\u001B[6D \u001B[2A\u001B[0K \u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 9s 1 actionable task: 1 executed \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':log').output == 'Before\nAfter' @@ -294,7 +293,7 @@ \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':buildSrc:helloWorld').output == 'Hello world' @@ -316,15 +315,13 @@ \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.strippedOutput == ''' > Task :buildSrc:helloWorld Hello world - - > Task :byeWorld Bye world @@ -336,29 +333,28 @@ def "strip output removes formatted work in-progress items"() { def consoleOutput = """ -\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D\u001B[1B -\u001B[1A> IDLE\u001B[0K\u001B[6D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[0K\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D\u001B[1B -\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[0K\u001B[33D\u001B[1B> IDLE\u001B[0K\u001B[6D\u001B[1B -\u001B[1A\u001B[1m> :run\u001B[m\u001B[6D\u001B[1B +\u001B[2A\u001B[1m<-------------> 0% INITIALIZING [0s]\u001B[m\u001B[36D\u001B[1B\u001B[1m> settings\u001B[m\u001B[10D +\u001B[1A> IDLE\u001B[0K\u001B[6D +\u001B[2A\u001B[1m<-------------> 0% CONFIGURING [1s]\u001B[m\u001B[0K\u001B[35D\u001B[1B\u001B[1m> root project\u001B[m\u001B[14D +\u001B[2A\u001B[1m<-------------> 0% EXECUTING [2s]\u001B[m\u001B[0K\u001B[33D\u001B[1B> IDLE\u001B[0K\u001B[6D +\u001B[1A\u001B[1m> :run\u001B[m\u001B[6D \u001B[2A\u001B[0K \u001B[1m> Task :run\u001B[m\u001B[0K Hello, World! \u001B[0K \u001B[0K -\u001B[2A\u001B[1m<=============> 100% EXECUTING [3s]\u001B[m\u001B[35D\u001B[1B> IDLE\u001B[6D\u001B[1B +\u001B[2A\u001B[1m<=============> 100% EXECUTING [3s]\u001B[m\u001B[35D\u001B[1B> IDLE\u001B[6D \u001B[2A\u001B[0K \u001B[0K \u001B[32;1mBUILD SUCCESSFUL\u001B[0;39m in 6s 1 actionable task: 1 executed \u001B[2K""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.strippedOutput == ''' - > Task :run Hello, World! @@ -377,7 +373,7 @@ > :otherBuild > :abc""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':helloWorld').output == 'Hello, World!' @@ -391,7 +387,7 @@ > :otherBuild > Doing some work""" when: - GroupedOutputFixture groupedOutput = new GroupedOutputFixture(consoleOutput) + GroupedOutputFixture groupedOutput = new GroupedOutputFixture(LogContent.of(consoleOutput)) then: groupedOutput.task(':helloWorld').output == 'Hello, World!' @@ -406,7 +402,7 @@ [3A [1m< [0;32;1;0;39;1m-------------> 0% CONFIGURING [5s] [m [35D [1B [1m> root project > Compiling C:\\tcagent1\\work\\4b92f910977a653d\\subprojects\\logging\\build\\tmp\\test files\\ConsoleBuildSrcFunctionalTest\\can_group_task_outp..._buildSrc\\j2q4s\\build.gradle into local compilation cache > Compiling build file 'C:\\tcagent1\\work\\4b92f910977a653d\\subprojects\\logging\\build\\tmp\\test files\\ConsoleBuildSrcFunctionalTest\\can_group_task_outp..._buildSrc\\j2q4s\\build.gradle' to cross build script cache [m [420D [2B """ when: - new GroupedOutputFixture(consoleOutput) + new GroupedOutputFixture(LogContent.of(consoleOutput)) then: noExceptionThrown() Index: subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt =================================================================== diff -u -N -ra22d178e6b377c53603a5990ec3abc8630285930 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt (.../PrecompiledScriptPluginAccessorsTest.kt) (revision a22d178e6b377c53603a5990ec3abc8630285930) +++ subprojects/kotlin-dsl-plugins/src/integTest/kotlin/org/gradle/kotlin/dsl/plugins/precompiled/PrecompiledScriptPluginAccessorsTest.kt (.../PrecompiledScriptPluginAccessorsTest.kt) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -373,8 +373,8 @@ withPrecompiledScriptApplying(pluginId, pluginJar) gradleExecuterFor(arrayOf("classes")).withStackTraceChecksDisabled().run().apply { - assertRawOutputContains("An exception occurred applying plugin request [id: '$pluginId']") - assertRawOutputContains("'InvalidPlugin' is neither a plugin or a rule source and cannot be applied.") + assertOutputContains("An exception occurred applying plugin request [id: '$pluginId']") + assertOutputContains("'InvalidPlugin' is neither a plugin or a rule source and cannot be applied.") } } Index: subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy =================================================================== diff -u -N -r66e42a9b8fd2c3d829ab4600f680f5dc3a5c7aaf -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy (.../AbstractConsoleBuildPhaseFunctionalTest.groovy) (revision 66e42a9b8fd2c3d829ab4600f680f5dc3a5c7aaf) +++ subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/AbstractConsoleBuildPhaseFunctionalTest.groovy (.../AbstractConsoleBuildPhaseFunctionalTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -129,7 +129,7 @@ gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -217,7 +217,7 @@ gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -312,7 +312,7 @@ gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll @@ -451,12 +451,13 @@ gradle.waitForFinish() where: - attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY] + attachment << [ConsoleAttachment.ATTACHED, ConsoleAttachment.ATTACHED_STDOUT_ONLY, ConsoleAttachment.NOT_ATTACHED] } @Unroll def "does not show progress bar when stdout is #attachment"() { when: + executer.withTestConsoleAttached(attachment) succeeds() then: @@ -465,7 +466,7 @@ result.assertNotOutput("EXECUTING") where: - attachment << [ConsoleAttachment.ATTACHED_STDERR_ONLY, ConsoleAttachment.NOT_ATTACHED] + attachment << [ConsoleAttachment.ATTACHED_STDERR_ONLY] } void assertHasBuildPhase(String message) { Index: subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy =================================================================== diff -u -N -rc1ef580d94d1af17f159badc353544e17141a744 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy (.../AbstractConsoleBuildResultFunctionalTest.groovy) (revision c1ef580d94d1af17f159badc353544e17141a744) +++ subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractConsoleBuildResultFunctionalTest.groovy (.../AbstractConsoleBuildResultFunctionalTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -25,8 +25,8 @@ abstract class AbstractConsoleBuildResultFunctionalTest extends AbstractConsoleGroupedTaskFunctionalTest { protected final String buildFailed = 'BUILD FAILED' protected final String buildSuccess = 'BUILD SUCCESSFUL' - protected final StyledOutput buildFailedStyled = styled(buildFailed, Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) - protected final StyledOutput buildSuccessStyled = styled(buildSuccess, Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD) + protected final StyledOutput buildFailedStyled = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text(buildFailed).off() + protected final StyledOutput buildSuccessStyled = styled(Ansi.Color.GREEN, Ansi.Attribute.INTENSITY_BOLD).text(buildSuccess).off() abstract String getFailureMessage() @@ -50,19 +50,19 @@ succeeds('all') then: - result.assertRawOutputContains(successMessage) - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* +BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 2 executed .*""" when: succeeds('all') then: - result.assertRawOutputContains(successMessage) - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(successMessage) + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).* +BUILD SUCCESSFUL in \\d+s 2 actionable tasks: 1 executed, 1 up-to-date .*""" } @@ -95,8 +95,9 @@ succeeds('success') then: - LogContent.of(result.output).removeAnsiChars().withNormalizedEol().matches """(?s).*build finished\\n* -BUILD SUCCESSFUL in \\d+s\\n* + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().matches """(?s).*build finished + +BUILD SUCCESSFUL in \\d+s 1 actionable task: 1 executed .*""" } @@ -123,9 +124,9 @@ // Check that the failure text appears either stdout or stderr def outputWithFailure = errorsShouldAppearOnStdout() ? failure.output : failure.error def outputWithoutFailure = errorsShouldAppearOnStdout() ? failure.error : failure.output - def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).removeAnsiChars().removeDebugPrefix().withNormalizedEol() + def outputWithFailureAndNoDebugging = LogContent.of(outputWithFailure).ansiCharsToColorText().removeDebugPrefix().withNormalizedEol() - outputWithFailure.contains("Build failed with an exception.") + outputWithFailureAndNoDebugging.contains("FAILURE: Build failed with an exception.") outputWithFailureAndNoDebugging.contains(""" * What went wrong: Execution failed for task ':broken'. @@ -134,8 +135,7 @@ !outputWithoutFailure.contains("Build failed with an exception.") !outputWithoutFailure.contains("* What went wrong:") - outputWithFailure.contains("BUILD FAILED") - failure.assertHasRawErrorOutput(failureMessage) + outputWithFailureAndNoDebugging.contains(failureMessage) where: level << [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE, LogLevel.WARN, LogLevel.QUIET] @@ -156,7 +156,7 @@ fails("broken") and: - result.assertRawOutputContains("1 actionable task: 1 executed") + LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol().contains("1 actionable task: 1 executed") where: level << [LogLevel.DEBUG, LogLevel.INFO, LogLevel.LIFECYCLE] Index: subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy =================================================================== diff -u -N -rdeb222a7d71d67b885d07f180fa4ebcd4f2cf532 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy (.../AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy) (revision deb222a7d71d67b885d07f180fa4ebcd4f2cf532) +++ subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy (.../AbstractGroupedProjectConfigureLoggingFunctionalTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -47,7 +47,7 @@ run() then: - def normalizedOutput = LogContent.of(result.output).removeAnsiChars().withNormalizedEol() + def normalizedOutput = LogContent.of(result.output).ansiCharsToPlainText().withNormalizedEol() normalizedOutput.contains(""" > Configure project : root project Index: subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy =================================================================== diff -u -N -r686d8a472bb3774fd9789455357f067a723da92e -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy (.../RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy) (revision 686d8a472bb3774fd9789455357f067a723da92e) +++ subprojects/logging/src/integTest/groovy/org/gradle/internal/logging/console/taskgrouping/rich/RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy (.../RichConsoleBasicGroupedTaskLoggingFunctionalTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -19,16 +19,17 @@ import org.fusesource.jansi.Ansi import org.gradle.api.logging.configuration.ConsoleOutput import org.gradle.integtests.fixtures.console.AbstractConsoleGroupedTaskFunctionalTest.StyledOutput +import org.gradle.integtests.fixtures.executer.LogContent import org.gradle.internal.logging.console.taskgrouping.AbstractBasicGroupedTaskLoggingFunctionalTest import spock.lang.Issue @SuppressWarnings("IntegrationTestFixtures") class RichConsoleBasicGroupedTaskLoggingFunctionalTest extends AbstractBasicGroupedTaskLoggingFunctionalTest { ConsoleOutput consoleType = ConsoleOutput.Rich - private final StyledOutput failingTask = styled("> Task :failing", Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) - private final StyledOutput succeedingTask = styled("> Task :succeeding", null, Ansi.Attribute.INTENSITY_BOLD) - private final StyledOutput configuringProject = styled("> Configure project :", Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD) + private final StyledOutput failingTask = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text("> Task :failing").styled(null).text(" FAILED").off() + private final StyledOutput succeedingTask = styled(Ansi.Attribute.INTENSITY_BOLD).text("> Task :succeeding").off() + private final StyledOutput configuringProject = styled(Ansi.Color.RED, Ansi.Attribute.INTENSITY_BOLD).text("> Configure project :").off() @Issue("gradle/gradle#2038") def "tasks with no actions are not displayed"() { @@ -56,7 +57,7 @@ then: result.groupedOutput.task(':failing').output == 'hello' - result.assertRawOutputContains(failingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) } def "group header is printed red if task failed and there is no output"() { @@ -71,7 +72,7 @@ fails('failing') then: - result.assertRawOutputContains(failingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(failingTask.output) } def "group header is printed white if task succeeds"() { @@ -86,7 +87,7 @@ succeeds('succeeding') then: - result.assertRawOutputContains(succeedingTask.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(succeedingTask.output) } def "configure project group header is printed red if configuration fails with additional failures"() { @@ -104,7 +105,7 @@ fails('failing') then: - result.assertRawOutputContains(configuringProject.output) + LogContent.of(result.output).ansiCharsToColorText().withNormalizedEol().contains(configuringProject.output) } def "tasks that complete without output do not break up other task output"() { Index: subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java =================================================================== diff -u -N -ra7be515ea1b7013b7b25125370f875cf1c17eb6f -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java (.../ConsoleConfigureAction.java) (revision a7be515ea1b7013b7b25125370f875cf1c17eb6f) +++ subprojects/logging/src/main/java/org/gradle/internal/logging/sink/ConsoleConfigureAction.java (.../ConsoleConfigureAction.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -25,78 +25,65 @@ import org.gradle.internal.nativeintegration.console.TestConsoleMetadata; import org.gradle.internal.nativeintegration.services.NativeServices; -import javax.annotation.Nullable; import java.io.OutputStream; import java.io.OutputStreamWriter; public class ConsoleConfigureAction { public static void execute(OutputEventRenderer renderer, ConsoleOutput consoleOutput) { + execute(renderer, consoleOutput, getConsoleMetaData(), renderer.getOriginalStdOut(), renderer.getOriginalStdErr()); + } + + public static void execute(OutputEventRenderer renderer, ConsoleOutput consoleOutput, ConsoleMetaData consoleMetadata, OutputStream stdout, OutputStream stderr) { if (consoleOutput == ConsoleOutput.Auto) { - configureAutoConsole(renderer); + configureAutoConsole(renderer, consoleMetadata, stdout, stderr); } else if (consoleOutput == ConsoleOutput.Rich) { - configureRichConsole(renderer, false); + configureRichConsole(renderer, consoleMetadata, stdout, stderr, false); } else if (consoleOutput == ConsoleOutput.Verbose) { - configureRichConsole(renderer, true); + configureRichConsole(renderer, consoleMetadata, stdout, stderr, true); } else if (consoleOutput == ConsoleOutput.Plain) { - configurePlainConsole(renderer); + configurePlainConsole(renderer, consoleMetadata, stdout, stderr); } } - private static void configureRichConsole(OutputEventRenderer renderer, boolean verbose) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - configureRichConsole(renderer, consoleMetaData, shouldForce(consoleMetaData), verbose); - } - - private static boolean shouldForce(ConsoleMetaData consoleMetaData) { - return consoleMetaData == null || consoleMetaData instanceof TestConsoleMetadata; - } - - private static void configureAutoConsole(OutputEventRenderer renderer) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - if (consoleMetaData != null) { - configureRichConsole(renderer, consoleMetaData, false, false); - } else { - configurePlainConsole(renderer, null); - } - } - - private static void configurePlainConsole(OutputEventRenderer renderer) { - ConsoleMetaData consoleMetaData = getConsoleMetaData(); - configurePlainConsole(renderer, consoleMetaData); - } - - @Nullable private static ConsoleMetaData getConsoleMetaData() { String testConsole = System.getProperty(TestConsoleMetadata.TEST_CONSOLE_PROPERTY); if (testConsole != null) { return TestConsoleMetadata.valueOf(testConsole); } ConsoleDetector consoleDetector = NativeServices.getInstance().get(ConsoleDetector.class); - return consoleDetector.getConsole(); + ConsoleMetaData metaData = consoleDetector.getConsole(); + if (metaData != null) { + return metaData; + } + return FallbackConsoleMetaData.NOT_ATTACHED; } - private static void configurePlainConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData) { + private static void configureAutoConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { + if (consoleMetaData.isStdOut() || consoleMetaData.isStdErr()) { + configureRichConsole(renderer, consoleMetaData, stdout, stderr, false); + } else { + configurePlainConsole(renderer, consoleMetaData, stdout, stderr); + } + } + + private static void configurePlainConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr) { // Redirect stderr to stdout if a console is attached to both stdout and stderr - renderer.addPlainConsole(consoleMetaData != null && consoleMetaData.isStdOut() && consoleMetaData.isStdErr()); + // This avoids interleaving problems when stdout and stderr end up at the same location + renderer.addPlainConsole(stdout, stderr, consoleMetaData != null && consoleMetaData.isStdOut() && consoleMetaData.isStdErr()); } - private static void configureRichConsole(OutputEventRenderer renderer, @Nullable ConsoleMetaData consoleMetaData, boolean force, boolean verbose) { - if (consoleMetaData == null) { - consoleMetaData = FallbackConsoleMetaData.ATTACHED; - } - if (consoleMetaData.isStdOut()) { - OutputStream originalStdOut = renderer.getOriginalStdOut(); - OutputStreamWriter outStr = new OutputStreamWriter(force ? originalStdOut : AnsiConsoleUtil.wrapOutputStream(originalStdOut)); - Console console = new AnsiConsole(outStr, outStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, verbose); - } else if (consoleMetaData.isStdErr()) { - // Only stderr is connected to a terminal - OutputStream originalStdErr = renderer.getOriginalStdErr(); - OutputStreamWriter errStr = new OutputStreamWriter(force ? originalStdErr : AnsiConsoleUtil.wrapOutputStream(originalStdErr)); + private static void configureRichConsole(OutputEventRenderer renderer, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { + boolean force = !consoleMetaData.isWrapStreams(); + if (consoleMetaData.isStdErr() && !consoleMetaData.isStdOut()) { + // Only stderr is connected to a console. Currently we can write rich text to one stream only, so prefer stderr in this case + OutputStreamWriter errStr = new OutputStreamWriter(force ? stderr : AnsiConsoleUtil.wrapOutputStream(stderr)); Console console = new AnsiConsole(errStr, errStr, renderer.getColourMap(), consoleMetaData, force); - renderer.addRichConsole(console, consoleMetaData, verbose); + renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); } else { - renderer.addRichConsole(null, consoleMetaData, verbose); + // Prefer stdout when is connected to a console or neither stream connected to a console + OutputStreamWriter outStr = new OutputStreamWriter(force ? stdout : AnsiConsoleUtil.wrapOutputStream(stdout)); + Console console = new AnsiConsole(outStr, outStr, renderer.getColourMap(), consoleMetaData, force); + renderer.addRichConsole(console, consoleMetaData, stdout, stderr, verbose); } } } Index: subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java =================================================================== diff -u -N -ra7be515ea1b7013b7b25125370f875cf1c17eb6f -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java (.../OutputEventRenderer.java) (revision a7be515ea1b7013b7b25125370f875cf1c17eb6f) +++ subprojects/logging/src/main/java/org/gradle/internal/logging/sink/OutputEventRenderer.java (.../OutputEventRenderer.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -23,7 +23,6 @@ import org.gradle.internal.Factory; import org.gradle.internal.event.ListenerBroadcast; import org.gradle.internal.logging.config.LoggingRouter; -import org.gradle.internal.logging.console.AnsiConsole; import org.gradle.internal.logging.console.BuildLogLevelFilterRenderer; import org.gradle.internal.logging.console.BuildStatusRenderer; import org.gradle.internal.logging.console.ColorMap; @@ -55,7 +54,6 @@ import javax.annotation.Nullable; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.util.concurrent.atomic.AtomicReference; /** @@ -159,25 +157,9 @@ public void attachConsole(OutputStream outputStream, OutputStream errorStream, ConsoleOutput consoleOutput, @Nullable ConsoleMetaData consoleMetadata) { synchronized (lock) { if (consoleMetadata == null) { - consoleMetadata = consoleOutput == ConsoleOutput.Plain ? FallbackConsoleMetaData.NOT_ATTACHED : FallbackConsoleMetaData.ATTACHED; + consoleMetadata = FallbackConsoleMetaData.NOT_ATTACHED; } - StandardOutputListener outputListener = new StreamBackedStandardOutputListener(outputStream); - StandardOutputListener errorListener = new StreamBackedStandardOutputListener(errorStream); - if (consoleOutput == ConsoleOutput.Plain) { - addPlainConsole(outputListener, errorListener, consoleMetadata.isStdOut() && consoleMetadata.isStdErr()); - } else { - Console console; - if (consoleMetadata.isStdOut()) { - OutputStreamWriter writer = new OutputStreamWriter(outputStream); - console = new AnsiConsole(writer, writer, getColourMap(), consoleMetadata, true); - } else if (consoleMetadata.isStdErr()) { - OutputStreamWriter writer = new OutputStreamWriter(errorStream); - console = new AnsiConsole(writer, writer, getColourMap(), consoleMetadata, true); - } else { - console = null; - } - addRichConsole(console, outputListener, errorListener, consoleMetadata, consoleOutput == ConsoleOutput.Verbose); - } + ConsoleConfigureAction.execute(this, consoleOutput, consoleMetadata, outputStream, errorStream); } } @@ -248,31 +230,24 @@ } } - public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData) { - return addRichConsole(console, consoleMetaData, false); - } - - public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData, boolean verbose) { - return addRichConsole(console, new StreamBackedStandardOutputListener((Appendable) originalStdOut), new StreamBackedStandardOutputListener((Appendable) originalStdErr), consoleMetaData, verbose); - } - - private OutputEventRenderer addRichConsole(Console console, StandardOutputListener outputListener, StandardOutputListener errorListener, ConsoleMetaData consoleMetaData, boolean verbose) { + public OutputEventRenderer addRichConsole(Console console, ConsoleMetaData consoleMetaData, OutputStream stdout, OutputStream stderr, boolean verbose) { OutputEventListener consoleChain; boolean stdoutAttachedToConsole = consoleMetaData.isStdOut(); boolean stderrAttachedToConsole = consoleMetaData.isStdErr(); + StandardOutputListener outputListener = new StreamBackedStandardOutputListener(stdout); + StandardOutputListener errorListener = new StreamBackedStandardOutputListener(stderr); if (stdoutAttachedToConsole && stderrAttachedToConsole) { OutputEventListener consoleListener = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); - } else if (stdoutAttachedToConsole) { - OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); - OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, new StyledTextOutputBackedRenderer(console.getBuildOutputArea()), false); - consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); } else if (stderrAttachedToConsole) { OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(outputListener)); OutputEventListener stderrChain = new FlushConsoleListener(console, new StyledTextOutputBackedRenderer(console.getBuildOutputArea())); consoleChain = getPlainConsoleChain(stdoutChain, stderrChain, false, verbose); } else { - consoleChain = getPlainConsoleChain(outputListener, errorListener, false, verbose); + OutputEventListener stdoutChain = new StyledTextOutputBackedRenderer(console.getBuildOutputArea()); + OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); + OutputEventListener consoleListener = new ErrorOutputDispatchingListener(stderrChain, stdoutChain, false); + consoleChain = getRichConsoleChain(console, consoleMetaData, verbose, consoleListener); } return addConsoleChain(consoleChain); @@ -295,14 +270,10 @@ ); } - public OutputEventRenderer addPlainConsole(boolean redirectStderr) { - return addPlainConsole(new StreamBackedStandardOutputListener((Appendable) originalStdOut), new StreamBackedStandardOutputListener((Appendable) originalStdErr), redirectStderr); + public OutputEventRenderer addPlainConsole(OutputStream stdout, OutputStream stderr, boolean redirectStderr) { + return addConsoleChain(getPlainConsoleChain(new StreamBackedStandardOutputListener(stdout), new StreamBackedStandardOutputListener(stderr), redirectStderr, true)); } - private OutputEventRenderer addPlainConsole(StandardOutputListener outputListener, StandardOutputListener errorListener, boolean redirectStderr) { - return addConsoleChain(getPlainConsoleChain(outputListener, errorListener, redirectStderr, true)); - } - private OutputEventListener getPlainConsoleChain(StandardOutputListener outputListener, StandardOutputListener errorListener, boolean redirectStderr, boolean verbose) { final OutputEventListener stdoutChain = new UserInputStandardOutputRenderer(new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(outputListener))); final OutputEventListener stderrChain = new StyledTextOutputBackedRenderer(new StreamingStyledTextOutput(errorListener)); Index: subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy =================================================================== diff -u -N -r410a52b5b4cf97750f0e1b8fee12f8b63f5665d1 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy (.../OutputEventRendererTest.groovy) (revision 410a52b5b4cf97750f0e1b8fee12f8b63f5665d1) +++ subprojects/logging/src/test/groovy/org/gradle/internal/logging/sink/OutputEventRendererTest.groovy (.../OutputEventRendererTest.groovy) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -288,7 +288,7 @@ def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -306,7 +306,7 @@ metaData.stdOut >> true metaData.stdErr >> false renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start(description: 'description', buildOperationStart: true, id: 1L, buildOperationId: 1L, buildOperationCategory: BuildOperationCategory.TASK)) @@ -324,7 +324,7 @@ metaData.stdOut >> false metaData.stdErr >> true renderer.attachSystemOutAndErr() - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(start('description')) @@ -342,7 +342,7 @@ def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) when: renderer.onOutput(event(tenAm, 'info', LogLevel.INFO)) @@ -359,7 +359,7 @@ def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -376,7 +376,7 @@ def snapshot = renderer.snapshot() metaData.stdOut >> true metaData.stdErr >> false - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush @@ -393,7 +393,7 @@ def snapshot = renderer.snapshot() metaData.stdOut >> false metaData.stdErr >> true - renderer.addRichConsole(console, metaData) + renderer.addRichConsole(console, metaData, outputs.stdOutPrintStream, outputs.stdErrPrintStream, false) renderer.onOutput(event('info', LogLevel.INFO)) renderer.onOutput(event('error', LogLevel.ERROR)) renderer.restore(snapshot) // close console to flush Index: subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java =================================================================== diff -u -N -r34c3667350566dc89fcdd01dd1005194b34a2cb1 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java (.../ConsoleMetaData.java) (revision 34c3667350566dc89fcdd01dd1005194b34a2cb1) +++ subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/ConsoleMetaData.java (.../ConsoleMetaData.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -40,4 +40,6 @@ * @return The height of the console (rows). If no information is available return 0. */ int getRows(); + + boolean isWrapStreams(); } Index: subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java =================================================================== diff -u -N -r410a52b5b4cf97750f0e1b8fee12f8b63f5665d1 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java (.../FallbackConsoleMetaData.java) (revision 410a52b5b4cf97750f0e1b8fee12f8b63f5665d1) +++ subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/FallbackConsoleMetaData.java (.../FallbackConsoleMetaData.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -45,4 +45,9 @@ public int getRows() { return 0; } + + @Override + public boolean isWrapStreams() { + return attached; + } } Index: subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java =================================================================== diff -u -N -r6111ed8ea6b7a99db2331733452f473019aa150e -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java (.../NativePlatformConsoleMetaData.java) (revision 6111ed8ea6b7a99db2331733452f473019aa150e) +++ subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/NativePlatformConsoleMetaData.java (.../NativePlatformConsoleMetaData.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -48,4 +48,9 @@ public int getRows() { return terminal.getTerminalSize().getRows(); } + + @Override + public boolean isWrapStreams() { + return true; + } } Index: subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java =================================================================== diff -u -N -r4ad97147c65bfe014ab43adc0fab377300b5b890 -r6059db136a3c6c23a6544778ba29cfaa79c149d5 --- subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java (.../TestConsoleMetadata.java) (revision 4ad97147c65bfe014ab43adc0fab377300b5b890) +++ subprojects/native/src/main/java/org/gradle/internal/nativeintegration/console/TestConsoleMetadata.java (.../TestConsoleMetadata.java) (revision 6059db136a3c6c23a6544778ba29cfaa79c149d5) @@ -18,7 +18,6 @@ public enum TestConsoleMetadata implements ConsoleMetaData { BOTH(true, true), - NEITHER(false, false), STDOUT_ONLY(true, false), STDERR_ONLY(false, true); @@ -52,6 +51,11 @@ return 40; } + @Override + public boolean isWrapStreams() { + return false; + } + public String getCommandLineArgument() { return "-D" + TEST_CONSOLE_PROPERTY + "=" + name(); }