Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add safe config updating #7224

Open
wants to merge 29 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ef27c83
add key updating
Efnilite Nov 16, 2024
f9bcc6c
update VoidNode
Efnilite Nov 16, 2024
e80baf3
add getIndex to Node
Efnilite Nov 16, 2024
49a6bfa
replace insert with add at index to match List
Efnilite Nov 16, 2024
802db39
ensure correct order when adding entries
Efnilite Nov 16, 2024
ea09b63
update InvalidNode
Efnilite Nov 16, 2024
ef91bf5
update SimpleNode
Efnilite Nov 16, 2024
e7d2501
update EntryNode
Efnilite Nov 16, 2024
777861d
add iterator for VoidNodes for comments, update SectionNode
Efnilite Nov 17, 2024
4b0ed3c
add getting a node from full idx
Efnilite Nov 19, 2024
c6c20a4
added comparisons between diff lines, getting path, reformatted
Efnilite Nov 19, 2024
830e758
update to make it actually work
Efnilite Nov 19, 2024
a2b87a6
add formatted debug method
Efnilite Nov 21, 2024
2c09b12
fix error message
Efnilite Nov 21, 2024
ce406eb
reformatted, reduced visibility of getAt
Efnilite Nov 21, 2024
5156672
update node comparisons
Efnilite Nov 21, 2024
9bba911
finalize
Efnilite Nov 21, 2024
e04340b
update docs
Efnilite Nov 21, 2024
5cd0756
backup before updating, lol
Efnilite Nov 21, 2024
cec1734
Merge branch 'dev/feature' into feature/safe-config-update
Efnilite Nov 21, 2024
f894839
Update src/main/java/ch/njol/skript/config/Config.java
Efnilite Nov 22, 2024
20d7fdf
requested changes
Efnilite Nov 22, 2024
5f883ee
change to map
Efnilite Nov 22, 2024
4a16762
fix paths containing dots causing problems for getPath
Efnilite Nov 22, 2024
5a0c42c
Merge branch 'dev/feature' into feature/safe-config-update
Efnilite Nov 23, 2024
081c8c8
update
Efnilite Nov 27, 2024
2c3b70c
revert reformatting of node classes
Efnilite Nov 28, 2024
bc40b24
add missing methods to Node
Efnilite Nov 28, 2024
937b7a4
Merge branch 'dev/feature' into feature/safe-config-update
Efnilite Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,17 @@ public static void debug(final String info) {
SkriptLogger.log(SkriptLogger.DEBUG, info);
}

/**
* Sends a debug message with formatted objects if {@link #debug()} returns true.
*
* @param message The message to send
* @param objects The objects to format the message with
* @see String#formatted(Object...)
*/
public static void debug(String message, Object... objects) {
debug(message.formatted(objects));
}

/**
* @see SkriptLogger#log(Level, String)
*/
Expand Down
134 changes: 47 additions & 87 deletions src/main/java/ch/njol/skript/SkriptConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import ch.njol.skript.config.EnumParser;
import ch.njol.skript.config.Option;
import ch.njol.skript.config.OptionSection;
import ch.njol.skript.config.SectionNode;
import ch.njol.skript.hooks.Hook;
import ch.njol.skript.hooks.VaultHook;
import ch.njol.skript.hooks.regions.GriefPreventionHook;
Expand Down Expand Up @@ -332,111 +331,72 @@ private static void userDisableHooks(Class<? extends Hook<?>> hookClass, boolean
/**
* This should only be used in special cases
*/
@Nullable
public static Config getConfig() {
public static @Nullable Config getConfig() {
return mainConfig;
}

// also used for reloading
static boolean load() {

/**
* Reloads the main config file.
*/
static void load() {
try {
final File oldConfigFile = new File(Skript.getInstance().getDataFolder(), "config.cfg");
final File configFile = new File(Skript.getInstance().getDataFolder(), "config.sk");
if (oldConfigFile.exists()) {
if (!configFile.exists()) {
oldConfigFile.renameTo(configFile);
Skript.info("[1.3] Renamed your 'config.cfg' to 'config.sk' to match the new format");
} else {
Skript.error("Found both a new and an old config, ignoring the old one");
}
}
File configFile = new File(Skript.getInstance().getDataFolder(), "config.sk");

if (!configFile.exists()) {
Skript.error("Config file 'config.sk' does not exist!");
return false;
return;
}
if (!configFile.canRead()) {
Skript.error("Config file 'config.sk' cannot be read!");
return false;
return;
}
Config mc;

Config mainConfig;
try {
mc = new Config(configFile, false, false, ":");
} catch (final IOException e) {
Skript.error("Could not load the main config: " + e.getLocalizedMessage());
return false;
mainConfig = new Config(configFile, false, false, ":");
} catch (IOException ex) {
Skript.exception(ex, "Could not load the main config");
return;
}
mainConfig = mc;
SkriptConfig.mainConfig = mainConfig;

String configVersion = mc.get(version.key);
String configVersion = mainConfig.get(version.key);
if (configVersion == null || Skript.getVersion().compareTo(new Version(configVersion)) != 0) {
try {
final InputStream in = Skript.getInstance().getResource("config.sk");
if (in == null) {
if (!mainConfig.getMainNode().isValid()) {
Skript.error("Your config is outdated, but cannot be updated because it contains errors.");
return;
}

try (InputStream stream = Skript.getInstance().getResource("config.sk")) {
if (stream == null) {
Skript.error("Your config is outdated, but Skript couldn't find the newest config in its jar.");
return false;
}
final Config newConfig = new Config(in, "Skript.jar/config.sk", false, false, ":");
in.close();

boolean forceUpdate = false;

if (mc.getMainNode().get("database") != null) { // old database layout
forceUpdate = true;
try {
final SectionNode oldDB = (SectionNode) mc.getMainNode().get("database");
assert oldDB != null;
final SectionNode newDBs = (SectionNode) newConfig.getMainNode().get(databases.key);
assert newDBs != null;
final SectionNode newDB = (SectionNode) newDBs.get("database 1");
assert newDB != null;

newDB.setValues(oldDB);

// '.db' was dynamically added before
final String file = newDB.getValue("file");
assert file != null;
if (!file.endsWith(".db"))
newDB.set("file", file + ".db");

final SectionNode def = (SectionNode) newDBs.get("default");
assert def != null;
def.set("backup interval", "" + mc.get("variables backup interval"));
} catch (final Exception e) {
Skript.error("An error occurred while trying to update the config's database section.");
Skript.error("You'll have to update the config yourself:");
Skript.error("Open the new config.sk as well as the created backup, and move the 'database' section from the backup to the start of the 'databases' section");
Skript.error("of the new config (i.e. the line 'databases:' should be directly above 'database:'), and add a tab in front of every line that you just copied.");
return false;
}
return;
}

if (newConfig.setValues(mc, version.key, databases.key) || forceUpdate) { // new config is different
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little worried this behavior isn't maintained. Can you show the results of some tests with a config file updating from like, 2.4 -> 2.9.5 and likewise with 2.4->2.10? I'm not entirely sure how it worked tbh.

final File bu = FileUtils.backup(configFile);
newConfig.getMainNode().set(version.key, Skript.getVersion().toString());
if (mc.getMainNode().get(databases.key) != null)
newConfig.getMainNode().set(databases.key, mc.getMainNode().get(databases.key));
mc = mainConfig = newConfig;
mc.save(configFile);
Skript.info("Your configuration has been updated to the latest version. A backup of your old config file has been created as " + bu.getName());
} else { // only the version changed
mc.getMainNode().set(version.key, Skript.getVersion().toString());
mc.save(configFile);
Config newConfig = new Config(stream, "Skript.jar/config.sk", false, false, ":");

File backup = FileUtils.backup(configFile);
boolean updated = mainConfig.updateNodes(newConfig);
// mainConfig.getMainNode().set(version.key, Skript.getVersion().toString()); TODO FOR TESTING!
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just so i dont forget

mainConfig.save(configFile);
SkriptConfig.mainConfig = mainConfig;

if (updated) {
Skript.info("Your configuration has been updated to the latest version. " +
"A backup of your old config file has been created as " + backup.getName());
} else {
Skript.info("Your configuration is outdated, but no changes were performed. " +
"A backup of your config file has been created as " + backup.getName());
}
} catch (final IOException e) {
Skript.error("Could not load the new config from the jar file: " + e.getLocalizedMessage());
} catch (IOException ex) {
Skript.exception(ex, "Could not update the main config");
return;
}
}

mc.load(SkriptConfig.class);

// if (!keepConfigsLoaded.value())
// mainConfig = null;
} catch (final RuntimeException e) {
Skript.exception(e, "An error occurred while loading the config");
return false;

mainConfig.load(SkriptConfig.class);
} catch (RuntimeException ex) {
Skript.exception(ex, "An error occurred while loading the config");
}
return true;
}

}
Loading
Loading