1. Mapping Files

Mapping Files 

Tasks like package, packageSrc, and packageDoc accept mappings of type Seq[(File, String)] from an input file to the path to use in the resulting artifact (jar). Similarly, tasks that copy files accept mappings of type Seq[(File, File)] from an input file to the destination file. There are some methods on PathFinder and Path that can be useful for constructing the Seq[(File, String)] or Seq[(File, File)] sequences.

A common way of making this sequence is to start with a PathFinder or Seq[File] (which is implicitly convertible to PathFinder) and then call the pair method. See the PathFinder API for details, but essentially this method accepts a function File => Option[String] or File => Option[File] that is used to generate mappings.

Relative to a directory 

The Path.relativeTo method is used to map a File to its path String relative to a base directory or directories. The relativeTo method accepts a base directory or sequence of base directories to relativize an input file against. The first directory that is an ancestor of the file is used in the case of a sequence of base directories.

For example:

import Path.relativeTo
val files: Seq[File] = file("/a/b/C.scala") :: Nil
val baseDirectories: Seq[File] = file("/a") :: Nil
val mappings: Seq[(File,String)] = files pair relativeTo(baseDirectories)

val expected = (file("/a/b/C.scala") -> "b/C.scala") :: Nil
assert( mappings == expected )

Rebase 

The Path.rebase method relativizes an input file against one or more base directories (the first argument) and then prepends a base String or File (the second argument) to the result. As with relativeTo, the first base directory that is an ancestor of the input file is used in the case of multiple base directories.

For example, the following demonstrates building a Seq[(File, String)] using rebase:

import Path.rebase
val files: Seq[File] = file("/a/b/C.scala") :: Nil
val baseDirectories: Seq[File] = file("/a") :: Nil
val mappings: Seq[(File,String)] = files pair rebase(baseDirectories, "pre/")

val expected = (file("/a/b/C.scala") -> "pre/b/C.scala" ) :: Nil
assert( mappings == expected )

Or, to build a Seq[(File, File)]:

import Path.rebase
val files: Seq[File] = file("/a/b/C.scala") :: Nil
val baseDirectories: Seq[File] = file("/a") :: Nil
val newBase: File = file("/new/base")
val mappings: Seq[(File,File)] = files pair rebase(baseDirectories, newBase)

val expected = (file("/a/b/C.scala") -> file("/new/base/b/C.scala") ) :: Nil
assert( mappings == expected )

Flatten 

The Path.flat method provides a function that maps a file to the last component of the path (its name). For a File to File mapping, the input file is mapped to a file with the same name in a given target directory. For example:

import Path.flat
val files: Seq[File] = file("/a/b/C.scala") :: Nil
val mappings: Seq[(File,String)] = files pair flat

val expected = (file("/a/b/C.scala") -> "C.scala" ) :: Nil
assert( mappings == expected )

To build a Seq[(File, File)] using flat:

import Path.flat
val files: Seq[File] = file("/a/b/C.scala") :: Nil
val newBase: File = file("/new/base")
val mappings: Seq[(File,File)] = files pair flat(newBase)

val expected = (file("/a/b/C.scala") -> file("/new/base/C.scala") ) :: Nil
assert( mappings == expected )

Alternatives 

To try to apply several alternative mappings for a file, use |, which is implicitly added to a function of type A => Option[B]. For example, to try to relativize a file against some base directories but fall back to flattening:

import Path.relativeTo
val files: Seq[File] = file("/a/b/C.scala") :: file("/zzz/D.scala") :: Nil
val baseDirectories: Seq[File] = file("/a") :: Nil
val mappings: Seq[(File,String)] = files pair ( relativeTo(baseDirectories) | flat )

val expected = (file("/a/b/C.scala") -> "b/C.scala") ) :: (file("/zzz/D.scala") -> "D.scala") ) :: Nil
assert( mappings == expected )