From af53ed7f186983a408ec241dbd8ad0c2d3f97879 Mon Sep 17 00:00:00 2001 From: Eyre_S Date: Fri, 25 Nov 2022 20:43:46 +0800 Subject: [PATCH] add config command with create/list/show with --user/--sys, add global param --debug/--verbose - set default _debug output to false - add global param --debug/--verbose to enable _debug output - changed user config store path - on windows, it will be "~/AppData/Roaming" - on linux, it still is "~/.config" - added supported to system global config - which means "C:/ProgramData" on Windows and "/etc" on linux - the system global config can be override by user config - add config command - with param --user/--sys, which can control config command do on which config field. the default is user. - with subcommand create, it can create sekai-scores config dir and config file. it follows config field. - with subcommand list/show, it can show the config loaded. it shows all of the config will be load. so, it do not follow config field setting. - without subcommand, it will output the config file path. --- .../java/cc/sukazyo/sekai_cli/ClientMain.java | 30 ++++- .../java/cc/sukazyo/sekai_cli/Config.java | 105 +++++++++++++++--- .../main/java/cc/sukazyo/sekai_cli/Log.java | 27 ++++- .../cc/sukazyo/sekai_cli/client/AddScore.java | 7 +- .../cc/sukazyo/sekai_cli/client/Configs.java | 89 +++++++++++++++ .../test/java/cc/sukazyo/sekai_cli/CLI.java | 16 +++ 6 files changed, 245 insertions(+), 29 deletions(-) create mode 100644 sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/Configs.java create mode 100644 sekai-cli/src/test/java/cc/sukazyo/sekai_cli/CLI.java diff --git a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java index 5252715..2ced1ab 100644 --- a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java +++ b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/ClientMain.java @@ -1,18 +1,38 @@ package cc.sukazyo.sekai_cli; import cc.sukazyo.sekai_cli.client.AddScore; +import cc.sukazyo.sekai_cli.client.Configs; -import java.util.Arrays; +import java.util.List; + +import static cc.sukazyo.sekai_cli.Log._user; public class ClientMain { - public static final Config config = Config.loadUserConfig(); + private static Config config = null; + + public static Config config() { + if (config == null) config = Config.load(); + if (config == null) { + _user("read config failed."); + System.exit(1); + } + return config; + } public static void main (String[] args) { - if (args.length > 0) { - if (args[0].equals("add")) { - AddScore.main(Arrays.copyOfRange(args, 1, args.length)); + final List $args = new java.util.ArrayList<>(List.of(args)); + if ($args.remove("--debug")) Log.enableDebugging(); + if ($args.remove("--verbose")) Log.enableDebugging(); + + if ($args.size() > 0) { + final String i0 = $args.remove(0); + if (i0.equals("add")) { + AddScore.main($args.toArray(String[]::new)); + $done(); + } else if (i0.equals("config")) { + Configs.main($args.toArray(String[]::new)); $done(); } } diff --git a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java index 6baea15..df1205e 100644 --- a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java +++ b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Config.java @@ -4,12 +4,14 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; import static cc.sukazyo.sekai_cli.Log._debug; +import static cc.sukazyo.sekai_cli.Log._user; public class Config { @@ -46,29 +48,98 @@ public class Config { return v; } - static Config loadUserConfig() { - try { - - final Properties props = new Properties(); - final File propFile = Paths.get(getAppConfigPath(getSysUserConfigRoot()).toString(), CONFIG_FILE).toFile(); - props.load(new FileInputStream(propFile)); - _debug("loaded config file: " + propFile.getAbsolutePath()); - - return new Config(props); - - } catch (IOException e) { - throw new RuntimeException("error while load user config", e); - } + public void echo() { + echo("user.sekai-id", String.valueOf(sekai_id)); + echo("db.server", db_host); + echo("db.database", db_name); + echo("db.auth.user", db_auth_user); + echo("db.auth.password", db_auth_pwd); + echo("db.table-prefix", db_prefix); } - private static Path getAppConfigPath(Path configRoot) { + private void echo (String k, String v) { + if (v == null) System.out.println(k + " [unset]"); + System.out.println(k + " = " + v); + } + + static Config load() { + + final Properties props = new Properties(); + final File propFileSys = getAppConfigFile(getAppConfigPath(getSysGlobalConfigRoot())); + final File propFileUser = getAppConfigFile(getAppConfigPath(getSysUserConfigRoot())); + + final boolean propSysLoaded = load(props, propFileSys); + final boolean propUserLoaded = load(props, propFileUser); + if (!propUserLoaded && !propSysLoaded) { + _user("no config available.\n use `$ sekai-cli config create | edit` to create a config file and edit it."); + return null; + } + + return new Config(props); + + } + + private static boolean load (Properties target, File file) { + try { + target.load(new FileInputStream(file)); + } catch (FileNotFoundException e) { + _debug("config not created yet: " + file.getAbsolutePath()); + _debug(e); + return false; + } catch (SecurityException e) { + _debug("reading config: " + file.getAbsolutePath() + ": permission denied"); + _debug(e); + return false; + } catch (IOException e) { + _debug("failed read config: " + file.getAbsolutePath()); + _debug(e); + return false; + } + _debug("loaded config file: " + file.getAbsolutePath()); + return true; + } + + public static File getAppConfigFile (Path appConfigPath) { + return Paths.get(appConfigPath.toString(), CONFIG_FILE).toFile(); + } + + public static Path getAppConfigPath(Path configRoot) { return Paths.get(configRoot.toString(), CONFIG_ROOT_NAME); } - private static Path getSysUserConfigRoot () { - final Path userhome = Paths.get(System.getProperty("user.home"), ".config"); - _debug("read config from user home : " + userhome.toAbsolutePath()); + public static Path getSysUserConfigRoot () { + final Path userhome = Paths.get(System.getProperty("user.home"), SysType.get().userConfigPath); + _debug("read config from user home config : " + userhome.toAbsolutePath()); return userhome; } + public static Path getSysGlobalConfigRoot () { + final Path syshome = Paths.get(File.listRoots()[0].getPath(), SysType.get().sysConfigPath); + _debug("read config from system global config : " + syshome.toAbsolutePath()); + return syshome; + } + + public enum SysType { + + WINDOWS(new String[]{"AppData", "Roaming"}, new String[]{"ProgramData"}), +// LINUX(userConfigPath, sysConfigPath), +// MACOS(userConfigPath, sysConfigPath), + UNKNOWN(new String[]{".config"}, new String[]{"etc"}); + + public final String[] userConfigPath; + public final String[] sysConfigPath; + + SysType (String[] userConfigPath, String[] sysConfigPath) { + this.userConfigPath = userConfigPath; + this.sysConfigPath = sysConfigPath; + } + + public static SysType get () { + final String sysName = System.getProperty("os.name"); + if (sysName.contains("Windows")) return SysType.WINDOWS; + return UNKNOWN; + } + + } + } diff --git a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java index 89b7da5..14f788a 100644 --- a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java +++ b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/Log.java @@ -1,13 +1,36 @@ package cc.sukazyo.sekai_cli; +import java.io.PrintWriter; +import java.io.StringWriter; + public class Log { - private static final boolean IS_DEBUG = true; + private static boolean IS_DEBUG = false; + + public static void enableDebugging () { + if (IS_DEBUG) _debug("trying to enable debug: already in debug mode."); + else { + IS_DEBUG = true; + _debug("enabled debug\n cli will output the debug log now."); + } + } public static void _debug (String m) { if (!isDebug()) return; m = "[DEBUG]" + m; - m = m.replaceAll("\\n", "'''''''"); + m = m.replaceAll("\\n", "\n'''''''"); + System.out.println(m); + } + + public static void _debug (Exception e) { + final StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + _debug(sw.toString()); + } + + public static void _user (String m) { + m = "sekai-cli: " + m; + m = m.replaceAll("\\n", "\nsekai-cli: "); System.out.println(m); } diff --git a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/AddScore.java b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/AddScore.java index f9d91df..10ca384 100644 --- a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/AddScore.java +++ b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/AddScore.java @@ -2,8 +2,6 @@ package cc.sukazyo.sekai_cli.client; import cc.sukazyo.sekai_scores.ScoreBase; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.InputMismatchException; import java.util.Scanner; @@ -44,11 +42,10 @@ public class AddScore { } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { System.out.println("unsupported yet."); - final StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - _debug(sw.toString()); + _debug(e); } catch (InputMismatchException e) { System.out.println("unavailable input: " + e.getMessage()); + _debug(e); } } diff --git a/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/Configs.java b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/Configs.java new file mode 100644 index 0000000..d41fc49 --- /dev/null +++ b/sekai-cli/src/main/java/cc/sukazyo/sekai_cli/client/Configs.java @@ -0,0 +1,89 @@ +package cc.sukazyo.sekai_cli.client; + +import cc.sukazyo.sekai_cli.ClientMain; +import cc.sukazyo.sekai_cli.Config; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +import static cc.sukazyo.sekai_cli.Log._debug; +import static cc.sukazyo.sekai_cli.Log._user; + +public class Configs { + + public static void main (String[] args) { + + final List $args = new java.util.ArrayList<>(List.of(args)); + Path configRoot = Config.getSysUserConfigRoot(); + if ($args.remove("--user")) + configRoot = Config.getSysUserConfigRoot(); + if ($args.remove("--sys")) + configRoot = Config.getSysGlobalConfigRoot(); + + if ($args.isEmpty()) { + showConfigPath(configRoot); + } else if ($args.get(0).equals("create")) { + createConfigFile(configRoot); + } else if ($args.get(0).equals("list") || $args.get(0).equals("show")) { + listConfig(); + } else { + System.out.println("unknown command in config manager."); + } + + } + + private static void listConfig () { + ClientMain.config().echo(); + } + + private static void createConfigFile (Path configRoot) { + // check system/user config root + if (!configRoot.toFile().isDirectory()) { + _user(String.format("the config root `%s` is not a directory!", configRoot.toAbsolutePath())); + return; + } + // check and create sekai config dir + final Path configPath = Config.getAppConfigPath(configRoot); + final File configPathDir = configPath.toFile(); + if (configPathDir.exists()) { + if (!configPathDir.isDirectory()) { + _user(String.format("the config path `%s` is not a directory!", configPath.toAbsolutePath())); + return; + } + } else { + try { + _debug("try create config path " + configPath.toAbsolutePath()); + if (!configPathDir.mkdir()) { + _user(String.format("failed to create config path `%s`", configPath.toAbsolutePath())); + return; + } + } catch (SecurityException e) { + _user(String.format("%s: permission denied", configPath.toAbsolutePath())); + return; + } + } + // create config file + final File configFile = Config.getAppConfigFile(configPath); + try { + _debug("try create config " + configFile.getAbsolutePath()); + if (!configFile.createNewFile()) { + _user(String.format("%s: already exists.", configFile.getAbsolutePath())); + return; + } + } catch (IOException e) { + _user(String.format("%s: create file failed: %s", configFile.getAbsolutePath(), e.getMessage())); + return; + } catch (SecurityException e) { + _user(String.format("%s: permission denied", configFile.getAbsolutePath())); + return; + } + System.out.println(configFile.getAbsolutePath()); + } + + private static void showConfigPath (Path configRoot) { + System.out.println(Config.getAppConfigFile(Config.getAppConfigPath(configRoot)).getAbsolutePath()); + } + +} diff --git a/sekai-cli/src/test/java/cc/sukazyo/sekai_cli/CLI.java b/sekai-cli/src/test/java/cc/sukazyo/sekai_cli/CLI.java new file mode 100644 index 0000000..f0f8a24 --- /dev/null +++ b/sekai-cli/src/test/java/cc/sukazyo/sekai_cli/CLI.java @@ -0,0 +1,16 @@ +package cc.sukazyo.sekai_cli; + +import java.util.Scanner; + +public class CLI { + + public static void main (String[] args) { + + final Scanner in = new Scanner(System.in); + System.out.print("$ java -jar sekai-cli.jar "); + String[] $args = in.nextLine().split(" "); + ClientMain.main($args); + + } + +}