semi-auto cleanup
This commit is contained in:
1 parent
cad80f82c6
commit
8f61271606
99 files changed
+11463
-8007
No files matched your search
@@ -18,6 +18,7 @@ import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.commands.CommandRuntimeException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -40,22 +41,28 @@ import org.apache.commons.io.IOUtils;
|
||||
*/
|
||||
public class AppStoreManager
|
||||
{
|
||||
/** A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the
|
||||
/**
|
||||
* A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the
|
||||
* {@code /script download} command and getting the suggestions.
|
||||
*/
|
||||
private static StoreNode APP_STORE_ROOT = StoreNode.folder(null, "");
|
||||
|
||||
/** This is the base link to the scarpet app repo from the github api.
|
||||
/**
|
||||
* This is the base link to the scarpet app repo from the github api.
|
||||
*/
|
||||
private static String scarpetRepoLink = "https://api.github.com/repos/gnembon/scarpet/contents/programs/";
|
||||
|
||||
private static record AppInfo(String name, String url, StoreNode source) {}
|
||||
private record AppInfo(String name, String url, StoreNode source)
|
||||
{
|
||||
}
|
||||
|
||||
public static class ScarpetAppStoreValidator extends Validator<String>
|
||||
{
|
||||
@Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String stringInput)
|
||||
@Override
|
||||
public String validate(final CommandSourceStack source, final CarpetRule<String> currentRule, String newValue, final String stringInput)
|
||||
{
|
||||
if (newValue.equals(currentRule.value())) {
|
||||
if (newValue.equals(currentRule.value()))
|
||||
{
|
||||
// Don't refresh the local repo if it's the same (world change), helps preventing hitting rate limits from github when
|
||||
// getting suggestions. Pending is a way to invalidate the cache when it gets old, and investigating api usage further
|
||||
return newValue;
|
||||
@@ -66,12 +73,19 @@ public class AppStoreManager
|
||||
scarpetRepoLink = null;
|
||||
return newValue;
|
||||
}
|
||||
if (newValue.endsWith("/")) newValue = newValue.replaceAll("/$", "");
|
||||
scarpetRepoLink = "https://api.github.com/repos/"+newValue+"/";
|
||||
if (newValue.endsWith("/"))
|
||||
{
|
||||
newValue = newValue.replaceAll("/$", "");
|
||||
}
|
||||
scarpetRepoLink = "https://api.github.com/repos/" + newValue + "/";
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() { return "Appstore link should point to a valid github repository";}
|
||||
public String description()
|
||||
{
|
||||
return "Appstore link should point to a valid github repository";
|
||||
}
|
||||
}
|
||||
|
||||
public static class StoreNode
|
||||
@@ -81,18 +95,19 @@ public class AppStoreManager
|
||||
public Map<String, StoreNode> children;
|
||||
public boolean sealed;
|
||||
public String value;
|
||||
public static StoreNode folder(StoreNode parent, String name)
|
||||
|
||||
public static StoreNode folder(final StoreNode parent, final String name)
|
||||
{
|
||||
StoreNode node = new StoreNode(parent, name);
|
||||
final StoreNode node = new StoreNode(parent, name);
|
||||
node.children = new HashMap<>();
|
||||
node.value = null;
|
||||
node.sealed = false;
|
||||
return node;
|
||||
}
|
||||
|
||||
public static StoreNode scriptFile(StoreNode parent, String name, String value)
|
||||
public static StoreNode scriptFile(final StoreNode parent, final String name, final String value)
|
||||
{
|
||||
StoreNode node = new StoreNode(parent, name);
|
||||
final StoreNode node = new StoreNode(parent, name);
|
||||
node.children = null;
|
||||
node.value = value;
|
||||
node.sealed = true;
|
||||
@@ -103,19 +118,23 @@ public class AppStoreManager
|
||||
{
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public String pathElement()
|
||||
{
|
||||
return name+(isLeaf()?"":"/");
|
||||
return name + (isLeaf() ? "" : "/");
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return createPrePath().toString();
|
||||
}
|
||||
|
||||
private StringBuilder createPrePath()
|
||||
{
|
||||
return this == APP_STORE_ROOT ? new StringBuilder() : parent.createPrePath().append(pathElement());
|
||||
}
|
||||
private StoreNode(StoreNode parent, String name)
|
||||
|
||||
private StoreNode(final StoreNode parent, final String name)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
@@ -124,32 +143,38 @@ public class AppStoreManager
|
||||
|
||||
public synchronized void fillChildren() throws IOException
|
||||
{
|
||||
if (sealed) return;
|
||||
if (scarpetRepoLink == null) throw new IOException("Accessing scarpet app repo is disabled");
|
||||
if (sealed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (scarpetRepoLink == null)
|
||||
{
|
||||
throw new IOException("Accessing scarpet app repo is disabled");
|
||||
}
|
||||
|
||||
String queryPath = scarpetRepoLink + getPath();
|
||||
String response;
|
||||
final String queryPath = scarpetRepoLink + getPath();
|
||||
final String response;
|
||||
try
|
||||
{
|
||||
response = IOUtils.toString(new URL(queryPath), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
// Not sealing to allow retrying
|
||||
throw new IOException("Problems fetching " + queryPath, e);
|
||||
}
|
||||
JsonArray files = JsonParser.parseString(response).getAsJsonArray();
|
||||
for(JsonElement je : files)
|
||||
final JsonArray files = JsonParser.parseString(response).getAsJsonArray();
|
||||
for (final JsonElement je : files)
|
||||
{
|
||||
JsonObject jo = je.getAsJsonObject();
|
||||
String name = jo.get("name").getAsString();
|
||||
final JsonObject jo = je.getAsJsonObject();
|
||||
final String name = jo.get("name").getAsString();
|
||||
if (jo.get("type").getAsString().equals("dir"))
|
||||
{
|
||||
children.put(name, folder(this, name));
|
||||
}
|
||||
else// if (name.matches("(\\w+\\.scl?)"))
|
||||
{
|
||||
String value = jo.get("download_url").getAsString();
|
||||
final String value = jo.get("download_url").getAsString();
|
||||
children.put(name, scriptFile(this, name, value));
|
||||
}
|
||||
}
|
||||
@@ -159,12 +184,16 @@ public class AppStoreManager
|
||||
/**
|
||||
* Returns true if doing down the directory structire cannot continue since the matching element is either a leaf or
|
||||
* a string not matching of any node.
|
||||
*
|
||||
* @param pathElement
|
||||
* @return
|
||||
*/
|
||||
public boolean cannotContinueFor(String pathElement) throws IOException
|
||||
public boolean cannotContinueFor(final String pathElement) throws IOException
|
||||
{
|
||||
if (isLeaf()) return true;
|
||||
if (isLeaf())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
fillChildren();
|
||||
return !children.containsKey(pathElement);
|
||||
}
|
||||
@@ -173,120 +202,140 @@ public class AppStoreManager
|
||||
{
|
||||
if (isLeaf())
|
||||
{
|
||||
if (name.endsWith(".sc"))
|
||||
return Collections.singletonList(getPath());
|
||||
return Collections.emptyList();
|
||||
return name.endsWith(".sc") ? Collections.singletonList(getPath()) : Collections.emptyList();
|
||||
}
|
||||
fillChildren();
|
||||
String prefix = getPath();
|
||||
final String prefix = getPath();
|
||||
return children.values().stream().
|
||||
filter(n -> (!n.isLeaf() || n.name.endsWith(".sc"))).
|
||||
map(s -> prefix+s.pathElement().replaceAll("/$", "")).
|
||||
map(s -> prefix + s.pathElement().replaceAll("/$", "")).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public StoreNode drillDown(String pathElement) throws IOException
|
||||
public StoreNode drillDown(final String pathElement) throws IOException
|
||||
{
|
||||
if (isLeaf()) throw new IOException(pathElement+" is not a folder");
|
||||
if (isLeaf())
|
||||
{
|
||||
throw new IOException(pathElement + " is not a folder");
|
||||
}
|
||||
fillChildren();
|
||||
if (!children.containsKey(pathElement)) throw new IOException("Folder "+pathElement+" is not present");
|
||||
if (!children.containsKey(pathElement))
|
||||
{
|
||||
throw new IOException("Folder " + pathElement + " is not present");
|
||||
}
|
||||
return children.get(pathElement);
|
||||
}
|
||||
|
||||
public String getValue(String file) throws IOException
|
||||
public String getValue(final String file) throws IOException
|
||||
{
|
||||
StoreNode leaf = drillDown(file);
|
||||
if (!leaf.isLeaf()) throw new IOException(file+" is not a file");
|
||||
final StoreNode leaf = drillDown(file);
|
||||
if (!leaf.isLeaf())
|
||||
{
|
||||
throw new IOException(file + " is not a file");
|
||||
}
|
||||
return leaf.value;
|
||||
}
|
||||
}
|
||||
|
||||
/** This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed
|
||||
/**
|
||||
* This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed
|
||||
* {@code survival/a} then it will return all the files in the {@code survival} directory of the scarpet repo (and
|
||||
* will automatically highlight those starting with a), and the string {@code survival/} as the current most valid path.
|
||||
*
|
||||
* @param currentPath The path down which we want to search for files
|
||||
* @return A pair of the current valid path, as well as the set of all the file/directory names at the end of that path
|
||||
*/
|
||||
public static List<String> suggestionsFromPath(String currentPath) throws IOException
|
||||
public static List<String> suggestionsFromPath(final String currentPath) throws IOException
|
||||
{
|
||||
String[] path = currentPath.split("/");
|
||||
final String[] path = currentPath.split("/");
|
||||
StoreNode appKiosk = APP_STORE_ROOT;
|
||||
for(String pathElement : path)
|
||||
for (final String pathElement : path)
|
||||
{
|
||||
if (appKiosk.cannotContinueFor(pathElement)) break;
|
||||
if (appKiosk.cannotContinueFor(pathElement))
|
||||
{
|
||||
break;
|
||||
}
|
||||
appKiosk = appKiosk.children.get(pathElement);
|
||||
}
|
||||
List<String> filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList());
|
||||
if (filteredSuggestions.size() == 1) {
|
||||
final List<String> filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList());
|
||||
if (filteredSuggestions.size() == 1)
|
||||
{
|
||||
if (!appKiosk.isLeaf())
|
||||
{
|
||||
return suggestionsFromPath(filteredSuggestions.get(0)); // Start suggesting directory contents
|
||||
}
|
||||
}
|
||||
return filteredSuggestions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Downloads script and saves it to appropriate place.
|
||||
/**
|
||||
* Downloads script and saves it to appropriate place.
|
||||
*
|
||||
* @param path The user-inputted path to the script
|
||||
* @return {@code 1} if we succesfully saved the script, {@code 0} otherwise
|
||||
*/
|
||||
|
||||
public static int downloadScript(CommandSourceStack source, String path)
|
||||
public static int downloadScript(final CommandSourceStack source, final String path)
|
||||
{
|
||||
AppInfo nodeInfo = getFileNode(path);
|
||||
final AppInfo nodeInfo = getFileNode(path);
|
||||
return downloadScript(source, path, nodeInfo, false);
|
||||
}
|
||||
|
||||
private static int downloadScript(CommandSourceStack source, String path, AppInfo nodeInfo, boolean useTrash)
|
||||
private static int downloadScript(final CommandSourceStack source, final String path, final AppInfo nodeInfo, final boolean useTrash)
|
||||
{
|
||||
String code;
|
||||
final String code;
|
||||
try
|
||||
{
|
||||
code = IOUtils.toString(new URL(nodeInfo.url()), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: "+e.getMessage()));
|
||||
throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: " + e.getMessage()));
|
||||
}
|
||||
if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash)) return 0;
|
||||
boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source());
|
||||
return success?1:0;
|
||||
if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
final boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source());
|
||||
return success ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Gets the code once the user inputs the command.
|
||||
/**
|
||||
* Gets the code once the user inputs the command.
|
||||
*
|
||||
* @param appPath The user inputted path to the scarpet script
|
||||
* @return Pair of app file name and content
|
||||
*/
|
||||
public static AppInfo getFileNode(String appPath)
|
||||
public static AppInfo getFileNode(final String appPath)
|
||||
{
|
||||
return getFileNodeFrom(APP_STORE_ROOT, appPath);
|
||||
}
|
||||
|
||||
public static AppInfo getFileNodeFrom(StoreNode start, String appPath)
|
||||
public static AppInfo getFileNodeFrom(final StoreNode start, final String appPath)
|
||||
{
|
||||
String[] path = appPath.split("/");
|
||||
final String[] path = appPath.split("/");
|
||||
StoreNode appKiosk = start;
|
||||
try
|
||||
{
|
||||
for(String pathElement : Arrays.copyOfRange(path, 0, path.length-1))
|
||||
for (final String pathElement : Arrays.copyOfRange(path, 0, path.length - 1))
|
||||
{
|
||||
appKiosk = appKiosk.drillDown(pathElement);
|
||||
String appName = path[path.length-1];
|
||||
}
|
||||
final String appName = path[path.length - 1];
|
||||
appKiosk.getValue(appName);
|
||||
return new AppInfo(appName, appKiosk.getValue(appName), appKiosk);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new CommandRuntimeException(Messenger.c("rb '"+ appPath + "' is not a valid path to a scarpet app: "+e.getMessage()));
|
||||
throw new CommandRuntimeException(Messenger.c("rb '" + appPath + "' is not a valid path to a scarpet app: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean saveScriptToFile(CommandSourceStack source, String path, String appFileName, String code, boolean globalSavePath, boolean useTrash)
|
||||
public static boolean saveScriptToFile(final CommandSourceStack source, final String path, final String appFileName, final String code, final boolean globalSavePath, final boolean useTrash)
|
||||
{
|
||||
Path scriptLocation;
|
||||
final Path scriptLocation;
|
||||
if (globalSavePath && !source.getServer().isDedicatedServer()) // never happens, this is always called with globalSavePath being false
|
||||
{ //cos config folder only is in clients
|
||||
scriptLocation = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts/appstore").toAbsolutePath().resolve(path);
|
||||
@@ -307,29 +356,29 @@ public class AppStoreManager
|
||||
int i = 0;
|
||||
while (Files.exists(trashPath))
|
||||
{
|
||||
String[] nameAndExtension = appFileName.split("\\.");
|
||||
String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1],i);
|
||||
final String[] nameAndExtension = appFileName.split("\\.");
|
||||
final String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1], i);
|
||||
trashPath = trashPath.getParent().resolve(newFileName);
|
||||
i++;
|
||||
}
|
||||
Files.move(scriptLocation, trashPath);
|
||||
}
|
||||
Messenger.m(source, String.format("gi Note: replaced existing app '%s'"+(useTrash ? " (old moved to /trash folder)" : ""), appFileName));
|
||||
Messenger.m(source, String.format("gi Note: replaced existing app '%s'" + (useTrash ? " (old moved to /trash folder)" : ""), appFileName));
|
||||
}
|
||||
BufferedWriter writer = Files.newBufferedWriter(scriptLocation);
|
||||
final BufferedWriter writer = Files.newBufferedWriter(scriptLocation);
|
||||
writer.write(code);
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
Messenger.m(source, "r Error while downloading app: " + e.toString());
|
||||
Messenger.m(source, "r Error while downloading app: " + e);
|
||||
CarpetScriptServer.LOG.warn("Error while downloading app", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void writeUrlToFile(String url, Path destination) throws IOException
|
||||
public static void writeUrlToFile(final String url, final Path destination) throws IOException
|
||||
{
|
||||
try (final InputStream in = new URL(url).openStream())
|
||||
{
|
||||
@@ -337,88 +386,112 @@ public class AppStoreManager
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFullContentUrl(String original, StoreNode storeSource)
|
||||
private static String getFullContentUrl(final String original, final StoreNode storeSource)
|
||||
{
|
||||
if (original.matches("^https?://.*$")) // We've got a full url here: Just use it
|
||||
{
|
||||
return original;
|
||||
}
|
||||
if (original.charAt(0) == '/') // We've got an absolute path: Use app store root
|
||||
{
|
||||
return getFileNode(original.substring(1)).url();
|
||||
}
|
||||
return getFileNodeFrom(storeSource, original).url(); // Relative path: Use download location
|
||||
}
|
||||
|
||||
public static void addResource(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value resource)
|
||||
public static void addResource(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value resource)
|
||||
{
|
||||
if (!(resource instanceof MapValue))
|
||||
throw new InternalExpressionException("This is not a valid resource map: "+resource.getString());
|
||||
Map<String, Value> resourceMap = ((MapValue) resource).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
||||
if (!resourceMap.containsKey("source")) throw new InternalExpressionException("Missing 'source' field in resource descriptor: "+resource.getString());
|
||||
String source = resourceMap.get("source").getString();
|
||||
String contentUrl = getFullContentUrl(source, storeSource);
|
||||
String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString();
|
||||
boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean();
|
||||
if (!(resource instanceof final MapValue map))
|
||||
{
|
||||
throw new InternalExpressionException("This is not a valid resource map: " + resource.getString());
|
||||
}
|
||||
final Map<String, Value> resourceMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
||||
if (!resourceMap.containsKey("source"))
|
||||
{
|
||||
throw new InternalExpressionException("Missing 'source' field in resource descriptor: " + resource.getString());
|
||||
}
|
||||
final String source = resourceMap.get("source").getString();
|
||||
final String contentUrl = getFullContentUrl(source, storeSource);
|
||||
final String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString();
|
||||
final boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean();
|
||||
|
||||
if (!carpetScriptHost.applyActionForResource(target, shared, p -> {
|
||||
try {
|
||||
try
|
||||
{
|
||||
writeUrlToFile(contentUrl, p);
|
||||
} catch (IOException e) {
|
||||
throw new InternalExpressionException("Unable to write resource "+target+": "+e.toString());
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new InternalExpressionException("Unable to write resource " + target + ": " + e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
throw new InternalExpressionException("Unable to write resource "+target);
|
||||
throw new InternalExpressionException("Unable to write resource " + target);
|
||||
}
|
||||
CarpetScriptServer.LOG.info("Downloaded resource "+target+" from "+contentUrl);
|
||||
CarpetScriptServer.LOG.info("Downloaded resource " + target + " from " + contentUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new StoreNode for an app's dependency with proper relativeness. Will be null if it comes from an external URL
|
||||
*
|
||||
* @param originalSource The StoreNode from the container's app
|
||||
* @param sourceString The string the app specified as source
|
||||
* @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)}
|
||||
* @param sourceString The string the app specified as source
|
||||
* @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)}
|
||||
* @return A {@link StoreNode} that can be used in an app that came from the provided source
|
||||
*/
|
||||
private static StoreNode getNewStoreNode(StoreNode originalSource, String sourceString, String contentUrl)
|
||||
private static StoreNode getNewStoreNode(final StoreNode originalSource, String sourceString, final String contentUrl)
|
||||
{
|
||||
StoreNode next = originalSource;
|
||||
if (sourceString == contentUrl) // External URL (check getFullUrlContent)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (sourceString.charAt(0) == '/') // Absolute URL
|
||||
{
|
||||
next = APP_STORE_ROOT;
|
||||
sourceString = sourceString.substring(1);
|
||||
}
|
||||
String[] dirs = sourceString.split("/");
|
||||
final String[] dirs = sourceString.split("/");
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < dirs.length - 1; i++)
|
||||
{
|
||||
next = next.drillDown(dirs[i]);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
return null; // Should never happen, but let's not give a potentially incorrect node just in case
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
public static void addLibrary(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value library) {
|
||||
if (!(library instanceof MapValue))
|
||||
throw new InternalExpressionException("This is not a valid library map: "+library.getString());
|
||||
Map<String, String> libraryMap = ((MapValue) library).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString()));
|
||||
String source = libraryMap.get("source");
|
||||
String contentUrl = getFullContentUrl(source, storeSource);
|
||||
String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1));
|
||||
public static void addLibrary(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value library)
|
||||
{
|
||||
if (!(library instanceof final MapValue map))
|
||||
{
|
||||
throw new InternalExpressionException("This is not a valid library map: " + library.getString());
|
||||
}
|
||||
final Map<String, String> libraryMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString()));
|
||||
final String source = libraryMap.get("source");
|
||||
final String contentUrl = getFullContentUrl(source, storeSource);
|
||||
final String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1));
|
||||
if (!(contentUrl.endsWith(".sc") || contentUrl.endsWith(".scl")))
|
||||
{
|
||||
throw new InternalExpressionException("App resource type must download a scarpet app or library.");
|
||||
}
|
||||
if (target.indexOf('/') != -1)
|
||||
{
|
||||
throw new InternalExpressionException("App resource tried to leave script reserved space");
|
||||
}
|
||||
try
|
||||
{
|
||||
downloadScript(carpetScriptHost.responsibleSource, target, new AppInfo(target, contentUrl, getNewStoreNode(storeSource, source, contentUrl)), true);
|
||||
}
|
||||
catch (CommandRuntimeException e)
|
||||
catch (final CommandRuntimeException e)
|
||||
{
|
||||
throw new InternalExpressionException("Error when installing app dependencies: " + e.toString());
|
||||
throw new InternalExpressionException("Error when installing app dependencies: " + e);
|
||||
}
|
||||
CarpetScriptServer.LOG.info("Downloaded app "+target+" from "+contentUrl);
|
||||
CarpetScriptServer.LOG.info("Downloaded app " + target + " from " + contentUrl);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user