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

Directories in packageMapping #6 #107

Merged
merged 3 commits into from
Dec 19, 2013
Merged
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 @@ -10,41 +10,42 @@ case class LinuxFileMetaData(
permissions: String = "755",
config: String = "false",
docs: Boolean = false) {

def withUser(u: String) = copy(user = u)
def withGroup(g: String) = copy(group = g)
def withPerms(p: String) = copy(permissions = p)
def withConfig(value:String = "true") = copy(config = value)
def withConfig(value: String = "true") = copy(config = value)
def asDocs() = copy(docs = true)
}

case class LinuxPackageMapping(
mappings: Traversable[(File, String)],
fileData: LinuxFileMetaData = LinuxFileMetaData(),
zipped: Boolean = false) {

def withUser(user: String) = copy(fileData = fileData withUser user)
def withGroup(group: String) = copy(fileData = fileData withGroup group)
def withPerms(perms: String) = copy(fileData = fileData withPerms perms)
def withConfig(c: String = "true") = copy(fileData = fileData withConfig c)
def withContents() = copy(mappings = SbtNativePackager.mapDirectoryAndContents(mappings.toSeq: _*))
def asDocs() = copy(fileData = fileData asDocs ())
/** Modifies the current package mapping to have gzipped data. */

/** Modifies the current package mapping to have gzipped data. */
def gzipped = copy(zipped = true)
}

// TODO - Maybe this can support globbing symlinks?
// Maybe it should share an ancestor with LinuxPackageMapping so we can configure symlinks the same time as normal files?
case class LinuxSymlink(link: String, destination: String)
object LinuxSymlink {

def makeRelative(from: String, to: String): String = {
val partsFrom: Seq[String] = from split "/" filterNot (_.isEmpty)
val partsTo: Seq[String] = to split "/" filterNot (_.isEmpty)

val prefixAndOne = (1 to partsFrom.length).map(partsFrom.take).dropWhile(seq => partsTo.startsWith(seq)).headOption getOrElse sys.error("Cannot symlink to yourself!")
val prefix = prefixAndOne dropRight 1
if(prefix.length > 0) {
val prefix = prefixAndOne dropRight 1
if (prefix.length > 0) {
val escapeCount = (partsTo.length - 1) - prefix.length
val escapes = (0 until escapeCount) map (i => "..")
val remainder = partsFrom drop prefix.length
Expand All @@ -53,29 +54,29 @@ object LinuxSymlink {
}
// TODO - Does this belong here?
def makeSymLinks(symlinks: Seq[LinuxSymlink], pkgDir: File, relativeLinks: Boolean = true): Unit = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. This is just formatting -.-

for(link <- symlinks) {
// TODO - drop preceeding '/'
def dropFirstSlash(n: String): String =
if(n startsWith "/") n drop 1
else n
def addFirstSlash(n: String): String =
if(n startsWith "/") n
else "/" + n
val to = pkgDir / dropFirstSlash(link.link)
val linkDir = to.getParentFile
if(!linkDir.isDirectory) IO.createDirectory(linkDir)
val name = IO.relativize(linkDir, to).getOrElse {
sys.error("Could not relativize names ("+to+") ("+linkDir+")!!! *(logic error)*")
}
val linkFinal =
if(relativeLinks) makeRelative(link.destination, link.link)
else addFirstSlash(link.destination)
// from ln man page
// -f --force remove existing destination files
if(!to.exists) Process(Seq("ln", "-sf", linkFinal, name), linkDir).! match {
case 0 => ()
case n => sys.error("Failed to symlink " + link.destination + " to " + to)
}
for (link <- symlinks) {
// TODO - drop preceeding '/'
def dropFirstSlash(n: String): String =
if (n startsWith "/") n drop 1
else n
def addFirstSlash(n: String): String =
if (n startsWith "/") n
else "/" + n
val to = pkgDir / dropFirstSlash(link.link)
val linkDir = to.getParentFile
if (!linkDir.isDirectory) IO.createDirectory(linkDir)
val name = IO.relativize(linkDir, to).getOrElse {
sys.error("Could not relativize names (" + to + ") (" + linkDir + ")!!! *(logic error)*")
}
val linkFinal =
if (relativeLinks) makeRelative(link.destination, link.link)
else addFirstSlash(link.destination)
// from ln man page
// -f --force remove existing destination files
if (!to.exists) Process(Seq("ln", "-sf", linkFinal, name), linkDir).! match {
case 0 => ()
case n => sys.error("Failed to symlink " + link.destination + " to " + to)
}
}
}
}
16 changes: 16 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/linux/LinuxPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ trait LinuxPlugin extends Plugin {
*/
def packageTemplateMapping(files: String*)(dir: File = new File(sys.props("java.io.tmpdir"))) = LinuxPackageMapping(files map ((dir, _)))

/**
* @see #mapDirectoryAndContents
* @param dirs - directories to map
*/
def packageDirectoryAndContentsMapping(dirs: (File, String)*) = LinuxPackageMapping(mapDirectoryAndContents(dirs: _*))

/**
* This method includes files and directories.
*
* @param dirs - directories to map
*/
def mapDirectoryAndContents(dirs: (File, String)*): Seq[(File, String)] = for {
(src, dest) <- dirs
path <- (src ***).get
} yield path -> path.toString.replaceFirst(src.toString, dest)

// TODO - we'd like a set of conventions to take universal mappings and create linux package mappings.

/** Create a ascii friendly string for a man page. */
Expand Down