Add option to merge into instead of overriding existing data in imports (#2324)

This commit is contained in:
Luck 2020-05-28 21:36:06 +01:00
parent 00b701f129
commit 25551641fc
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
8 changed files with 39 additions and 19 deletions

View File

@ -66,8 +66,9 @@ public class Importer implements Runnable {
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
private final Set<Sender> notify; private final Set<Sender> notify;
private final JsonObject data; private final JsonObject data;
private final boolean merge;
public Importer(LuckPermsPlugin plugin, Sender executor, JsonObject data) { public Importer(LuckPermsPlugin plugin, Sender executor, JsonObject data, boolean merge) {
this.plugin = plugin; this.plugin = plugin;
if (executor.isConsole()) { if (executor.isConsole()) {
@ -76,6 +77,7 @@ public class Importer implements Runnable {
this.notify = ImmutableSet.of(executor, plugin.getConsoleSender()); this.notify = ImmutableSet.of(executor, plugin.getConsoleSender());
} }
this.data = data; this.data = data;
this.merge = merge;
} }
private static final class UserData { private static final class UserData {
@ -92,7 +94,11 @@ public class Importer implements Runnable {
private void processGroup(String groupName, Set<Node> nodes) { private void processGroup(String groupName, Set<Node> nodes) {
Group group = this.plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join(); Group group = this.plugin.getStorage().createAndLoadGroup(groupName, CreationCause.INTERNAL).join();
if (this.merge) {
group.mergeNodes(DataType.NORMAL, nodes);
} else {
group.setNodes(DataType.NORMAL, nodes); group.setNodes(DataType.NORMAL, nodes);
}
this.plugin.getStorage().saveGroup(group); this.plugin.getStorage().saveGroup(group);
} }
@ -107,7 +113,11 @@ public class Importer implements Runnable {
if (userData.primaryGroup != null) { if (userData.primaryGroup != null) {
user.getPrimaryGroup().setStoredValue(userData.primaryGroup); user.getPrimaryGroup().setStoredValue(userData.primaryGroup);
} }
if (this.merge) {
user.mergeNodes(DataType.NORMAL, userData.nodes);
} else {
user.setNodes(DataType.NORMAL, userData.nodes); user.setNodes(DataType.NORMAL, userData.nodes);
}
this.plugin.getStorage().saveUser(user).join(); this.plugin.getStorage().saveUser(user).join();
this.plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId()); this.plugin.getUserManager().getHouseKeeper().cleanup(user.getUniqueId());
} }

View File

@ -74,7 +74,7 @@ public class GroupClone extends ChildCommand<Group> {
return CommandResult.NO_PERMISSION; return CommandResult.NO_PERMISSION;
} }
newGroup.replaceNodes(DataType.NORMAL, group.normalData().immutable()); newGroup.setNodes(DataType.NORMAL, group.normalData().immutable());
Message.CLONE_SUCCESS.send(sender, group.getName(), newGroup.getName()); Message.CLONE_SUCCESS.send(sender, group.getName(), newGroup.getName());

View File

@ -80,7 +80,7 @@ public class GroupRename extends ChildCommand<Group> {
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
newGroup.replaceNodes(DataType.NORMAL, group.normalData().immutable()); newGroup.setNodes(DataType.NORMAL, group.normalData().immutable());
Message.RENAME_SUCCESS.send(sender, group.getName(), newGroup.getName()); Message.RENAME_SUCCESS.send(sender, group.getName(), newGroup.getName());

View File

@ -53,7 +53,7 @@ public class ImportCommand extends SingleCommand {
private final AtomicBoolean running = new AtomicBoolean(false); private final AtomicBoolean running = new AtomicBoolean(false);
public ImportCommand(LocaleManager locale) { public ImportCommand(LocaleManager locale) {
super(CommandSpec.IMPORT.localize(locale), "Import", CommandPermission.IMPORT, Predicates.not(1)); super(CommandSpec.IMPORT.localize(locale), "Import", CommandPermission.IMPORT, Predicates.notInRange(1, 2));
} }
@Override @Override
@ -105,7 +105,7 @@ public class ImportCommand extends SingleCommand {
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
Importer importer = new Importer(plugin, sender, data); Importer importer = new Importer(plugin, sender, data, args.contains("--merge"));
// Run the importer in its own thread. // Run the importer in its own thread.
plugin.getBootstrap().getScheduler().executeAsync(() -> { plugin.getBootstrap().getScheduler().executeAsync(() -> {

View File

@ -73,7 +73,7 @@ public class UserClone extends ChildCommand<User> {
return CommandResult.NO_PERMISSION; return CommandResult.NO_PERMISSION;
} }
otherUser.replaceNodes(DataType.NORMAL, user.normalData().immutable()); otherUser.setNodes(DataType.NORMAL, user.normalData().immutable());
Message.CLONE_SUCCESS.send(sender, user.getFormattedDisplayName(), otherUser.getFormattedDisplayName()); Message.CLONE_SUCCESS.send(sender, user.getFormattedDisplayName(), otherUser.getFormattedDisplayName());

View File

@ -89,12 +89,14 @@ public enum CommandSpec {
NETWORK_SYNC("Sync changes with the storage and request that all other servers on the network do the same", "/%s networksync"), NETWORK_SYNC("Sync changes with the storage and request that all other servers on the network do the same", "/%s networksync"),
IMPORT("Imports data from a (previously created) export file", "/%s import <file>", IMPORT("Imports data from a (previously created) export file", "/%s import <file>",
Argument.list( Argument.list(
Argument.create("file", true, "the file to import from") Argument.create("file", true, "the file to import from"),
Argument.create("--merge", false, "merge import into existing data")
) )
), ),
EXPORT("Exports all permissions data to an 'export' file. Can be re-imported at a later time.", "/%s export <file>", EXPORT("Exports all permissions data to an 'export' file. Can be re-imported at a later time.", "/%s export <file>",
Argument.list( Argument.list(
Argument.create("file", true, "the file to export to") Argument.create("file", true, "the file to export to"),
Argument.create("--without-users", false, "exclude users from the export")
) )
), ),
RELOAD_CONFIG("Reload some of the config options", "/%s reloadconfig"), RELOAD_CONFIG("Reload some of the config options", "/%s reloadconfig"),

View File

@ -28,7 +28,6 @@ package me.lucko.luckperms.common.model;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import me.lucko.luckperms.common.cache.Cache; import me.lucko.luckperms.common.cache.Cache;
import me.lucko.luckperms.common.config.ConfigKeys; import me.lucko.luckperms.common.config.ConfigKeys;
@ -336,19 +335,23 @@ public final class NodeMap {
void setContent(Iterable<? extends Node> set) { void setContent(Iterable<? extends Node> set) {
this.map.clear(); this.map.clear();
this.inheritanceMap.clear(); this.inheritanceMap.clear();
for (Node n : set) { mergeContent(set);
add(n);
}
} }
void setContent(Stream<? extends Node> stream) { void setContent(Stream<? extends Node> stream) {
this.map.clear(); this.map.clear();
this.inheritanceMap.clear(); this.inheritanceMap.clear();
stream.forEach(this::add); mergeContent(stream);
} }
void setContent(Multimap<ImmutableContextSet, ? extends Node> multimap) { void mergeContent(Iterable<? extends Node> set) {
setContent(multimap.values()); for (Node n : set) {
add(n);
}
}
void mergeContent(Stream<? extends Node> stream) {
stream.forEach(this::add);
} }
boolean removeIf(Predicate<? super Node> predicate) { boolean removeIf(Predicate<? super Node> predicate) {

View File

@ -253,8 +253,13 @@ public abstract class PermissionHolder {
invalidateCache(); invalidateCache();
} }
public void replaceNodes(DataType type, Multimap<ImmutableContextSet, ? extends Node> multimap) { public void setNodes(DataType type, Multimap<ImmutableContextSet, ? extends Node> multimap) {
getData(type).setContent(multimap); getData(type).setContent(multimap.values());
invalidateCache();
}
public void mergeNodes(DataType type, Iterable<? extends Node> set) {
getData(type).mergeContent(set);
invalidateCache(); invalidateCache();
} }