This message was deleted.
# plugin-development
s
This message was deleted.
v
It's better you don't. Instead add an extension to
Project
that has that method. And also consider non-Project ways to access the method. For example with configuration cache at execution time, you must not access
Project
. So maybe provide a shared build service that consumers can get to use the method or something like that.
c
Adding extensions really only cover configuring data. I need a method that will construct a Zip4jFileTree object just like
zipTree()
does today. It seems like extensions should cover something like this, but all examples are just about configuring properties on Interfaces instead of registering services to invoke and perform logic. Could you sketch out what you mean by those suggestions?
v
Adding extensions really only cover configuring data
No, that's the most typical usage, but extensions can as well have methods that take arguments and return things
c
Ok great, but I haven’t run across any examples of that. Do you have some examples?
v
What do you need? An example of how to write a method?
c
An example of registering an extension that implements some logic that can be invoked from build.gradle files.
v
Just make your extension have a method
Registering is not in any way different
c
So far all of the extensions I’ve seen are interfaces.
v
But they don't need to be, it's just less boilerplate if you only have properties to set.
Make it an abstract class, with the properties abstract so that you don't need too much additional boilerplate and add your method
c
Ok so I could register a concrete class and implement what I need there?
v
You can even use a constructor of any arbitrary class and add that as extension, I just wouldn't recommend that. Because things created by Gradle get automatically decorated with things like
ExtensionAware
and you can get services you need injected and abstract properties implemented for you.
c
I have some other questions about access to certain services related to
AbstractArchiveFileTree
. To implement the methods required from that class I’d need access to
FileHasher
implementation and
DirectoryFileTreeFactory
implementation. Where would I get those from?
v
Those are all three internal classes, so you shouldn't and there might not be a good way to get hold of them from plugin code.
c
Maybe, but there doesn’t appear to be any other option for creating your own implementation of File Trees.
AbstractArchiveFileTree
implements
FileSystemMirroringFileTree
and that extends
MinimalFileTree
and
MinimalFileCollection
all of which are internal.
v
Well, you are probably not expected to implement your own. 😄
o
Unfortunately I think the best solution at the moment is to pass a
Callable
implementation (but not a java lambda, it cannot be serialized reliably) to
Project#files
that unzips into a temporary directory / cache somewhere and returns the files from disk.
c
I’m not sure I understand that suggestion. I was trying to integrate a different zip library that offers password protected zips and other features that don’t exist in Java’s native Zip libs.
t
here's a blog post demonstrating slightly non trivial extensions https://dev.to/autonomousapps/gradle-plugins-and-extensions-a-primer-for-the-bemused-51lp
o
Charlie: Yes, but as far as I am aware Gradle does not support custom FileCollection implementations. My suggestion is a way to expose a FileCollection for the zip contents, like zipTree does.
c
@tony Yes I read some of your article. I saw something like what I was hoping to do, but it was all in Kotlin and I’m working in Groovy so open classes doesn’t quite port over the same way. I think @Vampire answered my original question, but at this point we’re going back and forth on if it’s possible or how to work around the fact that Gradle didn’t expect for plugins to offer their own versions of FileCollections/FileTrees. Although if it did there are lots of examples where that could really extend the power of Gradle. Just imagine an S3FileCollection, SFTPFileCollection, etc.
👍 1
@Octavia Togami so is your suggestion to perform the immediately unzipping of the data upon FileCollection definition? So imagine if I had
zip4j.tree("…")
it would return a FileCollection or FileTree based on the contents of the zip extracted already? So
zip4j.tree("…")
-> unzip to tempDir and return
fileTree("${tempDir}")
?
o
No, my suggestion is to perform it inside a
Callable
so it's only unpacked when needed.
But yes, the process is otherwise as you say (though it's probably better to just use
fileTree(tempDir)
)
c
Ok so really wrap it like
zip4j.tree("…")
->return
fileTree( { unzip( tempDir ) } )
? I think I remember
file(..)
,
files(..)
,
fileTree(…)
can take in a
Closure
that returns a File or something along those lines.
o
fileTree( { unzip( tempDir ); return tempDir; } )
to be clear about what it should return; but assuming Groovy/Kotlin yes this should work. They can take a Closure, Kotlin function, or Callable that resolves to a File, String, (in the case of
files
) Iterable, and more: https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#file-java.lang.Object-
👍 1