mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
Compare commits
5 commits
d5abe0d411
...
63f9f8e21d
Author | SHA1 | Date | |
---|---|---|---|
|
63f9f8e21d | ||
|
b8ccbc5e48 | ||
|
a687c5afd8 | ||
|
3969d81db7 | ||
|
a30d0624a1 |
14 changed files with 266 additions and 123 deletions
|
@ -70,6 +70,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
||||||
/**
|
/**
|
||||||
* The path to the folder with updates/webroot
|
* The path to the folder with updates/webroot
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public final Path updatesDir;
|
public final Path updatesDir;
|
||||||
|
|
||||||
// Constant paths
|
// Constant paths
|
||||||
|
@ -359,9 +360,7 @@ public void run() {
|
||||||
syncProfilesDir();
|
syncProfilesDir();
|
||||||
|
|
||||||
// Sync updates dir
|
// Sync updates dir
|
||||||
if (!IOHelper.isDir(updatesDir))
|
config.updatesProvider.syncInitially();
|
||||||
Files.createDirectory(updatesDir);
|
|
||||||
updatesManager.readUpdatesDir();
|
|
||||||
|
|
||||||
|
|
||||||
modulesManager.invokeEvent(new LaunchServerProfilesSyncEvent(this));
|
modulesManager.invokeEvent(new LaunchServerProfilesSyncEvent(this));
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
package pro.gravit.launchserver.auth.updates;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.launcher.core.hasher.HashedDir;
|
||||||
|
import pro.gravit.launcher.core.serialize.HInput;
|
||||||
|
import pro.gravit.launcher.core.serialize.HOutput;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.modules.events.LaunchServerUpdatesSyncEvent;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class LocalUpdatesProvider extends UpdatesProvider {
|
||||||
|
private final transient Logger logger = LogManager.getLogger();
|
||||||
|
public String cacheFile = ".updates-cache";
|
||||||
|
public String updatesDir = "updates";
|
||||||
|
public boolean cacheUpdates = true;
|
||||||
|
private volatile transient Map<String, HashedDir> updatesDirMap;
|
||||||
|
|
||||||
|
private void writeCache(Path file) throws IOException {
|
||||||
|
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
||||||
|
output.writeLength(updatesDirMap.size(), 0);
|
||||||
|
for (Map.Entry<String, HashedDir> entry : updatesDirMap.entrySet()) {
|
||||||
|
output.writeString(entry.getKey(), 0);
|
||||||
|
entry.getValue().write(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Saved {} updates to cache", updatesDirMap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readCache(Path file) throws IOException {
|
||||||
|
Map<String, HashedDir> updatesDirMap = new HashMap<>(16);
|
||||||
|
try (HInput input = new HInput(IOHelper.newInput(file))) {
|
||||||
|
int size = input.readLength(0);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
String name = input.readString(0);
|
||||||
|
HashedDir dir = new HashedDir(input);
|
||||||
|
updatesDirMap.put(name, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Found {} updates from cache", updatesDirMap.size());
|
||||||
|
this.updatesDirMap = Collections.unmodifiableMap(updatesDirMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readUpdatesFromCache() throws IOException {
|
||||||
|
readCache(Path.of(cacheFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readUpdatesDir() throws IOException {
|
||||||
|
var cacheFilePath = Path.of(cacheFile);
|
||||||
|
if (cacheUpdates) {
|
||||||
|
if (Files.exists(cacheFilePath)) {
|
||||||
|
try {
|
||||||
|
readCache(cacheFilePath);
|
||||||
|
return;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error("Read updates cache failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sync(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(LaunchServer server) {
|
||||||
|
super.init(server);
|
||||||
|
try {
|
||||||
|
if (!IOHelper.isDir(Path.of(updatesDir)))
|
||||||
|
Files.createDirectory(Path.of(updatesDir));
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Updates not synced", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void syncInitially() throws IOException {
|
||||||
|
readUpdatesDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sync(Collection<String> dirs) throws IOException {
|
||||||
|
logger.info("Syncing updates dir");
|
||||||
|
Map<String, HashedDir> newUpdatesDirMap = new HashMap<>(16);
|
||||||
|
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(Path.of(updatesDir))) {
|
||||||
|
for (final Path updateDir : dirStream) {
|
||||||
|
if (Files.isHidden(updateDir))
|
||||||
|
continue; // Skip hidden
|
||||||
|
|
||||||
|
// Resolve name and verify is dir
|
||||||
|
String name = IOHelper.getFileName(updateDir);
|
||||||
|
if (!IOHelper.isDir(updateDir)) {
|
||||||
|
if (!IOHelper.isFile(updateDir) && Stream.of(".jar", ".exe", ".hash").noneMatch(e -> updateDir.toString().endsWith(e)))
|
||||||
|
logger.warn("Not update dir: '{}'", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add from previous map (it's guaranteed to be non-null)
|
||||||
|
if (dirs != null && !dirs.contains(name)) {
|
||||||
|
HashedDir hdir = updatesDirMap.get(name);
|
||||||
|
if (hdir != null) {
|
||||||
|
newUpdatesDirMap.put(name, hdir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync and sign update dir
|
||||||
|
logger.info("Syncing '{}' update dir", name);
|
||||||
|
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
||||||
|
newUpdatesDirMap.put(name, updateHDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
||||||
|
if (cacheUpdates) {
|
||||||
|
try {
|
||||||
|
writeCache(Path.of(cacheFile));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error("Write updates cache failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.modulesManager.invokeEvent(new LaunchServerUpdatesSyncEvent(server));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashedDir getUpdatesDir(String updateName) {
|
||||||
|
return updatesDirMap.get(updateName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upload(String updateName, Map<String, Path> files, boolean deleteAfterUpload) throws IOException {
|
||||||
|
var path = Path.of(updatesDir).resolve(updateName);
|
||||||
|
for(var e : files.entrySet()) {
|
||||||
|
var target = path.resolve(e.getKey());
|
||||||
|
var source = Path.of(e.getKey());
|
||||||
|
IOHelper.createParentDirs(target);
|
||||||
|
if(deleteAfterUpload) {
|
||||||
|
Files.move(source, target);
|
||||||
|
} else {
|
||||||
|
Files.copy(source, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String updateName, List<String> files) throws IOException {
|
||||||
|
var path = Path.of(updatesDir).resolve(updateName);
|
||||||
|
for(var e : files) {
|
||||||
|
var target = path.resolve(e);
|
||||||
|
Files.delete(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String updateName) throws IOException {
|
||||||
|
var path = Path.of(updatesDir).resolve(updateName);
|
||||||
|
IOHelper.deleteDir(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(String updateName) throws IOException {
|
||||||
|
var path = Path.of(updatesDir).resolve(updateName);
|
||||||
|
Files.createDirectories(path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package pro.gravit.launchserver.auth.updates;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.core.hasher.HashedDir;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.utils.ProviderMap;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class UpdatesProvider {
|
||||||
|
public static final ProviderMap<UpdatesProvider> providers = new ProviderMap<>("UpdatesProvider");
|
||||||
|
private static boolean registredProviders = false;
|
||||||
|
protected transient LaunchServer server;
|
||||||
|
|
||||||
|
public static void registerProviders() {
|
||||||
|
if (!registredProviders) {
|
||||||
|
registredProviders = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sync() throws IOException {
|
||||||
|
sync(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void syncInitially() throws IOException;
|
||||||
|
|
||||||
|
public abstract void sync(Collection<String> updateNames) throws IOException;
|
||||||
|
|
||||||
|
public abstract HashedDir getUpdatesDir(String updateName);
|
||||||
|
|
||||||
|
public abstract void upload(String updateName, Map<String, Path> files, boolean deleteAfterUpload) throws IOException;
|
||||||
|
|
||||||
|
public abstract void delete(String updateName, List<String> files) throws IOException;
|
||||||
|
|
||||||
|
public abstract void delete(String updateName) throws IOException;
|
||||||
|
|
||||||
|
public abstract void create(String updateName) throws IOException;
|
||||||
|
}
|
|
@ -14,11 +14,11 @@
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class BinaryPipeline {
|
public abstract class BinaryPipeline {
|
||||||
public final List<LauncherBuildTask> tasks = new ArrayList<>();
|
public final List<LauncherBuildTask> tasks = new ArrayList<>();
|
||||||
public final Path buildDir;
|
public final Path buildDir;
|
||||||
public final String nameFormat;
|
public final String nameFormat;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
protected transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public BinaryPipeline(Path buildDir, String nameFormat) {
|
public BinaryPipeline(Path buildDir, String nameFormat) {
|
||||||
this.buildDir = buildDir;
|
this.buildDir = buildDir;
|
||||||
|
@ -80,27 +80,6 @@ public Optional<LauncherBuildTask> getTaskBefore(Predicate<LauncherBuildTask> pr
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(Path target, boolean deleteTempFiles) throws IOException {
|
|
||||||
logger.info("Building launcher binary file");
|
|
||||||
Path thisPath = null;
|
|
||||||
long time_start = System.currentTimeMillis();
|
|
||||||
long time_this = time_start;
|
|
||||||
for (LauncherBuildTask task : tasks) {
|
|
||||||
logger.info("Task {}", task.getName());
|
|
||||||
Path oldPath = thisPath;
|
|
||||||
thisPath = task.process(oldPath);
|
|
||||||
long time_task_end = System.currentTimeMillis();
|
|
||||||
long time_task = time_task_end - time_this;
|
|
||||||
time_this = time_task_end;
|
|
||||||
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
|
||||||
}
|
|
||||||
long time_end = System.currentTimeMillis();
|
|
||||||
if (deleteTempFiles) IOHelper.move(thisPath, target);
|
|
||||||
else IOHelper.copy(thisPath, target);
|
|
||||||
IOHelper.deleteDir(buildDir, false);
|
|
||||||
logger.info("Build successful from {} millis", time_end - time_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String nextName(String taskName) {
|
public String nextName(String taskName) {
|
||||||
return nameFormat.formatted(taskName);
|
return nameFormat.formatted(taskName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package pro.gravit.launchserver.binary;
|
package pro.gravit.launchserver.binary;
|
||||||
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.binary.tasks.LauncherBuildTask;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class LauncherBinary extends BinaryPipeline {
|
public abstract class LauncherBinary extends BinaryPipeline {
|
||||||
public final LaunchServer server;
|
public final LaunchServer server;
|
||||||
|
@ -19,11 +21,27 @@ protected LauncherBinary(LaunchServer server, Path binaryFile, String nameFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path resolve(LaunchServer server, String ext) {
|
public static Path resolve(LaunchServer server, String ext) {
|
||||||
return server.config.copyBinaries ? server.updatesDir.resolve(server.config.binaryName + ext) : server.dir.resolve(server.config.binaryName + ext);
|
return Path.of(server.config.binaryName + ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build() throws IOException {
|
public void build() throws IOException {
|
||||||
build(syncBinaryFile, server.config.launcher.deleteTempFiles);
|
logger.info("Building launcher binary file");
|
||||||
|
Path thisPath = null;
|
||||||
|
long time_start = System.currentTimeMillis();
|
||||||
|
long time_this = time_start;
|
||||||
|
for (LauncherBuildTask task : tasks) {
|
||||||
|
logger.info("Task {}", task.getName());
|
||||||
|
Path oldPath = thisPath;
|
||||||
|
thisPath = task.process(oldPath);
|
||||||
|
long time_task_end = System.currentTimeMillis();
|
||||||
|
long time_task = time_task_end - time_this;
|
||||||
|
time_this = time_task_end;
|
||||||
|
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
||||||
|
}
|
||||||
|
long time_end = System.currentTimeMillis();
|
||||||
|
server.config.updatesProvider.upload(null, Map.of(syncBinaryFile.toString(), thisPath), true);
|
||||||
|
IOHelper.deleteDir(buildDir, false);
|
||||||
|
logger.info("Build successful from {} millis", time_end - time_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean exists() {
|
public final boolean exists() {
|
||||||
|
|
|
@ -40,14 +40,13 @@ public void invoke(String... args) throws Exception {
|
||||||
logger.error("Profile {} not found", args[0]);
|
logger.error("Profile {} not found", args[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var clientDir = server.updatesDir.resolve(profile.getDir()).toAbsolutePath();
|
logger.warn("THIS ACTION DELETE PROFILE AND ALL FILES IN {}", profile.getDir());
|
||||||
logger.warn("THIS ACTION DELETE PROFILE AND ALL FILES IN {}", clientDir);
|
|
||||||
if(!showApplyDialog("Continue?")) {
|
if(!showApplyDialog("Continue?")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.info("Delete {} ({})", profile.getTitle(), profile.getUUID());
|
logger.info("Delete {} ({})", profile.getTitle(), profile.getUUID());
|
||||||
server.config.profileProvider.deleteProfile(profile);
|
server.config.profileProvider.deleteProfile(profile);
|
||||||
logger.info("Delete {}", clientDir);
|
logger.info("Delete {}", profile.getDir());
|
||||||
IOHelper.deleteDir(clientDir, true);
|
server.config.updatesProvider.delete(profile.getDir());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
|
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
|
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
|
||||||
|
import pro.gravit.launchserver.auth.updates.LocalUpdatesProvider;
|
||||||
|
import pro.gravit.launchserver.auth.updates.UpdatesProvider;
|
||||||
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
||||||
import pro.gravit.launchserver.components.Component;
|
import pro.gravit.launchserver.components.Component;
|
||||||
import pro.gravit.launchserver.components.ProGuardComponent;
|
import pro.gravit.launchserver.components.ProGuardComponent;
|
||||||
|
@ -32,13 +34,13 @@ public final class LaunchServerConfig {
|
||||||
public String[] mirrors;
|
public String[] mirrors;
|
||||||
public String binaryName;
|
public String binaryName;
|
||||||
public boolean copyBinaries = true;
|
public boolean copyBinaries = true;
|
||||||
public boolean cacheUpdates = true;
|
|
||||||
public LauncherConfig.LauncherEnvironment env;
|
public LauncherConfig.LauncherEnvironment env;
|
||||||
public Map<String, AuthProviderPair> auth;
|
public Map<String, AuthProviderPair> auth;
|
||||||
// Handlers & Providers
|
// Handlers & Providers
|
||||||
public ProtectHandler protectHandler;
|
public ProtectHandler protectHandler;
|
||||||
public Map<String, Component> components;
|
public Map<String, Component> components;
|
||||||
public ProfileProvider profileProvider = new LocalProfileProvider();
|
public ProfileProvider profileProvider = new LocalProfileProvider();
|
||||||
|
public UpdatesProvider updatesProvider = new LocalUpdatesProvider();
|
||||||
public NettyConfig netty;
|
public NettyConfig netty;
|
||||||
public LauncherConf launcher;
|
public LauncherConf launcher;
|
||||||
public JarSignerConf sign;
|
public JarSignerConf sign;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
import pro.gravit.launchserver.auth.profiles.ProfileProvider;
|
import pro.gravit.launchserver.auth.profiles.ProfileProvider;
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
|
import pro.gravit.launchserver.auth.updates.UpdatesProvider;
|
||||||
import pro.gravit.launchserver.components.Component;
|
import pro.gravit.launchserver.components.Component;
|
||||||
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
||||||
import pro.gravit.launchserver.socket.WebSocketService;
|
import pro.gravit.launchserver.socket.WebSocketService;
|
||||||
|
@ -48,6 +49,7 @@ public void registerAdapters(GsonBuilder builder) {
|
||||||
builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers));
|
builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers));
|
||||||
builder.registerTypeAdapter(MixProvider.class, new UniversalJsonAdapter<>(MixProvider.providers));
|
builder.registerTypeAdapter(MixProvider.class, new UniversalJsonAdapter<>(MixProvider.providers));
|
||||||
builder.registerTypeAdapter(ProfileProvider.class, new UniversalJsonAdapter<>(ProfileProvider.providers));
|
builder.registerTypeAdapter(ProfileProvider.class, new UniversalJsonAdapter<>(ProfileProvider.providers));
|
||||||
|
builder.registerTypeAdapter(UpdatesProvider.class, new UniversalJsonAdapter<>(UpdatesProvider.providers));
|
||||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||||
//ClientWebSocketService.appendTypeAdapters(builder);
|
//ClientWebSocketService.appendTypeAdapters(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,112 +18,38 @@
|
||||||
|
|
||||||
public class UpdatesManager {
|
public class UpdatesManager {
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
private final Logger logger = LogManager.getLogger();
|
|
||||||
private final Path cacheFile;
|
|
||||||
private volatile Map<String, HashedDir> updatesDirMap;
|
|
||||||
|
|
||||||
public UpdatesManager(LaunchServer server) {
|
public UpdatesManager(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.cacheFile = server.dir.resolve(".updates-cache");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeCache(Path file) throws IOException {
|
|
||||||
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
|
||||||
output.writeLength(updatesDirMap.size(), 0);
|
|
||||||
for (Map.Entry<String, HashedDir> entry : updatesDirMap.entrySet()) {
|
|
||||||
output.writeString(entry.getKey(), 0);
|
|
||||||
entry.getValue().write(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.debug("Saved {} updates to cache", updatesDirMap.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readCache(Path file) throws IOException {
|
|
||||||
Map<String, HashedDir> updatesDirMap = new HashMap<>(16);
|
|
||||||
try (HInput input = new HInput(IOHelper.newInput(file))) {
|
|
||||||
int size = input.readLength(0);
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
String name = input.readString(0);
|
|
||||||
HashedDir dir = new HashedDir(input);
|
|
||||||
updatesDirMap.put(name, dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.debug("Found {} updates from cache", updatesDirMap.size());
|
|
||||||
this.updatesDirMap = Collections.unmodifiableMap(updatesDirMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void readUpdatesFromCache() throws IOException {
|
public void readUpdatesFromCache() throws IOException {
|
||||||
readCache(cacheFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void readUpdatesDir() throws IOException {
|
public void readUpdatesDir() throws IOException {
|
||||||
if (server.config.cacheUpdates) {
|
|
||||||
if (Files.exists(cacheFile)) {
|
|
||||||
try {
|
|
||||||
readCache(cacheFile);
|
|
||||||
return;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
logger.error("Read updates cache failed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
syncUpdatesDir(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
logger.info("Syncing updates dir");
|
server.config.updatesProvider.sync(dirs);
|
||||||
Map<String, HashedDir> newUpdatesDirMap = new HashMap<>(16);
|
|
||||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(server.updatesDir)) {
|
|
||||||
for (final Path updateDir : dirStream) {
|
|
||||||
if (Files.isHidden(updateDir))
|
|
||||||
continue; // Skip hidden
|
|
||||||
|
|
||||||
// Resolve name and verify is dir
|
|
||||||
String name = IOHelper.getFileName(updateDir);
|
|
||||||
if (!IOHelper.isDir(updateDir)) {
|
|
||||||
if (!IOHelper.isFile(updateDir) && Stream.of(".jar", ".exe", ".hash").noneMatch(e -> updateDir.toString().endsWith(e)))
|
|
||||||
logger.warn("Not update dir: '{}'", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add from previous map (it's guaranteed to be non-null)
|
|
||||||
if (dirs != null && !dirs.contains(name)) {
|
|
||||||
HashedDir hdir = updatesDirMap.get(name);
|
|
||||||
if (hdir != null) {
|
|
||||||
newUpdatesDirMap.put(name, hdir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync and sign update dir
|
|
||||||
logger.info("Syncing '{}' update dir", name);
|
|
||||||
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
|
||||||
newUpdatesDirMap.put(name, updateHDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
|
||||||
if (server.config.cacheUpdates) {
|
|
||||||
try {
|
|
||||||
writeCache(cacheFile);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
logger.error("Write updates cache failed", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server.modulesManager.invokeEvent(new LaunchServerUpdatesSyncEvent(server));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public HashSet<String> getUpdatesList() {
|
public HashSet<String> getUpdatesList() {
|
||||||
HashSet<String> set = new HashSet<>();
|
return new HashSet<>();
|
||||||
for (Map.Entry<String, HashedDir> entry : updatesDirMap.entrySet())
|
|
||||||
set.add(entry.getKey());
|
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public HashedDir getUpdate(String name) {
|
public HashedDir getUpdate(String name) {
|
||||||
return updatesDirMap.get(name);
|
return server.config.updatesProvider.getUpdatesDir(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void addUpdate(String name, HashedDir dir) {
|
public void addUpdate(String name, HashedDir dir) {
|
||||||
updatesDirMap.put(name, dir);
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
7
gradlew
vendored
7
gradlew
vendored
|
@ -15,6 +15,8 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
@ -84,7 +86,8 @@ done
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||||
|
' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
|
@ -13,6 +13,8 @@
|
||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
||||||
Subproject commit 6639aefae714e6671e0dd3fecc803845d0e07d42
|
Subproject commit 9127b086a22c01a174e74a5101329500b106de62
|
Loading…
Reference in a new issue