Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix updating global locks with updateDependencies set #90

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,10 @@ class DependencyLockPlugin implements Plugin<Project> {
private void maybeApplyLock(Configuration conf, DependencyLockExtension extension, Map overrides, String globalLockFileName, String lockFilename) {
File dependenciesLock
File globalLock = new File(project.rootProject.projectDir, globalLockFileName ?: extension.globalLockFile)
boolean isGlobal = false
if (globalLock.exists()) {
dependenciesLock = globalLock
isGlobal = true
} else {
dependenciesLock = new File(project.projectDir, lockFilename ?: extension.lockFile)
}
Expand All @@ -307,11 +309,11 @@ class DependencyLockPlugin implements Plugin<Project> {
boolean hasGenerateTask = hasGenerationTask(taskNames)
if (dependenciesLock.exists()) {
if (!hasGenerateTask) {
applyLock(conf, dependenciesLock, overrides)
applyLock(conf, dependenciesLock, overrides, [], isGlobal)
appliedLock = true
} else if (hasUpdateTask(taskNames)) {
def updates = project.hasProperty(UPDATE_DEPENDENCIES) ? parseUpdates(project.property(UPDATE_DEPENDENCIES) as String) : extension.updateDependencies
applyLock(conf, dependenciesLock, overrides, updates)
applyLock(conf, dependenciesLock, overrides, updates, isGlobal)
appliedLock = true
}
}
Expand Down Expand Up @@ -361,12 +363,20 @@ class DependencyLockPlugin implements Plugin<Project> {
updates.tokenize(',') as Set
}

void applyLock(Configuration conf, File dependenciesLock, Map overrides, Collection<String> updates = []) {
private static boolean isTopLevel(info, deps, isGlobal) {
// If this is not listed as being depended on at all, it must be a top-level dependency
if (info.transitive == null) return true

// If a dependency is listed as being depended on by something that we know is a project, then it must be a top-level dependency
return isGlobal && info.transitive.any { deps[it]?.project }
}

void applyLock(Configuration conf, File dependenciesLock, Map overrides, Collection<String> updates = [], boolean isGlobal) {
LOGGER.info("Using ${dependenciesLock.name} to lock dependencies in $conf")
def locks = loadLock(dependenciesLock)

if (updates) {
locks = locks.collectEntries { configurationName, deps -> [(configurationName): deps.findAll { coord, info -> (info.transitive == null) && !updates.contains(coord) }] }
locks = locks.collectEntries { configurationName, deps -> [(configurationName): deps.findAll { coord, info -> isTopLevel(info, deps, isGlobal) && !updates.contains(coord) }] }
}

// in the old format, all first level props were groupId:artifactId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,95 @@ class DependencyLockLauncherSpec extends IntegrationSpec {
!result.standardOutput.contains("is using a deprecated lock format")
}

def 'only the update dependency and its transitives are updated when using a global lock'() {
addSubproject('sub1', """\
dependencies {
compile 'test.example:bar:1.+'
compile 'test.example:qux:latest.release'
}
""".stripIndent())
buildFile << """\
allprojects {
${applyPlugin(DependencyLockPlugin)}
group = 'test'
}
subprojects {
apply plugin: 'java'
repositories { maven { url '${Fixture.repo}' } }
}
dependencyLock {
includeTransitives = true
}
""".stripIndent()

def lockFile = new File(projectDir, 'global.lock')
def lockText = '''\
{
"_global_": {
"test.example:bar": {
"locked": "1.0.0",
"requested": "1.+",
"transitive": [
"test:sub1"
]
},
"test.example:qux": {
"locked": "1.0.0",
"requested": "latest.release",
"transitive": [
"test:sub1"
]
},
"test.example:foo": {
"locked": "1.0.0",
"transitive": [
"test.example:bar",
"test.example:qux"
]
},
"test:sub1": {
"project": true
}
}
}'''.stripIndent()
lockFile.text = lockText

def updatedLock = '''\
{
"_global_": {
"test.example:bar": {
"locked": "1.1.0",
"transitive": [
"test:sub1"
]
},
"test.example:foo": {
"locked": "1.0.1",
"transitive": [
"test.example:bar",
"test.example:qux"
]
},
"test.example:qux": {
"locked": "1.0.0",
"transitive": [
"test:sub1"
]
},
"test:sub1": {
"project": true
}
}
}'''.stripIndent()

when:
def results = runTasksSuccessfully('updateGlobalLock', '-PdependencyLock.updateDependencies=test.example:bar')

then:
println results.standardOutput
new File(projectDir, 'build/global.lock').text == updatedLock
}

@Ignore
def 'diff the generated lock with the existing lock '() {
def dependenciesLock = new File(projectDir, 'dependencies.lock')
Expand Down