Vladimir Sitnikov
04/28/2025, 7:22 AMConfigurableFileCollection
vs ListProperty<RegularFile>
Is there anything like “prefer ConfigurableFileCollection
in newer code” or “prefer ListProperty<RegularFile>
in newer code” ?
I assume the answer should be the same for both task properties and extension properties, however, it would be great to learn if there’s a difference.Vampire
04/28/2025, 7:24 AMVladimir Sitnikov
04/28/2025, 9:31 AMListProperty<RegularFile>
usages while I previously sticked to ConfigurableFileCollection
, so I decided to ask.
---
I saw AGP was migrating off FileCollection
, however, it looks like there was no CFC#finalizeValue()
back then.Vampire
04/28/2025, 11:52 AMConfigurableFileCollection
to Provider<...>
is because they want to lazify everything by using `Provider`s, but that is then just a misunderstanding, as ConfigurableFileCollection
is properly lazy already and if you need its contents as Provider<...>
, you can use FileCollection#elements
.Vampire
04/28/2025, 11:54 AMConfigurableFileCollection
to Property
predates the FileCollection.elements
method, so maybe back then it could have made sense. 🤷♂️Martin
04/28/2025, 2:03 PMRegularFile
?Martin
04/28/2025, 2:04 PMConfigurableFileCollection
can be "rooted" (if they are built from FileTree
). I don't think you can do the same with RegularFile
?Martin
04/28/2025, 2:05 PM*.graphql
in the hierarchy at src/main/graphql
to a task but that graphql path is not important. It could very well be under build/foobar/graphql
and the snapshotting should be exactly the same as long as the contents of the folder stays the same. You just can't do this with a ListProperty<RegularFile>
Emmanuel Guerin
04/29/2025, 3:16 PMFileCollection
to a Provider<RegularFile>
when it is expected the collection only has a single element.
For example in the case of a Task that has a RegularFileProperty
as input, and it needs to be passed something coming from a dependency resolution.
The best I have so far is this:
fun setFilePropertyFromCollection(fileProperty: RegularFileProperty, collection: FileCollection) {
fileProperty.fileProvider(collection.elements.map {
it.singleOrNull()?.asFile ?: throw IllegalArgumentException("FileCollection must contain exactly one element")
})
}
This seems to keep the task dependencies and all the right things. Do you have anything better?
But this transforms FileCollection
to a Provider<File>
. I don't know how it can be transformed into a Provider<RegularFile>
.Martin
04/29/2025, 3:39 PMFile
into a RegularFile
is tricking Gradle dependency injection:
abstract class Unused @Inject constructor( val files: FileFactory)
fun setFilePropertyFromCollection(collection: FileCollection): Provider<RegularFile> {
val factory = objects.newInstance(Unused::class.java)
return collection.elements.map {
val file = it.singleOrNull()?.asFile ?: throw IllegalArgumentException("FileCollection must contain exactly one element")
check(file.isFile)
factory.files.file(file)
}
}
Martin
04/29/2025, 3:39 PMProvider<File>
though 🤷Vladimir Sitnikov
04/29/2025, 3:41 PMlayout.file(provider { File(".") }
?
See https://chatgpt.com/share/6810f339-92ec-800f-8edd-89b32dbf93a6Martin
04/29/2025, 3:42 PMMartin
04/29/2025, 3:43 PMRegularFileProperty
and Provider<RegularFile>
Vladimir Sitnikov
04/29/2025, 3:44 PMProperty<RegularFile>
vs RegularFileProperty
?
The Provider<..>
does not have setter methods,Martin
04/29/2025, 3:45 PMMartin
04/29/2025, 3:46 PMProvider
and Property
, all the specialized classes like ListProperty
as well are complexifying stuff
But I'm rambling, don't mind meVladimir Sitnikov
04/29/2025, 3:46 PMVampire
04/29/2025, 5:08 PMval files: FileCollection = null!!
val fileProperty: RegularFileProperty = null!!
val file: Provider<RegularFile?> = layout.file(files.elements.map { it.single().asFile })
fileProperty.set(file)