<commit_before>package com.beust.kobalt

import com.beust.jcommander.JCommander
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.app.*
import com.beust.kobalt.app.remote.KobaltClient
import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.app.remote.RemoteDependencyData
import com.beust.kobalt.internal.Gc
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.*
import com.google.common.collect.HashMultimap
import java.io.File
import java.net.URLClassLoader
import java.nio.file.Paths
import javax.inject.Inject

fun main(argv: Array<String>) {
    val result = mainNoExit(argv)
    if (result != 0) {
        System.exit(result)
    }
}

private fun parseArgs(argv: Array<String>): Main.RunInfo {
    val args = Args()
    val result = JCommander(args)
    result.parse(*argv)
    KobaltLogger.LOG_LEVEL = if (args.log < 0) {
            Constants.LOG_DEFAULT_LEVEL
        } else if (args.log > Constants.LOG_MAX_LEVEL) {
            Constants.LOG_MAX_LEVEL
        } else args.log
    return Main.RunInfo(result, args)
}

fun mainNoExit(argv: Array<String>): Int {
    val (jc, args) = parseArgs(argv)
    Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
    val result = Kobalt.INJECTOR.getInstance(Main::class.java).run {
        val runResult = run(jc, args, argv)
        pluginInfo.cleanUp()
        executors.shutdown()
        runResult
    }
    return result
}

private class Main @Inject constructor(
        val plugins: Plugins,
        val taskManager: TaskManager,
        val http: Http,
        val files: KFiles,
        val executors: KobaltExecutors,
        val dependencyManager: DependencyManager,
        val checkVersions: CheckVersions,
        val github: GithubApi2,
        val updateKobalt: UpdateKobalt,
        val client: KobaltClient,
        val pluginInfo: PluginInfo,
        val projectGenerator: ProjectGenerator,
        val serverFactory: KobaltServer.IFactory,
        val projectFinder: ProjectFinder,
        val dependencyData: RemoteDependencyData,
        val resolveDependency: ResolveDependency) {

    data class RunInfo(val jc: JCommander, val args: Args)

    private fun installCommandLinePlugins(args: Args): ClassLoader {
        var pluginClassLoader = javaClass.classLoader
        val dependencies = arrayListOf<IClasspathDependency>()
        args.pluginIds?.let {
            // We want this call to go to the network if no version was specified, so set localFirst to false
            dependencies.addAll(it.split(',').map { dependencyManager.create(it) })
        }
        args.pluginJarFiles?.let {
            dependencies.addAll(it.split(',').map { FileDependency(it) })
        }
        if (dependencies.size > 0) {
            val urls = dependencies.map { it.jarFile.get().toURI().toURL() }
            pluginClassLoader = URLClassLoader(urls.toTypedArray())
            plugins.installPlugins(dependencies, pluginClassLoader)
        }

        return pluginClassLoader
    }

    fun run(jc: JCommander, args: Args, argv: Array<String>): Int {

        //
        // Install plug-ins requested from the command line
        //
        val pluginClassLoader = installCommandLinePlugins(args)

        // --listTemplates
        if (args.listTemplates) {
            Templates().displayTemplates(pluginInfo)
            return 0
        }

        if (args.client) {
            client.run()
            return 0
        }

        var result = 0
        val latestVersionFuture = github.latestKobaltVersion

        try {
            result = runWithArgs(jc, args, argv, pluginClassLoader)
        } catch(ex: Throwable) {
            error("", ex.cause ?: ex)
            result = 1
        }

        if (!args.update) {
            updateKobalt.checkForNewVersion(latestVersionFuture)
        }
        return result
    }

    private fun runWithArgs(jc: JCommander, args: Args, argv: Array<String>, pluginClassLoader: ClassLoader): Int {
//        val file = File("/Users/beust/.kobalt/repository/com/google/guava/guava/19.0-rc2/guava-19.0-rc2.pom")
//        val md5 = Md5.toMd5(file)
//        val md52 = MessageDigest.getInstance("MD5").digest(file.readBytes()).toHexString()
        var result = 0
        val p = if (args.buildFile != null) File(args.buildFile) else findBuildFile()
        args.buildFile = p.absolutePath
        val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)

        if (!args.update) {
            println(AsciiArt.banner + Kobalt.version + "\n")
        }

        if (args.templates != null) {
            //
            // --init: create a new build project and install the wrapper
            // Make sure the wrapper won't call us back with --noLaunch
            //
            projectGenerator.run(args, pluginClassLoader)
            // The wrapper has to call System.exit() in order to set the exit code,
            // so make sure we call it last (or possibly launch it in a separate JVM).
            com.beust.kobalt.wrapper.Main.main(arrayOf("--noLaunch") + argv)
        } else if (args.usage) {
            jc.usage()
        } else {
            // Options that don't need Build.kt to be parsed first
            if (args.gc) {
                Gc().run()
            } else if (args.update) {
                // --update
                updateKobalt.updateKobalt()
            } else {
                //
                // Everything below requires to parse the build file first
                //
                if (!buildFile.exists()) {
                    error(buildFile.path.toFile().path + " does not exist")
                } else {

                    // DONOTCOMMIT
//                    val data = dependencyData.dependenciesDataFor(homeDir("kotlin/ktor/kobalt/src/Build.kt"), Args(),
//                            useGraph = true)
//                    println("Data: $data")

                    val allProjects = projectFinder.initForBuildFile(buildFile, args)

                    if (args.serverMode) {
                        // --server
                        val port = serverFactory.create(args.force, args.port,
                            { buildFile -> projectFinder.initForBuildFile(BuildFile(Paths.get(buildFile),
                                    buildFile), args) },
                            { cleanUp() })
                        .call()
                    } else if (args.projectInfo) {
                        // --projectInfo
                        allProjects.forEach {
                            it.compileDependencies.filter { it.isMaven }.forEach {
                                resolveDependency.run(it.id)
                            }
                        }
                    } else if (args.dependency != null) {
                        // --resolve
                        args.dependency?.let { resolveDependency.run(it) }
                    } else if (args.tasks) {
                        // --tasks<commit_msg>—listTemplates after parsing the build file.<commit_after>package com.beust.kobalt

import com.beust.jcommander.JCommander
import com.beust.kobalt.api.IClasspathDependency
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.PluginTask
import com.beust.kobalt.app.*
import com.beust.kobalt.app.remote.KobaltClient
import com.beust.kobalt.app.remote.KobaltServer
import com.beust.kobalt.app.remote.RemoteDependencyData
import com.beust.kobalt.internal.Gc
import com.beust.kobalt.internal.KobaltSettings
import com.beust.kobalt.internal.PluginInfo
import com.beust.kobalt.internal.TaskManager
import com.beust.kobalt.internal.build.BuildFile
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.Http
import com.beust.kobalt.maven.dependency.FileDependency
import com.beust.kobalt.misc.*
import com.google.common.collect.HashMultimap
import java.io.File
import java.net.URLClassLoader
import java.nio.file.Paths
import javax.inject.Inject

fun main(argv: Array<String>) {
    val result = mainNoExit(argv)
    if (result != 0) {
        System.exit(result)
    }
}

private fun parseArgs(argv: Array<String>): Main.RunInfo {
    val args = Args()
    val result = JCommander(args)
    result.parse(*argv)
    KobaltLogger.LOG_LEVEL = if (args.log < 0) {
            Constants.LOG_DEFAULT_LEVEL
        } else if (args.log > Constants.LOG_MAX_LEVEL) {
            Constants.LOG_MAX_LEVEL
        } else args.log
    return Main.RunInfo(result, args)
}

fun mainNoExit(argv: Array<String>): Int {
    val (jc, args) = parseArgs(argv)
    Kobalt.init(MainModule(args, KobaltSettings.readSettingsXml()))
    val result = Kobalt.INJECTOR.getInstance(Main::class.java).run {
        val runResult = run(jc, args, argv)
        pluginInfo.cleanUp()
        executors.shutdown()
        runResult
    }
    return result
}

private class Main @Inject constructor(
        val plugins: Plugins,
        val taskManager: TaskManager,
        val http: Http,
        val files: KFiles,
        val executors: KobaltExecutors,
        val dependencyManager: DependencyManager,
        val checkVersions: CheckVersions,
        val github: GithubApi2,
        val updateKobalt: UpdateKobalt,
        val client: KobaltClient,
        val pluginInfo: PluginInfo,
        val projectGenerator: ProjectGenerator,
        val serverFactory: KobaltServer.IFactory,
        val projectFinder: ProjectFinder,
        val dependencyData: RemoteDependencyData,
        val resolveDependency: ResolveDependency) {

    data class RunInfo(val jc: JCommander, val args: Args)

    private fun installCommandLinePlugins(args: Args): ClassLoader {
        var pluginClassLoader = javaClass.classLoader
        val dependencies = arrayListOf<IClasspathDependency>()
        args.pluginIds?.let {
            // We want this call to go to the network if no version was specified, so set localFirst to false
            dependencies.addAll(it.split(',').map { dependencyManager.create(it) })
        }
        args.pluginJarFiles?.let {
            dependencies.addAll(it.split(',').map { FileDependency(it) })
        }
        if (dependencies.size > 0) {
            val urls = dependencies.map { it.jarFile.get().toURI().toURL() }
            pluginClassLoader = URLClassLoader(urls.toTypedArray())
            plugins.installPlugins(dependencies, pluginClassLoader)
        }

        return pluginClassLoader
    }

    fun run(jc: JCommander, args: Args, argv: Array<String>): Int {

        //
        // Install plug-ins requested from the command line
        //
        val pluginClassLoader = installCommandLinePlugins(args)

        if (args.client) {
            client.run()
            return 0
        }

        var result = 0
        val latestVersionFuture = github.latestKobaltVersion

        try {
            result = runWithArgs(jc, args, argv, pluginClassLoader)
        } catch(ex: Throwable) {
            error("", ex.cause ?: ex)
            result = 1
        }

        if (!args.update) {
            updateKobalt.checkForNewVersion(latestVersionFuture)
        }
        return result
    }

    private fun runWithArgs(jc: JCommander, args: Args, argv: Array<String>, pluginClassLoader: ClassLoader): Int {
//        val file = File("/Users/beust/.kobalt/repository/com/google/guava/guava/19.0-rc2/guava-19.0-rc2.pom")
//        val md5 = Md5.toMd5(file)
//        val md52 = MessageDigest.getInstance("MD5").digest(file.readBytes()).toHexString()
        var result = 0
        val p = if (args.buildFile != null) File(args.buildFile) else findBuildFile()
        args.buildFile = p.absolutePath
        val buildFile = BuildFile(Paths.get(p.absolutePath), p.name)

        if (!args.update) {
            println(AsciiArt.banner + Kobalt.version + "\n")
        }

        if (args.templates != null) {
            //
            // --init: create a new build project and install the wrapper
            // Make sure the wrapper won't call us back with --noLaunch
            //
            projectGenerator.run(args, pluginClassLoader)
            // The wrapper has to call System.exit() in order to set the exit code,
            // so make sure we call it last (or possibly launch it in a separate JVM).
            com.beust.kobalt.wrapper.Main.main(arrayOf("--noLaunch") + argv)
        } else if (args.usage) {
            jc.usage()
        } else {
            // Options that don't need Build.kt to be parsed first
            if (args.gc) {
                Gc().run()
            } else if (args.update) {
                // --update
                updateKobalt.updateKobalt()
            } else {
                //
                // Everything below requires to parse the build file first
                //
                if (!buildFile.exists()) {
                    error(buildFile.path.toFile().path + " does not exist")
                } else {
                    val allProjects = projectFinder.initForBuildFile(buildFile, args)

                    if (args.listTemplates) {
                        // --listTemplates
                        Templates().displayTemplates(pluginInfo)
                    } else if (args.serverMode) {
                        // --server
                        val port = serverFactory.create(args.force, args.port,
                            { buildFile -> projectFinder.initForBuildFile(BuildFile(Paths.get(buildFile),
                                    buildFile), args) },
                            { cleanUp() })
                        .call()
                    } else if (args.projectInfo) {
                        // --projectInfo
                        allProjects.forEach {
                            it.compileDependencies.filter { it.isMaven }.forEach {
                                resolveDependency.run(it.id)
                            }
                        }
                    } else if (args.dependency != null) {
                        // --resolve
                        args.dependency?.let { resolveDependency.run(it) }
                    } else if (args.tasks) {
                        // --tasks
{'fraction_non_alphanumeric': 0.09988257235615114, 'fraction_numerical': 0.0031083788077640394, 'mean_word_length': 1.886939182452642, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5312268', 'n_tokens_mistral': 4134, 'n_tokens_neox': 3980, 'n_words': 896}