<lambda>null1 package task
2 
3 import org.gradle.api.Action
4 import org.gradle.api.DefaultTask
5 import org.gradle.api.file.ConfigurableFileTree
6 import org.gradle.api.file.DirectoryProperty
7 import org.gradle.api.file.FileType
8 import org.gradle.api.file.ProjectLayout
9 import org.gradle.api.provider.Property
10 import org.gradle.api.tasks.Input
11 import org.gradle.api.tasks.InputFiles
12 import org.gradle.api.tasks.OutputDirectory
13 import org.gradle.api.tasks.TaskAction
14 import org.gradle.api.tasks.util.PatternFilterable
15 import org.gradle.work.ChangeType
16 import org.gradle.work.Incremental
17 import org.gradle.work.InputChanges
18 import java.io.File
19 import java.nio.file.Files
20 import javax.inject.Inject
21 import kotlin.io.path.Path
22 
23 @Suppress("LeakingThis")
24 internal abstract class SymlinkSourcesTask : DefaultTask() {
25     @get:Input
26     abstract val sourcesRoot: Property<String>
27 
28     @get:InputFiles
29     @get:Incremental
30     protected abstract val files: ConfigurableFileTree
31 
32     fun files(filter: Action<PatternFilterable>) {
33         filter.execute(files)
34     }
35 
36     @get:OutputDirectory
37     abstract val destinationDir: DirectoryProperty
38 
39     @get:Inject
40     protected abstract val layout: ProjectLayout
41 
42     init {
43         group = "symlink"
44         files.from(sourcesRoot)
45     }
46 
47     @TaskAction
48     fun execute(inputChanges: InputChanges) {
49         val sourcesRootDir = File(sourcesRoot.get())
50         inputChanges.getFileChanges(files).forEach { change ->
51             val file = change.file
52             val relativePath = file.canonicalFile.relativeTo(sourcesRootDir)
53             val symbolicLinkPath = Path("${destinationDir.get()}/$relativePath")
54             val symbolicLinkFile = symbolicLinkPath.toFile()
55             if (file !in files && file.absolutePath != sourcesRootDir.absolutePath) {
56                 logger.info("Cleaning up filtered out symlink {}", symbolicLinkPath)
57                 symbolicLinkFile.deleteRecursively()
58             } else if (change.changeType == ChangeType.REMOVED) {
59                 logger.info("Removing symbolic link at {}", symbolicLinkPath)
60                 symbolicLinkFile.deleteRecursively()
61             } else if (change.fileType == FileType.FILE && change.changeType == ChangeType.ADDED && !symbolicLinkFile.exists()) {
62                 logger.info("Creating symbolic link to {}", file.path)
63                 symbolicLinkFile.parentFile.mkdirs()
64                 Files.createSymbolicLink(symbolicLinkPath, file.toPath())
65             }
66         }
67     }
68 }