Convert logging related gradle classes to java (#44771)
This commit converts the logging related classes (only used for vagrant) to java from groovy. relates #34459
This commit is contained in:
parent
8bac13d5b2
commit
b3d8b39f29
|
@ -1,64 +0,0 @@
|
||||||
package org.elasticsearch.gradle
|
|
||||||
|
|
||||||
import org.gradle.api.logging.LogLevel
|
|
||||||
import org.gradle.api.logging.Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes data passed to this stream as log messages.
|
|
||||||
*
|
|
||||||
* The stream will be flushed whenever a newline is detected.
|
|
||||||
* Allows setting an optional prefix before each line of output.
|
|
||||||
*/
|
|
||||||
public class LoggingOutputStream extends OutputStream {
|
|
||||||
|
|
||||||
/** The starting length of the buffer */
|
|
||||||
static final int DEFAULT_BUFFER_LENGTH = 4096
|
|
||||||
|
|
||||||
/** The buffer of bytes sent to the stream */
|
|
||||||
byte[] buffer = new byte[DEFAULT_BUFFER_LENGTH]
|
|
||||||
|
|
||||||
/** Offset of the start of unwritten data in the buffer */
|
|
||||||
int start = 0
|
|
||||||
|
|
||||||
/** Offset of the end (semi-open) of unwritten data in the buffer */
|
|
||||||
int end = 0
|
|
||||||
|
|
||||||
/** Logger to write stream data to */
|
|
||||||
Logger logger
|
|
||||||
|
|
||||||
/** Prefix to add before each line of output */
|
|
||||||
String prefix = ""
|
|
||||||
|
|
||||||
/** Log level to write log messages to */
|
|
||||||
LogLevel level
|
|
||||||
|
|
||||||
void write(final int b) throws IOException {
|
|
||||||
if (b == 0) return;
|
|
||||||
if (b == (int)'\n' as char) {
|
|
||||||
// always flush with newlines instead of adding to the buffer
|
|
||||||
flush()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end == buffer.length) {
|
|
||||||
if (start != 0) {
|
|
||||||
// first try shifting the used buffer back to the beginning to make space
|
|
||||||
System.arraycopy(buffer, start, buffer, 0, end - start)
|
|
||||||
} else {
|
|
||||||
// need more space, extend the buffer
|
|
||||||
}
|
|
||||||
final int newBufferLength = buffer.length + DEFAULT_BUFFER_LENGTH;
|
|
||||||
final byte[] newBuffer = new byte[newBufferLength];
|
|
||||||
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
|
|
||||||
buffer = newBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[end++] = (byte) b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush() {
|
|
||||||
if (end == start) return
|
|
||||||
logger.log(level, prefix + new String(buffer, start, end - start));
|
|
||||||
start = end
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -40,9 +40,6 @@ public class BatsOverVagrantTask extends VagrantCommandTask {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected OutputStream createLoggerOutputStream() {
|
protected OutputStream createLoggerOutputStream() {
|
||||||
return new TapLoggerOutputStream(
|
return new TapLoggerOutputStream(logger, getProgressLoggerFactory().newOperation(boxName).setDescription(boxName));
|
||||||
command: commandLine.join(' '),
|
|
||||||
factory: getProgressLoggerFactory(),
|
|
||||||
logger: logger)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to Elasticsearch under one or more contributor
|
|
||||||
* license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright
|
|
||||||
* ownership. Elasticsearch licenses this file to you under
|
|
||||||
* the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
* not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.gradle.vagrant
|
|
||||||
|
|
||||||
import org.elasticsearch.gradle.LoggingOutputStream
|
|
||||||
import org.gradle.api.GradleScriptException
|
|
||||||
import org.gradle.api.logging.Logger
|
|
||||||
import org.gradle.internal.logging.progress.ProgressLogger
|
|
||||||
|
|
||||||
import java.util.regex.Matcher
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapts an OutputStream containing output from bats into a ProgressLogger
|
|
||||||
* and a Logger. Every test output goes to the ProgressLogger and all failures
|
|
||||||
* and non-test output goes to the Logger. That means you can always glance
|
|
||||||
* at the result of the last test and the cumulative pass/fail/skip stats and
|
|
||||||
* the failures are all logged.
|
|
||||||
*
|
|
||||||
* There is a Tap4j project but we can't use it because it wants to parse the
|
|
||||||
* entire TAP stream at once and won't parse it stream-wise.
|
|
||||||
*/
|
|
||||||
public class TapLoggerOutputStream extends LoggingOutputStream {
|
|
||||||
private final ProgressLogger progressLogger
|
|
||||||
private boolean isStarted = false
|
|
||||||
private final Logger logger
|
|
||||||
private int testsCompleted = 0
|
|
||||||
private int testsFailed = 0
|
|
||||||
private int testsSkipped = 0
|
|
||||||
private Integer testCount
|
|
||||||
private String countsFormat
|
|
||||||
|
|
||||||
TapLoggerOutputStream(Map args) {
|
|
||||||
logger = args.logger
|
|
||||||
progressLogger = args.factory.newOperation(VagrantLoggerOutputStream)
|
|
||||||
progressLogger.setDescription("TAP output for `${args.command}`")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() {
|
|
||||||
if (isStarted == false) {
|
|
||||||
progressLogger.started()
|
|
||||||
isStarted = true
|
|
||||||
}
|
|
||||||
if (end == start) return
|
|
||||||
line(new String(buffer, start, end - start))
|
|
||||||
start = end
|
|
||||||
}
|
|
||||||
|
|
||||||
void line(String line) {
|
|
||||||
// System.out.print "===> $line\n"
|
|
||||||
if (testCount == null) {
|
|
||||||
try {
|
|
||||||
testCount = line.split('\\.').last().toInteger()
|
|
||||||
def length = (testCount as String).length()
|
|
||||||
countsFormat = "%0${length}d"
|
|
||||||
countsFormat = "[$countsFormat|$countsFormat|$countsFormat/$countsFormat]"
|
|
||||||
return
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new GradleScriptException(
|
|
||||||
'Error parsing first line of TAP stream!!', e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Matcher m = line =~ /(?<status>ok|not ok) \d+(?<skip> # skip (?<skipReason>\(.+\))?)? \[(?<suite>.+)\] (?<test>.+)/
|
|
||||||
if (!m.matches()) {
|
|
||||||
/* These might be failure report lines or comments or whatever. Its hard
|
|
||||||
to tell and it doesn't matter. */
|
|
||||||
logger.warn(line)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
boolean skipped = m.group('skip') != null
|
|
||||||
boolean success = !skipped && m.group('status') == 'ok'
|
|
||||||
String skipReason = m.group('skipReason')
|
|
||||||
String suiteName = m.group('suite')
|
|
||||||
String testName = m.group('test')
|
|
||||||
|
|
||||||
String status
|
|
||||||
if (skipped) {
|
|
||||||
status = "SKIPPED"
|
|
||||||
testsSkipped++
|
|
||||||
} else if (success) {
|
|
||||||
status = " OK"
|
|
||||||
testsCompleted++
|
|
||||||
} else {
|
|
||||||
status = " FAILED"
|
|
||||||
testsFailed++
|
|
||||||
}
|
|
||||||
|
|
||||||
String counts = sprintf(countsFormat,
|
|
||||||
[testsCompleted, testsFailed, testsSkipped, testCount])
|
|
||||||
progressLogger.progress("Tests $counts, $status [$suiteName] $testName")
|
|
||||||
if (!success) {
|
|
||||||
logger.warn(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -78,11 +78,9 @@ public class VagrantCommandTask extends LoggedExec {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OutputStream createLoggerOutputStream() {
|
protected OutputStream createLoggerOutputStream() {
|
||||||
return new VagrantLoggerOutputStream(
|
return new VagrantLoggerOutputStream(getProgressLoggerFactory().newOperation(boxName + " " + command).setDescription(boxName),
|
||||||
command: commandLine.join(' '),
|
|
||||||
factory: getProgressLoggerFactory(),
|
|
||||||
/* Vagrant tends to output a lot of stuff, but most of the important
|
/* Vagrant tends to output a lot of stuff, but most of the important
|
||||||
stuff starts with ==> $box */
|
stuff starts with ==> $box */
|
||||||
squashedPrefix: "==> $boxName: ")
|
"==> $boxName: ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to Elasticsearch under one or more contributor
|
|
||||||
* license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright
|
|
||||||
* ownership. Elasticsearch licenses this file to you under
|
|
||||||
* the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
* not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.gradle.vagrant
|
|
||||||
|
|
||||||
import org.elasticsearch.gradle.LoggingOutputStream
|
|
||||||
import org.gradle.internal.logging.progress.ProgressLogger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapts an OutputStream being written to by vagrant into a ProcessLogger. It
|
|
||||||
* has three hacks to make the output nice:
|
|
||||||
*
|
|
||||||
* 1. Attempt to filter out the "unimportant" output from vagrant. Usually
|
|
||||||
* vagrant prefixes its more important output with "==> $boxname: ". The stuff
|
|
||||||
* that isn't prefixed that way can just be thrown out.
|
|
||||||
*
|
|
||||||
* 2. It also attempts to detect when vagrant does tricks assuming its writing
|
|
||||||
* to a terminal emulator and renders the output more like gradle users expect.
|
|
||||||
* This means that progress indicators for things like box downloading work and
|
|
||||||
* box importing look pretty good.
|
|
||||||
*
|
|
||||||
* 3. It catches lines that look like "==> $boxName ==> Heading text" and stores
|
|
||||||
* the text after the second arrow as a "heading" for use in annotating
|
|
||||||
* provisioning. It does this because provisioning can spit out _lots_ of text
|
|
||||||
* and its very easy to lose context when there isn't a scrollback. So we've
|
|
||||||
* sprinkled `echo "==> Heading text"` into the provisioning scripts for this
|
|
||||||
* to catch so it can render the output like
|
|
||||||
* "Heading text > stdout from the provisioner".
|
|
||||||
*/
|
|
||||||
public class VagrantLoggerOutputStream extends LoggingOutputStream {
|
|
||||||
private static final String HEADING_PREFIX = '==> '
|
|
||||||
|
|
||||||
private final ProgressLogger progressLogger
|
|
||||||
private boolean isStarted = false
|
|
||||||
private String squashedPrefix
|
|
||||||
private String lastLine = ''
|
|
||||||
private boolean inProgressReport = false
|
|
||||||
private String heading = ''
|
|
||||||
|
|
||||||
VagrantLoggerOutputStream(Map args) {
|
|
||||||
progressLogger = args.factory.newOperation(VagrantLoggerOutputStream)
|
|
||||||
progressLogger.setDescription("Vagrant output for `$args.command`")
|
|
||||||
squashedPrefix = args.squashedPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() {
|
|
||||||
if (isStarted == false) {
|
|
||||||
progressLogger.started()
|
|
||||||
isStarted = true
|
|
||||||
}
|
|
||||||
if (end == start) return
|
|
||||||
line(new String(buffer, start, end - start))
|
|
||||||
start = end
|
|
||||||
}
|
|
||||||
|
|
||||||
void line(String line) {
|
|
||||||
if (line.startsWith('\r\u001b')) {
|
|
||||||
/* We don't want to try to be a full terminal emulator but we want to
|
|
||||||
keep the escape sequences from leaking and catch _some_ of the
|
|
||||||
meaning. */
|
|
||||||
line = line.substring(2)
|
|
||||||
if ('[K' == line) {
|
|
||||||
inProgressReport = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (line.startsWith(squashedPrefix)) {
|
|
||||||
line = line.substring(squashedPrefix.length())
|
|
||||||
inProgressReport = false
|
|
||||||
lastLine = line
|
|
||||||
if (line.startsWith(HEADING_PREFIX)) {
|
|
||||||
line = line.substring(HEADING_PREFIX.length())
|
|
||||||
heading = line + ' > '
|
|
||||||
} else {
|
|
||||||
line = heading + line
|
|
||||||
}
|
|
||||||
} else if (inProgressReport) {
|
|
||||||
inProgressReport = false
|
|
||||||
line = lastLine + line
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
progressLogger.progress(line)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.gradle;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes data passed to this stream as log messages.
|
||||||
|
*
|
||||||
|
* The stream will be flushed whenever a newline is detected.
|
||||||
|
* Allows setting an optional prefix before each line of output.
|
||||||
|
*/
|
||||||
|
public abstract class LoggingOutputStream extends OutputStream {
|
||||||
|
/** The starting length of the buffer */
|
||||||
|
private static final int DEFAULT_BUFFER_LENGTH = 4096;
|
||||||
|
|
||||||
|
/** The buffer of bytes sent to the stream */
|
||||||
|
private byte[] buffer = new byte[DEFAULT_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
/** Offset of the start of unwritten data in the buffer */
|
||||||
|
private int start = 0;
|
||||||
|
|
||||||
|
/** Offset of the end (semi-open) of unwritten data in the buffer */
|
||||||
|
private int end = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(final int b) throws IOException {
|
||||||
|
if (b == 0) return;
|
||||||
|
if (b == '\n') {
|
||||||
|
// always flush with newlines instead of adding to the buffer
|
||||||
|
flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end == buffer.length) {
|
||||||
|
if (start != 0) {
|
||||||
|
// first try shifting the used buffer back to the beginning to make space
|
||||||
|
int len = end - start;
|
||||||
|
System.arraycopy(buffer, start, buffer, 0, len);
|
||||||
|
start = 0;
|
||||||
|
end = len;
|
||||||
|
} else {
|
||||||
|
// otherwise extend the buffer
|
||||||
|
buffer = Arrays.copyOf(buffer, buffer.length + DEFAULT_BUFFER_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[end++] = (byte) b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
if (end == start) return;
|
||||||
|
logLine(new String(buffer, start, end - start));
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void logLine(String line);
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.gradle.vagrant;
|
||||||
|
|
||||||
|
import org.elasticsearch.gradle.LoggingOutputStream;
|
||||||
|
import org.gradle.api.GradleScriptException;
|
||||||
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.gradle.internal.logging.progress.ProgressLogger;
|
||||||
|
|
||||||
|
import java.util.Formatter;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts an OutputStream containing TAP output from bats into a ProgressLogger and a Logger.
|
||||||
|
*
|
||||||
|
* TAP (Test Anything Protocol, https://testanything.org) is used by BATS for its output format.
|
||||||
|
*
|
||||||
|
* Every test output goes to the ProgressLogger and all failures
|
||||||
|
* and non-test output goes to the Logger. That means you can always glance
|
||||||
|
* at the result of the last test and the cumulative pass/fail/skip stats and
|
||||||
|
* the failures are all logged.
|
||||||
|
*
|
||||||
|
* There is a Tap4j project but we can't use it because it wants to parse the
|
||||||
|
* entire TAP stream at once and won't parse it stream-wise.
|
||||||
|
*/
|
||||||
|
public class TapLoggerOutputStream extends LoggingOutputStream {
|
||||||
|
|
||||||
|
private static final Pattern lineRegex =
|
||||||
|
Pattern.compile("(?<status>ok|not ok) \\d+(?<skip> # skip (?<skipReason>\\(.+\\))?)? \\[(?<suite>.+)\\] (?<test>.+)");
|
||||||
|
|
||||||
|
private final Logger logger;
|
||||||
|
private final ProgressLogger progressLogger;
|
||||||
|
private boolean isStarted = false;
|
||||||
|
private int testsCompleted = 0;
|
||||||
|
private int testsFailed = 0;
|
||||||
|
private int testsSkipped = 0;
|
||||||
|
private Integer testCount;
|
||||||
|
private String countsFormat;
|
||||||
|
|
||||||
|
TapLoggerOutputStream(Logger logger, ProgressLogger progressLogger) {
|
||||||
|
this.logger = logger;
|
||||||
|
this.progressLogger = progressLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logLine(String line) {
|
||||||
|
if (isStarted == false) {
|
||||||
|
progressLogger.started("started");
|
||||||
|
isStarted = true;
|
||||||
|
}
|
||||||
|
if (testCount == null) {
|
||||||
|
try {
|
||||||
|
int lastDot = line.lastIndexOf('.');
|
||||||
|
testCount = Integer.parseInt(line.substring(lastDot + 1));
|
||||||
|
int length = String.valueOf(testCount).length();
|
||||||
|
String count = "%0" + length + "d";
|
||||||
|
countsFormat = "[" + count +"|" + count + "|" + count + "/" + count + "]";
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new GradleScriptException("Error parsing first line of TAP stream!!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Matcher m = lineRegex.matcher(line);
|
||||||
|
if (m.matches() == false) {
|
||||||
|
/* These might be failure report lines or comments or whatever. Its hard
|
||||||
|
to tell and it doesn't matter. */
|
||||||
|
logger.warn(line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean skipped = m.group("skip") != null;
|
||||||
|
boolean success = skipped == false && m.group("status").equals("ok");
|
||||||
|
String skipReason = m.group("skipReason");
|
||||||
|
String suiteName = m.group("suite");
|
||||||
|
String testName = m.group("test");
|
||||||
|
|
||||||
|
final String status;
|
||||||
|
if (skipped) {
|
||||||
|
status = "SKIPPED";
|
||||||
|
testsSkipped++;
|
||||||
|
} else if (success) {
|
||||||
|
status = " OK";
|
||||||
|
testsCompleted++;
|
||||||
|
} else {
|
||||||
|
status = " FAILED";
|
||||||
|
testsFailed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
String counts = new Formatter().format(countsFormat, testsCompleted, testsFailed, testsSkipped, testCount).out().toString();
|
||||||
|
progressLogger.progress("BATS " + counts + ", " + status + " [" + suiteName + "] " + testName);
|
||||||
|
if (success == false) {
|
||||||
|
logger.warn(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
flush();
|
||||||
|
progressLogger.completed();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.gradle.vagrant;
|
||||||
|
|
||||||
|
import org.elasticsearch.gradle.LoggingOutputStream;
|
||||||
|
import org.gradle.internal.logging.progress.ProgressLogger;
|
||||||
|
|
||||||
|
public class VagrantLoggerOutputStream extends LoggingOutputStream {
|
||||||
|
private static final String HEADING_PREFIX = "==> ";
|
||||||
|
|
||||||
|
private final ProgressLogger progressLogger;
|
||||||
|
private final String squashedPrefix;
|
||||||
|
private boolean isStarted = false;
|
||||||
|
private String lastLine = "";
|
||||||
|
private boolean inProgressReport = false;
|
||||||
|
private String heading = "";
|
||||||
|
|
||||||
|
VagrantLoggerOutputStream(ProgressLogger progressLogger, String squashedPrefix) {
|
||||||
|
this.progressLogger = progressLogger;
|
||||||
|
this.squashedPrefix = squashedPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void logLine(String line) {
|
||||||
|
if (isStarted == false) {
|
||||||
|
progressLogger.started("started");
|
||||||
|
isStarted = true;
|
||||||
|
}
|
||||||
|
if (line.startsWith("\r\u001b")) {
|
||||||
|
/* We don't want to try to be a full terminal emulator but we want to
|
||||||
|
keep the escape sequences from leaking and catch _some_ of the
|
||||||
|
meaning. */
|
||||||
|
line = line.substring(2);
|
||||||
|
if ("[K".equals(line)) {
|
||||||
|
inProgressReport = true;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (line.startsWith(squashedPrefix)) {
|
||||||
|
line = line.substring(squashedPrefix.length());
|
||||||
|
inProgressReport = false;
|
||||||
|
lastLine = line;
|
||||||
|
if (line.startsWith(HEADING_PREFIX)) {
|
||||||
|
line = line.substring(HEADING_PREFIX.length());
|
||||||
|
heading = line + " > ";
|
||||||
|
} else {
|
||||||
|
line = heading + line;
|
||||||
|
}
|
||||||
|
} else if (inProgressReport) {
|
||||||
|
inProgressReport = false;
|
||||||
|
line = lastLine + line;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
progressLogger.progress(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
flush();
|
||||||
|
progressLogger.completed();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue