001package com.github.sormuras.bach; 002 003import com.github.sormuras.bach.internal.VersionSupport; 004import java.io.PrintWriter; 005import java.io.Writer; 006import java.lang.module.ModuleDescriptor.Version; 007import java.nio.file.Path; 008import java.util.Locale; 009import java.util.Optional; 010 011/** Global settings with nested topic-specific configurations. */ 012public record Configuration( 013 boolean verbose, 014 boolean lenient, 015 int timeout, 016 Pathing pathing, 017 Printing printing, 018 Tooling tooling, 019 Options.ProjectOptions projectOptions) { 020 021 public static final String // 022 EXTERNAL_MODULES_DIRECTORY = ".bach/external-modules", 023 EXTERNAL_TOOL_LAYERS_DIRECTORY = ".bach/external-tool-layers", 024 EXTERNAL_TOOL_PROGRAMS_DIRECTORY = ".bach/external-tool-programs", 025 EXTERNAL_TOOL_PROGRAM_ARGSFILE = "java.args", 026 LOGBOOK_ARCHIVE_FILE = "logbooks/logbook-{TIMESTAMP}.md", 027 LOGBOOK_MARKDOWN_FILE = "logbook.md", 028 TIMESTAMP_PATTERN = "yyyyMMdd-HHmmss", 029 WORKSPACE_DIRECTORY = ".bach/workspace"; 030 031 public static Path computeJavaExecutablePath(String name) { 032 var windows = System.getProperty("os.name").toLowerCase(Locale.ROOT).startsWith("win"); 033 return Path.of(System.getProperty("java.home"), "bin", name + (windows ? ".exe" : "")); 034 } 035 036 public static String computeJarFileName(String module, Version version) { 037 return module + "@" + VersionSupport.toNumberAndPreRelease(version) + ".jar"; 038 } 039 040 public static Configuration of() { 041 var pathing = Pathing.ofCurrentWorkingDirectory(); 042 var printing = 043 new Printing(new PrintWriter(System.out, true), new PrintWriter(System.err, true)); 044 return Configuration.of(pathing, printing); 045 } 046 047 public static Configuration of(Pathing pathing, Printing printing) { 048 var tooling = 049 new Tooling( 050 ToolFinder.compose( 051 ToolFinder.ofSystem(), 052 ToolFinder.ofBach(), 053 ToolFinder.ofLayers(pathing.externalToolLayers()), 054 ToolFinder.ofPrograms( 055 pathing.externalToolPrograms(), 056 pathing.javaExecutable(), 057 EXTERNAL_TOOL_PROGRAM_ARGSFILE))); 058 return new Configuration( 059 false, 060 false, 061 9, 062 pathing, 063 printing, 064 tooling, 065 new Options.ProjectOptions(Optional.empty(), Optional.empty())); 066 } 067 068 /** {@link Path}-related settings. */ 069 public record Pathing( 070 Path root, 071 Path externalModules, 072 Path externalToolLayers, 073 Path externalToolPrograms, 074 Path workspace, 075 Path javaExecutable) { 076 077 public static Pathing of(Path root) { 078 return new Pathing( 079 root, 080 root.resolve(EXTERNAL_MODULES_DIRECTORY), 081 root.resolve(EXTERNAL_TOOL_LAYERS_DIRECTORY), 082 root.resolve(EXTERNAL_TOOL_PROGRAMS_DIRECTORY), 083 root.resolve(WORKSPACE_DIRECTORY), 084 computeJavaExecutablePath("java")); 085 } 086 087 public static Pathing ofCurrentWorkingDirectory() { 088 return Pathing.of(Path.of("")); 089 } 090 091 public Path root(String first, String... more) { 092 return root.resolve(Path.of(first, more)); 093 } 094 095 public Path workspace(String first, String... more) { 096 return workspace.resolve(Path.of(first, more)); 097 } 098 } 099 100 /** Print-related settings and common {@link PrintWriter} objects. */ 101 public record Printing(PrintWriter out, PrintWriter err) { 102 public static Printing ofErrorsOnly() { 103 return new Printing(new PrintWriter(Writer.nullWriter()), new PrintWriter(System.err, true)); 104 } 105 } 106 107 /** {@link ToolFinder}-related and {@link java.util.spi.ToolProvider}-related settings. */ 108 public record Tooling(ToolFinder finder) {} 109 110 public Configuration with(Options options) { 111 return new Configuration( 112 options.forConfiguration().verbose().orElse(verbose), 113 options.forConfiguration().lenient().orElse(lenient), 114 options.forConfiguration().timeout().orElse(timeout), 115 pathing, 116 printing, 117 tooling, 118 options.forProject()); 119 } 120}