8 Commits
1.0.3 ... 1.0.4

16 changed files with 163 additions and 31 deletions

View File

@@ -27,3 +27,9 @@
- 更换 Kotlin Multiplatform 中的配置依赖 `autowire(...)` 写法为 `sweet.autowire(...)`
- 生成的代码使用 `@Nonnull` 标记以使其能够在 Kotlin DSL 脚本中识别为非空返回值类型
- 一些其它功能性的改进
## 1.0.4 | 2023.11.14
- 新增 `isUseDependencyResolutionManagement` 选项,默认启用,现在你可以选择是否允许插件使用 `dependencyResolutionManagement` 配置库依赖
- 新增 `isDebug` 选项,默认不启用,你可以启用此选项来在自动装配时输出详细的依赖搜索信息
- 一些其它功能性的改进

View File

@@ -30,3 +30,10 @@
- Change the configuration dependency `autowire(...)` in Kotlin Multiplatform to `sweet.autowire(...)`
- Generated code is marked with `@Nonnull` to make it recognized as a non-null return type in Kotlin DSL scripts
- Some other functional improvements
## 1.0.4 | 2023.11.14
- Added `isUseDependencyResolutionManagement` option, enabled by default, now you can choose whether to allow plugins to
use `dependencyResolutionManagement` to configure library dependencies
- Added `isDebug` option, not enabled by default, you can enable this option to output detailed dependency search information during autowiring
- Some other functional improvements

View File

@@ -31,6 +31,9 @@
如果你的项目依然在使用 `buildscript` 的方式进行管理,请迁移到新方式,否则会发生错误。
如果你的项目不能使用 `dependencyResolutionManagement` 进行管理,你可以参考此页面最下方的 [自定义选项](#自定义选项)
通过配置 `isUseDependencyResolutionManagement = false` 来使用传统的库依赖管理方式。
## 快速开始
首先,打开你根项目的 `settings.gradle``settings.gradle.kts`
@@ -1146,9 +1149,18 @@ sweetDependency {
// 启用 SweetDependency设置为 false 将禁用所有功能
isEnable = true
// 是否启用调试模式
// 默认不启用,启用后将在自动装配时输出详细的依赖搜索信息
isDebug = false
// SweetDependency 配置文件名称
configFileName = "sweet-dependency-config.yaml"
// 是否使用 Settings.dependencyResolutionManagement 管理库依赖
// 此功能默认启用,如果你的项目必须存在自定义的 "repositories" 方法块,请关闭此功能
// 注意:关闭后配置文件中的 "repositories-mode" 选项将不再有效
isUseDependencyResolutionManagement = true
// 是否启用依赖自动装配日志
// 此功能默认启用,会在当前根项目 (Root Project) 的 ".gradle/sweet-dependency" 目录下创建日志文件
isEnableDependenciesAutowireLog = true
@@ -1164,7 +1176,9 @@ sweetDependency {
```groovy
sweetDependency {
enable true
debug false
configFileName 'sweet-dependency-config.yaml'
useDependencyResolutionManagement true
enableDependenciesAutowireLog true
enableVerboseMode true
}

View File

@@ -32,6 +32,10 @@ Note that `SweetDependency` supports at least Gradle `7.x.x` and is managed usin
If your project is still managed using the `buildscript` method, please migrate to the new method, otherwise errors will occur.
If your project cannot be managed using `dependencyResolutionManagement`, you can refer to the [Custom Preferences](#custom-preferences)
at the bottom of this page,
use traditional library dependency management by configuring `isUseDependencyResolutionManagement = false`.
## Quick Start
First, open `settings.gradle` or `settings.gradle.kts` of your root project.
@@ -1216,9 +1220,20 @@ sweetDependency {
// Enable SweetDependency, set to false will disable all functions
isEnable = true
// Whether to enable debug mode
// Not enabled by default,
// if enabled, detailed dependencies search information will be output during autowiring
isDebug = false
// SweetDependency configuration file name
configFileName = "sweet-dependency-config.yaml"
// Whether to use Settings.dependencyResolutionManagement to manage library dependencies
// This function is enabled by default,
// if your project must have a custom "repositories" method block, please disable this function
// Note: The "repositories-mode" option in the configuration file will no longer be effective after disabled
isUseDependencyResolutionManagement = true
// Whether to enable dependency autowiring logging
// This function is enabled by default and will create a log file in the ".gradle/sweet-dependency" directory of the current root project
isEnableDependenciesAutowireLog = true
@@ -1235,7 +1250,9 @@ sweetDependency {
```groovy
sweetDependency {
enable true
debug false
configFileName 'sweet-dependency-config.yaml'
useDependencyResolutionManagement true
enableDependenciesAutowireLog true
enableVerboseMode true
}

View File

@@ -4,7 +4,7 @@ project.description=An easy autowire and manage dependencies Gradle plugin.
project.url=https://github.com/HighCapable/SweetDependency
project.groupName=com.highcapable.sweetdependency
project.moduleName=sweet-dependency
project.version=1.0.3
project.version=1.0.4
project.licence.name=Apache License 2.0
project.licence.url=https://github.com/HighCapable/SweetDependency/blob/master/LICENSE
project.developer.id="0"

View File

@@ -8,7 +8,7 @@ pluginManagement {
plugins {
// Import the SweetDependency plugin here
// 在这里引入 SweetDependency 插件
id("com.highcapable.sweetdependency") version "1.0.2"
id("com.highcapable.sweetdependency") version "1.0.4"
}
sweetDependency {
configFileName = "sweet-dependency-config.yaml"

View File

@@ -8,7 +8,7 @@ pluginManagement {
plugins {
// Import the SweetDependency plugin here
// 在这里引入 SweetDependency 插件
id("com.highcapable.sweetdependency") version "1.0.2"
id("com.highcapable.sweetdependency") version "1.0.4"
}
sweetDependency {
configFileName = "sweet-dependency-config.yaml"

View File

@@ -7,8 +7,8 @@ pluginManagement {
}
}
plugins {
id("com.highcapable.sweetdependency") version "1.0.3"
id("com.highcapable.sweetproperty") version "1.0.4"
id("com.highcapable.sweetdependency") version "1.0.4"
id("com.highcapable.sweetproperty") version "1.0.5"
}
sweetDependency {
isEnableVerboseMode = false

View File

@@ -253,7 +253,19 @@ internal object DependencyManager {
forEachIndexed { index, entry ->
val currentVersionFilterExclusionList = versionFilterExclusionList.depends(currentVersion)
val availableVersions = mutableListOf<DependencyVersion>()
poms.add(MavenParser.acquire(dependencyName, entry, currentVersion))
poms.add(MavenParser.acquire(dependencyName, entry, currentVersion).also {
if (!SweetDependencyConfigs.configs.isDebug) return@also
val isNotFound = it.versions.isEmpty()
logDoneOrWarn("$positionTagName > OBTAIN (${index + 1}/$size) ${dependencyName.description}", isNotFound)
logDoneOrWarn(
"""
- Repository (${entry.nodeName}): ${it.url}
- Last Updated: ${it.lastUpdated}
- Versions: ${it.versions}
- Adopted Versions: ${currentVersionFilterExclusionList.filter(it.versions)}
""".trimIndent(), isNotFound, noTag = true
)
})
if (index == lastIndex) poms.noEmpty()
?.sortedByDescending { it.lastUpdated }
?.let { if (it.all { e -> e.lastUpdated <= 0L }) it.sortedByDescending { e -> e.versions.size } else it }
@@ -333,4 +345,13 @@ internal object DependencyManager {
}
else -> SLog.info("$positionTagName > UP-TO-DATE ${dependencyName.description} version $currentVersion", SLog.DONE)
}
/**
* 打印完成或警告 Log
* @param msg 消息内容
* @param isWarn 是否为警告模式 - 默认否
* @param noTag 无标签 - 默认否
*/
private fun logDoneOrWarn(msg: String, isWarn: Boolean = false, noTag: Boolean = false) =
if (isWarn) SLog.warn(msg, noTag = noTag) else SLog.info(msg, SLog.DONE, noTag = noTag)
}

View File

@@ -23,6 +23,7 @@ package com.highcapable.sweetdependency.manager
import com.highcapable.sweetdependency.document.PreferencesDocument
import com.highcapable.sweetdependency.document.RepositoryDocument
import com.highcapable.sweetdependency.document.factory.RepositoryList
import com.highcapable.sweetdependency.exception.SweetDependencyUnresolvedException
import com.highcapable.sweetdependency.gradle.helper.GradleHelper
import com.highcapable.sweetdependency.manager.const.AdditionalRepositories
@@ -33,6 +34,7 @@ import com.highcapable.sweetdependency.utils.debug.SLog
import com.highcapable.sweetdependency.utils.noBlank
import com.highcapable.sweetdependency.utils.noEmpty
import com.highcapable.sweetdependency.utils.toFile
import org.gradle.api.Project
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.ArtifactRepository
import org.gradle.api.artifacts.repositories.AuthenticationSupported
@@ -46,32 +48,27 @@ import org.gradle.api.initialization.resolve.RepositoriesMode as GradleRepositor
*/
internal object RepositoryManager {
/** 当前存储库数组 */
private var repositories: RepositoryList = mutableListOf()
/**
* 当前是否使用 [Settings.dependencyResolutionManagement] 管理库依赖
* @return [Boolean]
*/
private val isUseDependencyResolutionManagement get() = SweetDependencyConfigs.configs.isUseDependencyResolutionManagement
/**
* 生成并应用存储库数组
* @param settings 当前设置
*/
internal fun generateAndApply(settings: Settings) {
val repositories = SweetDependencyConfigs.document.repositories()
repositories = SweetDependencyConfigs.document.repositories()
Repositories.generate(repositories)
/**
* 应用存储库数组到 Gradle
* @param isPlugins 当前应用类型是否为插件依赖
*/
fun RepositoryHandler.apply(isPlugins: Boolean) = repositories.forEach {
if (it.isIncludeScope(isPlugins)) when (it.nodeType) {
RepositoryDocument.RepositoryType.GOOGLE -> google { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN_CENTRAL -> mavenCentral { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN_LOCAL -> mavenLocal { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN -> maven { applyToArtifact(it) }
RepositoryDocument.RepositoryType.GRADLE_PLUGIN_PORTAL -> gradlePluginPortal { applyToArtifact(it) }
else -> {}
}
}
settings.pluginManagement {
this.repositories.clear()
this.repositories.apply(isPlugins = true)
}
settings.dependencyResolutionManagement {
if (isUseDependencyResolutionManagement) settings.dependencyResolutionManagement {
this.repositoriesMode.set(when (SweetDependencyConfigs.document.preferences().repositoriesMode) {
PreferencesDocument.RepositoriesMode.PREFER_PROJECT -> GradleRepositoriesMode.PREFER_PROJECT
PreferencesDocument.RepositoriesMode.PREFER_SETTINGS -> GradleRepositoriesMode.PREFER_SETTINGS
@@ -82,6 +79,33 @@ internal object RepositoryManager {
}
}
/**
* 应用存储库数组
* @param rootProject 当前根项目
*/
internal fun apply(rootProject: Project) {
if (!isUseDependencyResolutionManagement)
rootProject.allprojects {
this.repositories.clear()
this.repositories.apply(isPlugins = false)
}
}
/**
* 应用存储库数组到 Gradle
* @param isPlugins 当前应用类型是否为插件依赖
*/
private fun RepositoryHandler.apply(isPlugins: Boolean) = repositories.forEach {
if (it.isIncludeScope(isPlugins)) when (it.nodeType) {
RepositoryDocument.RepositoryType.GOOGLE -> google { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN_CENTRAL -> mavenCentral { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN_LOCAL -> mavenLocal { applyToArtifact(it) }
RepositoryDocument.RepositoryType.MAVEN -> maven { applyToArtifact(it) }
RepositoryDocument.RepositoryType.GRADLE_PLUGIN_PORTAL -> gradlePluginPortal { applyToArtifact(it) }
else -> {}
}
}
/**
* 应用存储库到 [ArtifactRepository]
* @param document 存储库配置项文档实体

View File

@@ -57,26 +57,32 @@ internal object MavenParser {
val isIncludeScope = repo.isIncludeScope(dependencyName.type == DependencyName.Type.PLUGIN)
/** 离线模式下不会自动装配、更新在线依赖 */
if (isIncludeScope && GradleHelper.isOfflineMode) return MavenMetadata()
var currentUrl: String
return when {
repo.url.isNotBlank() -> "$headerUrlOrPath$METADATA_FILE_NAME".executeUrlBody(repo.credentials.username, repo.credentials.password)
repo.path.isNotBlank() -> "$headerUrlOrPath$METADATA_LOCAL_FILE_NAME".executeFileBody()
repo.url.isNotBlank() -> "$headerUrlOrPath$METADATA_FILE_NAME"
.apply { currentUrl = this }
.executeUrlBody(repo.credentials.username, repo.credentials.password)
repo.path.isNotBlank() -> "$headerUrlOrPath$METADATA_LOCAL_FILE_NAME"
.apply { currentUrl = this }
.executeFileBody()
else -> SError.make("Could not resolve this repository \"${repo.nodeName}\"")
}.trim().toMetadata(currentVersion)
}.trim().toMetadata(currentUrl, currentVersion)
}
/**
* 解析 [METADATA_FILE_NAME]、[METADATA_LOCAL_FILE_NAME] 内容到 [MavenMetadata] 实体
* @param url 当前依赖获取 URL
* @param currentVersion 当前依赖版本
* @return [MavenMetadata]
*/
private fun String.toMetadata(currentVersion: DependencyVersion) = runCatching {
if (!(contains("<metadata ") || contains("<metadata>")) || !endsWith("</metadata>")) return@runCatching MavenMetadata()
private fun String.toMetadata(url: String, currentVersion: DependencyVersion) = runCatching {
if (!(contains("<metadata ") || contains("<metadata>")) || !endsWith("</metadata>")) return@runCatching MavenMetadata(url)
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(InputSource(StringReader(this))).let { document ->
val lastUpdated = document.getElementsByTagName("lastUpdated").item(0)?.textContent?.toLongOrNull() ?: 0L
val versionNodeList = document.getElementsByTagName("version")
val versions = mutableListOf<DependencyVersion>()
for (i in 0..versionNodeList.length) versionNodeList.item(i)?.textContent?.also { versions.add(currentVersion.clone(it)) }
MavenMetadata(versions.noEmpty()?.reversed()?.toMutableList() ?: mutableListOf(), lastUpdated)
MavenMetadata(url, versions.noEmpty()?.reversed()?.toMutableList() ?: mutableListOf(), lastUpdated)
}
}.getOrNull() ?: MavenMetadata()
}.getOrNull() ?: MavenMetadata(url)
}

View File

@@ -25,10 +25,12 @@ import com.highcapable.sweetdependency.gradle.entity.DependencyVersion
/**
* Maven Metadata 实体
* @param url 依赖获取 URL
* @param versions 版本数组
* @param lastUpdated 最后更新时间戳
*/
internal data class MavenMetadata(
internal var url: String = "",
internal var versions: MutableList<DependencyVersion> = mutableListOf(),
internal var lastUpdated: Long = 0L
)

View File

@@ -83,6 +83,8 @@ internal object RuntimeDebugTransaction {
"Gradle Version" value GradleHelper.version,
"Plugin Version" value SweetDependency.VERSION,
"Plugin Configuration" to mapOf(
"isEnable" value configs.isEnable,
"isDebug" value configs.isDebug,
"configFileName" with "(path) ${configs.configFilePath}" to mapOf(
"preferences" to mapOf(
"autowire-on-sync-mode" value preferences.autowireOnSyncMode,
@@ -103,6 +105,7 @@ internal object RuntimeDebugTransaction {
"plugins" to pluginsMap,
"libraries" to librariesMap
),
"isUseDependencyResolutionManagement" value configs.isUseDependencyResolutionManagement,
"isEnableDependenciesAutowireLog" value configs.isEnableDependenciesAutowireLog,
"isEnableVerboseMode" value configs.isEnableVerboseMode
),

View File

@@ -22,6 +22,7 @@
package com.highcapable.sweetdependency.plugin.config.proxy
import com.highcapable.sweetdependency.SweetDependency
import org.gradle.api.initialization.Settings
/**
* [SweetDependency] 配置类接口类
@@ -41,9 +42,15 @@ internal interface ISweetDependencyConfigs {
/** 是否启用插件 */
val isEnable: Boolean
/** 是否启用调试模式 */
val isDebug: Boolean
/** [SweetDependency] 的配置文件路径 */
val configFilePath: String
/** 是否使用 [Settings.dependencyResolutionManagement] 管理库依赖 */
val isUseDependencyResolutionManagement: Boolean
/** 是否启用依赖自动装配日志 */
val isEnableDependenciesAutowireLog: Boolean

View File

@@ -26,6 +26,7 @@ package com.highcapable.sweetdependency.plugin.extension.dsl.configure
import com.highcapable.sweetdependency.SweetDependency
import com.highcapable.sweetdependency.environment.Environment
import com.highcapable.sweetdependency.plugin.config.proxy.ISweetDependencyConfigs
import org.gradle.api.initialization.Settings
/**
* [SweetDependency] 配置方法体实现类
@@ -46,6 +47,14 @@ open class SweetDependencyConfigureExtension internal constructor() {
var isEnable = true
@JvmName("enable") set
/**
* 是否启用调试模式
*
* 默认不启用 - 启用后将在自动装配时输出详细的依赖搜索信息
*/
var isDebug = false
@JvmName("debug") set
/**
* [SweetDependency] 配置文件名称
*
@@ -54,6 +63,16 @@ open class SweetDependencyConfigureExtension internal constructor() {
var configFileName = ISweetDependencyConfigs.DEFAULT_CONFIG_FILE_NAME
@JvmName("configFileName") set
/**
* 是否使用 [Settings.dependencyResolutionManagement] 管理库依赖
*
* 此功能默认启用 - 如果你的项目必须存在自定义的 "repositories" 方法块 - 请关闭此功能
*
* - 注意:关闭后配置文件中的 "repositories-mode" 选项将不再有效
*/
var isUseDependencyResolutionManagement = true
@JvmName("useDependencyResolutionManagement") set
/**
* 是否启用依赖自动装配日志
*
@@ -76,12 +95,16 @@ open class SweetDependencyConfigureExtension internal constructor() {
*/
internal fun build(): ISweetDependencyConfigs {
val currentEnable = isEnable
val currentDebug = isDebug
val currentConfigFilePath = Environment.resourcesDir(configFileName).absolutePath
val currentUseDependencyResolutionManagement = isUseDependencyResolutionManagement
val currentEnableDependenciesAutowireLog = isEnableDependenciesAutowireLog
val currentEnableVerboseMode = isEnableVerboseMode
return object : ISweetDependencyConfigs {
override val isEnable get() = currentEnable
override val isDebug get() = currentDebug
override val configFilePath get() = currentConfigFilePath
override val isUseDependencyResolutionManagement get() = currentUseDependencyResolutionManagement
override val isEnableDependenciesAutowireLog get() = currentEnableDependenciesAutowireLog
override val isEnableVerboseMode get() = currentEnableVerboseMode
}

View File

@@ -81,8 +81,10 @@ internal class SweetDependencyExtensionImpl : BaseExtensionImpl() {
}
override fun onTransaction(transaction: ProjectTransaction) {
if (transaction.isRoot) DependencyManager.resolve(transaction.current)
transaction.evaluation { project, isRoot -> if (isRoot) DependencyManager.deploy(project) }
if (transaction.isRoot) {
RepositoryManager.apply(transaction.current)
DependencyManager.resolve(transaction.current)
}; transaction.evaluation { project, isRoot -> if (isRoot) DependencyManager.deploy(project) }
}
/**