All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.com.xml.guard.tasks.MoveDirTask.kt Maven / Gradle / Ivy

package com.xml.guard.tasks

import com.xml.guard.entensions.GuardExtension
import com.xml.guard.utils.*
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.TaskAction
import java.io.File
import javax.inject.Inject

/**
 * User: ljx
 * Date: 2022/2/25
 * Time: 19:06
 */
open class MoveDirTask @Inject constructor(
    private val guardExtension: GuardExtension,
    private val variantName: String,
) : DefaultTask() {

    init {
        group = "guard"
    }

    @TaskAction
    fun execute() {
        val moveFile = guardExtension.moveDir
        if (moveFile.isEmpty()) return
        val androidProjects = allDependencyAndroidProjects(project)
        androidProjects.forEach { it.moveDir(moveFile) }
    }

    private fun Project.moveDir(moveFile: Map) {
        // 查找清单文件里的package属性值
        val manifestPackage = findPackage()
        // 1、替换manifest文件 、layout、navigation、xml目录下的文件、Java、Kt文件
        val dirs = findXmlDirs(variantName, "layout", "navigation", "xml")
        dirs.add(manifestFile())
        val aidlDirs = aidlDirs(variantName)
        dirs.addAll(aidlDirs)
        val javaDirs = javaDirs(variantName)
        dirs.addAll(javaDirs)
        val moveDirs = mutableListOf()
        moveDirs.addAll(aidlDirs)
        moveDirs.addAll(javaDirs)
        files(dirs).asFileTree.forEach {
            it.replaceText(moveFile, manifestPackage)
        }

        // 2、开始移动目录
        moveFile.forEach { (oldPath, newPath) ->
            val oldPackagePath = oldPath.replace(".", File.separator)
            for (javaDir in moveDirs) {
                val oldDir = File(javaDir, oldPackagePath)
                if (!oldDir.exists()) {
                    continue
                }
                if (oldPath == manifestPackage) {
                    // 包名目录下的直接子类移动位置,需要重新手动导入R类及BuildConfig类(如果有用到的话)
                    oldDir.listFiles { f -> !f.isDirectory }?.forEach { file ->
                        file.insertImportXxxIfAbsent(oldPath)
                    }
                }
                val oldRelativePath = oldPath.replace(".", File.separator)
                val newRelativePath = newPath.replace(".", File.separator)
                oldDir.allFiles().forEach {
                    val toPath = it.absolutePath.replace(
                        "${File.separator}$oldRelativePath${File.separator}",
                        "${File.separator}$newRelativePath${File.separator}"
                    )
                    val toFilename = File(toPath)
                    if (!toFilename.exists()) toFilename.parentFile.mkdirs()
                    it.renameTo(toFilename)
                }
            }
        }
    }

    private fun File.allFiles(): List {
        val files = mutableListOf()
        listFiles()?.forEach {
            if (it.isDirectory) {
                files.addAll(it.allFiles())
            } else {
                files.add(it)
            }
        }
        return files
    }

    private fun File.replaceText(map: Map, manifestPackage: String) {
        var replaceText = this.readText()

        if ((this.isKt || this.isJava)
            && replaceText.contains("${manifestPackage}.*")
        ) {
            replaceText = this.insertImportXxxIfAbsent(manifestPackage)
        }

        map.forEach { (oldPath, newPath) ->
            replaceText = when {
                this.isAndroidManifest && oldPath == manifestPackage -> {
                    replaceText.replaceWords("$oldPath.", "$newPath.")
                        .replaceWords("""android:name=".""", """android:name="${newPath}.""")
                }
                else -> {
                    replaceText.replaceWords(oldPath, newPath)
                }
            }
            if (this.isKt || this.isJava) {
                // 移动目录时,manifest里的package属性不会更改,上面代码会将将R、BuildConfig等类路径替换掉,所以这里需要还原回去
                replaceText = replaceText
                    .replaceWords("$newPath.R", "$oldPath.R")
                    .replaceWords("$newPath.BR", "$oldPath.BR")
                    .replaceWords("$newPath.BuildConfig", "$oldPath.BuildConfig")
                    .replaceWords("$newPath.databinding", "$oldPath.databinding")
            }
        }
        writeText(replaceText)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy