From 0d47b8de34935b4baee7b5a580faf1daaef9ac75 Mon Sep 17 00:00:00 2001 From: Cervator Date: Fri, 29 Oct 2021 22:40:24 -0500 Subject: [PATCH 1/2] feat: upgrade the groovyw system to be closer in sync with Terasology --- config/groovy/common.groovy | 292 +++++++++++++++++++++++------- config/groovy/lib.groovy | 43 +++++ config/groovy/module.groovy | 50 ++++- config/groovy/util.groovy | 192 +++++++++++++------- gradle/wrapper/groovy-wrapper.jar | Bin 5142 -> 5280 bytes groovyw | 57 +++--- groovyw.bat | 31 +++- templates/build.gradle | 4 +- 8 files changed, 508 insertions(+), 161 deletions(-) create mode 100644 config/groovy/lib.groovy diff --git a/config/groovy/common.groovy b/config/groovy/common.groovy index 59db8312c..f8ae06053 100644 --- a/config/groovy/common.groovy +++ b/config/groovy/common.groovy @@ -1,9 +1,17 @@ import groovy.json.JsonSlurper -@GrabResolver(name = 'grgit-backup', root = 'https://ajoberstar.github.io/bintray-backup/') +@Grab(group = 'org.slf4j', module = 'slf4j-api', version = '1.6.1') +@Grab(group = 'org.slf4j', module = 'slf4j-nop', version = '1.6.1') + +// TODO: Temp replacement for jcenter, grgit is not in MavenCentral yet +@GrabResolver(name = 'ajoberstar-backup', root = 'https://ajoberstar.github.io/bintray-backup/') @Grab(group = 'org.ajoberstar', module = 'grgit', version = '1.9.3') import org.ajoberstar.grgit.Grgit +import org.ajoberstar.grgit.exception.GrgitException import org.ajoberstar.grgit.Remote +import org.eclipse.jgit.errors.RepositoryNotFoundException + +import static Ansi.* class common { @@ -22,7 +30,7 @@ class common { /** The clean human readable name for the type */ def itemType - /** Things we don't want to retrieve/update as they live in the main MovingBlocks/Terasology repo */ + /** Things we don't want to retrieve/update */ def excludedItems /** For keeping a list of items retrieved so far */ @@ -93,13 +101,10 @@ class common { */ def retrieve(String[] items, boolean recurse) { println "Now inside retrieve, user (recursively? $recurse) wants: $items" - for (String itemName: items) { + for (String itemName : items) { println "Starting retrieval for $itemType $itemName, are we recursing? $recurse" - if (itemsRetrieved.size() > 0) { - println "So far we've processed: $itemsRetrieved" - } + println "Retrieved so far: $itemsRetrieved" retrieveItem(itemName, recurse) - println "Done retrieving $itemName" } } @@ -117,34 +122,21 @@ class common { } else if (itemsRetrieved.contains(itemName)) { println "We already retrieved $itemName - skipping" } else { + itemsRetrieved << itemName def targetUrl = "https://github.com/${githubTargetHome}/${itemName}" - def failUrl = "https://github.com/${githubDefaultHome}/${itemName}" - def failed = false; - - if (!isUrlValid(targetUrl)) { - println "Can't retrieve $itemType from $targetUrl - URL appears invalid. Typo? Not created yet?" - - if (isUrlValid(failUrl)) { - println "Failed to retrieve $itemType $itemName, failing over to default modules repository." - Grgit.clone dir: targetDir, uri: failUrl - itemsRetrieved << itemName - failed = true - } else { - println "$itemType $itemName does not exist in $githubDefaultHome. Failed to retrieve $itemName." - return - } - } - - if (githubTargetHome != githubDefaultHome && !failed) { + try { println "Retrieving $itemType $itemName from $targetUrl" - println "Doing a retrieve from a custom remote: $githubTargetHome - will name it as such plus add the $githubDefaultHome remote as '$defaultRemote'" - Grgit.clone dir: targetDir, uri: targetUrl, remote: githubTargetHome - println "Primary clone operation complete, about to add the '$defaultRemote' remote for the $githubDefaultHome org address" - addRemote(itemName, defaultRemote, "https://github.com/${githubDefaultHome}/${itemName}") - itemsRetrieved << itemName - } else if (!failed) { - Grgit.clone dir: targetDir, uri: targetUrl - itemsRetrieved << itemName + if (githubTargetHome != githubDefaultHome) { + println "Doing a retrieve from a custom remote: $githubTargetHome - will name it as such plus add the $githubDefaultHome remote as '$defaultRemote'" + Grgit.clone dir: targetDir, uri: targetUrl, remote: githubTargetHome + println "Primary clone operation complete, about to add the '$defaultRemote' remote for the $githubDefaultHome org address" + addRemote(itemName, defaultRemote, "https://github.com/${githubDefaultHome}/${itemName}") + } else { + Grgit.clone dir: targetDir, uri: targetUrl + } + } catch (GrgitException exception) { + println color("Unable to clone $itemName, Skipping: ${exception.getMessage()}", Ansi.RED) + return } // This step allows the item type to check the newly cloned item and add in extra template stuff @@ -180,9 +172,6 @@ class common { println "Creating target directory" targetDir.mkdir() - // TODO: For Terasology modules this happens automatically, but DS modules don't have that logic yet. Review when they do - itemTypeScript.createDirectoryStructure(targetDir) - // For now everything gets the same .gitignore, but beyond that defer to the itemType for specifics println "Creating .gitignore" File gitignore = new File(targetDir, ".gitignore") @@ -195,38 +184,103 @@ class common { addRemote(itemName, defaultRemote, "https://github.com/${githubDefaultHome}/${itemName}.git") } + /** + * Check if an item was updated within the provided time limit + * @param file the item's FETCH_HEAD file in the .git directory + * @param timeLimit the time limit for considering something recently updated, for example: use(groovy.time.TimeCategory){ 10.minute } + */ + def isRecentlyUpdated(File file, def timeLimit){ + Date lastUpdate = new Date(file.lastModified()) + def recentlyUpdated = use(groovy.time.TimeCategory){ + def timeElapsedSinceUpdate = new Date() - lastUpdate + if (timeElapsedSinceUpdate < timeLimit){ + return true + } else { + return false + } + } + } + /** * Update a given item. * @param itemName the name of the item to update */ - def updateItem(String itemName) { - println "Attempting to update $itemType $itemName" + def updateItem(String itemName, boolean skipRecentUpdates = false) { File targetDir = new File(targetDirectory, itemName) - if (!targetDir.exists()) { - println "$itemType \"$itemName\" not found" + if (!Character.isLetterOrDigit(itemName.charAt(0))){ + println color ("Skipping update for $itemName: starts with non-alphanumeric symbol", Ansi.YELLOW) return } - def itemGit = Grgit.open(dir: targetDir) - - // Do a check for the default remote before we attempt to update - def remotes = itemGit.remote.list() - def targetUrl = remotes.find{ - it.name == defaultRemote - }?.url - if (targetUrl == null || !isUrlValid(targetUrl)) { - println "While updating $itemName found its '$defaultRemote' remote invalid or its URL unresponsive: $targetUrl" + if (!targetDir.exists()) { + println color("$itemType \"$itemName\" not found", Ansi.RED) return } + try { + def itemGit = Grgit.open(dir: targetDir) + + // Do a check for the default remote before we attempt to update + def remotes = itemGit.remote.list() + def targetUrl = remotes.find { + it.name == defaultRemote + }?.url + if (targetUrl == null) { + println color("While updating $itemName remote `$defaultRemote` is not found.", Ansi.RED) + return + } - // At this point we should have a valid remote to pull from. If local repo is clean then pull! - def clean = itemGit.status().clean - println "Is \"$itemName\" clean? $clean" - if (!clean) { - println "$itemType has uncommitted changes. Aborting." - return + // At this point we should have a valid remote to pull from. If local repo is clean then pull! + def clean = itemGit.status().clean + def branchName = itemGit.branch.getCurrent().fullName + + print "$itemType '$itemName' [$branchName]: " + + if (!clean) { + println color("uncommitted changes. Skipping.", Ansi.YELLOW) + } else { + println color("updating $itemType $itemName", Ansi.GREEN) + + File targetDirFetchHead = new File("$targetDir/.git/FETCH_HEAD") + if (targetDirFetchHead.exists()){ + // If the FETCH_HEAD has been modified within time limit and -skip-recently-updated flag was passed, skip updating + def timeLimit = use(groovy.time.TimeCategory){ 10.minute } + if (skipRecentUpdates && isRecentlyUpdated(targetDirFetchHead, timeLimit)){ + println color("Skipping update for $itemName: updated within last $timeLimit", Ansi.YELLOW) + return + } + // Always update modified time for FETCH_HEAD if it exists + targetDirFetchHead.setLastModified(new Date().getTime()) + } + + try { + def current_sha = itemGit.log(maxCommits: 1).find().getAbbreviatedId(8) + itemGit.pull remote: defaultRemote + def post_update_sha = itemGit.log(maxCommits: 1).find().getAbbreviatedId(8) + + if (current_sha != post_update_sha){ + // TODO this can be probably converted to do one composite diff of the full update + // once this PR is merged for grgit: https://github.com/ajoberstar/grgit/pull/318 + println color("Updating $current_sha..$post_update_sha", Ansi.GREEN) + def commits = itemGit.log {range(current_sha, post_update_sha)} + for (commit in commits){ + println("----${commit.getAbbreviatedId(8)}----") + def diff = itemGit.show(commit: commit.id) + print("added: ${diff.added.size()}, ") + print("copied: ${diff.copied.size()}, ") + print("modified: ${diff.modified.size()}, ") + print("removed: ${diff.removed.size()}, ") + println("renamed: ${diff.renamed.size()}") + } + print("\n") + } else { + println color ("No changes found", Ansi.YELLOW) + } + } catch (GrgitException exception) { + println color("Unable to update $itemName, Skipping: ${exception.getMessage()}", Ansi.RED) + } + } + } catch (RepositoryNotFoundException exception) { + println color("Skipping update for $itemName: no repository found (probably engine module)", Ansi.LIGHT_YELLOW) } - println "Updating $itemType $itemName" - itemGit.pull remote: defaultRemote } /** @@ -241,7 +295,7 @@ class common { def remoteGit = Grgit.open(dir: "${targetDirectory}/${itemName}") def remote = remoteGit.remote.list() def index = 1 - for (Remote item: remote) { + for (Remote item : remote) { println(index + " " + item.name + " (" + item.url + ")") index++ } @@ -293,7 +347,8 @@ class common { println "Added the remote '$remoteName' for $itemType '$itemName' - but the URL $url failed a test lookup. Typo? Not created yet?" } } else { - println "Remote already exists" + println "Remote already exists, fetching latest" + remoteGit.fetch remote: remoteName } } @@ -323,13 +378,17 @@ class common { * @return a String[] containing the names of items available for download. */ String[] retrieveAvailableItems() { + if (itemListCached) { + return cachedItemList + } // TODO: We need better ways to display the result especially when it contains a lot of items // However, in some cases heavy filtering could still mean that very few items will actually display ... // Another consideration is if we should be more specific in the API request, like only retrieving name + description - def githubHomeApiUrl = "https://api.github.com/users/$githubTargetHome/repos?per_page=100" + def githubHomeApiUrl = "https://api.github.com/users/$githubTargetHome/repos?per_page=99" + //Note: 99 instead of 100 - see TODO below .. - if(!isUrlValid(githubHomeApiUrl)){ + if (!isUrlValid(githubHomeApiUrl)) { println "Deduced GitHub API URL $githubHomeApiUrl seems inaccessible." return [] } @@ -339,17 +398,26 @@ class common { def currentPageUrl = githubHomeApiUrl def slurper = new JsonSlurper() while (currentPageUrl) { + //println "currentPageUrl: $currentPageUrl" new URL(currentPageUrl).openConnection().with { connection -> connection.content.withReader { reader -> slurper.parseText(reader.text).each { item -> mappedPossibleItems.put(item.name, item.description) + //println "Want to get item " + item.name } } currentPageUrl = getLink(connection, "next") + // TODO: This comparison is vulnerable to a page request size of "100" or anything that starts with a 1, but just using 99 above .. + if (currentPageUrl.contains("page=1")) { + //println "The pagination warped back to page 1, we're done!" + currentPageUrl = null + } } } - return itemTypeScript.filterItemsFromApi(mappedPossibleItems) + String[] items = itemTypeScript.filterItemsFromApi(mappedPossibleItems) + + return items; } /** @@ -408,12 +476,12 @@ class common { * Retrieves all the downloaded items in the form of a list. * @return a String[] containing the names of downloaded items. */ - String[] retrieveLocalItems(){ - def localItems =[] + String[] retrieveLocalItems() { + def localItems = [] targetDirectory.eachDir() { dir -> String itemName = dir.getName() // Don't consider excluded items - if(!(excludedItems.contains(itemName))){ + if (!(excludedItems.contains(itemName))) { localItems << itemName } } @@ -421,11 +489,103 @@ class common { } void cacheItemList() { - cachedItemList = retrieveAvailableItems() + if (!itemListCached) { + cachedItemList = retrieveAvailableItems() + } itemListCached = true } void unCacheItemList() { itemListCached = false } + + void writeDependencyDotFileForModule(File dependencyFile, File module) { + if (module.name.contains(".")) { + println "\"" + module.name + "\" is not a valid source (non-jar) module - skipping" + } else if (itemsRetrieved.contains(module.name)) { + println "Module \"" + module.name + "\" was already handled - skipping" + } else if (!module.exists()) { + println "Module \"" + module.name + "\" is not locally available - skipping" + itemsRetrieved << module.name + } else { + def foundDependencies = itemTypeScript.findDependencies(module, false) + if (foundDependencies.length == 0) { + // if no other dependencies exist, depend on engine + dependencyFile.append(" \"" + module.name + "\" -> \"engine\"\n") + itemsRetrieved << module.name + } else { + // add each of $foundDependencies as item -> foundDependency lines + for (dependency in foundDependencies) { + dependencyFile.append(" \"" + module.name + "\" -> \"$dependency\"\n") + } + itemsRetrieved << module.name + + // find dependencies to progress with + String[] uniqueDependencies = foundDependencies - itemsRetrieved + if (uniqueDependencies.length > 0) { + for (dependency in uniqueDependencies) { + writeDependencyDotFileForModule(dependencyFile, new File("modules/$dependency")) + } + } + } + } + } + + def refreshGradle() { + def localItems = [] + targetDirectory.eachDir() { dir -> + String itemName = dir.getName() + // Don't consider excluded items + if (!(excludedItems.contains(itemName))) { + localItems << itemName + } else { + println "Skipping $dir as it is in the exclude list" + } + } + + for (String item : localItems) { + itemTypeScript.refreshGradle(new File(targetDirectory, item)) + } + } +} + +/** + * Small ANSI coloring utility. + * @see https://gist.github.com/tvinke/db4d21dfdbdae49e6f92dcf1ca6120de + * @see http://www.bluesock.org/~willg/dev/ansi.html + * @see https://gist.github.com/dainkaplan/4651352 + */ +class Ansi { + + static final String NORMAL = "\u001B[0m" + + static final String BOLD = "\u001B[1m" + static final String ITALIC = "\u001B[3m" + static final String UNDERLINE = "\u001B[4m" + static final String BLINK = "\u001B[5m" + static final String RAPID_BLINK = "\u001B[6m" + static final String REVERSE_VIDEO = "\u001B[7m" + static final String INVISIBLE_TEXT = "\u001B[8m" + + static final String BLACK = "\u001B[30m" + static final String RED = "\u001B[31m" + static final String GREEN = "\u001B[32m" + static final String YELLOW = "\u001B[33m" + static final String BLUE = "\u001B[34m" + static final String MAGENTA = "\u001B[35m" + static final String CYAN = "\u001B[36m" + static final String WHITE = "\u001B[37m" + + static final String DARK_GRAY = "\u001B[1;30m" + static final String LIGHT_RED = "\u001B[1;31m" + static final String LIGHT_GREEN = "\u001B[1;32m" + static final String LIGHT_YELLOW = "\u001B[1;33m" + static final String LIGHT_BLUE = "\u001B[1;34m" + static final String LIGHT_PURPLE = "\u001B[1;35m" + static final String LIGHT_CYAN = "\u001B[1;36m" + + static String color(String text, String ansiValue) { + ansiValue + text + NORMAL + } + } diff --git a/config/groovy/lib.groovy b/config/groovy/lib.groovy new file mode 100644 index 000000000..d3a1ebc9d --- /dev/null +++ b/config/groovy/lib.groovy @@ -0,0 +1,43 @@ + +class lib { + + def excludedItems = [] + + def getGithubDefaultHome(Properties properties) { + return properties.alternativeGithubHome ?: "MovingBlocks" + } + + File targetDirectory = new File("libs") + def itemType = "library" + + // Libs currently do not care about dependencies + String[] findDependencies(File targetDir) { + return [] + } + + // TODO: Libs don't copy anything in yet .. they might be too unique. Some may Gradle stuff but not all (like the Index) + def copyInTemplateFiles(File targetDir) { + + } + + /** + * Filters the given items based on this item type's preferences + * @param possibleItems A map of repos (possible items) and their descriptions (potential filter data) + * @return A list containing only the items this type cares about + */ + List filterItemsFromApi(Map possibleItems) { + List itemList = [] + + // Libs only includes repos found to have a particular string snippet in their description + // TODO: Consideration for libraries - generic vs project specific? TeraMath could be used in DestSol etc ... + itemList = possibleItems.findAll { + it.value?.contains("Automation category: Terasology Library") + }.collect {it.key} + + return itemList + } + + def refreshGradle(File targetDir) { + println "Skipping refreshGradle for lib $targetDir- they vary too much to use any Gradle templates" + } +} diff --git a/config/groovy/module.groovy b/config/groovy/module.groovy index 7eab64464..200c66cdd 100644 --- a/config/groovy/module.groovy +++ b/config/groovy/module.groovy @@ -1,8 +1,23 @@ +/* + * Copyright 2020 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import groovy.json.JsonSlurper class module { - - def excludedItems = ["core", "DestinationSol.github.io"] + def excludedItems = ["engine", "core", "out", "build", "DestinationSol.github.io"] def getGithubDefaultHome(Properties properties) { return properties.alternativeGithubHome ?: "DestinationSol" @@ -11,8 +26,8 @@ class module { File targetDirectory = new File("modules") def itemType = "module" - String[] findDependencies(File targetDir) { - def foundDependencies = readModuleDependencies(new File(targetDir, "module.json")) + String[] findDependencies(File targetDir, boolean respectExcludedItems = true) { + def foundDependencies = readModuleDependencies(new File(targetDir, "module.json"), respectExcludedItems) println "Looked for dependencies, found: " + foundDependencies return foundDependencies } @@ -20,10 +35,10 @@ class module { /** * Reads a given module info file to figure out which if any dependencies it has. Filters out any already retrieved. * This method is only for modules. - * @param targetModuleInfo the target file to check (a module.txt file or similar) + * @param targetModuleInfo the target file to check (a module.json file or similar) * @return a String[] containing the next level of dependencies, if any */ - String[] readModuleDependencies(File targetModuleInfo) { + String[] readModuleDependencies(File targetModuleInfo, boolean respectExcludedItems = true) { def qualifiedDependencies = [] if (!targetModuleInfo.exists()) { println "The module info file did not appear to exist - can't calculate dependencies" @@ -32,7 +47,7 @@ class module { def slurper = new JsonSlurper() def moduleConfig = slurper.parseText(targetModuleInfo.text) for (dependency in moduleConfig.dependencies) { - if (excludedItems.contains(dependency.id)) { + if (respectExcludedItems && excludedItems.contains(dependency.id)) { println "Skipping listed dependency $dependency.id as it is in the exclude list (shipped with primary project)" } else { println "Accepting listed dependency $dependency.id" @@ -43,12 +58,19 @@ class module { } def copyInTemplateFiles(File targetDir) { + // Copy in the template build.gradle for modules + println "In copyInTemplateFiles for module $targetDir.name - copying in a build.gradle then next checking for module.json" + File targetBuildGradle = new File(targetDir, 'build.gradle') + targetBuildGradle.delete() + targetBuildGradle << new File('templates/build.gradle').text + // Copy in the template module.json for modules (if one doesn't exist yet) File moduleManifest = new File(targetDir, 'module.json') if (!moduleManifest.exists()) { def moduleText = new File("templates/module.json").text + moduleManifest << moduleText.replaceAll('MODULENAME', targetDir.name) - println "WARNING: Module ${targetDir.name} did not have a module.json! One was created, please review and submit to GitHub" + println "WARNING: the module ${targetDir.name} did not have a module.json! One was created, please review and submit to GitHub" } // Always use the latest build.gradle @@ -90,4 +112,16 @@ class module { return itemList } + + def refreshGradle(File targetDir) { + // Copy in the template build.gradle for modules + if (!new File(targetDir, "module.json").exists()) { + println "$targetDir has no module.json, it must not want a fresh build.gradle" + return + } + println "In refreshGradle for module $targetDir - copying in a fresh build.gradle" + File targetBuildGradle = new File(targetDir, 'build.gradle') + targetBuildGradle.delete() + targetBuildGradle << new File('templates/build.gradle').text + } } diff --git a/config/groovy/util.groovy b/config/groovy/util.groovy index 2aa7cf191..fa8593401 100644 --- a/config/groovy/util.groovy +++ b/config/groovy/util.groovy @@ -38,14 +38,15 @@ excludedItems = common.excludedItems targetDirectory = common.targetDirectory def recurse = false -switch(cleanerArgs[0]) { +switch (cleanerArgs[0]) { case "recurse": recurse = true println "We're retrieving recursively (all the things depended on too)" - // We just fall through here to the get logic after setting a boolean - //noinspection GroovyFallthrough +// We just fall through here to the get logic after setting a boolean +//noinspection GroovyFallthrough case "get": println "Preparing to get $itemType" + //println "cleanerArgs is $cleanerArgs" if (cleanerArgs.length == 1) { def itemString = common.getUserString("Enter what to get - separate multiple with spaces, CapiTaliZation MatterS): ") println "User wants: $itemString" @@ -56,20 +57,30 @@ switch(cleanerArgs[0]) { cleanerArgs = common.processCustomRemote(cleanerArgs) ArrayList selectedItems = new ArrayList() - common.cacheItemList() for (String arg : cleanerArgs) { + //println "Checking arg $arg" if (!arg.contains('*') && !arg.contains('?')) { + println "Got into the non-wilcard option to fetch a fully specified item for $arg" selectedItems.add(arg) } else { + println "Got into the wildcard option to fetch something matching a pattern for $arg, may need to cache first" + common.cacheItemList() selectedItems.addAll(common.retrieveAvalibleItemsWithWildcardMatch(arg)); } } common.unCacheItemList() - common.retrieve(((String[])selectedItems.toArray()), recurse) + common.retrieve(((String[]) selectedItems.toArray()), recurse) } break - + case "get-all": + println "Preparing to get all modules" + ArrayList selectedItems = new ArrayList() + common.cacheItemList() + selectedItems.addAll(common.retrieveAvalibleItemsWithWildcardMatch("*")); + common.unCacheItemList() + common.retrieve(((String[]) selectedItems.toArray()), recurse) + break case "create": println "We're doing a create" String name @@ -106,8 +117,9 @@ switch(cleanerArgs[0]) { case "update-all": println "We're updating every $itemType" println "List of local entries: ${common.retrieveLocalItems()}" - for(item in common.retrieveLocalItems()){ - common.updateItem(item) + def skipRecentlyUpdated = cleanerArgs.contains("-skip-recently-updated") + for (item in common.retrieveLocalItems()) { + common.updateItem(item, skipRecentlyUpdated) } break @@ -142,31 +154,82 @@ switch(cleanerArgs[0]) { break case "list": - ListFormat listFormat = determineListFormat(cleanerArgs) String[] availableItems = common.retrieveAvailableItems() String[] localItems = common.retrieveLocalItems() String[] downloadableItems = availableItems.minus(localItems) - println "The following items are available for download:" - if (availableItems.size() == 0) { - println "No items available for download." - } else if (downloadableItems.size() == 0) { - println "All items are already downloaded." + + ListFormat listFormat = determineListFormat(cleanerArgs) + + if (cleanerArgs.contains("--local")) { + printListItems(localItems, listFormat) } else { - printListItems(downloadableItems, listFormat) + println "The following items are available for download:" + if (availableItems.size() == 0) { + println "No items available for download." + } else if (downloadableItems.size() == 0) { + println "All items are already downloaded." + } else { + printListItems(downloadableItems, listFormat) + } + println "\nThe following items are already downloaded:" + if (localItems.size() == 0) { + println "No items downloaded." + } else { + printListItems(localItems, listFormat) + } } - println "\nThe following items are already downloaded:" - if(localItems.size() == 0) { - println "No items downloaded." + break + + case "refresh": + println "We're refreshing Gradle for every $itemType" + common.refreshGradle() + break + + case "createDependencyDotFile": + if (itemType != "module") { + println "Dependency dot file can only be created for modules" + break + } + String source = "" + if (cleanerArgs.length == 1 || cleanerArgs[1] == "*") { + // getting dependency dot file for all modules + source = "all" + } else if (cleanerArgs.length > 2) { + println "Please enter only one module or none to create a dependency dot file showing all modules" + } else if (cleanerArgs[1].contains('*') || cleanerArgs[1].contains('?')) { + println "Please enter a fully specified item instead of " + cleanerArgs[1] + " - CapiTaliZation MatterS" } else { - printListItems(localItems, listFormat) + // getting dependency dot file for specified module only + source = cleanerArgs[1] } + + if (source != "") { + def dependencyFile = new File("dependency.dot") + dependencyFile.write "digraph moduleDependencies {\n" + if (source == "all") { + println "Creating the dependency dot file for all modules as \"dependencies.dot\"" + def modules = new File("modules") + modules.eachFile { + common.writeDependencyDotFileForModule(dependencyFile, it) + } + } else { + println "Creating the dependency dot file for module \"$source\" as \"dependencies.dot\"" + common.writeDependencyDotFileForModule(dependencyFile, new File("modules/$source")) + } + dependencyFile.append("}") + } + break default: println "UNRECOGNIZED COMMAND '" + cleanerArgs[0] + "' - please try again or use 'groovyw usage' for help" } -enum ListFormat { DEFAULT, SIMPLE, CONDENSED }; +enum ListFormat { + DEFAULT, SIMPLE, CONDENSED +} + +; private ListFormat determineListFormat(String[] args) { for (listFormat in ListFormat.values()) { @@ -182,19 +245,19 @@ private void printListItems(String[] items, ListFormat listFormat) { case ListFormat.SIMPLE: printListItemsSimple(items); break; case ListFormat.CONDENSED: printListItemsCondensed(items); break; default: items.size() < DEFAULT_FORMAT_CONDENSATION_THRESHOLD ? - printListItemsSimple(items) : - printListItemsCondensed(items) + printListItemsSimple(items) : + printListItemsCondensed(items) } } private void printListItemsSimple(String[] items) { for (item in items.sort()) { - println "--$item" + println "$item" } } private void printListItemsCondensed(String[] items) { - for (group in items.groupBy {it[0].toUpperCase()}) { + for (group in items.groupBy { it[0].toUpperCase() }) { println "--" + group.key + ": " + group.value.sort().join(", ") } } @@ -203,42 +266,47 @@ private void printListItemsCondensed(String[] items) { * Simply prints usage information. */ def printUsage() { - println "" - println "Utility script for interacting with project items. General syntax:" - println " groovyw (type) (sub-command)" - println "- 'type' may be module, meta, lib or facade - but so far for DestSol only module is supported" - println "" - println "Available sub-commands:" - println "- 'get' - retrieves one or more items in source form (separate with spaces)" - println "- 'recurse' - retrieves the given item(s) *and* their dependencies in source form (really only for modules)" - println "- 'list' - lists items that are available for download or downloaded already." - println "- 'create' - creates a new item of the given type." - println "- 'update' - updates an item (git pulls latest from current origin, if workspace is clean" - println "- 'update-all' - updates all local items of the given type." - println "- 'add-remote (item) (name)' - adds a remote (name) to (item) with the default URL." - println "- 'add-remote (item) (name) (URL)' - adds a remote with the given URL" - println "- 'list-remotes (item)' - lists all remotes for (item) " - println "" - println "Available flags:" - println "'-remote [someRemote]' to clone from an alternative remote, also adding the upstream org (like MovingBlocks) repo as 'origin'" - println " Note: 'get' + 'recurse' only. This will override an alternativeGithubHome set via gradle.properties." - println "'-simple-list-format' to print one item per row for the 'list' sub-command, even for large numbers of items" - println "'-condensed-list-format' to group items by starting letter for the 'list' sub-command (default with many items)" - println "" - println "Example: 'groovyw module create MySpaceShips' - would create that module" - println "Example: 'groovyw module get caution - remote vampcat - would retrieve caution module from vampcat's account on github.'" - println "Example: 'groovyw module get *' - would retrieve all the modules in the DestinationSol organisation on GitHub." - println "Example: 'groovyw module get ?r*' - would retrieve all the modules in the DestinationSol organisation on GitHub" + - " that start with any single character, then an \"r\" and then end with anything else." + - " This should retrieve the draconic, organic and tribe repositories from the DestinationSol organisation on GitHub." - println "" - println "*NOTE*: On UNIX platforms (MacOS and Linux), the wildcard arguments must be escaped with single quotes e.g. groovyw module get '*'." - println "" - println "*NOTE*: Item names are case sensitive. If you add items then `gradlew idea` or similar may be needed to refresh your IDE" - println "" - println "If you omit further arguments beyond the sub command you'll be prompted for details" - println "" - println "For advanced usage see project documentation. For instance you can provide an alternative GitHub home" - println "A gradle.properties file (one exists under '/templates' in an engine workspace) can provide such overrides" - println "" + + println(""" + Utility script for interacting with Destination Sol. General syntax: + groovyw (type) (sub-command) + - 'type' may be module or lib (Destination Sol still only supports a subset vs Terasology) + + Available sub-commands: + - 'get' - retrieves one or more items in source form (separate with spaces) + - 'get-all' - retrieves all modules that can be found on the configured remote locations + - 'recurse' - retrieves the given item(s) *and* their dependencies in source form (really only for modules) + - 'list' - lists items that are available for download or downloaded already. + - 'create' - creates a new item of the given type. + - 'update' - updates an item (git pulls latest from current origin, if workspace is clean + - 'update-all' - updates all local items of the given type. + - 'add-remote (item) (name)' - adds a remote (name) to (item) with the default URL. + - 'add-remote (item) (name) (URL)' - adds a remote with the given URL + - 'list-remotes (item)' - lists all remotes for (item) + - 'refresh' - replaces the Gradle build file for all items of the given type from the latest template + - 'createDependencyDotFile' - creates a dot file recursively listing dependencies of given locally available module, can be visualized with e.g. graphviz + + Available flags: + '-remote [someRemote]' to clone from an alternative remote, also adding the upstream org (like MovingBlocks) repo as 'origin' + Note: 'get' + 'recurse' only. This will override an alternativeGithubHome set via gradle.properties. + '-simple-list-format' to print one item per row for the 'list' sub-command, even for large numbers of items + '-condensed-list-format' to group items by starting letter for the 'list' sub-command (default with many items) + '-skip-recently-updated' (Only for update-all) to skip updating modules that have already been updated within 10 minutes + + Example: 'groovyw module create MySpaceShips' - would create that module + Example: 'groovyw module get caution - remote vampcat - would retrieve caution module from vampcat's account on github.' + Example: 'groovyw module get *' - would retrieve all the modules in the DestinationSol organisation on GitHub. + Example: 'groovyw module get ?r*' - would retrieve all the modules in the DestinationSol organisation on GitHub + that start with any single character, then an \\"r\\" and then end with anything else. + This should retrieve the draconic, organic and tribe repositories from the DestinationSol organisation on GitHub. + + *NOTE*: On UNIX platforms (MacOS and Linux), the wildcard arguments must be escaped with single quotes e.g. groovyw module get '*'. + + *NOTE*: Item names are case sensitive. If you add items then `gradlew idea` or similar may be needed to refresh your IDE + + If you omit further arguments beyond the sub-command you'll be prompted for details + + For advanced usage see project documentation. For instance you can provide an alternative GitHub home + A gradle.properties file (one exists under '/templates' in an engine workspace) can provide such overrides + """.stripIndent()) } diff --git a/gradle/wrapper/groovy-wrapper.jar b/gradle/wrapper/groovy-wrapper.jar index dc694676103d5d1e836fb9a36d4804c3a1279cf9..7fadbd5150cc523b5104c87aabab138320b42805 100644 GIT binary patch delta 4690 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 delta 4501 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 QIa6jL{e2Q1x_|Hf4>WU_VE_OC diff --git a/groovyw b/groovyw index b67153763..e57f3169f 100755 --- a/groovyw +++ b/groovyw @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -33,11 +49,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar:$APP_HOME/gradle/wrapper/groovy-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,35 +156,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args -save ( ) { +save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GroovyWrapperMain config/groovy/util.groovy "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/groovyw.bat b/groovyw.bat index de0f3d5e4..d2623ce34 100644 --- a/groovyw.bat +++ b/groovyw.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= @@ -58,10 +77,17 @@ set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute -@REM set CMD_LINE_ARGS=%* +@REM Escapes all arguments containing either "*" or "?" before passing them to the groovy process :process_args +@REM If we have no more arguments to process then exit the loop IF "%1"=="" GOTO end SET ARG=%~1 +@REM "echo "%ARG%" will simply output the argument as an escaped text string +@REM for piping to other applications. This is needed to ensure that the arguments are not expanded. +@REM findstr is a built-in Windows utility (it has been since Windows 2000) +@REM that finds matches in strings based on regular expressions. +@REM The "&&" operator is followed if the findstr program returns an exit code of 0 +@REM Otherwise, the "||" operator is followed instead. echo "%ARG%" | findstr /C:"\*" 1>nul && ( SET CMD_LINE_ARGS=%CMD_LINE_ARGS% "%ARG%" ) || ( @@ -75,6 +101,8 @@ SHIFT GOTO process_args :end +@REM For some reason, the escaped arguments always contain an extra space at the end, which confuses groovy. +@REM This should remove it. SET CMD_LINE_ARGS=%CMD_LINE_ARGS:~1% :execute @@ -82,6 +110,7 @@ SET CMD_LINE_ARGS=%CMD_LINE_ARGS:~1% set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar;%APP_HOME%\gradle\wrapper\groovy-wrapper.jar; + @rem Execute Groovy via the Gradle Wrapper "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GroovyWrapperMain config/groovy/util.groovy %CMD_LINE_ARGS% diff --git a/templates/build.gradle b/templates/build.gradle index a14af1abb..ea4bd8da8 100644 --- a/templates/build.gradle +++ b/templates/build.gradle @@ -64,7 +64,7 @@ configurations.all { resolutionStrategy.cacheChangingModulesFor 0, 'seconds' } -// Set dependencies. Note that the dependency information from module.txt is used for other Terasology modules +// Set dependencies. Note that the dependency information from module.json is used for other DestinationSol modules dependencies { // Check to see if this module is not the root Gradle project - if so we are in a multi-project workspace if (project.name != project(':').name) { @@ -138,7 +138,7 @@ dependencies { // TODO: Only use engine, engine-tests, and maybe core for compilation, but remove when publishing? compile(group: 'org.destinationsol.engine', name: 'engine', version: '+', changing: true) - // To get Terasology module dependencies we simply declare them against Artifactory + // To get DestinationSol module dependencies we simply declare them against Artifactory moduleDepends.each { println "*** Attempting to fetch dependency module from Artifactory for " + project.name + ": " + it // The '+' is satisfied by any version From 31d46210c589623ec8875bb81cfa5951b6c94244 Mon Sep 17 00:00:00 2001 From: Rasmus Praestholm Date: Tue, 2 Nov 2021 22:33:12 -0500 Subject: [PATCH 2/2] Update config/groovy/common.groovy Co-authored-by: BenjaminAmos <24301287+BenjaminAmos@users.noreply.github.com> --- config/groovy/common.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/groovy/common.groovy b/config/groovy/common.groovy index f8ae06053..112d3fe7f 100644 --- a/config/groovy/common.groovy +++ b/config/groovy/common.groovy @@ -408,7 +408,7 @@ class common { } currentPageUrl = getLink(connection, "next") // TODO: This comparison is vulnerable to a page request size of "100" or anything that starts with a 1, but just using 99 above .. - if (currentPageUrl.contains("page=1")) { + if (currentPageUrl != null && currentPageUrl.contains("page=1")) { //println "The pagination warped back to page 1, we're done!" currentPageUrl = null }