mirror of
https://github.com/HighCapable/SweetDependency.git
synced 2025-09-08 03:24:29 +08:00
Initial commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/5/18.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.highcapable.sweetdependency.document
|
||||
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
|
||||
import com.highcapable.sweetdependency.manager.content.Repositories
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.toSpaceList
|
||||
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* 依赖每项文档实体
|
||||
* @param alias 别名
|
||||
* @param version 版本
|
||||
* @param versionRef 版本引用
|
||||
* @param versions 版本别名数组
|
||||
* @param isAutoUpdate 是否自动更新
|
||||
* @param versionFilter 版本过滤器文档实体
|
||||
* @param repositories 指定使用的存储库名称
|
||||
*/
|
||||
@Serializable
|
||||
internal data class DependencyDocument(
|
||||
@SerialName("alias")
|
||||
internal var alias: String = "",
|
||||
@SerialName("version")
|
||||
internal var version: String = "",
|
||||
@SerialName("version-ref")
|
||||
internal var versionRef: String = "",
|
||||
@SerialName("versions")
|
||||
internal var versions: MutableMap<String, String> = mutableMapOf(),
|
||||
@SerialName("auto-update")
|
||||
internal var isAutoUpdate: Boolean = true,
|
||||
@SerialName("version-filter")
|
||||
internal var versionFilter: VersionFilterDocument? = null,
|
||||
@SerialName("repositories")
|
||||
internal var repositories: String = ""
|
||||
) : IYamlDocument {
|
||||
|
||||
/**
|
||||
* 获取版本
|
||||
* @return [DependencyVersion]
|
||||
*/
|
||||
internal fun version() = DependencyVersion(version)
|
||||
|
||||
/**
|
||||
* 获取版本别名数组
|
||||
* @return <[MutableMap]><[String], [DependencyVersion]>
|
||||
*/
|
||||
internal fun versions() = mutableMapOf<String, DependencyVersion>().also {
|
||||
versions.forEach { (key, value) -> it[key] = DependencyVersion(value.replace(DependencyVersion.LATEST_VERSION_NAME, version)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新版本
|
||||
* @param newVersion 新版本
|
||||
*/
|
||||
internal fun updateVersion(newVersion: DependencyVersion) {
|
||||
version = newVersion.current
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新版本
|
||||
* @param document 当前文档实例
|
||||
*/
|
||||
internal fun updateVersion(document: DependencyDocument) {
|
||||
version = document.version
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定使用的存储库数组
|
||||
* @return [MutableList]<[RepositoryDocument]>
|
||||
*/
|
||||
internal fun repositories() = mutableListOf<RepositoryDocument>().apply {
|
||||
repositories.toSpaceList().forEach {
|
||||
add(Repositories.all().firstOrNull { e -> e.nodeName == it } ?: SError.make("Could not found repository with name \"$it\""))
|
||||
}
|
||||
}.distinctBy { it.url.ifBlank { it.path } }.toMutableList()
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/5/17.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document
|
||||
|
||||
import com.highcapable.sweetdependency.document.factory.checkingName
|
||||
import com.highcapable.sweetdependency.utils.camelcase
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.gradle.api.initialization.resolve.RepositoriesMode as GradleRepositoriesMode
|
||||
|
||||
/**
|
||||
* 偏好配置项文档实体
|
||||
* @param autowireOnSyncMode Gradle Sync 自动装配、更新依赖模式
|
||||
* @param repositoriesMode 存储库装载模式
|
||||
* @param dependenciesNamespace 依赖命名空间
|
||||
* @param versionFilter 版本过滤器文档实体
|
||||
*/
|
||||
@Serializable
|
||||
internal data class PreferencesDocument(
|
||||
@SerialName("autowire-on-sync-mode")
|
||||
internal var autowireOnSyncMode: AutowireOnSyncMode = AutowireOnSyncMode.UPDATE_OPTIONAL_DEPENDENCIES,
|
||||
@SerialName("repositories-mode")
|
||||
internal var repositoriesMode: RepositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS,
|
||||
@SerialName("dependencies-namespace")
|
||||
internal var dependenciesNamespace: DependenciesNamespaceDocument = DependenciesNamespaceDocument(),
|
||||
@SerialName("version-filter")
|
||||
internal var versionFilter: VersionFilterDocument = VersionFilterDocument()
|
||||
) : IYamlDocument {
|
||||
|
||||
@Serializable
|
||||
internal data class DependenciesNamespaceDocument(
|
||||
@SerialName("plugins")
|
||||
var plugins: String = "libs",
|
||||
@SerialName("libraries")
|
||||
var libraries: String = ""
|
||||
) : IYamlDocument {
|
||||
|
||||
init {
|
||||
if (plugins.isNotBlank() && libraries.isNotBlank() && plugins == libraries)
|
||||
SError.make("Duplicated dependencies namespace \"$plugins\"")
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件依赖命名空间
|
||||
* @return [String]
|
||||
*/
|
||||
internal fun plugins() = plugins.apply { checkingName("plugins namespace", isCheckExtName = true) }.camelcase()
|
||||
|
||||
/**
|
||||
* 获取库依赖命名空间
|
||||
* @return [String]
|
||||
*/
|
||||
internal fun libraries() = libraries.apply { checkingName("libraries namespace", isCheckExtName = true) }.camelcase()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gradle Sync 自动装配、更新依赖模式定义类
|
||||
*/
|
||||
internal enum class AutowireOnSyncMode {
|
||||
/** 自动装配和更新可选依赖 (插件依赖 + 库依赖) */
|
||||
UPDATE_OPTIONAL_DEPENDENCIES,
|
||||
|
||||
/** 自动装配和更新所有依赖 (插件依赖 + 库依赖) */
|
||||
UPDATE_ALL_DEPENDENCIES,
|
||||
|
||||
/** 仅自动装配使用“+”填充版本的依赖 (插件依赖 + 库依赖) */
|
||||
ONLY_AUTOWIRE_DEPENDENCIES,
|
||||
|
||||
/** 自动装配和更新可选依赖 (插件依赖) */
|
||||
UPDATE_OPTIONAL_PLUGINS,
|
||||
|
||||
/** 自动装配和更新所有依赖 (插件依赖) */
|
||||
UPDATE_ALL_PLUGINS,
|
||||
|
||||
/** 仅自动装配使用“+”填充版本的依赖 (插件依赖) */
|
||||
ONLY_AUTOWIRE_PLUGINS,
|
||||
|
||||
/** 自动装配和更新可选依赖 (库依赖) */
|
||||
UPDATE_OPTIONAL_LIBRARIES,
|
||||
|
||||
/** 自动装配和更新所有依赖 (库依赖) */
|
||||
UPDATE_ALL_LIBRARIES,
|
||||
|
||||
/** 仅自动装配使用“+”填充版本的依赖 (库依赖) */
|
||||
ONLY_AUTOWIRE_LIBRARIES,
|
||||
|
||||
/** 什么也不做 - 关闭所有功能 */
|
||||
OFF
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储库装载模式定义类 (跟随 Gradle 进行配置调整)
|
||||
*/
|
||||
internal enum class RepositoriesMode {
|
||||
/** 参考 [GradleRepositoriesMode.PREFER_PROJECT] */
|
||||
PREFER_PROJECT,
|
||||
|
||||
/** 参考 [GradleRepositoriesMode.PREFER_SETTINGS] */
|
||||
PREFER_SETTINGS,
|
||||
|
||||
/** 参考 [GradleRepositoriesMode.FAIL_ON_PROJECT_REPOS] */
|
||||
FAIL_ON_PROJECT_REPOS
|
||||
}
|
||||
}
|
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/5/17.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document
|
||||
|
||||
import com.highcapable.sweetdependency.SweetDependency
|
||||
import com.highcapable.sweetdependency.manager.const.InternalRepositories
|
||||
import com.highcapable.sweetdependency.manager.content.Repositories
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.parseUnixFileSeparator
|
||||
import com.highcapable.sweetdependency.utils.toSpaceList
|
||||
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import org.gradle.api.artifacts.repositories.PasswordCredentials
|
||||
import org.gradle.api.artifacts.repositories.RepositoryContentDescriptor
|
||||
|
||||
/**
|
||||
* 存储库配置项文档实体
|
||||
* @param isEnable 是否启用
|
||||
* @param scope 作用域
|
||||
* @param content 内容过滤器
|
||||
* @param credentials 身份验证配置项文档实体
|
||||
* @param url URL 地址
|
||||
* @param path 文件路径
|
||||
*/
|
||||
@Serializable
|
||||
internal data class RepositoryDocument(
|
||||
@SerialName("enable")
|
||||
internal var isEnable: Boolean = true,
|
||||
@SerialName("scope")
|
||||
internal var scope: RepositoryScope = RepositoryScope.ALL,
|
||||
@SerialName("content")
|
||||
internal var content: ContentDocument = ContentDocument(),
|
||||
@SerialName("credentials")
|
||||
internal var credentials: CredentialsDocument = CredentialsDocument(),
|
||||
@SerialName("url")
|
||||
internal var url: String = "",
|
||||
@SerialName("path")
|
||||
internal var path: String = "",
|
||||
) : IYamlDocument {
|
||||
|
||||
/**
|
||||
* 身份验证配置项文档实体
|
||||
*
|
||||
* 这些内容来自 [PasswordCredentials]
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
*/
|
||||
@Serializable
|
||||
internal data class CredentialsDocument(
|
||||
@SerialName("username")
|
||||
internal var username: String = "",
|
||||
@SerialName("password")
|
||||
internal var password: String = ""
|
||||
) : IYamlDocument
|
||||
|
||||
/**
|
||||
* 内容配置文档实体
|
||||
*
|
||||
* 这些内容来自 [RepositoryContentDescriptor]
|
||||
* @param exclude 排除配置文档实体
|
||||
* @param include 包含配置文档实体
|
||||
*/
|
||||
@Serializable
|
||||
internal data class ContentDocument(
|
||||
@SerialName("exclude")
|
||||
internal var exclude: FilterDocument = FilterDocument(),
|
||||
@SerialName("include")
|
||||
internal var include: FilterDocument = FilterDocument()
|
||||
) : IYamlDocument {
|
||||
|
||||
/**
|
||||
* 内容过滤器配置文档实体
|
||||
*
|
||||
* 这些内容来自 [RepositoryContentDescriptor]
|
||||
* @param group 过滤器条件内容
|
||||
* @param groupAndSubgroups 过滤器条件内容
|
||||
* @param groupByRegex 过滤器条件内容
|
||||
* @param module 过滤器条件内容
|
||||
* @param moduleByRegex 过滤器条件内容
|
||||
* @param version 过滤器条件内容
|
||||
* @param versionByRegex 过滤器条件内容
|
||||
*/
|
||||
@Serializable
|
||||
internal data class FilterDocument(
|
||||
@SerialName("group")
|
||||
internal var group: String = "",
|
||||
@SerialName("group-and-subgroups")
|
||||
internal var groupAndSubgroups: String = "",
|
||||
@SerialName("group-by-regex")
|
||||
internal var groupByRegex: String = "",
|
||||
@SerialName("module")
|
||||
internal var module: String = "",
|
||||
@SerialName("module-by-regex")
|
||||
internal var moduleByRegex: String = "",
|
||||
@SerialName("version")
|
||||
internal var version: String = "",
|
||||
@SerialName("version-by-regex")
|
||||
internal var versionByRegex: String = ""
|
||||
) : IYamlDocument {
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun group() = group.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun groupAndSubgroups() = groupAndSubgroups.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun groupByRegex() = groupByRegex.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun module() = module.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun moduleByRegex() = moduleByRegex.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun version() = version.toSpaceList()
|
||||
|
||||
/**
|
||||
* 获取过滤器条件内容
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun versionByRegex() = versionByRegex.toSpaceList()
|
||||
|
||||
/**
|
||||
* 当前规则是否为空
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal fun isEmpty() =
|
||||
group.isBlank() && groupAndSubgroups.isBlank() && groupByRegex.isBlank() &&
|
||||
module.isBlank() && moduleByRegex.isBlank() &&
|
||||
version.isBlank() && versionByRegex.isBlank()
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前规则是否为空
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal fun isEmpty() = exclude.isEmpty() && include.isEmpty()
|
||||
}
|
||||
|
||||
/** 节点名称 */
|
||||
@Transient
|
||||
internal var nodeName = ""
|
||||
|
||||
/** 节点类型 */
|
||||
@Transient
|
||||
internal var nodeType = RepositoryType.UNSPECIFIED
|
||||
|
||||
/**
|
||||
* 存储库作用域定义类
|
||||
*/
|
||||
internal enum class RepositoryScope {
|
||||
/** 作用于所有类型依赖 */
|
||||
ALL,
|
||||
|
||||
/** 作用于插件依赖 */
|
||||
PLUGINS,
|
||||
|
||||
/** 作用于库依赖 */
|
||||
LIBRARIES
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储库已知类型定义类
|
||||
*/
|
||||
internal enum class RepositoryType {
|
||||
/** 未指定 */
|
||||
UNSPECIFIED,
|
||||
|
||||
/** Google Maven */
|
||||
GOOGLE,
|
||||
|
||||
/** 中央存储库 */
|
||||
MAVEN_CENTRAL,
|
||||
|
||||
/** 本地存储库 */
|
||||
MAVEN_LOCAL,
|
||||
|
||||
/** 自定义存储库 */
|
||||
MAVEN,
|
||||
|
||||
/** Gradle Plugin 存储库 */
|
||||
GRADLE_PLUGIN_PORTAL
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否包含在作用域内
|
||||
* @param isPlugins 当前类型是否为插件依赖
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal fun isIncludeScope(isPlugins: Boolean) =
|
||||
if (isPlugins) scope == RepositoryScope.ALL || scope == RepositoryScope.PLUGINS
|
||||
else scope == RepositoryScope.ALL || scope == RepositoryScope.LIBRARIES
|
||||
|
||||
/**
|
||||
* 创建当前实体
|
||||
* @param name 键值名称
|
||||
* @return [RepositoryDocument]
|
||||
*/
|
||||
internal fun build(name: String) = apply {
|
||||
when (name) {
|
||||
InternalRepositories.Name.GOOGLE -> {
|
||||
url = url.ifBlank { InternalRepositories.GOOGLE }
|
||||
nodeType = RepositoryType.GOOGLE
|
||||
}
|
||||
InternalRepositories.Name.MAVEN_CENTRAL -> {
|
||||
url = url.ifBlank { InternalRepositories.MAVEN_CENTRAL }
|
||||
nodeType = RepositoryType.MAVEN_CENTRAL
|
||||
}
|
||||
InternalRepositories.Name.GRADLE_PLUGIN_PORTAL -> {
|
||||
url = url.ifBlank { InternalRepositories.GRADLE_PLUGIN_PORTAL }
|
||||
nodeType = RepositoryType.GRADLE_PLUGIN_PORTAL
|
||||
}
|
||||
InternalRepositories.Name.MAVEN_LOCAL -> {
|
||||
path = path.ifBlank { Repositories.defaultMavenLocalPath }
|
||||
nodeType = RepositoryType.MAVEN_LOCAL
|
||||
}
|
||||
InternalRepositories.Name.MAVEN -> SError.make("Use \"maven\" as a repository name is an error, please choose another name")
|
||||
InternalRepositories.Name.IVY -> SError.make("Ivy is not support on ${SweetDependency.TAG} ${SweetDependency.VERSION}")
|
||||
else -> {
|
||||
url = url.ifBlank {
|
||||
Repositories.findAdditional(name).ifBlank {
|
||||
SError.make("Could not found internal or additional repository URL by repository name \"$name\", you must specify a URL")
|
||||
}
|
||||
}; nodeType = RepositoryType.MAVEN
|
||||
}
|
||||
}; nodeName = name
|
||||
if (url.isNotBlank() && path.isNotBlank()) SError.make("There can only be one \"url\" and \"path\" parameter of \"$name\"")
|
||||
if (path.isNotBlank() && (path.startsWith("https://") || path.startsWith("http://"))) SError.make("Invalid repository path: $path")
|
||||
if (url.isNotBlank() && url.startsWith("https://").not() && url.startsWith("http://").not()) SError.make("Invalid repository URL: $url")
|
||||
if (path.isNotBlank()) path = path.parseUnixFileSeparator()
|
||||
}
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/5/17.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package com.highcapable.sweetdependency.document
|
||||
|
||||
import com.highcapable.sweetdependency.SweetDependency
|
||||
import com.highcapable.sweetdependency.document.factory.DependencyMap
|
||||
import com.highcapable.sweetdependency.document.factory.RepositoryList
|
||||
import com.highcapable.sweetdependency.document.factory.checkingName
|
||||
import com.highcapable.sweetdependency.document.factory.convertToDependencyAmbiguousName
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyName
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
|
||||
import com.highcapable.sweetdependency.utils.capitalize
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.findDuplicates
|
||||
import com.highcapable.sweetdependency.utils.hasDuplicate
|
||||
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* 项目 (根节点) 配置文档实体
|
||||
* @param preferences 偏好配置项文档实体
|
||||
* @param repositories 每项存储库配置项文档实体
|
||||
* @param plugins 每项插件依赖文档实体
|
||||
* @param libraries 每项库依赖文档实体
|
||||
* @param versions 每项版本定义数组
|
||||
*/
|
||||
@Serializable
|
||||
internal data class RootConfigDocument(
|
||||
@SerialName("preferences")
|
||||
internal var preferences: PreferencesDocument? = PreferencesDocument(),
|
||||
@SerialName("repositories")
|
||||
internal var repositories: MutableMap<String, RepositoryDocument?>? = null,
|
||||
@SerialName("plugins")
|
||||
internal var plugins: MutableMap<String, DependencyDocument>? = null,
|
||||
@SerialName("libraries")
|
||||
internal var libraries: MutableMap<String, MutableMap<String, DependencyDocument>>? = null,
|
||||
@SerialName("versions")
|
||||
internal var versions: MutableMap<String, String>? = null
|
||||
) : IYamlDocument {
|
||||
|
||||
internal companion object {
|
||||
|
||||
/** 默认文档内容 */
|
||||
private const val DEFAULT_CONTENT = """
|
||||
# SweetDependency project configuration file
|
||||
# You can adjust your custom configuration to your liking here
|
||||
# You can visit ${SweetDependency.PROJECT_URL} for more help
|
||||
#
|
||||
# SweetDependency 项目配置文件
|
||||
# 你可以在这里调整你喜欢的自定义配置
|
||||
# 你可以前往 ${SweetDependency.PROJECT_URL} 以获得更多帮助
|
||||
|
||||
# Configure preferences
|
||||
# 配置偏好设置
|
||||
preferences:
|
||||
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
|
||||
repositories-mode: FAIL_ON_PROJECT_REPOS
|
||||
|
||||
# Configure repositories used by dependencies
|
||||
# 配置依赖使用的存储库
|
||||
repositories:
|
||||
gradle-plugin-portal:
|
||||
scope: PLUGINS
|
||||
google:
|
||||
maven-central:
|
||||
|
||||
# Configure plugins that need to be used
|
||||
# For example:
|
||||
# plugins:
|
||||
# org.jetbrains.kotlin.jvm:
|
||||
# version: +
|
||||
#
|
||||
# 配置需要使用的插件依赖
|
||||
# 例如:
|
||||
# plugins:
|
||||
# org.jetbrains.kotlin.jvm:
|
||||
# version: +
|
||||
plugins:
|
||||
|
||||
# Configure libraries that need to be used
|
||||
# For example:
|
||||
# libraries:
|
||||
# com.google.code.gson:
|
||||
# gson:
|
||||
# version: +
|
||||
#
|
||||
# 配置需要使用的库依赖
|
||||
# 例如:
|
||||
# libraries:
|
||||
# com.google.code.gson:
|
||||
# gson:
|
||||
# version: +
|
||||
libraries:
|
||||
|
||||
"""
|
||||
|
||||
/** 默认文档内容 */
|
||||
internal val defaultContent = DEFAULT_CONTENT.trimIndent()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前偏好配置项文档实体
|
||||
* @return [PreferencesDocument]
|
||||
*/
|
||||
internal fun preferences() = preferences ?: PreferencesDocument()
|
||||
|
||||
/**
|
||||
* 获取当前存储库配置项文档实体
|
||||
* @return [RepositoryList]
|
||||
*/
|
||||
internal fun repositories() = repositories?.let {
|
||||
mutableListOf<RepositoryDocument>().apply {
|
||||
it.forEach { (name, repository) -> (repository ?: RepositoryDocument()).build(name).also { if (it.isEnable) add(it) } }
|
||||
}
|
||||
} ?: mutableListOf()
|
||||
|
||||
/**
|
||||
* 获取当前插件依赖数组
|
||||
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
|
||||
* @return [DependencyMap]
|
||||
*/
|
||||
internal fun plugins(duplicate: Boolean = false) = createPlugins().resolveDependencies(typeName = "plugin", duplicate)
|
||||
|
||||
/**
|
||||
* 获取当前库依赖数组
|
||||
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
|
||||
* @return [DependencyMap]
|
||||
*/
|
||||
internal fun libraries(duplicate: Boolean = false) = createLibraries().resolveDependencies(typeName = "library", duplicate)
|
||||
|
||||
/**
|
||||
* 处理依赖数组
|
||||
* @param typeName 依赖类型名称
|
||||
* @param duplicate 允许重复 - 忽略处理后版本重复的异常 - 默认否
|
||||
*/
|
||||
private fun DependencyMap.resolveDependencies(typeName: String, duplicate: Boolean = false) = apply {
|
||||
val firstTypeName = typeName.capitalize()
|
||||
val checkDuplicateAlias = mutableMapOf<String, String>()
|
||||
val refLibraries = mutableListOf<Triple<DependencyName, String, DependencyVersion>>()
|
||||
val ambiguousNames = mutableListOf<String>()
|
||||
eachDependencies { dependencyName, artifact ->
|
||||
artifact.alias.checkingName("$typeName \"$dependencyName\" alias", isCheckMultiName = true)
|
||||
artifact.versions().forEach { (name, _) -> name.checkingName("$typeName \"$dependencyName\" version alias") }
|
||||
if (artifact.alias.isNotBlank())
|
||||
if (checkDuplicateAlias.contains(artifact.alias).not())
|
||||
checkDuplicateAlias[artifact.alias] = dependencyName.current
|
||||
else SError.make(
|
||||
"Duplicated alias \"${artifact.alias}\", " +
|
||||
"already declared in $typeName \"${checkDuplicateAlias[artifact.alias]}\""
|
||||
)
|
||||
if (artifact.version().isNoSpecific && (artifact.versions().isNotEmpty() || artifact.versionRef.isNotBlank()))
|
||||
SError.make(
|
||||
"$firstTypeName \"$dependencyName\" has declared that it does not specify a version, " +
|
||||
"so it cannot use \"versions\" or \"version-ref\""
|
||||
)
|
||||
if (artifact.versionRef.isNotBlank() && artifact.versionRef.startsWith("<this>::"))
|
||||
artifact.versionRef = artifact.versionRef.replace("<this>:", dependencyName.groupId)
|
||||
refLibraries.add(Triple(dependencyName, artifact.alias, artifact.version()))
|
||||
}
|
||||
eachDependencies { dependencyName, artifact ->
|
||||
/** 处理版本引用 */
|
||||
fun resolveVersionRef() {
|
||||
refLibraries.firstOrNull { artifact.versionRef.let { e -> e == it.first.current || e == it.second } }?.also {
|
||||
if (dependencyName == it.first || dependencyName.current == it.second)
|
||||
SError.make("$firstTypeName \"$dependencyName\" declared \"version-ref\" from itself (recursive call found)")
|
||||
when {
|
||||
it.third.isNoSpecific -> SError.make(
|
||||
"$firstTypeName \"${it.first}\" does not specify a version, so it can no longer be " +
|
||||
"declared as \"version-ref\" by $typeName \"$dependencyName\""
|
||||
)
|
||||
it.third.isBlank -> SError.make(
|
||||
"$firstTypeName \"${it.first}\" already has \"version-ref\" declared, so it can no longer" +
|
||||
" be declared as \"version-ref\" by $typeName \"$dependencyName\" (recursive call found)"
|
||||
)
|
||||
}; artifact.updateVersion(it.third)
|
||||
} ?: SError.make(
|
||||
"Could not found any versions or dependencies associated with " +
|
||||
"version-ref \"${artifact.versionRef}\" of $typeName \"$dependencyName\""
|
||||
)
|
||||
}
|
||||
if (artifact.version().isNoSpecific) return@eachDependencies
|
||||
if (artifact.version().isBlank)
|
||||
if (artifact.versionRef.isNotBlank())
|
||||
versions()[artifact.versionRef]?.also { artifact.version = it } ?: resolveVersionRef()
|
||||
else SError.make("Missing declared version when configuring $typeName \"$dependencyName\"")
|
||||
else if (artifact.version().isBlank.not() && artifact.versionRef.isNotBlank() && duplicate.not())
|
||||
SError.make("$firstTypeName \"$dependencyName\" can only have one \"version\" or \"version-ref\" node, please delete one")
|
||||
}
|
||||
eachDependencies { dependencyName, artifact ->
|
||||
ambiguousNames.add(dependencyName.ambiguousName())
|
||||
if (artifact.alias.isNotBlank()) {
|
||||
artifact.alias.checkingName("$typeName \"$dependencyName\" alias", isCheckMultiName = true)
|
||||
ambiguousNames.add(artifact.alias.convertToDependencyAmbiguousName())
|
||||
}; this[dependencyName] = artifact
|
||||
}
|
||||
if (ambiguousNames.hasDuplicate()) ambiguousNames.findDuplicates().forEach {
|
||||
SError.make("Found ambiguous name \"$it\" in declared dependencies, please checking your $typeName aliases that your declared")
|
||||
} else ambiguousNames.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前版本定义数组
|
||||
* @return [MutableMap]<[String], [String]>
|
||||
*/
|
||||
internal fun versions() = versions?.onEach { (name, _) -> name.checkingName("versions name") } ?: mutableMapOf()
|
||||
|
||||
/**
|
||||
* 重新创建 [plugins]
|
||||
* @return [DependencyMap]
|
||||
*/
|
||||
private fun createPlugins() = mutableMapOf<DependencyName, DependencyDocument>().apply {
|
||||
plugins?.forEach { (notation, artifact) -> this[DependencyName.plugin(notation)] = artifact }
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新创建 [libraries]
|
||||
* @return [DependencyMap]
|
||||
*/
|
||||
private fun createLibraries() = mutableMapOf<DependencyName, DependencyDocument>().apply {
|
||||
libraries?.forEach { (groupId, libraries) ->
|
||||
libraries.forEach { (artifactId, artifact) -> this[DependencyName.library(groupId, artifactId)] = artifact }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环每项 [plugins]、[libraries]
|
||||
* @param result 回调每项结果
|
||||
*/
|
||||
private inline fun DependencyMap.eachDependencies(result: (dependencyName: DependencyName, artifact: DependencyDocument) -> Unit) =
|
||||
forEach { (dependencyName, artifact) -> result(dependencyName, artifact) }
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/6/9.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document
|
||||
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
|
||||
import com.highcapable.sweetdependency.manager.content.Repositories
|
||||
import com.highcapable.sweetdependency.utils.filter
|
||||
import com.highcapable.sweetdependency.utils.toSpaceList
|
||||
import com.highcapable.sweetdependency.utils.yaml.proxy.IYamlDocument
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* 版本过滤器文档实体
|
||||
* @param isUseInternal 使用内置过滤器
|
||||
* @param exclusionList 排除列表
|
||||
*/
|
||||
@Serializable
|
||||
internal data class VersionFilterDocument(
|
||||
@SerialName("use-internal")
|
||||
internal var isUseInternal: Boolean = true,
|
||||
@SerialName("exclusion-list")
|
||||
internal var exclusionList: String = ""
|
||||
) : IYamlDocument {
|
||||
|
||||
/**
|
||||
* 版本排除列表实体
|
||||
* @param list 当前排除列表数组
|
||||
*/
|
||||
internal class ExclusionList internal constructor(private val list: MutableList<String>) {
|
||||
|
||||
/**
|
||||
* 获取当前排除列表数组
|
||||
* @return [MutableList]<[String]>
|
||||
*/
|
||||
internal fun all() = list
|
||||
|
||||
/**
|
||||
* 当前是否存在排除列表
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal fun isEmpty() = all().isEmpty()
|
||||
|
||||
/**
|
||||
* 当前是否不存在排除列表
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal fun isNotEmpty() = isEmpty().not()
|
||||
|
||||
/**
|
||||
* 依赖于当前 [version] 提供的版本并在 [all] 中排除 (不区分大小写)
|
||||
*
|
||||
* 此操作会调用 [clone] 创建一个新实例并返回
|
||||
* @param version 当前版本
|
||||
* @return [ExclusionList]
|
||||
*/
|
||||
internal fun depends(version: DependencyVersion) = clone().apply {
|
||||
if (version.isAutowire.not() && version.isBlank.not()) all().removeAll { version.deployed.lowercase().contains(it.lowercase()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 [all] 过滤当前版本字符串 (不区分大小写)
|
||||
* @param versions 当前版本字符串数组
|
||||
* @return [MutableList]<[DependencyVersion]>
|
||||
*/
|
||||
internal fun filter(versions: MutableList<DependencyVersion>) =
|
||||
if (all().isEmpty()) versions else versions.filter { version -> all().none { version.current.lowercase().contains(it.lowercase()) } }
|
||||
|
||||
/**
|
||||
* 克隆并创建一个新实例
|
||||
* @return [ExclusionList]
|
||||
*/
|
||||
private fun clone() = ExclusionList(mutableListOf<String>().apply { addAll(all()) })
|
||||
|
||||
override fun toString() = all().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排除列表
|
||||
* @return [ExclusionList]
|
||||
*/
|
||||
internal fun exclusionList() = ExclusionList(mutableListOf<String>().apply {
|
||||
if (isUseInternal) addAll(Repositories.defaultVersionFilterExclusionList)
|
||||
addAll(exclusionList.toSpaceList())
|
||||
})
|
||||
}
|
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/5/31.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document.factory
|
||||
|
||||
import com.highcapable.sweetdependency.document.DependencyDocument
|
||||
import com.highcapable.sweetdependency.document.PreferencesDocument
|
||||
import com.highcapable.sweetdependency.document.RepositoryDocument
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyName
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyUpdateMode
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
|
||||
import com.highcapable.sweetdependency.gradle.factory.isUnSafeExtName
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.firstNumberToLetter
|
||||
|
||||
/** 存储库文档实体类型定义 */
|
||||
internal typealias RepositoryList = MutableList<RepositoryDocument>
|
||||
|
||||
/** 依赖文档实体类型定义 */
|
||||
internal typealias DependencyMap = MutableMap<DependencyName, DependencyDocument>
|
||||
|
||||
/** 依赖文档更新实体类型定义 */
|
||||
internal typealias DependencyUpdateMap = MutableMap<String, Pair<DependencyName, DependencyVersion>>
|
||||
|
||||
/** 依赖文档查找条件类型定义 */
|
||||
internal typealias DependenciesCondition = (dependencyName: DependencyName, artifact: DependencyDocument) -> Boolean
|
||||
|
||||
/**
|
||||
* 转换 [PreferencesDocument.AutowireOnSyncMode] 到 [DependencyUpdateMode]
|
||||
*
|
||||
* 如果为 [PreferencesDocument.AutowireOnSyncMode.OFF] 则会返回 null
|
||||
* @return [DependencyUpdateMode] or null
|
||||
*/
|
||||
internal fun PreferencesDocument.AutowireOnSyncMode.toUpdateMode() = when (this) {
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_DEPENDENCIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_DEPENDENCIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.UPDATE_ALL)
|
||||
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_DEPENDENCIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.ALL, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_PLUGINS ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_PLUGINS ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.UPDATE_ALL)
|
||||
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_PLUGINS ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.PLUGINS, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_OPTIONAL_LIBRARIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.UPDATE_OPTIONAL)
|
||||
PreferencesDocument.AutowireOnSyncMode.UPDATE_ALL_LIBRARIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.UPDATE_ALL)
|
||||
PreferencesDocument.AutowireOnSyncMode.ONLY_AUTOWIRE_LIBRARIES ->
|
||||
DependencyUpdateMode(DependencyUpdateMode.DependencyType.LIBRARIES, DependencyUpdateMode.UpdateType.ONLY_AUTOWIRE)
|
||||
PreferencesDocument.AutowireOnSyncMode.OFF -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并到依赖名称
|
||||
* @param groupId Group ID
|
||||
* @param artifactId Artifact ID
|
||||
* @return [String]
|
||||
*/
|
||||
internal fun spliceToDependencyNotation(groupId: String, artifactId: String) = "$groupId:$artifactId"
|
||||
|
||||
/**
|
||||
* 分离到依赖名称数组
|
||||
*
|
||||
* "com.mylibrary:library-core" → "com.mylibrary" | "library-core"
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun String.splitToDependencyNames() = trim().split(":").apply { if (size != 2) SError.make("Invalid dependency name \"$this\"") }
|
||||
|
||||
/**
|
||||
* 分离到依赖生成名称数组
|
||||
*
|
||||
* "com.mylibrary:library-core" → "com" | "mylibrary" | "library" | "core"
|
||||
* @return [List]<[String]>
|
||||
*/
|
||||
internal fun String.splitToDependencyGenerateNames() =
|
||||
trim().replace("_", "|").replace(".", "|").replace(":", "|").replace("-", "|").split("|").filter { it.isNotBlank() }
|
||||
|
||||
/**
|
||||
* 转换到依赖 URL 名称
|
||||
*
|
||||
* "com.mylibrary:library-core" → "com/mylibrary/library-core"
|
||||
* @return [String]
|
||||
*/
|
||||
internal fun String.convertToDependencyUrlName() = splitToDependencyNames().let { "${it[0].replace(".", "/")}/${it[1]}" }
|
||||
|
||||
/**
|
||||
* 转换到依赖模糊分离名称 (使用 [symbol] 进行分离)
|
||||
*
|
||||
* "com.mylibrary:library-core" → "com[symbol]mylibrary[symbol]library[symbol]core"
|
||||
* @param symbol 分隔符 - 默认 "."
|
||||
* @param isReplaceFirstChar 是否使用 [firstNumberToLetter] 替换每一段第一个字符 - 默认否
|
||||
* @param isLowerCase 是否全部转换为小写 - 默认是
|
||||
* @return [String]
|
||||
*/
|
||||
internal fun String.convertToDependencyAmbiguousName(symbol: String = ".", isReplaceFirstChar: Boolean = false, isLowerCase: Boolean = true) =
|
||||
mutableListOf<String>().apply {
|
||||
trim().replace(".", "|").replace("_", "|").replace(":", "|").replace("-", "|").split("|").forEach {
|
||||
add(if (isReplaceFirstChar) it.firstNumberToLetter() else it)
|
||||
}
|
||||
}.joinToString(symbol).let { if (isLowerCase) it.lowercase() else it }
|
||||
|
||||
/**
|
||||
* 检查名称、别名是否合法
|
||||
*
|
||||
* - 只能包含:'0-9'、'A-Z'、'a-z'、'.'、'_'、'-' 且必须以字母开头 (长度至少为 3 位)
|
||||
* - 不能是 [isUnSafeExtName]
|
||||
* @param content 内容
|
||||
* @param isCheckExtName 是否同时检查是否为 Gradle 使用的关键字名称 - 默认否
|
||||
* @param isCheckMultiName 是否同时检查是否可被 [splitToDependencyGenerateNames] 分割为两位及以上名称 - 默认否
|
||||
* @throws IllegalArgumentException 如果名称、别名不合法
|
||||
*/
|
||||
internal fun String.checkingName(content: String, isCheckExtName: Boolean = false, isCheckMultiName: Boolean = false) {
|
||||
if (isBlank()) return
|
||||
if (length < 3) SError.make("Illegal $content \"$this\", the length of $content must be >= 3")
|
||||
/**
|
||||
* 检查是否为 Gradle 使用的关键字名称
|
||||
* @param isEnable 默认跟随 [isCheckExtName]
|
||||
* @throws IllegalArgumentException 如果名称、别名不合法
|
||||
*/
|
||||
fun String.checkUnSafeExtName(isEnable: Boolean = isCheckExtName) {
|
||||
if (isEnable && isUnSafeExtName()) SError.make("This $content \"$this\" of \"${this@checkingName}\" is a Gradle built-in extension")
|
||||
}
|
||||
checkUnSafeExtName()
|
||||
if (isCheckMultiName) splitToDependencyGenerateNames().also { splitedNames ->
|
||||
if (splitedNames.isEmpty()) SError.make("This $content \"$this\" cannot be split, please check and try again")
|
||||
if (splitedNames.size < 2) SError.make("This $content \"$this\" must be able to be split into at least 2 parts")
|
||||
splitedNames[0].checkUnSafeExtName(isEnable = true)
|
||||
splitedNames.forEach {
|
||||
if (it.first() !in 'A'..'Z' && it.first() !in 'a'..'z')
|
||||
SError.make("Illegal $content \"$it\" of \"$this\", it must start with a letter")
|
||||
}
|
||||
}
|
||||
forEachIndexed { index, char ->
|
||||
if ((char !in 'A'..'Z' && char !in 'a'..'z' && index == 0) ||
|
||||
(char !in 'A'..'Z' && char !in 'a'..'z' &&
|
||||
char !in '0'..'9' && char != '_' && char != '-' && char != '.')
|
||||
) SError.make("Illegal $content \"$this\", it only allow 26 letters (upper and lower case) and '.', '_', '-' and must start with a letter")
|
||||
}
|
||||
}
|
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/6/1.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document.mapping
|
||||
|
||||
import com.highcapable.sweetdependency.document.RootConfigDocument
|
||||
import com.highcapable.sweetdependency.document.factory.DependencyUpdateMap
|
||||
import com.highcapable.sweetdependency.document.factory.spliceToDependencyNotation
|
||||
import com.highcapable.sweetdependency.document.mapping.entity.DependencyMapping
|
||||
import com.highcapable.sweetdependency.exception.SweetDependencyUnresolvedException
|
||||
import com.highcapable.sweetdependency.gradle.entity.DependencyName
|
||||
import com.highcapable.sweetdependency.plugin.config.proxy.ISweetDependencyConfigs
|
||||
import com.highcapable.sweetdependency.utils.debug.SError
|
||||
import com.highcapable.sweetdependency.utils.debug.SLog
|
||||
import com.highcapable.sweetdependency.utils.filter
|
||||
import com.highcapable.sweetdependency.utils.joinToContent
|
||||
import com.highcapable.sweetdependency.utils.toFile
|
||||
import com.highcapable.sweetdependency.utils.yaml.Yaml
|
||||
import com.highcapable.sweetdependency.utils.yaml.factory.asMap
|
||||
import com.highcapable.sweetdependency.utils.yaml.factory.isKeyExist
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* [RootConfigDocument] 的测绘实例实现类
|
||||
* @param configs 当前配置
|
||||
*/
|
||||
internal class RootConfigDocumentMapping internal constructor(private val configs: ISweetDependencyConfigs) {
|
||||
|
||||
private companion object {
|
||||
|
||||
/** 偏好设置节点名称 */
|
||||
private const val PREFERENCES_NODE_NAME = "preferences:"
|
||||
|
||||
/** 存储库节点名称 */
|
||||
private const val REPOSITORIES_NODE_NAME = "repositories:"
|
||||
|
||||
/** 版本节点名称 */
|
||||
private const val VERSIONS_NODE_NAME = "versions:"
|
||||
|
||||
/** 插件依赖节点名称 */
|
||||
private const val PLUGINS_NODE_NAME = "plugins:"
|
||||
|
||||
/** 库依赖节点名称 */
|
||||
private const val LIBRARIES_NODE_NAME = "libraries:"
|
||||
|
||||
/** 依赖版本起始内容 */
|
||||
private const val VERSION_NODE_CONTENT = "version:"
|
||||
|
||||
/** 依赖版本引用节点名称 (不包括结尾的“:”) */
|
||||
private const val VERSION_REF_NODE_NAME = "version-ref"
|
||||
|
||||
/** 4 个空格 (缩进) 内容 */
|
||||
private const val SPACE_OF_4 = " "
|
||||
|
||||
/** 6 个空格 (缩进) 内容 */
|
||||
private const val SPACE_OF_6 = " "
|
||||
}
|
||||
|
||||
/** 当前配置文件 */
|
||||
private var configFile: File? = null
|
||||
|
||||
/** 配置文件行内容数组 */
|
||||
private val configFileContents = mutableListOf<String>()
|
||||
|
||||
/** 插件依赖测绘实体数组 */
|
||||
private val pluginsMapping = mutableListOf<DependencyMapping>()
|
||||
|
||||
/** 库依赖测绘实体数组 */
|
||||
private val librariesMapping = mutableListOf<DependencyMapping>()
|
||||
|
||||
init {
|
||||
runCatching { createMapping() }.onFailure {
|
||||
when (it) {
|
||||
is SweetDependencyUnresolvedException -> throw it
|
||||
else -> SLog.error("Failed to create config file's mapping, this will cause problem")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建测绘数据 */
|
||||
private fun createMapping() {
|
||||
configFileContents.clear()
|
||||
configFileContents.addAll(configs.configFilePath.toFile().apply { configFile = this }.readText().split("\n"))
|
||||
var isFoundPluginsStartLine = false
|
||||
var pluginsStartLine = -1
|
||||
var pluginsLine = 0
|
||||
var isFoundLibrariesStartLine = false
|
||||
var librariesStartLine = -1
|
||||
var librariesLine = 0
|
||||
val pluginsContents = mutableListOf<String>()
|
||||
val librariesContents = mutableListOf<String>()
|
||||
configFileContents.forEachIndexed { index, content ->
|
||||
if (content.contains("\"\"")) SError.make("Character declared like -> \"\" <- are not allowed, detected at line ${index + 1}")
|
||||
}
|
||||
configFileContents.forEachIndexed { index, content ->
|
||||
if (content.startsWith(PREFERENCES_NODE_NAME) ||
|
||||
content.startsWith(REPOSITORIES_NODE_NAME) ||
|
||||
content.startsWith(VERSIONS_NODE_NAME) ||
|
||||
content.startsWith(LIBRARIES_NODE_NAME)
|
||||
) {
|
||||
isFoundPluginsStartLine = false
|
||||
return@forEachIndexed
|
||||
}
|
||||
if (content.startsWith(PLUGINS_NODE_NAME)) {
|
||||
isFoundPluginsStartLine = true
|
||||
pluginsStartLine = index
|
||||
}
|
||||
if (isFoundPluginsStartLine) pluginsContents.add(content)
|
||||
}
|
||||
configFileContents.forEachIndexed { index, content ->
|
||||
if (content.startsWith(PREFERENCES_NODE_NAME) ||
|
||||
content.startsWith(REPOSITORIES_NODE_NAME) ||
|
||||
content.startsWith(VERSIONS_NODE_NAME) ||
|
||||
content.startsWith(PLUGINS_NODE_NAME)
|
||||
) {
|
||||
isFoundLibrariesStartLine = false
|
||||
return@forEachIndexed
|
||||
}
|
||||
if (content.startsWith(LIBRARIES_NODE_NAME)) {
|
||||
isFoundLibrariesStartLine = true
|
||||
librariesStartLine = index
|
||||
}
|
||||
if (isFoundLibrariesStartLine) librariesContents.add(content)
|
||||
}
|
||||
if (pluginsContents.isNotEmpty())
|
||||
Yaml.loadFromStringAsNode(pluginsContents.joinToContent()).forEach { (_, rootNode) ->
|
||||
rootNode.asMap()?.forEach { (notation, artifactNode) ->
|
||||
if (artifactNode.asMap()?.isKeyExist(VERSION_REF_NODE_NAME) == false)
|
||||
pluginsMapping.add(DependencyMapping(notation.content))
|
||||
}
|
||||
}
|
||||
if (librariesContents.isNotEmpty())
|
||||
Yaml.loadFromStringAsNode(librariesContents.joinToContent()).forEach { (_, rootNode) ->
|
||||
rootNode.asMap()?.forEach { (groupId, libraryNode) ->
|
||||
libraryNode.asMap()?.forEach { (artifactId, artifactNode) ->
|
||||
val notation = spliceToDependencyNotation(groupId.content, artifactId.content)
|
||||
if (artifactNode.asMap()?.isKeyExist(VERSION_REF_NODE_NAME) == false)
|
||||
librariesMapping.add(DependencyMapping(notation))
|
||||
}
|
||||
}
|
||||
}
|
||||
pluginsContents.onEachIndexed { index, content ->
|
||||
if ((content.trim().startsWith(VERSION_NODE_CONTENT) && content.startsWith(SPACE_OF_4)).not()) return@onEachIndexed
|
||||
pluginsMapping[pluginsLine].versionLine = index + pluginsStartLine
|
||||
pluginsLine++
|
||||
}.clear()
|
||||
librariesContents.onEachIndexed { index, content ->
|
||||
if ((content.trim().startsWith(VERSION_NODE_CONTENT) && content.startsWith(SPACE_OF_6)).not()) return@onEachIndexed
|
||||
librariesMapping[librariesLine].versionLine = index + librariesStartLine
|
||||
librariesLine++
|
||||
}.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用测绘数据更新依赖版本内容
|
||||
* @param dependencies 需要更新的依赖名称和版本数组
|
||||
*/
|
||||
internal fun updateDependencies(dependencies: DependencyUpdateMap) {
|
||||
/**
|
||||
* 写入更新的依赖数据到文件内容
|
||||
* @param dependencies 依赖数组
|
||||
* @param spaceContent 空格内容
|
||||
*/
|
||||
fun List<DependencyMapping>.dumpToContents(dependencies: DependencyUpdateMap, spaceContent: String) =
|
||||
filter { dependencies.containsKey(it.notation) }.forEach {
|
||||
var codeNote = ""
|
||||
val originContent = configFileContents[it.versionLine]
|
||||
if (originContent.contains("#")) originContent.indexOf("#")
|
||||
.also { e -> if (e > 0) codeNote = originContent.substring(e - 1..originContent.lastIndex) }
|
||||
configFileContents[it.versionLine] = "$spaceContent$VERSION_NODE_CONTENT ${dependencies[it.notation]?.second?.mapped}$codeNote"
|
||||
}
|
||||
|
||||
val plugins = dependencies.filter { it.value.first.type == DependencyName.Type.PLUGIN }
|
||||
val libraries = dependencies.filter { it.value.first.type == DependencyName.Type.LIBRARY }
|
||||
if (plugins.isNotEmpty()) pluginsMapping.dumpToContents(plugins, SPACE_OF_4)
|
||||
if (libraries.isNotEmpty()) librariesMapping.dumpToContents(libraries, SPACE_OF_6)
|
||||
if (configFileContents.isNotEmpty()) configFile?.writeText(buildString { configFileContents.forEach { append("$it\n") } }.trim())
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SweetDependency - An easy autowire and manage dependencies Gradle plugin
|
||||
* Copyright (C) 2019-2023 HighCapable
|
||||
* https://github.com/HighCapable/SweetDependency
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is Created by fankes on 2023/6/1.
|
||||
*/
|
||||
package com.highcapable.sweetdependency.document.mapping.entity
|
||||
|
||||
/**
|
||||
* 每项依赖测绘实体
|
||||
* @param notation 依赖名称或 ID
|
||||
* @param versionLine 版本所处行号
|
||||
*/
|
||||
internal data class DependencyMapping(internal var notation: String = "", internal var versionLine: Int = -1)
|
Reference in New Issue
Block a user