From ba83d795681b9abacf883726185b573637c50314 Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet Date: Tue, 11 Nov 2014 18:14:39 -0800 Subject: Move offline repo logic into buildSrc. The code was previously in build.gradle but didn't handle parent poms. In order to use the PomHandler class in buildSrc, I had to move all the code under buildSrc, as a new plugin. Change-Id: Id5fae475c5a85060f04939c34d244146fc0d3593 --- .../offline/CopyProjectDependencyTask.groovy | 83 ++++++++++++++++ .../artifacts/offline/OfflineRepoPlugin.groovy | 105 +++++++++++++++++++++ .../tools/internal/artifacts/PomHandler.java | 6 +- .../gradle-plugins/offline-repo.properties | 1 + 4 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 src/main/groovy/com/android/tools/internal/artifacts/offline/CopyProjectDependencyTask.groovy create mode 100644 src/main/groovy/com/android/tools/internal/artifacts/offline/OfflineRepoPlugin.groovy create mode 100644 src/main/resources/META-INF/gradle-plugins/offline-repo.properties (limited to 'src') diff --git a/src/main/groovy/com/android/tools/internal/artifacts/offline/CopyProjectDependencyTask.groovy b/src/main/groovy/com/android/tools/internal/artifacts/offline/CopyProjectDependencyTask.groovy new file mode 100644 index 0000000..43a20a2 --- /dev/null +++ b/src/main/groovy/com/android/tools/internal/artifacts/offline/CopyProjectDependencyTask.groovy @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * 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 + * + * http://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. + */ +package com.android.tools.internal.artifacts.offline + +import com.android.tools.internal.artifacts.PomHandler +import com.google.common.io.Files +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.gradle.api.tasks.TaskAction + +/** + */ +public class CopyProjectDependencyTask extends DefaultTask { + + @TaskAction + void copy() { + def conf = project.findProject(':base:gradle').configurations.runtime + + // select transitive dependencies, from this configuration and all referenced subprojects. + def componentIds = conf.incoming.resolutionResult.allDependencies.findAll { + it.selected.id instanceof ModuleComponentIdentifier + } + // remove duplicates. + componentIds = componentIds.unique { dep1, dep2 -> + dep1.selected.id.displayName <=> dep2.selected.id.displayName + } + + def repoDir = new File(project.rootDir.parentFile, 'prebuilts/tools/common/m2/repository') + + componentIds.each { dep -> + ModuleComponentIdentifier componentId = dep.selected.id + makeOfflineCopyFor(componentId.group, componentId.module, componentId.version, repoDir) + } + } + + protected void makeOfflineCopyFor(String group, String module, String version, File repoDir) { + def artifactPath = "${group.replace('.' as char, File.separatorChar)}${File.separatorChar}${module}${File.separatorChar}${version}" + + def artifactFolder = new File(repoDir, artifactPath) + + // find the jar file. + def srcFile = new File(artifactFolder, "${module}-${version}.jar") + + File destinationFolder = new File(project.ext.offlineRepo, artifactPath) + destinationFolder.mkdirs() + + if (srcFile.isFile()) { + Files.copy(srcFile, new File(destinationFolder, srcFile.getName())) + } + + // find the src jar file. + srcFile = new File(artifactFolder, "${module}-${version}-sources.jar") + if (srcFile.isFile()) { + Files.copy(srcFile, new File(destinationFolder, srcFile.getName())) + } + + // find the pom file. + srcFile = new File(artifactFolder, "${module}-${version}.pom") + if (srcFile.isFile()) { + Files.copy(srcFile, new File(destinationFolder, srcFile.getName())) + } + + // search for a parent pom. + def pomHandler = new PomHandler(srcFile) + def parentPomId = pomHandler.parentPom + if (parentPomId != null) { + makeOfflineCopyFor(parentPomId.group, parentPomId.name, parentPomId.version, repoDir) + } + } +} diff --git a/src/main/groovy/com/android/tools/internal/artifacts/offline/OfflineRepoPlugin.groovy b/src/main/groovy/com/android/tools/internal/artifacts/offline/OfflineRepoPlugin.groovy new file mode 100644 index 0000000..7dbb54d --- /dev/null +++ b/src/main/groovy/com/android/tools/internal/artifacts/offline/OfflineRepoPlugin.groovy @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * 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 + * + * http://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. + */ + +package com.android.tools.internal.artifacts.offline + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.tasks.bundling.Zip + +/** + * small plugin to setup task for creating offline repo. + */ +class OfflineRepoPlugin implements Plugin { + @Override + void apply(Project project) { + + project.ext.offlineRepo = new File(project.buildDir, 'intermediaries/repo') + + Task prepareOfflineRepo = project.tasks.create('prepareOfflineRepo') + prepareOfflineRepo.doFirst { + project.ext.offlineRepo.mkdirs() + } + + /* + * Identify all project and subprojects output artifacts and copy .jar and .pom + * files into the repoDir local maven repository + */ + Task copySubProjectsArtifacts = project.tasks.create('copySubProjectsArtifacts') + copySubProjectsArtifacts.dependsOn prepareOfflineRepo + copySubProjectsArtifacts.doFirst { + + // top project is the root of all the gradle plugin dependencies + def topProject = project.findProject(':base:gradle') + // select the (unique) subprojects only and the top project + def projectsToConsider = topProject.configurations.runtime.incoming.resolutionResult.allDependencies.findResults { + (it.selected.id instanceof ProjectComponentIdentifier) ? project.findProject(it.selected.id.projectPath) : null + } + projectsToConsider.unique().add(topProject) + + // for each projects, check its output artifact and copy it only with the associated pom file to our + // local maven repo. + projectsToConsider.each { someProject -> + someProject.configurations.runtime.artifacts.files.each { file -> + String relativePath = "${someProject.group.replace('.' as char, File.separatorChar)}${File.separatorChar}${someProject.name}${File.separatorChar}${someProject.version}" + File outDir = new File(project.ext.offlineRepo, relativePath) + File sourceDir = new File(new File(project.ext.localRepo), relativePath) + outDir.mkdirs() + project.copy { + from new File(sourceDir, file.name) + into outDir + } + project.copy { + from new File(sourceDir, file.name.replace(".jar", ".pom")) + into outDir + } + } + } + } + + /** + * Identify all transitive dependencies from the passed project and copy each jar and pom files into + * a maven style repository located at outDir. + */ + Task copyProjectDependencies = project.tasks.create('copyProjectDependencies', CopyProjectDependencyTask) + copyProjectDependencies.dependsOn prepareOfflineRepo + + Task makeOfflineRepo = project.tasks.create('makeOfflineRepo') { + outputs.dir project.ext.offlineRepo + } + makeOfflineRepo.dependsOn project.tasks.publishLocal + + copyProjectDependencies.mustRunAfter 'publishLocal' + makeOfflineRepo.dependsOn copyProjectDependencies + copySubProjectsArtifacts.mustRunAfter 'publishLocal' + makeOfflineRepo.dependsOn copySubProjectsArtifacts + + /** + * Zip the maven style repository into a zip file. + */ + Task zipOfflineRepo = project.tasks.create('zipOfflineRepo', Zip) { + inputs.files makeOfflineRepo.outputs.files + File outputFile = new File(project.ext.androidHostDist, 'offline_repo.zip') + outputs.file outputFile + from makeOfflineRepo.outputs.files + archiveName outputFile.name + destinationDir outputFile.parentFile + } + zipOfflineRepo.dependsOn makeOfflineRepo + } +} diff --git a/src/main/java/com/android/tools/internal/artifacts/PomHandler.java b/src/main/java/com/android/tools/internal/artifacts/PomHandler.java index 372380d..c0df733 100644 --- a/src/main/java/com/android/tools/internal/artifacts/PomHandler.java +++ b/src/main/java/com/android/tools/internal/artifacts/PomHandler.java @@ -39,7 +39,7 @@ import java.io.IOException; * - parent POM * - packaging */ -class PomHandler { +public class PomHandler { private final File pomFile; private Document document = null; @@ -83,7 +83,7 @@ class PomHandler { } } - PomHandler(File pomFile) { + public PomHandler(File pomFile) { this.pomFile = pomFile; } @@ -137,7 +137,7 @@ class PomHandler { return new FakeModuleVersionIdentifier(group, name, version); } - ModuleVersionIdentifier getParentPom() throws IOException { + public ModuleVersionIdentifier getParentPom() throws IOException { Document document = getDocument(); Node rootNode = document.getDocumentElement(); diff --git a/src/main/resources/META-INF/gradle-plugins/offline-repo.properties b/src/main/resources/META-INF/gradle-plugins/offline-repo.properties new file mode 100644 index 0000000..c748d9e --- /dev/null +++ b/src/main/resources/META-INF/gradle-plugins/offline-repo.properties @@ -0,0 +1 @@ +implementation-class=com.android.tools.internal.artifacts.offline.OfflineRepoPlugin \ No newline at end of file -- cgit v1.2.3