All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.tools.info.CeylonInfoTool Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.tools.info;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import com.redhat.ceylon.cmr.api.ArtifactContext;
import com.redhat.ceylon.cmr.api.ModuleDependencyInfo;
import com.redhat.ceylon.cmr.api.ModuleQuery;
import com.redhat.ceylon.cmr.api.ModuleSearchResult;
import com.redhat.ceylon.cmr.api.ModuleSearchResult.ModuleDetails;
import com.redhat.ceylon.cmr.api.ModuleVersionArtifact;
import com.redhat.ceylon.cmr.api.ModuleVersionDetails;
import com.redhat.ceylon.cmr.api.ModuleVersionQuery;
import com.redhat.ceylon.cmr.api.RepositoryManager;
import com.redhat.ceylon.cmr.api.VersionComparator;
import com.redhat.ceylon.cmr.ceylon.RepoUsingTool;
import com.redhat.ceylon.common.Versions;
import com.redhat.ceylon.common.config.DefaultToolOptions;
import com.redhat.ceylon.common.tool.Argument;
import com.redhat.ceylon.common.tool.Description;
import com.redhat.ceylon.common.tool.Option;
import com.redhat.ceylon.common.tool.OptionArgument;
import com.redhat.ceylon.common.tool.ParsedBy;
import com.redhat.ceylon.common.tool.RemainingSections;
import com.redhat.ceylon.common.tool.StandardArgumentParsers;
import com.redhat.ceylon.common.tool.Summary;
import com.redhat.ceylon.common.tools.CeylonTool;
import com.redhat.ceylon.common.tools.ModuleSpec;

@Summary("Prints information about modules in repositories")
@Description("When passed a search query like `*foo*` it will look at all the modules in all " +
        "repositories and see if the word `foo` appears anywhere in the name, description, " +
        "version, license or any other field in the module's descriptor and print their names. " +
        "\n\n" +
        "When passed a partial module name like `com.acme.foo*` it will look at all the " +
        "modules in all the repositories and see if their names start with `com.acme.foo` " +
        "and print their names." +
        "\n\n" +
        "When passed a complete module name like `com.acme.foobar` it will print the list " +
        "of available versions for that module, with the module repository in which each " +
        "version was found. Versions marked with `*` are not currently available on the local " +
        "file system but will be downloaded on-demand from remote servers." +
        "\n\n" +
        "When passed a complete module name and version like `com.acme.foobar/1.0` it will " +
        "print information about the contents of a module archive, its description, its licence " +
        "and its dependencies")
@RemainingSections("## EXAMPLE\n\n"
        + "First list the available modules in the 'ceylon' namespace:\n\n"
        + "    ceylon info 'ceylon.*'\n\n"
        + "Next list the versions of a module:\n\n"
        + "    ceylon info ceylon.collection\n\n"
        + "Then view information for a particular version:\n\n"
        + "    ceylon info ceylon.collection/1.2.0\n\n")
public class CeylonInfoTool extends RepoUsingTool {

    private static final int INFINITE_DEPTH = -1;
    
    public enum Formatting {
        simple, fancy
    }
    
    public enum Incompatible {
        yes, no, auto
    }
    
    private List modules;
    private boolean showVersions;
    private boolean showDependencies;
    private Incompatible showIncompatible = Incompatible.auto;
    private boolean showFullDescription;
    private String showType;
    private int depth = 1;
    private String findMember;
    private String findPackage;
    private boolean showNames;
    private boolean exactMatch;
    private boolean requireAll;
    private boolean printOverrides;
    private Formatting formatting;
    private List sourceFolders = DefaultToolOptions.getCompilerSourceDirs();

    private Integer jvmBinaryMajor = null;
    private Integer jvmBinaryMinor = null;
    private Integer jsBinaryMajor = null;
    private Integer jsBinaryMinor = null;
    private ModuleQuery.Type queryType = ModuleQuery.Type.ALL;
    
    public CeylonInfoTool() {
        super(CeylonInfoMessages.RESOURCE_BUNDLE);
    }
    
    @Override
    protected boolean includeJDK() {
        return true;
    }
    
    @Override
    protected List getSourceDirs() {
        return sourceFolders;
    }
    
    @OptionArgument(longName="src", argumentName="dir")
    @ParsedBy(StandardArgumentParsers.PathArgumentParser.class)
    @Description("A directory containing Ceylon and/or Java source code (default: `./source`)")
    public void setSourceFolders(List sourceFolders) {
        this.sourceFolders = sourceFolders;
    }
    
    @Argument(argumentName="module", multiplicity="+")
    public void setModules(List modules) {
        setModuleSpecs(ModuleSpec.parseEachList(modules));
    }
    
    public void setModuleSpecs(List modules) {
        this.modules = modules;
    }
    
    @Option(longName="show-versions")
    @Description("Show the versions when searching for modules")
    public void setShowVersions(boolean showVersions) {
        this.showVersions = showVersions;
    }

    @Option(longName="print-overrides")
    @Description("Print a usable module overrides file when there are duplicate versions, selecting the latest versions")
    public void setPrintOverrides(boolean printOverrides) {
        this.printOverrides = printOverrides;
    }

    @Option(longName="show-dependencies")
    @Description("Show the dependencies whenever versions are shown")
    public void setShowDependencies(boolean showDependencies) {
        this.showDependencies = showDependencies;
    }
    
    @OptionArgument(argumentName="mode")
    @Description("Also show versions incompatible with the current Ceylon installation. " +
            "allowed values are: 'yes', 'no' and 'auto'")
    public void setShowIncompatible(Incompatible showIncompatible) {
        this.showIncompatible = showIncompatible;
    }
    
    @Option(longName="show-full-description")
    @Description("Shows the full description for module details")
    public void setShowFullDescription(boolean showFullDescription) {
        this.showFullDescription = showFullDescription;
    }
    
    @Option(longName="require-all")
    @Description("Only show those results that have all the requested artifact types")
    public void setRequireAll(boolean requireAll) {
        this.requireAll = requireAll;
    }
    
    @OptionArgument(argumentName = "type")
    @Description("The artifact types to show information for. " +
            "Allowed values include: `all`, `jvm`, `car`, `jar`, `js`, `src`, `code`, `ceylon` (default is `all`).")
    public void setShowType(String showType) {
        this.showType = showType;
    }
    
    @Description("The depth of the dependency tree to show, or `all` for the full tree. " +
    		"(Allowed values: any positive integer or `all`, default: `1`)")
    @OptionArgument(argumentName="depth")
    public void setDependencyDepth(String depth) {
        if ("all".equals(depth)) {
            setDependencyDepth(INFINITE_DEPTH);
        } else {
            setDependencyDepth(Integer.parseInt(depth));
        }
    }
    
    public void setDependencyDepth(int depth) {
        if (!(depth == INFINITE_DEPTH || depth >= 0)) {
            throw new IllegalArgumentException(CeylonInfoMessages.msg("illegal.depth"));
        }
        this.depth = depth;
    }
    
    @OptionArgument(argumentName = "member-name")
    @Description("Shows only those modules that contain members whose name match the given argument.")
    public void setFindMember(String findMember) {
        this.findMember = findMember;
    }
    
    @OptionArgument(argumentName = "package-name")
    @Description("Shows only those modules that contain packages whose name match the given argument.")
    public void setFindPackage(String findPackage) {
        this.findPackage = findPackage;
    }
    
    @Option(longName="show-names")
    @Description("Show the matching items when using the `find-member` or `find-package` option")
    public void setShowNames(boolean showNames) {
        this.showNames = showNames;
    }
    
    @Option(longName="exact-match")
    @Description("Only returns exact matches when using the `find-member` or `find-package` option")
    public void setExactMatch(boolean exactMatch) {
        this.exactMatch = exactMatch;
    }

    @OptionArgument(argumentName = "formatting")
    @Description("Set the output formatting to use, can be `simple` or `fancy`")
    public void setFormatting(Formatting formatting) {
        this.formatting = formatting;
    }

    @Override
    protected boolean needsSystemRepo() {
        return false;
    }

    @Override
    public void initialize(CeylonTool mainTool) {
        if (showType != null) {
            if ("car".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.CAR;
            } else if ("jar".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.JAR;
            } else if ("jvm".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.JVM;
            } else if ("js".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.JS;
            } else if ("src".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.SRC;
            } else if ("all".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.ALL;
            } else if ("code".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.CODE;
            } else if ("ceylon".equalsIgnoreCase(showType)) {
                queryType = ModuleQuery.Type.CEYLON_CODE;
            } else {
                throw new IllegalArgumentException(CeylonInfoMessages.msg("illegal.type", showType));
            }
        }
        if (findMember != null && "src".equalsIgnoreCase(showType)) {
            throw new IllegalArgumentException(CeylonInfoMessages.msg("incompatible.query.and.find"));
        }
        if (findMember != null && findPackage != null) {
            throw new IllegalArgumentException(CeylonInfoMessages.msg("incompatible.find.options"));
        }
        if (formatting == null) {
            formatting = (System.console() != null) ? Formatting.fancy : Formatting.simple;
        }
    }
    
    @Override
    public void run() throws Exception {
        if (showIncompatible != Incompatible.yes) {
            if (queryType.includes(ArtifactContext.CAR)) {
                jvmBinaryMajor = Versions.JVM_BINARY_MAJOR_VERSION;
                jvmBinaryMinor = Versions.JVM_BINARY_MINOR_VERSION;
            }
            if (queryType.includes(ArtifactContext.JS)) {
                jsBinaryMajor = Versions.JS_BINARY_MAJOR_VERSION;
                jsBinaryMinor = Versions.JS_BINARY_MINOR_VERSION;
            }
        }
        String msgkey = showIncompatible == Incompatible.no ? "module.not.found.compat" : "module.not.found";

        for (ModuleSpec module : modules) {
            String name = module.getName();
            if (!module.isVersioned() && (name.startsWith("*") || name.endsWith("*"))) {
                Collection modules = getModules(getRepositoryManager(), name, queryType, 
                		jvmBinaryMajor, jvmBinaryMinor, jsBinaryMajor, jsBinaryMinor);
                if (modules.isEmpty()) {
                    String err;
                    if (name.startsWith("*") || name.endsWith("*")) {
                        err = CeylonInfoMessages.msg("no.match", name);
                    } else {
                        err = getModuleNotFoundErrorMessage(getRepositoryManager(), module.getName(), module.getVersion(), msgkey);
                    }
                    errorAppend(err);
                    errorNewline();
                    continue;
                }
                outputModules(module, modules);
            } else {
                Collection versions = getModuleVersions(getRepositoryManager(), module.getName(), 
                		module.getVersion(), queryType, 
                		jvmBinaryMajor, jvmBinaryMinor, jsBinaryMajor, jsBinaryMinor);
                if (versions.isEmpty()) {
                    // try from source
                    ModuleVersionDetails fromSource = getVersionFromSource(name);
                    if (fromSource != null) {
                        // is it the version we're after?
                        versions = Arrays.asList(fromSource);
                    } else {
                        if (showIncompatible == Incompatible.auto &&
                                (jvmBinaryMajor != null || jvmBinaryMinor != null || jsBinaryMajor != null || jsBinaryMinor != null)) {
                            // If we were called with a specific version and we didn't find a "compatible"
                            // artifact then lets see if we can find an "incompatible" one
                            versions = getModuleVersions(getRepositoryManager(), module.getName(), module.getVersion(), 
                            		queryType, null, null, null, null);
                        }
                        if (versions.isEmpty()) {
                            String err = getModuleNotFoundErrorMessage(getRepositoryManager(), module.getName(), module.getVersion(), msgkey);
                            errorAppend(err);
                            errorNewline();
                            continue;
                        }
                    }
                }
                if (module.getVersion() == null || module.getVersion().isEmpty() || versions.size() > 1) {
                    outputVersions(module, versions);
                } else {
                    outputDetails(module, versions.iterator().next());
                }
            }
        }
    }

    private Collection getModules(RepositoryManager repoMgr, String name, ModuleQuery.Type type, 
    		Integer jvmBinaryMajor, Integer jvmBinaryMinor,
    		Integer jsBinaryMajor, Integer jsBinaryMinor) {
        String queryString = name;
        if (queryString.startsWith("*")) {
            queryString = queryString.substring(1);
        }
        if (queryString.endsWith("*")) {
            queryString = queryString.substring(0, queryString.length() - 1);
        }
        
        ModuleVersionQuery query = getModuleVersionQuery(queryString, null, type, 
        		jvmBinaryMajor, jvmBinaryMinor,
        		jsBinaryMajor, jsBinaryMinor);
        
        ModuleSearchResult result;
        if (!name.startsWith("*") || name.equals("*")) {
            result = repoMgr.completeModules(query);
        } else {
            result = repoMgr.searchModules(query);
        }
        return result.getResults();
    }

    @Override
    protected ModuleVersionQuery getModuleVersionQuery(String name, String version, ModuleQuery.Type type, 
    		Integer jvmBinaryMajor, Integer jvmBinaryMinor,
    		Integer jsBinaryMajor, Integer jsBinaryMinor) {
        ModuleVersionQuery query = super.getModuleVersionQuery(name, version, type, jvmBinaryMajor, jvmBinaryMinor,
        		jsBinaryMajor, jsBinaryMinor);
        if (findMember != null) {
            query.setMemberName(findMember);
        }
        if (findPackage != null) {
            query.setMemberName(findPackage);
            query.setMemberSearchPackageOnly(true);
        }
        query.setMemberSearchExact(exactMatch);
        if (requireAll) {
            query.setRetrieval(ModuleQuery.Retrieval.ALL);
        }
        return query;
    }
    
    private void outputModules(ModuleSpec query, Collection modules) throws IOException {
        if (formatting == Formatting.fancy) {
            if (findMember != null) {
                msg("module.query.member", query.getName(), findMember).newline();
            } else if (findPackage != null) {
                msg("module.query.package", query.getName(), findPackage).newline();
            } else {
                msg("module.query", query.getName()).newline();
            }
        }
        outputModules(modules);
    }

    private void outputModules(Collection modules) throws IOException {
        for (ModuleDetails module : modules) {
            outputModule(module);
        }
    }

    private void outputModule(ModuleDetails module) throws IOException {
        String prefix = (formatting == Formatting.fancy) ? "    " : "";
        if (formatting == Formatting.fancy || (!showVersions && !showNames)) {
            append(prefix).append(module.getName()).newline();
        }
        if (showVersions) {
            outputVersions(module.getName(), module.getVersions(), prefix + prefix);
        } else if (showNames) {
            outputNames(module.getName(), module.getLastVersion(), prefix + prefix);
        }
    }

    private void outputVersions(ModuleSpec module, Collection versions) throws IOException {
        String prefix = (formatting == Formatting.fancy) ? "    " : "";
        if (formatting == Formatting.fancy) {
            if (findMember != null) {
                msg("version.query.member", module.getName(), findMember).newline();
            } else if (findPackage != null) {
                msg("version.query.package", module.getName(), findPackage).newline();
            } else {
                msg("version.query", module.getName()).newline();
            }
        }
        outputVersions(module.getName(), versions, prefix);
    }

    private void outputVersions(String moduleName, Collection versions, String prefix) throws IOException {
        String namePrefix = (formatting == Formatting.fancy) ? prefix + "    " : "";
        for (ModuleVersionDetails version : versions) {
            if (formatting == Formatting.fancy || (!showDependencies && !showNames)) {
                append(prefix);
                if (formatting == Formatting.simple) {
                    append(moduleName).append("/");
                }
                append(version.getVersion());
                if (formatting == Formatting.fancy) {
                    append(" - ").append(version.getOrigin());
                    if (hasOnlyIncompatibleBinaries(version)) {
                        append(" ");
                        msg("label.incompatible.version");
                    }
                    if (version.isRemote()) {
                        append(" ");
                        msg("label.remote");
                    }
                }
                newline();
            }
            if (showDependencies) {
                if (formatting == Formatting.fancy || !version.getDependencies().isEmpty()) {
                    for (ModuleDependencyInfo dep : version.getDependencies()) {
                        if (formatting == Formatting.fancy) {
                            append(prefix).append("    ").append(dep);
                        } else {
                            append(moduleName).append("/").append(version.getVersion()).append(" ").append(dep.getModuleName());
                        }
                        newline();
                    }
                } else {
                    append(moduleName).append("/").append(version.getVersion()).newline();
                }
            }
            if (showNames) {
                outputNames(moduleName, version, namePrefix);
            }
        }
    }

    private boolean hasOnlyIncompatibleBinaries(ModuleVersionDetails version) {
        boolean hasBinaries = false;
        for (ModuleVersionArtifact at : version.getArtifactTypes()) {
            if (at.getSuffix().equals(ArtifactContext.CAR)) {
                if (Versions.isJvmBinaryVersionSupported(
                            at.getMajorBinaryVersion(),
                            at.getMinorBinaryVersion())) {
                    return false;
                }
                hasBinaries = true;
            }
            if (at.getSuffix().equals(ArtifactContext.JS)) {
                if (Versions.isJvmBinaryVersionSupported(
                            at.getMajorBinaryVersion(),
                            at.getMinorBinaryVersion())) {
                    return false;
                }
                hasBinaries = true;
            }
        }
        return hasBinaries;
    }

    private void outputNames(String moduleName, ModuleVersionDetails version, String prefix) throws IOException {
        for (String member : version.getMembers()) {
            if (formatting == Formatting.fancy) {
                append(prefix).append(member).newline();
            } else {
                append(moduleName);
                if (showVersions) {
                    append("/").append(version.getVersion());
                }
                append("::").append(member).newline();
            }
        }
    }

    private void outputDetails(ModuleSpec module, ModuleVersionDetails version) throws IOException {
        msg("module.name").append(module.getName()).newline();
        msg("module.version").append(version.getVersion()).newline();
        outputArtifacts(version.getArtifactTypes());
        msg("module.available").msg((version.isRemote() ? "available.remote" : "available.local")).newline();
        if (version.getOrigin() != null) {
            msg("module.origin").append(version.getOrigin()).newline();
        }
        if (version.getDoc() != null) {
            String docs = version.getDoc();
            if (!showFullDescription) {
                docs = summary(version.getDoc());
            }
            msg("module.description").append(docs).newline();
        }
        if (version.getLicense() != null) {
            msg("module.license").append(version.getLicense()).newline();
        }
        if (version.getAuthors() != null && !version.getAuthors().isEmpty()) {
            outputAuthors(version.getAuthors());
        }
        if (!version.getDependencies().isEmpty()) {
            msg("module.dependencies.tree", (depth == INFINITE_DEPTH ? "∞" : String.valueOf(depth))).newline();
            SortedMap> names = new TreeMap<>();
            recurseDependencies(version, names, 0);

            if (depth != 1) {
                newline();
                msg("module.dependencies.flat", (depth == INFINITE_DEPTH ? "∞" : String.valueOf(depth))).newline();
                listDependencies(names);
            }
            
            listDependencyConflictsIfAny(names);
        }
    }

    private void listDependencyConflictsIfAny(SortedMap> names) throws IOException {
        boolean hasNoDuplicate = true;
        StringBuilder overridesFile = null;
        if(printOverrides){
            overridesFile = new StringBuilder();
            overridesFile.append("\n");
        }
        for(Map.Entry> entry : names.entrySet()){
            if(entry.getValue().size() > 1){
                if(hasNoDuplicate){
                    hasNoDuplicate = false;
                    newline();
                    msg("module.dependencies.conflicts", (depth == INFINITE_DEPTH ? "∞" : String.valueOf(depth))).newline();
                }
                append("  ");
                append(entry.getKey());
                if(entry.getValue().size() > 1){
                    append(": ");
                    boolean first = true;
                    for(String v : entry.getValue()){
                        if(first)
                            first = false;
                        else
                            append(", ");
                        append(v);
                    }
                    if(printOverrides){
                        overridesFile.append(" \n");
                    }
                }
                newline();
            }
        }
        if(printOverrides && !hasNoDuplicate){
            overridesFile.append("\n");
            newline();
            msg("module.dependencies.overrides").newline();
            newline();
            append(overridesFile.toString());
        }
    }

    private void listDependencies(SortedMap> names) throws IOException {
        for(Map.Entry> entry : names.entrySet()){
            append("  ");
            append(entry.getKey());
            if(entry.getValue().size() > 1){
                append(": ");
                boolean first = true;
                for(String v : entry.getValue()){
                    if(first)
                        first = false;
                    else
                        append(", ");
                    append(v);
                }
            }else{
                append("/");
                append(entry.getValue().first());
            }
            newline();
        }
    }

    private String summary(String doc) {
        StringBuilder result = new StringBuilder();
        String[] lines = doc.split("\n");
        for (int i = 0; i < lines.length && i < 5; i++) {
            result.append(lines[i]).append('\n');
        }
        if (lines.length > 5) {
            result.append("...").append('\n');
        }
        return result.toString();
    }

    private void outputAuthors(NavigableSet authors) throws IOException {
        msg("module.authors");
        boolean first = true;
        for (String author : authors) {
            if (!first) {
                append(", ");
            }
            append(author);
            first = false;
        }
        newline();
    }

    private RepoUsingTool outputArtifacts(Set types) throws IOException {
        if(!types.isEmpty()) {
            msg("module.artifacts");
            boolean skipComma = true;
            boolean js = false;
            boolean docs = false;
            for (ModuleVersionArtifact type : types) {
                if (!skipComma) {
                    append(", ");
                }
                String suffix = type.getSuffix();
                int major = (type.getMajorBinaryVersion() != null) ? type.getMajorBinaryVersion() : 0;
                int minor = (type.getMinorBinaryVersion() != null) ? type.getMinorBinaryVersion() : 0;
                if (suffix.equalsIgnoreCase(ArtifactContext.CAR)) {
                    append("JVM (#");
                    append(major);
                    if (minor != 0) {
                        append(".");
                        append(minor);
                    }
                    if (!Versions.isJvmBinaryVersionSupported(major, minor)) {
                        append(" ");
                        msg("label.incompatible.version");
                    }
                    append(")");
                } else if (suffix.equalsIgnoreCase(ArtifactContext.JAR)) {
                    append("JVM (legacy)");
                } else if (suffix.equalsIgnoreCase(ArtifactContext.JS) || suffix.equalsIgnoreCase(ArtifactContext.JS_MODEL)) {
                    if (js) {
                        skipComma = true;
                        continue;
                    }
                    append("JavaScript (#");
                    append(major);
                    if (minor != 0) {
                        append(".");
                        append(minor);
                    }
                    if (!Versions.isJsBinaryVersionSupported(major, minor)) {
                        append(" ");
                        msg("label.incompatible.version");
                    }
                    append(")");
                    js = true;
                } else if (suffix.equalsIgnoreCase(ArtifactContext.RESOURCES)) {
                    append("JS Resources");
                } else if (suffix.equalsIgnoreCase(ArtifactContext.DOCS)) {
                    if (docs) {
                        skipComma = true;
                        continue;
                    }
                    append("Documentation");
                    docs = true;
                } else if (suffix.equalsIgnoreCase(ArtifactContext.SCRIPTS_ZIPPED)) {
                    append("Script Plugins");
                } else if (suffix.equalsIgnoreCase(ArtifactContext.SRC)) {
                    append("Sources");
                } else if (suffix.startsWith(".")) {
                    append(suffix.substring(1).toUpperCase());
                } else {
                    // We might need to add some special cases
                    // for these in the above list
                    append(type);
                }
                skipComma = false;
            }
            newline();
        }
        return this;
    }
    
    private void recurseDependencies(ModuleVersionDetails version, Map> names, final int depth) throws IOException {
        for (ModuleDependencyInfo dep : version.getDependencies()) {
            dependency(dep, names, depth+1);
        }
    }
    
    private void dependency(ModuleDependencyInfo dep, Map> names, final int depth) throws IOException {
        for (int ii = 0; ii < depth; ii++) {
            append("  ");
        }
        append(dep);
        SortedSet seenVersions = names.get(dep.getName());
        boolean recurse = this.depth == -1 || depth < this.depth;
        if(seenVersions != null){
            // already seen
            if(seenVersions.size() == 1 && seenVersions.first().equals(dep.getVersion()))
                append(" (already imported)");
            else
                append(" (already imported other version)");
            recurse = false;
        }else{
            seenVersions = new TreeSet<>(VersionComparator.INSTANCE);
            names.put(dep.getName(), seenVersions);
        }
        seenVersions.add(dep.getVersion());
        newline();
        
        if (recurse && !"ceylon.language".equals(dep.getName())) {
            Collection versions = getModuleVersions(dep.getName(), dep.getVersion(), queryType, 
            		jvmBinaryMajor, jvmBinaryMinor, jsBinaryMajor, jsBinaryMinor);
            if (!versions.isEmpty()) {
                recurseDependencies(versions.iterator().next(), names, depth + 1);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy