summaryrefslogtreecommitdiff
path: root/project/build/Packer.scala
blob: 8450f212fb8be306087a4697faa0bfcca6b0a2ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import sbt._
import java.io.{File,FileInputStream}
import java.util.jar.Manifest
import BasicLayer._
import FileUtilities._



object Packer {

  /**
   * A filter that exclude files that musn't be in a jar file.
   */
  // We must exclude the manifest because we generate it automatically, and when we add multiples other jars, they could have
  // also a manifest files each, resulting in conflicts for the FileUtilities.jar(..) method
  def jarPattern(path:PathFinder) = path.descendentsExcept(AllPassFilter, (".*"  - ".") || HiddenFileFilter || new ExactFilter("MANIFEST.MF")).get

  def createJar(j:Packaging,log:Logger):Option[String]=createJar(j.packagingConfig,log,jarPattern _,true)
  def createJar(j:PackagingConfiguration,log:Logger):Option[String]=createJar(j,log,jarPattern _,true)


  /**
   * Create a jar from the packaging trait. Is able to add directly others jars to it
   */
  def createJar(j:PackagingConfiguration,log:Logger,filter:(PathFinder)=>Iterable[Path],addIncludedLibs:Boolean):Option[String] = {
    def pack0(content:Iterable[Path])=jar(content.flatMap(filter(_)),j.jarDestination, j.manifest, false, log)

    j.jarsToInclude match {
      case Nil => pack0(j.content)
      case list if addIncludedLibs => {
        withTemporaryDirectory(log) { tmp: File =>
           val tmpPath = Path.fromFile(tmp)
           log.debug("List of jars to be added : " +list)
           def unzip0(l:List[Path]):Option[String] = l match {
              case x::xs => {unzip(x,tmpPath,log);unzip0(xs)} //TODO properly handle failing of unzip
              case Nil => None
           }
           unzip0(list)
           log.debug("Content of temp folder"+ tmpPath.##.**( GlobFilter("*")))
           pack0(j.content ++ Set(tmpPath ##))
       }
      }
      case _ => pack0(j.content)

    }
  }

}

/**
 * Create the jars of pack
 * @author Grégory Moix
 */
trait Packer {
  self: BasicLayer =>

  def libraryToCopy:List[Path] = Nil

  /**
   * The actual pack task.
   */
  def packF=  {
    import Packer._
    def iterate(steps:List[Step]):Option[String]= steps match{
        case x::xs => x match{
          case c:Packaging => {
            createJar(c,log) orElse iterate(xs)
          }
          case _ => iterate(xs)
        }
        case Nil => None
      }

     def copy0 ={
       copyFile(manifestPath,packingDestination/"META-INF"/"MANIFEST.MF",log) orElse {
       copy(libraryToCopy,packingDestination , true,true,log) match {
          case Right(_) => None
          case Left(e) => Some(e)
          }
       }
     }
     iterate(allSteps.topologicalSort) orElse copy0
  }
  lazy val pack=task{packF}.dependsOn(finishLayer)
}
class PackagingConfiguration(val jarDestination:Path, val content:Iterable[Path],val manifest:Manifest,val jarsToInclude:List[Path]){
  def this(jarDestination:Path,content:Iterable[Path])=this(jarDestination,content, new Manifest,Nil)
  def this(jarDestination:Path,content:Iterable[Path],jarsToInclude:List[Path])=this(jarDestination,content,new Manifest, jarsToInclude)
  //def this(jarName:String,destinationFunction:(String)=>Path,content:Iterable[Path],manifest:Manifest,jarsToInclude:List[Path]) =
  //  this(destinationFunction(jarName),content,manifest,jarsToInclude)
  //def this(jarName:String,destinationFunction:(String)=>Path,content:Iterable[Path]) =
  //  this(jarName,destinationFunction,content, new Manifest, Nil)
}

trait Packaging extends Step{
  //def manifest = new Manifest
  //final def simplePath = packagingDestination / jarName
  //final def libPath = packagingDestination /"lib" / jarName
  //def jarDestination:Path = libPath
  //def packagingDestination:Path
  //def jarName:String
  //def jarsToInclude:List[Path] = Nil
  //def jarContent:Iterable[Path]
  def packagingConfig:PackagingConfiguration

}

trait WrapperPackaging extends Packaging {
  self : WrapperStep =>

  def jarContent = {
    def getContent(list:List[Step],acc:List[Path]):List[Path]= list match {
      case Nil => acc
      case x::xs => x match {
        case w:WrapperStep => getContent(xs,getContent(w.dependencies.toList,acc))
        case c:CompilationStep => getContent(xs,(c.outputDirectory ##)::acc)
      }
    }
    getContent(dependencies.toList,Nil)
  }
}

/**
 * This trait is here to add the possiblity to have a different packing destination that is used right after the
 * compilation of the step has finished. It permits to have use libraries that are build using a plugin. (The plugin must
 * be a jar in order to be recognised by the compiler.
 */
trait EarlyPackaging extends Packaging{
  self:CompilationStep  =>
  //def earlyPackagingDestination:Path
  //def earlyJarDestination = earlyPackagingDestination / jarName
  def earlyPackagingConfig:PackagingConfiguration
}