kobalt-intellij-plugin icon indicating copy to clipboard operation
kobalt-intellij-plugin copied to clipboard

Wrapper files in project dir

Open dmitry-zhuravlev opened this issue 9 years ago • 15 comments
trafficstars

Every time when some Kobalt tasks executed within IDEA the following directories and files created:

{PROJECT_HOME_DIR}/kobalt/src/wrapper {PROJECT_HOME_DIR}/.kobalt {PROJECT_HOME_DIR}/kobaltw

But after distribution update in {HOME}/.kobalt/wrapper/dist the wrapper version in {PROJECT_HOME_DIR} becomes outdated and this lead to some version hell...

@cbeust So the question is: do we really need to generate this wrapper stuff in the project? Since this wrapper still refer to {HOME}/.kobalt/wrapper/dist/kobalt-${version}/.../kobalt-${version}.jar it is useless to keep wrapper in {PROJECT_HOME_DIR}.

dmitry-zhuravlev avatar May 10 '16 19:05 dmitry-zhuravlev

Generating these in the project allows that project to have its own independent Kobalt version. I think this scheme (which Gradle uses) works well.

What kind of dependency hell are you referring to? Let's try to fix that instead.

Cédric

On Tue, May 10, 2016 at 11:12 AM, Dmitry Zhuravlev <[email protected]

wrote:

Assigned #28 https://github.com/cbeust/kobalt-intellij-plugin/issues/28 to @cbeust https://github.com/cbeust.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/cbeust/kobalt-intellij-plugin/issues/28#event-656222661

cbeust avatar May 10 '16 21:05 cbeust

The problem is with version mismatch between wrapper existing in the project and new distribution which plugin downloads and install. After downloading a new distribution plugin updates "Build.kt" module with a new "kobalt.jar". Maybe we shouldn't always download a new distribution but only with a user permit? If user wants to download and install a new version then a wrapper inside the project should be upgraded too.

dmitry-zhuravlev avatar May 11 '16 08:05 dmitry-zhuravlev

Also Gradle have much less files in wrapper:

gradlew gradlew.bat gradle/wrapper/ gradle-wrapper.jar gradle-wrapper.properties

But Kobalt beside simmilar files have also: image

Maybe this set of files for wrapper could be somehow minimized?

dmitry-zhuravlev avatar May 11 '16 08:05 dmitry-zhuravlev

The one discrepancy between what Kobalt does when it updates itself and how the IDEA plug-in updates is that the IDEA plug-in probably doesn't update wrapperVersion.txt, so we should fix that.

Other than that, can you give a concrete example of a problem? What happened? Did something crash?

cbeust avatar May 11 '16 12:05 cbeust

Updating wrapperVersion.txt isn't enough I think, because wrapper itself can be changed since update.

Other than that, can you give a concrete example of a problem? What happened? Did something crash?

Not really crash. It works. But the problem is in update itself. Just downloading a new distribution not enough without wrapper update. But if we update everytime wrapper that means that we don't need wrapper :) As I understand the main purpose of wrapper (like in Gradle) is to hold the given version of Kobalt and not to update it everytime. So we need to improve the policy to update of distribution... Maybe we need to make additional button and if user click on this button then everyting in project updated (wrapper+new distribution downloaded). What do you think?

dmitry-zhuravlev avatar May 11 '16 12:05 dmitry-zhuravlev

Actually, the only reason for the wrapper is that without it, it's much harder to update. For example, if you invoke the following code:

java -jar foo.jar foo.Main

then that code is not guaranteed to be able to update foo.jar since it's in use by the current process (will fail on Windows for sure).

One potential workaround could be that the code would spawn a process that will update that jar file once the first process dies, but that's not ideal either.

Having said that, I would love it if we could completely remove the wrapper but I don't see an easy way out right now. Do you?

cbeust avatar May 11 '16 12:05 cbeust

Amending my post above.

Actually, the main value is more that you can switch the version number by editing a text file (kobalt-wrapper.properties). I think this is desirable.

Can we maintain this functionality without kobalt-wrapper.jar?

cbeust avatar May 11 '16 12:05 cbeust

Having said that, I would love it if we could completely remove the wrapper but I don't see an easy way out right now. Do you?

I think that we shouldn't completelly remove wrapper, otherwise how user can prevent update to the latest version if he didn't want to do so?

dmitry-zhuravlev avatar May 11 '16 14:05 dmitry-zhuravlev

That's my impression too, I can't think of another way to do this without a wrapper but just checking to make sure I'm not missing an obvious alternative.

cbeust avatar May 11 '16 16:05 cbeust

I'm taking another shot at documenting kobalt and it's hard to explain why the intellij plugin doesn't install the wrapper when it creates a new project. Without the wrapper, a project will not build on a CI server as easily as with it, and there's no good way to build from the command line.

@dmitry-zhuravlev what if there was a way for the IJ plugin to let kobalt install itself and create the project? Instead of the IJ plugin having to create the folders, the Build.kt, the wrapper, etc? The plugin would need only to run the equivalent of --init on the folder where the project should be created.

This would allow kobalt to evolve more independently of the IJ plugin.

pabl0rg avatar Mar 02 '17 21:03 pabl0rg

@pabl0rg

why the intellij plugin doesn't install the wrapper when it creates a new project.

IDEA plugin doesn't need this wrapper to execute Kobalt's build. In this case such wrapper spawn additional JVM process which is useless in this case.

a project will not build on a CI server as easily as with it

For that reason Kobalt can provide a task like "installWrapper" to generate it. So if user decide to move to comand line or use CI server he could generate the wrapper on his own.

what if there was a way for the IJ plugin to let kobalt install itself and create the project? Instead of the IJ plugin having to create the folders, the Build.kt, the wrapper, etc?

When user create a project using IDEA he primarily create an IDEA project. The Build.kt file will be created and adjusted in respect of IDEA project definition. Also the user can adjust Kobalt Build Script template in Editor > File and Code Templates. So he will have a more freedom to adjust project than just wrapper --init parameter.

This would allow kobalt to evolve more independently of the IJ plugin.

At the moment we have exactly which you call "evolve more independently". User can init java/kotlin project using Kobalt's wrapper "--init" command and then import project in IDEA. Or he could create IDEA project with Kobalt like build system by using UI wizzards and then use Kobalt like build system. So it is a two different use cases which normally shouldn't be intersected.

dmitry-zhuravlev avatar Mar 03 '17 13:03 dmitry-zhuravlev

Good points. So what we really need is to add an installWrapper task to Kobalt.

pabl0rg avatar Mar 03 '17 15:03 pabl0rg

But if you have kobaltw, you already have the wrapper, don't you?

cbeust avatar Mar 03 '17 17:03 cbeust

@cbeust I'm not sure I get your drift correctly. Are you saying the IDEA plugin could add a installWrapper "task" that uses kobaltw to install the wrapper? So it wouldn't be like the other tasks that kobalt itself exposes, but it could be listed as a task or something similar in the IDEA plugin?

pabl0rg avatar Mar 03 '17 20:03 pabl0rg

@cbeust @pabl0rg Just some example of how this task can look like:

@Task("installWrapper", "Task to install Kobalt wrapper in the project")
fun installWrapper(project: Project): TaskResult {
    val kobaltWrapperJarName = "kobalt-wrapper.jar"
    val kobaltWrapperBatFileName = "kobaltw.bat"
    val kobaltWrapperShFileName = "kobaltw"
    val currentDir = Paths.get(".").toAbsolutePath().normalize().toString()
    val wrapperLocationDir = currentDir + File.separator + "kobalt" + File.separator + "wrapper"
    val kobaltWrapperJarFile = File(project.javaClass.protectionDomain.codeSource?.location?.toURI()).parentFile?.listFiles { _, name -> name == kobaltWrapperJarName }?.getOrNull(0) ?: return TaskResult(false, errorMessage = "Cannot find $kobaltWrapperJarName")
    val binDirectory = File(project.javaClass.protectionDomain.codeSource?.location?.toURI()).parentFile?.parentFile?.parentFile?.listFiles { _, name -> name == "bin" }?.getOrNull(0) ?: return TaskResult(false, errorMessage = "Cannot find 'bin' directory")
    val kobaltWrapperBatFile = binDirectory.listFiles { _, name -> name == kobaltWrapperBatFileName }?.getOrNull(0) ?: return TaskResult(false, errorMessage = "Cannot find $kobaltWrapperBatFileName")
    val kobaltWrapperShFile = binDirectory.listFiles { _, name -> name == kobaltWrapperShFileName }?.getOrNull(0) ?: return TaskResult(false, errorMessage = "Cannot find $kobaltWrapperShFileName")
    File(wrapperLocationDir + File.separator + kobaltWrapperJarName).run {
        if (!exists()) mkdirs()
        Files.copy(kobaltWrapperJarFile.toPath(), FileOutputStream(this))
        println("Created $absolutePath")
    }
    File(currentDir + File.separator + kobaltWrapperBatFileName).run {
        Files.copy(kobaltWrapperBatFile.toPath(), FileOutputStream(this))
        println("Created $absolutePath")
    }

    File(currentDir + File.separator + kobaltWrapperShFileName).run {
        Files.copy(kobaltWrapperShFile.toPath(), FileOutputStream(this))
        println("Created $absolutePath")
    }
    return TaskResult()
}

dmitry-zhuravlev avatar Apr 11 '17 13:04 dmitry-zhuravlev