blog-software-java/src/main/java/eu/m724/blog/Main.java

184 lines
6.7 KiB
Java
Raw Normal View History

2025-01-07 11:41:30 +01:00
package eu.m724.blog;
2025-01-10 18:50:12 +01:00
import eu.m724.blog.data.Feed;
2025-01-08 18:40:11 +01:00
import eu.m724.blog.data.Post;
import eu.m724.blog.data.Site;
2025-01-18 21:22:42 +01:00
import org.apache.commons.cli.*;
2025-01-08 18:40:11 +01:00
import org.apache.commons.io.file.PathUtils;
2025-01-07 11:41:30 +01:00
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.RepositoryBuilder;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
2025-01-08 18:40:11 +01:00
import java.nio.file.Files;
import java.nio.file.Path;
2025-01-09 16:15:55 +01:00
import java.util.ArrayList;
import java.util.Comparator;
2025-01-08 18:40:11 +01:00
import java.util.stream.Collectors;
2025-01-07 11:41:30 +01:00
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("Hello world!");
2025-01-18 21:22:42 +01:00
var options = new Options()
2025-01-19 10:15:42 +01:00
.addOption("h", "help", false, "Show help")
2025-01-18 21:36:25 +01:00
.addOption("f", "force", false, "Overwrite current build")
2025-01-18 21:22:42 +01:00
.addOption("t", "template-dir", true, "Template directory. Default: working directory/template")
.addOption("o", "output-dir", true, "Output directory. Default: working directory/generated_out")
2025-01-20 17:34:01 +01:00
.addOption("s", "server", false, "Run webserver. Default: no")
.addOption("no-browser", false, "Do NOT open browser on server start")
2025-01-20 17:34:01 +01:00
.addOption("d", "draft", false, "Render drafts. Default: only with server");
2025-01-18 21:22:42 +01:00
CommandLine commandLine;
2025-01-20 17:34:01 +01:00
String wdStr;
2025-01-18 21:22:42 +01:00
try {
commandLine = new DefaultParser().parse(options, args);
2025-01-20 17:34:01 +01:00
2025-01-19 10:15:42 +01:00
if (commandLine.hasOption("help"))
throw new ParseException("Showing help");
2025-01-20 17:34:01 +01:00
if (commandLine.getArgs().length == 0)
throw new ParseException("Missing required argument: WORKDIR");
wdStr = commandLine.getArgs()[0];
2025-01-18 21:22:42 +01:00
} catch (ParseException e) {
System.out.println(e.getMessage());
2025-01-20 17:34:01 +01:00
new HelpFormatter().printHelp("blog-software-java [OPTION]... [WORKDIR]", options);
2025-01-18 21:22:42 +01:00
System.exit(1);
return;
}
2025-01-10 18:50:12 +01:00
2025-01-07 11:41:30 +01:00
2025-01-20 17:34:01 +01:00
var workingDirectory = Path.of(wdStr);
2025-01-18 21:22:42 +01:00
var templateDirectory = Path.of(commandLine.getOptionValue("output-dir", workingDirectory.resolve("template").toString()));
var outputDirectory = Path.of(commandLine.getOptionValue("output-dir", workingDirectory.resolve("generated_out").toString()));
var force = commandLine.hasOption("force");
var server = commandLine.hasOption("server");
var openBrowser = !commandLine.hasOption("no-browser");
var renderDrafts = commandLine.hasOption("draft") || server;
2025-01-10 18:50:12 +01:00
2025-01-07 11:41:30 +01:00
//
2025-01-18 21:22:42 +01:00
var start = System.nanoTime();
2025-01-07 11:41:30 +01:00
var repository = new RepositoryBuilder()
2025-01-10 14:43:24 +01:00
.setGitDir(workingDirectory.resolve(".git").toFile())
2025-01-07 11:41:30 +01:00
.build();
var git = new Git(repository);
//
2025-01-08 18:40:11 +01:00
if (outputDirectory.toFile().exists()) {
2025-01-07 11:41:30 +01:00
if (force) {
2025-01-08 18:40:11 +01:00
PathUtils.deleteDirectory(outputDirectory);
2025-01-07 11:41:30 +01:00
} else {
2025-01-20 17:34:01 +01:00
throw new FileAlreadyExistsException(outputDirectory.toString(), null, "Output directory already exists. --force?");
2025-01-07 11:41:30 +01:00
}
}
2025-01-08 18:40:11 +01:00
var site = Site.fromConfig(git);
2025-01-18 21:36:25 +01:00
var template = new TemplateRenderer(templateDirectory);
2025-01-07 11:41:30 +01:00
2025-01-08 18:40:11 +01:00
Files.createDirectory(outputDirectory);
2025-01-07 11:41:30 +01:00
2025-01-08 18:40:11 +01:00
copyIfExists(workingDirectory.resolve("assets"), outputDirectory.resolve("assets"));
copyIfExists(templateDirectory.resolve("static"), outputDirectory.resolve("static"));
2025-01-07 11:41:30 +01:00
2025-01-08 18:40:11 +01:00
Files.createDirectory(outputDirectory.resolve("post"));
var postDirectory = workingDirectory.resolve("posts");
2025-01-09 16:15:55 +01:00
var posts = new ArrayList<Post>();
2025-01-08 18:40:11 +01:00
try (var stream = Files.walk(postDirectory)) {
for (var path : stream.collect(Collectors.toSet())) {
2025-01-18 21:36:25 +01:00
if (!Files.isRegularFile(path))
continue; // directory is created below
2025-01-07 11:41:30 +01:00
2025-01-08 18:40:11 +01:00
if (!path.toString().endsWith(".html")) {
System.out.println("Post " + path.getFileName() + ": unsupported file type");
continue;
}
path = postDirectory.relativize(path);
var post = Post.fromFile(git, path);
2025-01-20 17:34:01 +01:00
if (post.draft() && !renderDrafts) {
System.out.println("Post " + path.getFileName() + ": draft, ignoring");
continue;
}
2025-01-08 18:40:11 +01:00
var render = template.renderPost(site, post);
var outFile = outputDirectory.resolve("post").resolve(path);
try {
Files.createDirectory(outFile.getParent());
2025-01-09 16:15:55 +01:00
} catch (FileAlreadyExistsException ignored) { }
2025-01-08 18:40:11 +01:00
Files.writeString(outFile, render);
2025-01-09 16:15:55 +01:00
posts.add(post);
2025-01-08 18:40:11 +01:00
}
}
2025-01-09 16:15:55 +01:00
posts.sort(Comparator.comparing(Post::createdAt).reversed());
Files.writeString(outputDirectory.resolve("index.html"), template.renderIndex(site, posts));
2025-01-10 18:50:12 +01:00
Files.writeString(outputDirectory.resolve("posts.rss"), Feed.generateRss(site, posts));
var end = System.nanoTime();
System.out.printf("Exported to %s (%.2f ms)\n", outputDirectory, (end - start) / 1000000.0);
if (server) {
var listenAddress = new Server(outputDirectory).start();
if (openBrowser) {
try {
var process = Runtime.getRuntime().exec(new String[] { "xdg-open", "http://" + listenAddress.getHostString() + ":" + listenAddress.getPort() });
var code = process.waitFor();
if (code != 0) {
throw new Exception("Exit code " + code);
}
System.out.println("Opened browser");
} catch (Exception e) {
System.out.println("Failed to open browser: " + e);
}
}
}
2025-01-08 18:40:11 +01:00
}
2025-01-10 14:43:24 +01:00
private static boolean copyTree(Path srcDir, Path destDir) throws IOException {
if (!Files.isDirectory(srcDir)) {
return false;
}
try (var walk = Files.walk(srcDir)) {
for (var src : walk.collect(Collectors.toSet())) {
var rel = srcDir.relativize(src);
var dest = destDir.resolve(rel);
if (Files.isRegularFile(src)) {
var parent = dest.getParent();
if (!Files.isDirectory(parent)) {
Files.createDirectories(parent);
}
2025-01-18 21:36:25 +01:00
Files.copy(src, dest);
2025-01-10 14:43:24 +01:00
}
}
}
return true;
}
2025-01-08 18:40:11 +01:00
2025-01-10 14:43:24 +01:00
private static void copyIfExists(Path srcDir, Path destDir) throws IOException {
System.out.print(srcDir);
2025-01-08 18:40:11 +01:00
2025-01-10 14:43:24 +01:00
if (copyTree(srcDir, destDir)) {
2025-01-08 18:40:11 +01:00
System.out.println(" copied");
} else {
System.out.println(" doesn't exist, not copying");
}
2025-01-07 11:41:30 +01:00
}
}