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",
|
||||
"workutils.config", "plugins.config"
|
||||
};
|
||||
java.nio.file.Path dataDir = java.nio.file.Paths.get(
|
||||
System.getProperty("user.dir"), "data");
|
||||
java.nio.file.Path dataDir = properties.getWorkutilsConfigFilePath().getParent();
|
||||
StringBuilder sb = new StringBuilder("data 目录文件状态:\n");
|
||||
for (String f : files) {
|
||||
java.nio.file.Path p = dataDir.resolve(f);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.example.workutils.biz.gitreview;
|
||||
|
||||
import com.example.workutils.system.config.WorkUtilsProperties;
|
||||
import com.example.workutils.system.support.ApplicationPaths;
|
||||
import com.example.workutils.system.support.FileOperationHelper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -265,7 +266,7 @@ public class GitReviewService {
|
||||
if (parent != null) {
|
||||
return parent;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve("data");
|
||||
return ApplicationPaths.current().resolve("data");
|
||||
}
|
||||
|
||||
private Path historyFile() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.example.workutils.system.config;
|
||||
|
||||
import com.example.workutils.system.support.ApplicationPaths;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@@ -42,6 +43,16 @@ import java.util.jar.JarFile;
|
||||
@Data
|
||||
public class WorkUtilsProperties {
|
||||
|
||||
private final ApplicationPaths applicationPaths;
|
||||
|
||||
public WorkUtilsProperties() {
|
||||
this(ApplicationPaths.current());
|
||||
}
|
||||
|
||||
WorkUtilsProperties(ApplicationPaths applicationPaths) {
|
||||
this.applicationPaths = applicationPaths;
|
||||
}
|
||||
|
||||
/** 基础目录 */
|
||||
private String baseDirectory;
|
||||
|
||||
@@ -105,17 +116,17 @@ public class WorkUtilsProperties {
|
||||
void snapshotDefaults() {
|
||||
// 基础目录:未配置则默认取运行目录(user.dir)
|
||||
if (baseDirectory == null || baseDirectory.trim().isEmpty()) {
|
||||
baseDirectory = System.getProperty("user.dir");
|
||||
baseDirectory = applicationPaths.home().toString();
|
||||
log.info("基础目录未配置,默认取运行目录: {}", baseDirectory);
|
||||
}
|
||||
// 导出目录:未配置则默认 {user.dir}/export
|
||||
if (exportDirectory == null || exportDirectory.trim().isEmpty()) {
|
||||
exportDirectory = System.getProperty("user.dir") + "/export";
|
||||
exportDirectory = applicationPaths.resolve("export").toString();
|
||||
log.info("导出目录未配置,默认: {}", exportDirectory);
|
||||
ensureExportDirExists();
|
||||
} else if (!Paths.get(exportDirectory).isAbsolute()) {
|
||||
// 相对路径 → 解析到 user.dir 下
|
||||
exportDirectory = Paths.get(System.getProperty("user.dir"), exportDirectory).toString();
|
||||
exportDirectory = applicationPaths.resolveConfigured(exportDirectory).toString();
|
||||
ensureExportDirExists();
|
||||
} else {
|
||||
ensureExportDirExists();
|
||||
@@ -234,11 +245,7 @@ public class WorkUtilsProperties {
|
||||
* 文件不存在时自动创建空文件。
|
||||
*/
|
||||
public Path getProjectPathsFilePath() {
|
||||
Path p = Paths.get(projectPathsFile != null ? projectPathsFile : "data/project_paths.txt");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(projectPathsFile, "data", "project_paths.txt");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,66 +256,42 @@ public class WorkUtilsProperties {
|
||||
* 否则解析到 user.dir 下。
|
||||
*/
|
||||
public Path getDamagedReposFilePath() {
|
||||
Path p = Paths.get(damagedReposFile != null ? damagedReposFile : "data/damaged_repos.cache");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(damagedReposFile, "data", "damaged_repos.cache");
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据源配置文件的实际路径
|
||||
*/
|
||||
public Path getDatasourcesFilePath() {
|
||||
Path p = Paths.get(datasourcesFile != null ? datasourcesFile : "data/datasources.json");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(datasourcesFile, "data", "datasources.json");
|
||||
}
|
||||
|
||||
/**
|
||||
* 外部配置文件(workutils.config)的实际路径
|
||||
*/
|
||||
public Path getWorkutilsConfigFilePath() {
|
||||
Path p = Paths.get(workutilsConfigFile != null ? workutilsConfigFile : "data/workutils.config");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(workutilsConfigFile, "data", "workutils.config");
|
||||
}
|
||||
|
||||
/**
|
||||
* MyBatis 生成器配置文件的实际路径
|
||||
*/
|
||||
public Path getMybatisGeneratorFilePath() {
|
||||
Path p = Paths.get(mybatisGeneratorFile != null ? mybatisGeneratorFile : "data/mybatis-generator.properties");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(mybatisGeneratorFile, "data", "mybatis-generator.properties");
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件状态配置文件的实际路径
|
||||
*/
|
||||
public Path getPluginsConfigFilePath() {
|
||||
Path p = Paths.get(pluginsConfigFile != null ? pluginsConfigFile : "data/plugins.config");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(pluginsConfigFile, "data", "plugins.config");
|
||||
}
|
||||
|
||||
/**
|
||||
* API 基类配置文件的实际路径
|
||||
*/
|
||||
public Path getApiBaseClassesFilePath() {
|
||||
Path p = Paths.get(apiBaseClassesFile != null ? apiBaseClassesFile : "data/api_base_classes.json");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
return Paths.get(System.getProperty("user.dir")).resolve(p);
|
||||
return applicationPaths.resolveConfigured(apiBaseClassesFile, "data", "api_base_classes.json");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,11 @@ public class HistoryPersistence {
|
||||
* @param name 文件名(不含路径),如 "scanner_history.txt"
|
||||
*/
|
||||
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 {
|
||||
Files.createDirectories(dataDir);
|
||||
} catch (IOException ignored) {
|
||||
|
||||
@@ -3,11 +3,11 @@ spring:
|
||||
name: workutils
|
||||
|
||||
workutils:
|
||||
# base dir, empty = defaults to user.dir
|
||||
# base dir, empty = defaults to the WorkUtils application home
|
||||
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: ""
|
||||
# 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"
|
||||
damaged-repos-file: "data/damaged_repos.cache"
|
||||
datasources-file: "data/datasources.json"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
base-directory=
|
||||
export-directory=
|
||||
|
||||
# ===== 数据文件路径(相对于 user.dir)=====
|
||||
# ===== 数据文件路径(相对于 WorkUtils 应用根目录)=====
|
||||
project-paths-file=data/project_paths.txt
|
||||
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