On Thu, Aug 8, 2013 at 2:29 PM, Luke Daley <luke.da...@gradleware.com>wrote:
> > 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). I agree with you there. > > > 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. > Cool. > > > 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. > > So we need to maintain the infection of the backwards compatible stuff with a non-backwards compatible class, to preserve backwards compatibility? Ouch. This is why I write web services instead of binary APIs. ;-) Fair enough. In this case I have a couple of suggestions: 1. Deprecate AbstractCopyTask. 2. Add a big fat warning to the javadoc/groovydoc so that innocent plugin writers (as well as not-so-innocent ones like me) know not to use it. Preferably with a suggested alternative. > > 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. I imagine so, and since I'm working on a project that uses it, I guess I'll give it a try and see what happens. Any quick advice on the best way to write an archive task that archives things completely differently? Implement CopySpec? Is there something I can wrap to do most of the heavy lifting? > > > > 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 > > >