When and why should I prefer using `Directory` and...
# community-support
s
When and why should I prefer using
Directory
and
RegularFile
over
File
in my API? The API that Gradle provides for working with Directory and RegularFile objects seems to be a bit lacking compared to plain Files.
v
Why should there be a reason not to do it? :-) There imho is no real lack in API. They have methods to resolve other directories and files, and they represent whether something is a file or directory. For any other operation you use the underlying
File
with
asFile
or what it was called.
s
There's a
project.file(Object)
method that gives you a File from whatever you pass to it. There's no such method to get a
Directory
or
RegularFile
from a String or a File. There's one method to get it from String (but NOT from a File) using
project.layout.projectDirectory.file
which is a lot to write. There's a different method,
project.layout.file
to get a
Provider<RegularFile>
from a Provider<File> (but NOT from a Provider<String>). This is what I call a lacking API. Whether it's a "real" lack or not is debatable.
(You can set a DirectoryProperty or a RegularFileProperty from a File but in my case I need to decide between
MapProperty<String, Directory>
and
MapProperty<String, File>
and it seems like the File option would be easier for the users to fill.)
v
File
might be easier to fill, but
Directory
has more semantic and clearly states in the type that you need a directory, not a file. That the new ways are a bit longer is right, but that is because the old ways are too short and type-un-unsafe. Back in the beginning many things were added as "convention property" or method directly to the
Project
instance and many things accepted
Object
as argument. This made it quite comfortable to use non-intelligently from Groovy DSL due to its duck-typing, so you can access any method and any property that just is there, independent of the type. But this also meant that things like methods taking
Object
could only fail at runtime. With the introduction of Kotlin DSL and thus more type-safety in the build scripts, this trend reversed and things are usually not added anymore to the
Project
instance dynamically, but to extensions, methods do not accept
Object
anymore, but the things they accept, ... This allows to fail early at compile time already and also to have much more intelligence in the support by a good IDE. So yes, if you nowaday want to get a modern version of a file relative to the project directory by
String
, you usually use
layout.projectDirectory.file(...)
. And if you want it from a
File
you would use
layout.file(provider { theFile })
, and thus could also use
layout.file(provider { file(whatever) })
if you really want to.
This is what I call a lacking API. Whether it's a "real" lack or not is debatable.
I'd say not, it is clear API. For
layout.projectDirectory.file
it does not make much sense to accept a
File
as it represents a file with path and could also be an absolute path, this would make the API less clear and more complex regarding what happens when, and also a user can always transform the
File
to a
String
with the information he intends to be used like the full path as he knows it is a relative path, or just the name. For
layout.file
it does not make much sense to accept a
String
, as usually such strings are not absolute paths but relative paths and for relative paths you have
layout.projectDirectory
and
layout.buildDirectory
to make it crystal clear relative to what the path is resolved. But feel free to open feature requests or pull requests for the additional API, then you get to know what the Gradle folks think about it. I'm must a user like you. 🙂
s
So what API is there for absolute paths then?
v
layout.file()
for example?