80 lines
3.3 KiB
Java
80 lines
3.3 KiB
Java
package io.gitlab.jfronny.woodpecker.include;
|
|
|
|
import com.amihaiemil.eoyaml.*;
|
|
import io.gitlab.jfronny.commons.HttpUtils;
|
|
import io.gitlab.jfronny.woodpecker.include.model.Pipeline;
|
|
import io.gitlab.jfronny.woodpecker.include.util.FilteringYamlMapping;
|
|
|
|
import java.io.*;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Paths;
|
|
import java.util.*;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.Consumer;
|
|
|
|
final class PipelineUnpacker implements BiConsumer<Pipeline, Consumer<Pipeline>> {
|
|
private final AtomicBoolean changed;
|
|
private final Set<String> included = new HashSet<>();
|
|
|
|
public PipelineUnpacker(AtomicBoolean changed) {
|
|
this.changed = changed;
|
|
}
|
|
|
|
@Override
|
|
public void accept(Pipeline pipeline, Consumer<Pipeline> pipelineConsumer) {
|
|
try {
|
|
processPipeline(pipeline, pipelineConsumer);
|
|
} catch (URISyntaxException e) {
|
|
throw new UncheckedIOException(new IOException("Could not find URL", e));
|
|
} catch (IOException e) {
|
|
throw new UncheckedIOException(e);
|
|
}
|
|
}
|
|
|
|
private void processPipeline(Pipeline pipeline, Consumer<Pipeline> pipelineConsumer) throws URISyntaxException, IOException {
|
|
YamlNode include = pipeline.data.value("include");
|
|
if (include == null) {
|
|
// Has no includes
|
|
pipelineConsumer.accept(pipeline);
|
|
return;
|
|
}
|
|
changed.set(true);
|
|
// Send included
|
|
//TODO switch back to switch pattern matching once that is available
|
|
if (include instanceof Scalar str) download(str.value(), null, pipelineConsumer);
|
|
else if (include instanceof YamlMapping map) {
|
|
for (YamlNode key : map.keys()) {
|
|
download(map.string(key), key.asScalar().value(), pipelineConsumer);
|
|
}
|
|
} else if (include instanceof YamlSequence seq) {
|
|
for (YamlNode node : seq) {
|
|
download(node.asScalar().value(), null, pipelineConsumer);
|
|
}
|
|
} else throw new IllegalStateException("Unexpected value: " + include);
|
|
if (pipeline.data.keys().size() > 1) {
|
|
// More than just includes: generate override without include node
|
|
Pipeline filtered = new Pipeline();
|
|
filtered.name = pipeline.name;
|
|
pipeline.data = new FilteringYamlMapping(pipeline.data, s -> !s.asScalar().value().equals("include"));
|
|
pipelineConsumer.accept(filtered);
|
|
}
|
|
}
|
|
|
|
private void download(String url, String fileName, Consumer<Pipeline> pipelineConsumer) throws URISyntaxException, IOException {
|
|
if (included.contains(url)) return;
|
|
included.add(url);
|
|
URI uri = new URI(url.replace(" ", "%20"));
|
|
if (!"http".equalsIgnoreCase(uri.getScheme()) && !"https".equalsIgnoreCase(uri.getScheme())) {
|
|
throw new URISyntaxException(url, "Could not find scheme");
|
|
}
|
|
try (InputStream is = HttpUtils.get(url).sendInputStream()) {
|
|
Pipeline pipeline = new Pipeline();
|
|
pipeline.name = fileName != null ? fileName : Paths.get(new URI(url.replace(" ", "%20")).getPath()).getFileName().toString();
|
|
pipeline.data = Yaml.createYamlInput(is).readYamlMapping();
|
|
processPipeline(pipeline, pipelineConsumer);
|
|
}
|
|
}
|
|
}
|