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

View File

@ -74,7 +74,7 @@ public class GroupClone extends ChildCommand<Group> {
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());

View File

@ -80,7 +80,7 @@ public class GroupRename extends ChildCommand<Group> {
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());

View File

@ -53,7 +53,7 @@ public class ImportCommand extends SingleCommand {
private final AtomicBoolean running = new AtomicBoolean(false);
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
@ -105,7 +105,7 @@ public class ImportCommand extends SingleCommand {
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.
plugin.getBootstrap().getScheduler().executeAsync(() -> {

View File

@ -73,7 +73,7 @@ public class UserClone extends ChildCommand<User> {
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());

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"),
IMPORT("Imports data from a (previously created) export file", "/%s import <file>",
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>",
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"),

View File

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

View File

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