On 08/08/2013, at 2:01 PM, Sean Reilly <seanjrei...@gmail.com> wrote:
> Luke, > > Thanks for the info. Comments inline: > > >>> I'm fine with that if that's really the case, but if so, is it possible >> for Gradle to emit (suitably grave) warnings if a plugin author uses the >> internal api at all? I don't want to use gradle plugins that drastically >> fail when I upgrade to a new version of gradle. >> There would be a pretty severe cost on doing this at runtime. It's >> something we can look into though. It's not an easy problem to solve. > > > Fair enough. Off of the top of my head the only thing that would work would > be some sort of classloader hierarchy for plugins, so that they would fail > period if they tried to access internal packages. I'm sure that this would > get really complicated really quickly, and it would probably just result in > a poor implementation of OSGi. Blech. There are long term plans to make a stronger boundary between the public/internal space. However, there is no plan to enforce runtime separation. I personally (other devs may feel different) don't want to go down this route. 3rd party code should be allowed to use internal API if they wish, but they take on the responsibility that comes with that (i.e. no guarantee of any kind of cross version compatibility). > One option I just thought of is a compile-time tool (e.g., a template > gradle project that could be used by plugin authors, etc) that warns when > internal classes are used at plugin build time. I don't have time to build > one, and I'm not suggesting that you do either — just registering it in > case someone else brings this up later... I like this better, and it's more realistic. We need a similar kind of reporting function for use of deprecated API. > Internal APIs can change at any time without notice. >> Internal classes are under an 'internal' package name space. > > > That's fair, but IMO it's only fair if the public, backwards compatible > apis don't depend on (or import) the private ones. You're right, more below. > I've taken a closer look, and it seems to me that in order to extend > AbstractCopyTask (which doesn't look internal, as it's not in any internal > package, right?), you are *required* to implement the getCopyAction() > method and return an instance of > org.gradle.api.internal.file.copy.CopyActionImpl, which is in the internal > package. So it looks to me like the internal api is 'infecting' the > org.gradle.api.tasks namespace. > > Is AbstractCopyTask in the wrong package (i.e., should it really be an > internal class?), It is, but we can't move it because that breaks binary compatibility. We have a historical leak with the copy task stuff that will be awkward until Gradle 2.0. We are in a bit of a mixed state here. > or is there some other suggested way of writing an > archive task other than subclassing AbstractArchiveTask/AbstractCopyTask? Effectively to use composition over inheritance. Subclassing tasks is problematic, but not always avoidable currently in Gradle. After a quick look at the RPM plugin, I can see why the author used subclassing as it's the most obvious solution to implement. I'm in no way assigning any blame there. However, many other parts of the plugin are using other parts of uncontentious internal api and will need to change. It's going to have to be rewritten. > > Cheers, > > Sean > > > > On Thu, Aug 8, 2013 at 12:57 PM, Luke Daley <luke.da...@gradleware.com>wrote: > >> >> On 08/08/2013, at 12:13 PM, Sean Reilly <seanjrei...@gmail.com> wrote: >> >>> So it's the plugin author's problem, and that's it? >> >> Internal APIs can change at any time without notice. >> >> Internal classes are under an 'internal' package name space. >> >>> I'm fine with that if that's really the case, but if so, is it possible >> for Gradle to emit (suitably grave) warnings if a plugin author uses the >> internal api at all? I don't want to use gradle plugins that drastically >> fail when I upgrade to a new version of gradle. >> >> There would be a pretty severe cost on doing this at runtime. It's >> something we can look into though. It's not an easy problem to solve. >> >>> And if that's not the case, and using the internal API is sometimes ok, >> is it possible to write a plugin that works with gradle 1.6 and 1.7 without >> using resorting to reflection? >> >> It depends on exactly how the API is being used. There's no simple answer >> to this question. >> >>> >>> Cheers, >>> >>> Sean >>> >>> >>> On Thu, Aug 8, 2013 at 12:08 PM, Luke Daley <luke.da...@gradleware.com> >> wrote: >>> Hi Sean, >>> >>> The RPM plugin is using internal API, which changed in this release. >>> >>> The RPM plugin will need to be updated. >>> >>> On 08/08/2013, at 11:52 AM, Sean Reilly <seanjrei...@gmail.com> wrote: >>> >>>> Hi All, >>>> >>>> I'm attempting to upgrade from gradle 1.6 to gradle 1.7, and I think >> I've encountered a potential backwards compatibility issue. >>>> >>>> I'm using the RPM plugin as follows: >>>> >>>> buildscript { >>>> repositories { >>>> mavenCentral() >>>> } >>>> dependencies { >>>> classpath 'com.trigonic:gradle-rpm-plugin:1.3' >>>> } >>>> } >>>> >>>> apply plugin: 'war' >>>> apply plugin: 'rpm' >>>> >>>> task rpm(type: Rpm, dependsOn: war) { >>>> packageName = "blah-${project.name}" >>>> version = "1.0.1" >>>> release = revision >>>> arch = NOARCH >>>> os = LINUX >>>> //more configuration, etc >>>> } >>>> >>>> Under gradle 1.6, this works fine, but if I run the same script with >> gradle 1.7, the build fails. >>>> >>>> >>>> I've included the stack trace below. At first glance it looks like a >> method has been removed from a gradle api class. >>>> >>>> Cheers, >>>> >>>> Sean >>>> >>>> >>>> FAILURE: Build failed with an exception. >>>> >>>> * Where: >>>> Script '/Users/sreilly/Projects/XXX/build.gradle' line: XXX >>>> >>>> * What went wrong: >>>> A problem occurred evaluating script. >>>>> Could not create task of type 'Rpm'. >>>> >>>> * Try: >>>> Run with --info or --debug option to get more log output. >>>> >>>> * Exception is: >>>> org.gradle.api.GradleScriptException: A problem occurred evaluating >> script. >>>> at >> org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:54) >>>> at >> org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:131) >>>> at >> org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.applyScript(DefaultObjectConfigurationAction.java:82) >>>> at >> org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.access$000(DefaultObjectConfigurationAction.java:32) >>>> at >> org.gradle.api.internal.plugins.DefaultObjectConfigurationAction$1.run(DefaultObjectConfigurationAction.java:54) >>>> at >> org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.execute(DefaultObjectConfigurationAction.java:114) >>>> at >> org.gradle.api.internal.project.AbstractPluginAware.apply(AbstractPluginAware.java:39) >>>> at >> org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:248) >>>> at >> org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:136) >>>> at >> org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:147) >>>> at >> org.gradle.api.internal.project.DefaultProject_Decorated.invokeMethod(Unknown >> Source) >>>> at >> org.gradle.api.internal.project.ProjectScript.apply(ProjectScript.groovy:34) >>>> at org.gradle.api.Script$apply.callCurrent(Unknown Source) >>>> at >> build_3ouab9f94ai0o2vmdevnmfcojb.run(/Users/sreilly/Projects/TelefonicaInsightServices/smartsteps/rest/build.gradle:4) >>>> at >> org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:52) >>>> at >> org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:131) >>>> at >> org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:38) >>>> at >> org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:25) >>>> at >> org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:34) >>>> at >> org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:55) >>>> at >> org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:469) >>>> at >> org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:77) >>>> at >> org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:31) >>>> at >> org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:142) >>>> at >> org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:113) >>>> at >> org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:81) >>>> at >> org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:64) >>>> at >> org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33) >>>> at >> org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24) >>>> at >> org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:35) >>>> at >> org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26) >>>> at >> org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:50) >>>> at >> org.gradle.api.internal.Actions$RunnableActionAdapter.execute(Actions.java:171) >>>> at >> org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:201) >>>> at >> org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:174) >>>> at >> org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:170) >>>> at >> org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:139) >>>> at >> org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33) >>>> at >> org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22) >>>> at org.gradle.launcher.Main.doAction(Main.java:48) >>>> at >> org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45) >>>> at org.gradle.launcher.Main.main(Main.java:39) >>>> at >> org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:50) >>>> at >> org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:32) >>>> at org.gradle.launcher.GradleMain.main(GradleMain.java:26) >>>> Caused by: org.gradle.api.tasks.TaskInstantiationException: Could not >> create task of type 'Rpm'. >>>> at >> org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:115) >>>> at >> org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:110) >>>> at >> org.gradle.api.internal.AbstractTask.injectIntoNewInstance(AbstractTask.java:145) >>>> at >> org.gradle.api.internal.project.taskfactory.TaskFactory.createTaskObject(TaskFactory.java:110) >>>> at >> org.gradle.api.internal.project.taskfactory.TaskFactory.createTask(TaskFactory.java:70) >>>> at >> org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory.createTask(AnnotationProcessingTaskFactory.java:100) >>>> at >> org.gradle.api.internal.project.taskfactory.DependencyAutoWireTaskFactory.createTask(DependencyAutoWireTaskFactory.java:39) >>>> at >> org.gradle.api.internal.tasks.DefaultTaskContainer.create(DefaultTaskContainer.java:55) >>>> at >> org.gradle.api.internal.project.AbstractProject.task(AbstractProject.java:912) >>>> at >> org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:248) >>>> at >> org.gradle.api.internal.BeanDynamicObject.invokeMethod(BeanDynamicObject.java:136) >>>> at >> org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:147) >>>> at >> org.gradle.groovy.scripts.BasicScript.methodMissing(BasicScript.java:83) >>>> at >> rpm_support_4gv6ia50cgflj085708i87sqoi.run(/Users/sreilly/Projects/TelefonicaInsightServices/smartsteps/rpm-support.gradle:3) >>>> at >> org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:52) >>>> ... 44 more >>>> Caused by: java.lang.NoSuchMethodError: >> org.gradle.api.internal.file.copy.CopyActionImpl.<init>(Lorg/gradle/api/internal/file/FileResolver;Lorg/gradle/api/internal/file/copy/CopySpecVisitor;)V >>>> at >> com.trigonic.gradle.plugins.rpm.Rpm$RpmCopyAction.<init>(Rpm.groovy:154) >>>> at com.trigonic.gradle.plugins.rpm.Rpm.<init>(Rpm.groovy:62) >>>> at com.trigonic.gradle.plugins.rpm.Rpm_Decorated.<init>(Unknown >> Source) >>>> at >> org.gradle.api.internal.DependencyInjectingInstantiator.newInstance(DependencyInjectingInstantiator.java:62) >>>> at >> org.gradle.api.internal.ClassGeneratorBackedInstantiator.newInstance(ClassGeneratorBackedInstantiator.java:36) >>>> at >> org.gradle.api.internal.project.taskfactory.TaskFactory$1.call(TaskFactory.java:113) >>>> ... 58 more >>>> >>>> >>>> BUILD FAILED >>>> >>> >>> -- >>> Luke Daley >>> Principal Engineer, Gradleware >>> http://gradleware.com >>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe from this list, please visit: >>> >>> http://xircles.codehaus.org/manage_email >>> >>> >>> >> >> -- >> Luke Daley >> Principal Engineer, Gradleware >> http://gradleware.com >> >> >> --------------------------------------------------------------------- >> To unsubscribe from this list, please visit: >> >> http://xircles.codehaus.org/manage_email >> >> >> -- Luke Daley Principal Engineer, Gradleware http://gradleware.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email