1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.build.checkapi
18
19import androidx.build.Version
20import com.google.common.io.Files
21import org.gradle.api.DefaultTask
22import org.gradle.api.GradleException
23import org.gradle.api.tasks.Input
24import org.gradle.api.tasks.InputFile
25import org.gradle.api.tasks.Optional
26import org.gradle.api.tasks.OutputFile
27import org.gradle.api.tasks.TaskAction
28import java.io.File
29import java.nio.charset.Charset
30import java.util.HashSet
31
32/**
33 * Task for updating the checked in API file with the newly generated one.
34 */
35open class UpdateApiTask : DefaultTask() {
36    @get:InputFile
37    lateinit var newApiFile: File
38    @get:[InputFile Optional]
39    var newRemovedApiFile: File? = null
40
41    @get:[Input Optional]
42    var whitelistErrors: Set<String> = HashSet()
43
44    @get:OutputFile
45    lateinit var oldApiFile: File
46    @get:[OutputFile Optional]
47    var oldRemovedApiFile: File? = null
48
49    @get:[OutputFile Optional]
50    var whitelistErrorsFile: File? = null
51
52    /**
53     * Actually copy the file to the desired location and update the whitelist warnings file.
54     */
55    @TaskAction
56    fun doUpdate() {
57        if (oldApiFile.exists() && newApiFile.readText() == oldApiFile.readText()) {
58            // whatever nothing changed
59            return
60        }
61
62        val version = Version(project.version as String)
63        if (version.isPatch()) {
64            throw GradleException("Public APIs may not be modified in patch releases.")
65        } else if (version.isFinalApi() && oldApiFile.exists() && !project.hasProperty("force")) {
66            throw GradleException("Public APIs may not be modified in finalized releases.")
67        }
68
69        Files.copy(newApiFile, oldApiFile)
70
71        if (oldRemovedApiFile != null) {
72            if (newRemovedApiFile != null) {
73                Files.copy(newRemovedApiFile!!, oldRemovedApiFile!!)
74            } else {
75                oldRemovedApiFile!!.delete()
76            }
77        }
78
79        if (whitelistErrorsFile != null && !whitelistErrors.isEmpty()) {
80            Files.newWriter(
81                    whitelistErrorsFile!!, Charset.defaultCharset()).use { writer ->
82                for (error in whitelistErrors) {
83                    writer.write(error + "\n")
84                }
85            }
86            logger.lifecycle("Whitelisted " + whitelistErrors.size + " error(s)...")
87        }
88
89        logger.lifecycle("Wrote public API definition to " + oldApiFile.name)
90    }
91}
92