1d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis/* 2ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlis * Copyright 2018 The Android Open Source Project 3d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 4d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Licensed under the Apache License, Version 2.0 (the "License"); 5d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * you may not use this file except in compliance with the License. 6d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * You may obtain a copy of the License at 7d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 8ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlis * http://www.apache.org/licenses/LICENSE-2.0 9d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 10d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Unless required by applicable law or agreed to in writing, software 11d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * distributed under the License is distributed on an "AS IS" BASIS, 12d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * See the License for the specific language governing permissions and 14ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlis * limitations under the License. 15d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis */ 16d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 17ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlispackage com.android.tools.build.jetifier.plugin.gradle 18d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 19ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.core.config.ConfigParser 20ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.processor.FileMapping 21d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.DefaultTask 22d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.Project 23d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.file.FileCollection 24d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.tasks.InputFiles 25d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.tasks.OutputDirectory 26d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport org.gradle.api.tasks.TaskAction 27d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisimport java.io.File 28d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 29d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis/** 30d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Task that processes given file collections using Jetifier. 31d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 32d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * This task also utilizes Gradle caching so it's run only when needed. 33d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 34d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Example usage in Gradle: 35d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * dependencies { 36d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * compile jetifier.process('groupId:artifactId:1.0') 37d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * } 38d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis */ 39d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlisopen class JetifyLibsTask : DefaultTask() { 40d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 41d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis companion object { 42d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis const val TASK_NAME = "jetifyLibs" 43d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis const val GROUP_ID = "Pre-build" 44d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis const val DESCRIPTION = "Rewrites input libraries to run with jetpack" 45d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 46d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis const val OUTPUT_DIR_APPENDIX = "jetifier" 47d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 4849f7010e84f8819274924817443b26fc3a117e22Filip Pavlis fun resolveTask(project: Project): JetifyLibsTask { 49d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis val task = project.tasks.findByName(TASK_NAME) as? JetifyLibsTask 50d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis if (task != null) { 51d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis return task 52d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 53d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis return project.tasks.create(TASK_NAME, JetifyLibsTask::class.java) 54d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 55d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 56d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 57d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis private val outputDir = File(project.buildDir, OUTPUT_DIR_APPENDIX) 58d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 5949f7010e84f8819274924817443b26fc3a117e22Filip Pavlis private val filesToProcess = mutableSetOf<FileMapping>() 60d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 61d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis override fun getGroup() = GROUP_ID 62d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 63d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis override fun getDescription() = DESCRIPTION 64d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 65d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis /** 66d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Adds individual files collection to be processed by Jetifier. 67d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * 68d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * See [JetifierExtension] for details on how to use this. 69d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis */ 7049f7010e84f8819274924817443b26fc3a117e22Filip Pavlis fun addFilesToProcess(files: FileCollection): FileCollection { 7149f7010e84f8819274924817443b26fc3a117e22Filip Pavlis return project.files(files.map { addFile(it).to }.toList()) 7249f7010e84f8819274924817443b26fc3a117e22Filip Pavlis } 7349f7010e84f8819274924817443b26fc3a117e22Filip Pavlis 7449f7010e84f8819274924817443b26fc3a117e22Filip Pavlis private fun addFile(file: File): FileMapping { 7549f7010e84f8819274924817443b26fc3a117e22Filip Pavlis val mappingMaybe = filesToProcess.firstOrNull { it.from == file } 7649f7010e84f8819274924817443b26fc3a117e22Filip Pavlis if (mappingMaybe != null) { 7749f7010e84f8819274924817443b26fc3a117e22Filip Pavlis return mappingMaybe 7849f7010e84f8819274924817443b26fc3a117e22Filip Pavlis } 7949f7010e84f8819274924817443b26fc3a117e22Filip Pavlis 8049f7010e84f8819274924817443b26fc3a117e22Filip Pavlis val newFile = File(outputDir, file.hashCode().toString() + "_" + file.name) 8149f7010e84f8819274924817443b26fc3a117e22Filip Pavlis val mapping = FileMapping(file, newFile) 8249f7010e84f8819274924817443b26fc3a117e22Filip Pavlis filesToProcess.add(mapping) 8349f7010e84f8819274924817443b26fc3a117e22Filip Pavlis return mapping 84d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 85d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 86d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis /** 87d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Used by Gradle to figure out whether this task should be re-run. If the result of this method 88d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * is different then the task is re-run. 89d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis */ 90d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis @InputFiles 9149f7010e84f8819274924817443b26fc3a117e22Filip Pavlis fun getInputFiles(): FileCollection { 9249f7010e84f8819274924817443b26fc3a117e22Filip Pavlis return project.files(filesToProcess.map { it.from }.toList()) 93d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 94d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 95d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis /** 96d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * Used by Gradle to figure out whether this task should be re-run and if other tasks that are 97d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * relying on files from this directory should be re-run. Actually not having this and only 98d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * having [InputFiles] annotation would disable the whole incremental mechanism for this task 99d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis * and lead to constant re-runs. 100d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis */ 101d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis @OutputDirectory 10249f7010e84f8819274924817443b26fc3a117e22Filip Pavlis fun getOutputDir(): File { 103d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis return outputDir 104d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 105d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 106d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis @TaskAction 107d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis @Throws(Exception::class) 108d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis fun run() { 109d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis val config = ConfigParser.loadConfigOrFail(TasksCommon.configFilePath) 110d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis 111d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis // Process the files using Jetifier 11249f7010e84f8819274924817443b26fc3a117e22Filip Pavlis TasksCommon.processFiles(config, filesToProcess, project.logger) 113d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis } 114d7b0788f3bf58fc26a936c2426ef1214ffb3a180Filip Pavlis}