Use application home for runtime data paths
This commit is contained in:
@@ -67,8 +67,7 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
|||||||
"damaged_repos.cache", "mybatis-generator.properties",
|
"damaged_repos.cache", "mybatis-generator.properties",
|
||||||
"workutils.config", "plugins.config"
|
"workutils.config", "plugins.config"
|
||||||
};
|
};
|
||||||
java.nio.file.Path dataDir = java.nio.file.Paths.get(
|
java.nio.file.Path dataDir = properties.getWorkutilsConfigFilePath().getParent();
|
||||||
System.getProperty("user.dir"), "data");
|
|
||||||
StringBuilder sb = new StringBuilder("data 目录文件状态:\n");
|
StringBuilder sb = new StringBuilder("data 目录文件状态:\n");
|
||||||
for (String f : files) {
|
for (String f : files) {
|
||||||
java.nio.file.Path p = dataDir.resolve(f);
|
java.nio.file.Path p = dataDir.resolve(f);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.example.workutils.biz.gitreview;
|
package com.example.workutils.biz.gitreview;
|
||||||
|
|
||||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||||
|
import com.example.workutils.system.support.ApplicationPaths;
|
||||||
import com.example.workutils.system.support.FileOperationHelper;
|
import com.example.workutils.system.support.FileOperationHelper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -265,7 +266,7 @@ public class GitReviewService {
|
|||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve("data");
|
return ApplicationPaths.current().resolve("data");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path historyFile() {
|
private Path historyFile() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.example.workutils.system.config;
|
package com.example.workutils.system.config;
|
||||||
|
|
||||||
|
import com.example.workutils.system.support.ApplicationPaths;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@@ -42,6 +43,16 @@ import java.util.jar.JarFile;
|
|||||||
@Data
|
@Data
|
||||||
public class WorkUtilsProperties {
|
public class WorkUtilsProperties {
|
||||||
|
|
||||||
|
private final ApplicationPaths applicationPaths;
|
||||||
|
|
||||||
|
public WorkUtilsProperties() {
|
||||||
|
this(ApplicationPaths.current());
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkUtilsProperties(ApplicationPaths applicationPaths) {
|
||||||
|
this.applicationPaths = applicationPaths;
|
||||||
|
}
|
||||||
|
|
||||||
/** 基础目录 */
|
/** 基础目录 */
|
||||||
private String baseDirectory;
|
private String baseDirectory;
|
||||||
|
|
||||||
@@ -105,17 +116,17 @@ public class WorkUtilsProperties {
|
|||||||
void snapshotDefaults() {
|
void snapshotDefaults() {
|
||||||
// 基础目录:未配置则默认取运行目录(user.dir)
|
// 基础目录:未配置则默认取运行目录(user.dir)
|
||||||
if (baseDirectory == null || baseDirectory.trim().isEmpty()) {
|
if (baseDirectory == null || baseDirectory.trim().isEmpty()) {
|
||||||
baseDirectory = System.getProperty("user.dir");
|
baseDirectory = applicationPaths.home().toString();
|
||||||
log.info("基础目录未配置,默认取运行目录: {}", baseDirectory);
|
log.info("基础目录未配置,默认取运行目录: {}", baseDirectory);
|
||||||
}
|
}
|
||||||
// 导出目录:未配置则默认 {user.dir}/export
|
// 导出目录:未配置则默认 {user.dir}/export
|
||||||
if (exportDirectory == null || exportDirectory.trim().isEmpty()) {
|
if (exportDirectory == null || exportDirectory.trim().isEmpty()) {
|
||||||
exportDirectory = System.getProperty("user.dir") + "/export";
|
exportDirectory = applicationPaths.resolve("export").toString();
|
||||||
log.info("导出目录未配置,默认: {}", exportDirectory);
|
log.info("导出目录未配置,默认: {}", exportDirectory);
|
||||||
ensureExportDirExists();
|
ensureExportDirExists();
|
||||||
} else if (!Paths.get(exportDirectory).isAbsolute()) {
|
} else if (!Paths.get(exportDirectory).isAbsolute()) {
|
||||||
// 相对路径 → 解析到 user.dir 下
|
// 相对路径 → 解析到 user.dir 下
|
||||||
exportDirectory = Paths.get(System.getProperty("user.dir"), exportDirectory).toString();
|
exportDirectory = applicationPaths.resolveConfigured(exportDirectory).toString();
|
||||||
ensureExportDirExists();
|
ensureExportDirExists();
|
||||||
} else {
|
} else {
|
||||||
ensureExportDirExists();
|
ensureExportDirExists();
|
||||||
@@ -234,11 +245,7 @@ public class WorkUtilsProperties {
|
|||||||
* 文件不存在时自动创建空文件。
|
* 文件不存在时自动创建空文件。
|
||||||
*/
|
*/
|
||||||
public Path getProjectPathsFilePath() {
|
public Path getProjectPathsFilePath() {
|
||||||
Path p = Paths.get(projectPathsFile != null ? projectPathsFile : "data/project_paths.txt");
|
return applicationPaths.resolveConfigured(projectPathsFile, "data", "project_paths.txt");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -249,66 +256,42 @@ public class WorkUtilsProperties {
|
|||||||
* 否则解析到 user.dir 下。
|
* 否则解析到 user.dir 下。
|
||||||
*/
|
*/
|
||||||
public Path getDamagedReposFilePath() {
|
public Path getDamagedReposFilePath() {
|
||||||
Path p = Paths.get(damagedReposFile != null ? damagedReposFile : "data/damaged_repos.cache");
|
return applicationPaths.resolveConfigured(damagedReposFile, "data", "damaged_repos.cache");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据源配置文件的实际路径
|
* 数据源配置文件的实际路径
|
||||||
*/
|
*/
|
||||||
public Path getDatasourcesFilePath() {
|
public Path getDatasourcesFilePath() {
|
||||||
Path p = Paths.get(datasourcesFile != null ? datasourcesFile : "data/datasources.json");
|
return applicationPaths.resolveConfigured(datasourcesFile, "data", "datasources.json");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 外部配置文件(workutils.config)的实际路径
|
* 外部配置文件(workutils.config)的实际路径
|
||||||
*/
|
*/
|
||||||
public Path getWorkutilsConfigFilePath() {
|
public Path getWorkutilsConfigFilePath() {
|
||||||
Path p = Paths.get(workutilsConfigFile != null ? workutilsConfigFile : "data/workutils.config");
|
return applicationPaths.resolveConfigured(workutilsConfigFile, "data", "workutils.config");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MyBatis 生成器配置文件的实际路径
|
* MyBatis 生成器配置文件的实际路径
|
||||||
*/
|
*/
|
||||||
public Path getMybatisGeneratorFilePath() {
|
public Path getMybatisGeneratorFilePath() {
|
||||||
Path p = Paths.get(mybatisGeneratorFile != null ? mybatisGeneratorFile : "data/mybatis-generator.properties");
|
return applicationPaths.resolveConfigured(mybatisGeneratorFile, "data", "mybatis-generator.properties");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件状态配置文件的实际路径
|
* 插件状态配置文件的实际路径
|
||||||
*/
|
*/
|
||||||
public Path getPluginsConfigFilePath() {
|
public Path getPluginsConfigFilePath() {
|
||||||
Path p = Paths.get(pluginsConfigFile != null ? pluginsConfigFile : "data/plugins.config");
|
return applicationPaths.resolveConfigured(pluginsConfigFile, "data", "plugins.config");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 基类配置文件的实际路径
|
* API 基类配置文件的实际路径
|
||||||
*/
|
*/
|
||||||
public Path getApiBaseClassesFilePath() {
|
public Path getApiBaseClassesFilePath() {
|
||||||
Path p = Paths.get(apiBaseClassesFile != null ? apiBaseClassesFile : "data/api_base_classes.json");
|
return applicationPaths.resolveConfigured(apiBaseClassesFile, "data", "api_base_classes.json");
|
||||||
if (p.isAbsolute()) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ public class HistoryPersistence {
|
|||||||
* @param name 文件名(不含路径),如 "scanner_history.txt"
|
* @param name 文件名(不含路径),如 "scanner_history.txt"
|
||||||
*/
|
*/
|
||||||
public HistoryPersistence(String name) {
|
public HistoryPersistence(String name) {
|
||||||
Path dataDir = Paths.get(System.getProperty("user.dir"), "data");
|
this(name, ApplicationPaths.current());
|
||||||
|
}
|
||||||
|
|
||||||
|
public HistoryPersistence(String name, ApplicationPaths applicationPaths) {
|
||||||
|
Path dataDir = applicationPaths.resolve("data");
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(dataDir);
|
Files.createDirectories(dataDir);
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ spring:
|
|||||||
name: workutils
|
name: workutils
|
||||||
|
|
||||||
workutils:
|
workutils:
|
||||||
# base dir, empty = defaults to user.dir
|
# base dir, empty = defaults to the WorkUtils application home
|
||||||
base-directory: ""
|
base-directory: ""
|
||||||
# export dir, empty = defaults to {user.dir}/export (auto-created on startup)
|
# export dir, empty = defaults to {application-home}/export (auto-created on startup)
|
||||||
export-directory: ""
|
export-directory: ""
|
||||||
# data file paths (relative -> under user.dir/data/, absolute -> as-is)
|
# data file paths (relative -> under application-home/data/, absolute -> as-is)
|
||||||
project-paths-file: "data/project_paths.txt"
|
project-paths-file: "data/project_paths.txt"
|
||||||
damaged-repos-file: "data/damaged_repos.cache"
|
damaged-repos-file: "data/damaged_repos.cache"
|
||||||
datasources-file: "data/datasources.json"
|
datasources-file: "data/datasources.json"
|
||||||
@@ -22,4 +22,4 @@ logging:
|
|||||||
com.example.workutils: INFO
|
com.example.workutils: INFO
|
||||||
org.springframework: WARN
|
org.springframework: WARN
|
||||||
pattern:
|
pattern:
|
||||||
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
base-directory=
|
base-directory=
|
||||||
export-directory=
|
export-directory=
|
||||||
|
|
||||||
# ===== 数据文件路径(相对于 user.dir)=====
|
# ===== 数据文件路径(相对于 WorkUtils 应用根目录)=====
|
||||||
project-paths-file=data/project_paths.txt
|
project-paths-file=data/project_paths.txt
|
||||||
damaged-repos-file=data/damaged_repos.cache
|
damaged-repos-file=data/damaged_repos.cache
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.example.workutils.system.config;
|
||||||
|
|
||||||
|
import com.example.workutils.system.support.ApplicationPaths;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class WorkUtilsPropertiesPathTest {
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
Path tempDirectory;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void relativeRuntimeFilesUseApplicationHome() {
|
||||||
|
WorkUtilsProperties properties = new WorkUtilsProperties(ApplicationPaths.of(tempDirectory));
|
||||||
|
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "project_paths.txt")),
|
||||||
|
properties.getProjectPathsFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "damaged_repos.cache")),
|
||||||
|
properties.getDamagedReposFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "datasources.json")),
|
||||||
|
properties.getDatasourcesFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "workutils.config")),
|
||||||
|
properties.getWorkutilsConfigFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "mybatis-generator.properties")),
|
||||||
|
properties.getMybatisGeneratorFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "plugins.config")),
|
||||||
|
properties.getPluginsConfigFilePath());
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "api_base_classes.json")),
|
||||||
|
properties.getApiBaseClassesFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void absoluteConfiguredFileIsPreserved() {
|
||||||
|
WorkUtilsProperties properties = new WorkUtilsProperties(ApplicationPaths.of(tempDirectory));
|
||||||
|
Path absolute = tempDirectory.resolve("外部 配置.json").toAbsolutePath().normalize();
|
||||||
|
properties.setDatasourcesFile(absolute.toString());
|
||||||
|
|
||||||
|
assertEquals(absolute, properties.getDatasourcesFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void snapshotDefaultsUsesApplicationHomeForBaseAndExportDirectories() {
|
||||||
|
WorkUtilsProperties properties = new WorkUtilsProperties(ApplicationPaths.of(tempDirectory));
|
||||||
|
|
||||||
|
properties.snapshotDefaults();
|
||||||
|
|
||||||
|
assertEquals(tempDirectory.toString(), properties.getBaseDirectory());
|
||||||
|
assertEquals(tempDirectory.resolve("export"), properties.getExportBasePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.example.workutils.system.support;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class HistoryPersistencePathTest {
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
Path tempDirectory;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void historyIsSavedUnderApplicationHomeWithUnicodeAndSpaces() {
|
||||||
|
HistoryPersistence persistence = new HistoryPersistence(
|
||||||
|
"扫描 历史.txt", ApplicationPaths.of(tempDirectory));
|
||||||
|
|
||||||
|
persistence.save(List.of("一条历史"));
|
||||||
|
|
||||||
|
assertEquals(tempDirectory.resolve(Path.of("data", "扫描 历史.txt")).toString(),
|
||||||
|
persistence.getFilePath());
|
||||||
|
assertEquals(List.of("一条历史"), persistence.load());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user