project/Packager.scala (90 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ import java.nio.file.attribute.BasicFileAttributes import java.nio.file.{FileVisitResult, Files, Path, Paths, SimpleFileVisitor, StandardCopyOption} import sbt.Keys._ import sbt._ object Packager { val packagedJars = TaskKey[Seq[File]]("packaged-jars", "list of jar files for packaging") val packager = TaskKey[File]("package", s"packages the project for deployment") val packagedJarsTask = (state, thisProjectRef).flatMap { (state, project) => /** return all tasks of given TaskKey's dependencies */ def taskInAllDependencies[T](taskKey: TaskKey[T]): Task[Seq[T]] = { val structure = Project.structure(state) Dag.topologicalSort(project) { ref => Project.getProject(ref, structure).toList.flatMap { p => p.dependencies.map(_.project) ++ p.aggregate } }.flatMap { p => taskKey in p get structure.data }.join } for { packaged <- taskInAllDependencies(packagedArtifacts) srcs <- taskInAllDependencies(packageSrc in Compile) docs <- taskInAllDependencies(packageDoc in Compile) } yield { packaged.flatten .collect { case (artifact, path) if artifact.extension == "jar" => path } .diff(srcs ++ docs) //remove srcs & docs since we do not need them in the dist .distinct } } val packagerTask = (baseDirectory, packagedJars, dependencyClasspath in Runtime, target, streams, version).map { (root, packaged, dependencies, target, streams, version) => val name = s"apache-s2graph-$version-incubating-bin" val base = target / name IO.delete(base) IO.createDirectory(base) val subdirectories = Seq("bin", "conf", "lib") val files = Seq("LICENSE", "NOTICE", "DISCLAIMER") for (dir <- subdirectories) { IO.createDirectory(base / dir) } for (file <- files) { val source = (root / file).toPath val target = (base / file).toPath Files.copy(source, target) } // copy jars to /lib val libs = dependencies.filter(_.data.ext == "jar").map(_.data) ++ packaged libs.foreach { jar => val source = jar.toPath val target = Paths.get(base.getPath, "lib", jar.getName) try { // try to create hard links for speed and to save disk space Files.createLink(target, source) streams.log.debug(s"Created link: $source -> $target") } catch { case e: Any => Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING) streams.log.debug(s"Copied: $source -> $target") } } // copy other files recursively for (subdir <- subdirectories if subdir != "lib") { val source = (root / subdir).toPath val target = (base / subdir).toPath Files.walkFileTree(source, new SimpleFileVisitor[Path] { override def preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult = { val dest = target.resolve(source.relativize(dir)) Files.createDirectories(dest) streams.log.debug(s"Created directory: $dest") FileVisitResult.CONTINUE } override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = { val dest = target.resolve(source.relativize(file)) Files.copy(file, dest) streams.log.debug(s"Copied: $file -> $dest") FileVisitResult.CONTINUE } }) } streams.log.info(s"Package for distribution located at $base") { import scala.sys.process._ streams.log.info(s"creating a tarball...") s"tar zcf $base.tar.gz -C $target $name".!! streams.log.info(s"Tarball is located at $base.tar.gz") } base } val defaultSettings = Seq( packagedJars <<= packagedJarsTask, packager <<= packagerTask ) }