2019-11-04 16:16:13 +00:00
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see <http://www.gnu.org/licenses/>.
package compiler
import (
2019-11-14 16:45:21 +00:00
"fmt"
2019-11-04 16:16:13 +00:00
"io/ioutil"
2019-11-10 09:48:07 +00:00
"os"
"path/filepath"
2019-11-11 09:22:55 +00:00
"sync"
2019-11-04 16:16:13 +00:00
2019-11-11 18:19:13 +00:00
. "github.com/mudler/luet/pkg/logger"
2019-11-04 16:16:13 +00:00
"github.com/mudler/luet/pkg/helpers"
pkg "github.com/mudler/luet/pkg/package"
2019-11-11 18:19:13 +00:00
"github.com/mudler/luet/pkg/solver"
2019-11-04 16:16:13 +00:00
"github.com/mudler/luet/pkg/tree"
2019-11-11 09:22:55 +00:00
"github.com/pkg/errors"
2019-11-04 16:16:13 +00:00
)
const BuildFile = "build.yaml"
type LuetCompiler struct {
2019-11-05 16:36:22 +00:00
* tree . CompilerRecipe
2019-11-15 23:38:07 +00:00
Backend CompilerBackend
Database pkg . PackageDatabase
2019-11-04 16:16:13 +00:00
}
2019-11-15 23:38:07 +00:00
func NewLuetCompiler ( backend CompilerBackend , t pkg . Tree , db pkg . PackageDatabase ) Compiler {
2019-11-05 16:36:22 +00:00
// The CompilerRecipe will gives us a tree with only build deps listed.
return & LuetCompiler {
Backend : backend ,
CompilerRecipe : & tree . CompilerRecipe {
tree . Recipe { PackageTree : t } ,
} ,
2019-11-15 23:38:07 +00:00
Database : db ,
2019-11-05 16:36:22 +00:00
}
2019-11-04 16:16:13 +00:00
}
2019-11-11 09:22:55 +00:00
func ( cs * LuetCompiler ) compilerWorker ( i int , wg * sync . WaitGroup , cspecs chan CompilationSpec , a * [ ] Artifact , m * sync . Mutex , concurrency int , keepPermissions bool , errors chan error ) {
defer wg . Done ( )
for s := range cspecs {
2019-11-15 23:38:07 +00:00
ar , err := cs . compile ( concurrency , keepPermissions , s )
2019-11-11 09:22:55 +00:00
if err != nil {
errors <- err
}
m . Lock ( )
* a = append ( * a , ar )
m . Unlock ( )
}
}
2019-11-15 17:11:26 +00:00
func ( cs * LuetCompiler ) CompileWithReverseDeps ( concurrency int , keepPermissions bool , ps CompilationSpecs ) ( [ ] Artifact , [ ] error ) {
artifacts , err := cs . CompileParallel ( concurrency , keepPermissions , ps )
if len ( err ) != 0 {
return artifacts , err
}
2019-11-16 13:16:44 +00:00
Info ( ":ant: Resolving reverse dependencies" )
2019-11-15 17:11:26 +00:00
toCompile := NewLuetCompilationspecs ( )
for _ , a := range artifacts {
w , asserterr := cs . Tree ( ) . World ( )
if asserterr != nil {
return nil , append ( err , asserterr )
}
revdeps := a . GetCompileSpec ( ) . GetPackage ( ) . Revdeps ( & w )
for _ , r := range revdeps {
spec , asserterr := cs . FromPackage ( r )
if err != nil {
return nil , append ( err , asserterr )
}
spec . SetOutputPath ( ps . All ( ) [ 0 ] . GetOutputPath ( ) )
toCompile . Add ( spec )
}
// for _, assertion := range a.GetSourceAssertion() {
// if assertion.Value && assertion.Package.Flagged() {
// spec, asserterr := cs.FromPackage(assertion.Package)
// if err != nil {
// return nil, append(err, asserterr)
// }
// w, asserterr := cs.Tree().World()
// if err != nil {
// return nil, append(err, asserterr)
// }
// revdeps := spec.GetPackage().Revdeps(&w)
// for _, r := range revdeps {
// spec, asserterr := cs.FromPackage(r)
// if asserterr != nil {
// return nil, append(err, asserterr)
// }
// spec.SetOutputPath(ps.All()[0].GetOutputPath())
// toCompile.Add(spec)
// }
// }
// }
}
uniques := toCompile . Unique ( ) . Remove ( ps )
for _ , u := range uniques . All ( ) {
2019-11-16 13:40:58 +00:00
Info ( " :arrow_right_hook:" , u . GetPackage ( ) . GetName ( ) , ":leaves:" , u . GetPackage ( ) . GetVersion ( ) , "(" , u . GetPackage ( ) . GetCategory ( ) , ")" )
2019-11-15 17:11:26 +00:00
}
artifacts2 , err := cs . CompileParallel ( concurrency , keepPermissions , uniques )
return append ( artifacts , artifacts2 ... ) , err
}
2019-11-11 09:22:55 +00:00
2019-11-15 17:11:26 +00:00
func ( cs * LuetCompiler ) CompileParallel ( concurrency int , keepPermissions bool , ps CompilationSpecs ) ( [ ] Artifact , [ ] error ) {
2019-11-16 13:40:58 +00:00
Spinner ( 22 )
defer SpinnerStop ( )
2019-11-11 09:22:55 +00:00
all := make ( chan CompilationSpec )
artifacts := [ ] Artifact { }
mutex := & sync . Mutex { }
2019-11-15 17:11:26 +00:00
errors := make ( chan error , ps . Len ( ) )
2019-11-11 09:22:55 +00:00
var wg = new ( sync . WaitGroup )
for i := 0 ; i < concurrency ; i ++ {
wg . Add ( 1 )
go cs . compilerWorker ( i , wg , all , & artifacts , mutex , concurrency , keepPermissions , errors )
}
2019-11-15 17:11:26 +00:00
for _ , p := range ps . All ( ) {
2019-11-15 23:38:07 +00:00
asserts , err := cs . ComputeDepTree ( p )
if err != nil {
panic ( err )
}
p . SetSourceAssertion ( asserts )
2019-11-11 09:22:55 +00:00
all <- p
}
close ( all )
wg . Wait ( )
close ( errors )
var allErrors [ ] error
for e := range errors {
allErrors = append ( allErrors , e )
}
return artifacts , allErrors
}
2019-11-11 18:19:13 +00:00
func ( cs * LuetCompiler ) compileWithImage ( image , buildertaggedImage , packageImage string , concurrency int , keepPermissions bool , p CompilationSpec ) ( Artifact , error ) {
p . SetSeedImage ( image ) // In this case, we ignore the build deps as we suppose that the image has them - otherwise we recompose the tree with a solver,
// and we build all the images first.
keepImg := true
keepPackageImg := true
2019-11-17 12:27:32 +00:00
err := os . MkdirAll ( p . Rel ( "build" ) , os . ModePerm )
if err != nil {
return nil , errors . Wrap ( err , "Error met while creating tempdir for building" )
}
buildDir , err := ioutil . TempDir ( p . Rel ( "build" ) , "pack" )
if err != nil {
return nil , errors . Wrap ( err , "Error met while creating tempdir for building" )
}
defer os . RemoveAll ( buildDir ) // clean up
2019-11-05 16:36:22 +00:00
2019-11-11 18:19:13 +00:00
// First we copy the source definitions into the output - we create a copy which the builds will need (we need to cache this phase somehow)
2019-11-17 12:27:32 +00:00
err = helpers . CopyDir ( p . GetPackage ( ) . GetPath ( ) , buildDir )
2019-11-11 18:19:13 +00:00
if err != nil {
return nil , errors . Wrap ( err , "Could not copy package sources" )
2019-11-08 18:57:23 +00:00
2019-11-11 18:19:13 +00:00
}
if buildertaggedImage == "" {
keepImg = false
buildertaggedImage = "luet/" + p . GetPackage ( ) . GetFingerPrint ( ) + "-builder"
}
if packageImage == "" {
keepPackageImg = false
packageImage = "luet/" + p . GetPackage ( ) . GetFingerPrint ( )
}
2019-11-10 09:48:07 +00:00
2019-11-11 18:19:13 +00:00
// First we create the builder image
p . WriteBuildImageDefinition ( filepath . Join ( buildDir , p . GetPackage ( ) . GetFingerPrint ( ) + "-builder.dockerfile" ) )
builderOpts := CompilerBackendOptions {
ImageName : buildertaggedImage ,
SourcePath : buildDir ,
DockerFileName : p . GetPackage ( ) . GetFingerPrint ( ) + "-builder.dockerfile" ,
Destination : p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + "-builder.image.tar" ) ,
}
2019-11-10 09:48:07 +00:00
2019-11-11 18:19:13 +00:00
err = cs . Backend . BuildImage ( builderOpts )
if err != nil {
2019-11-11 23:13:03 +00:00
return nil , errors . Wrap ( err , "Could not build image: " + image + " " + builderOpts . DockerFileName )
2019-11-11 18:19:13 +00:00
}
2019-11-10 09:48:07 +00:00
2019-11-11 18:19:13 +00:00
err = cs . Backend . ExportImage ( builderOpts )
if err != nil {
return nil , errors . Wrap ( err , "Could not export image" )
}
2019-11-10 09:48:07 +00:00
2019-11-11 18:19:13 +00:00
// Then we write the step image, which uses the builder one
p . WriteStepImageDefinition ( buildertaggedImage , filepath . Join ( buildDir , p . GetPackage ( ) . GetFingerPrint ( ) + ".dockerfile" ) )
runnerOpts := CompilerBackendOptions {
ImageName : packageImage ,
SourcePath : buildDir ,
DockerFileName : p . GetPackage ( ) . GetFingerPrint ( ) + ".dockerfile" ,
Destination : p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".image.tar" ) ,
}
2019-11-08 18:57:23 +00:00
2019-11-11 18:19:13 +00:00
if ! keepPackageImg {
2019-11-08 18:57:23 +00:00
err = cs . Backend . ImageDefinitionToTar ( runnerOpts )
if err != nil {
2019-11-11 09:22:55 +00:00
return nil , errors . Wrap ( err , "Could not export image to tar" )
2019-11-08 18:57:23 +00:00
}
2019-11-11 18:19:13 +00:00
} else {
if err := cs . Backend . BuildImage ( runnerOpts ) ; err != nil {
2019-11-11 23:13:03 +00:00
return nil , errors . Wrap ( err , "Failed building image for " + runnerOpts . ImageName + " " + runnerOpts . DockerFileName )
2019-11-11 18:19:13 +00:00
}
if err := cs . Backend . ExportImage ( runnerOpts ) ; err != nil {
return nil , errors . Wrap ( err , "Failed exporting image" )
2019-11-10 09:48:07 +00:00
}
2019-11-11 18:19:13 +00:00
}
2019-11-10 09:48:07 +00:00
2019-11-17 14:45:55 +00:00
var diffs [ ] ArtifactLayer
var artifact Artifact
if ! p . ImageUnpack ( ) {
// we have to get diffs only if spec is not unpacked
diffs , err = cs . Backend . Changes ( p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + "-builder.image.tar" ) , p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".image.tar" ) )
if err != nil {
return nil , errors . Wrap ( err , "Could not generate changes from layers" )
}
2019-11-11 18:19:13 +00:00
}
if ! keepImg {
// We keep them around, so to not reload them from the tar (which should be the "correct way") and we automatically share the same layers
2019-11-08 18:57:23 +00:00
// TODO: Handle caching and optionally do not remove things
err = cs . Backend . RemoveImage ( builderOpts )
if err != nil {
2019-11-12 21:17:51 +00:00
// TODO: Have a --fatal flag which enables Warnings to exit.
Warning ( "Could not remove image " , builderOpts . ImageName )
// return nil, errors.Wrap(err, "Could not remove image")
2019-11-08 18:57:23 +00:00
}
2019-11-11 18:19:13 +00:00
}
rootfs , err := ioutil . TempDir ( p . GetOutputPath ( ) , "rootfs" )
2019-11-11 23:13:03 +00:00
if err != nil {
return nil , errors . Wrap ( err , "Could not create tempdir" )
}
2019-11-11 18:19:13 +00:00
defer os . RemoveAll ( rootfs ) // clean up
2019-11-08 18:57:23 +00:00
2019-11-11 18:19:13 +00:00
// TODO: Compression and such
err = cs . Backend . ExtractRootfs ( CompilerBackendOptions { SourcePath : runnerOpts . Destination , Destination : rootfs } , keepPermissions )
if err != nil {
return nil , errors . Wrap ( err , "Could not extract rootfs" )
}
2019-11-17 14:45:55 +00:00
2019-11-17 11:08:13 +00:00
if p . ImageUnpack ( ) {
err = helpers . Tar ( rootfs , p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".package.tar" ) )
if err != nil {
return nil , errors . Wrap ( err , "Error met while creating package archive" )
}
2019-11-17 14:45:55 +00:00
artifact = NewPackageArtifact ( p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".package.tar" ) )
artifact . SetCompileSpec ( p )
} else {
artifact , err = ExtractArtifactFromDelta ( rootfs , p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".package.tar" ) , diffs , concurrency , keepPermissions , p . GetIncludes ( ) )
if err != nil {
return nil , errors . Wrap ( err , "Could not generate deltas" )
}
2019-11-17 11:08:13 +00:00
artifact . SetCompileSpec ( p )
2019-11-11 18:19:13 +00:00
}
2019-11-17 14:45:55 +00:00
2019-11-11 18:19:13 +00:00
return artifact , nil
}
2019-11-17 11:08:13 +00:00
2019-11-15 23:38:07 +00:00
func ( cs * LuetCompiler ) Prepare ( concurrency int ) error {
2019-11-11 18:19:13 +00:00
2019-11-15 23:38:07 +00:00
err := cs . Tree ( ) . ResolveDeps ( concurrency ) // FIXME: When done in parallel, this could be done on top before starting
if err != nil {
return errors . Wrap ( err , "While resoolving tree world deps" )
}
return nil
}
2019-11-13 08:42:52 +00:00
func ( cs * LuetCompiler ) packageFromImage ( p CompilationSpec , tag string , keepPermissions bool ) ( Artifact , error ) {
2019-11-16 13:16:44 +00:00
pkgTag := ":package: " + p . GetPackage ( ) . GetName ( )
2019-11-14 16:45:21 +00:00
Info ( pkgTag , " 🍩 Build starts 🔨 🔨 🔨 " )
2019-11-13 08:42:52 +00:00
builderOpts := CompilerBackendOptions {
ImageName : p . GetImage ( ) ,
Destination : p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".image.tar" ) ,
}
err := cs . Backend . DownloadImage ( builderOpts )
if err != nil {
return nil , errors . Wrap ( err , "Could not download image" )
}
if tag != "" {
err = cs . Backend . CopyImage ( p . GetImage ( ) , tag )
if err != nil {
return nil , errors . Wrap ( err , "Could not download image" )
}
}
err = cs . Backend . ExportImage ( builderOpts )
if err != nil {
return nil , errors . Wrap ( err , "Could not export image" )
}
rootfs , err := ioutil . TempDir ( p . GetOutputPath ( ) , "rootfs" )
if err != nil {
return nil , errors . Wrap ( err , "Could not create tempdir" )
}
defer os . RemoveAll ( rootfs ) // clean up
// TODO: Compression and such
err = cs . Backend . ExtractRootfs ( CompilerBackendOptions { SourcePath : builderOpts . Destination , Destination : rootfs } , keepPermissions )
if err != nil {
return nil , errors . Wrap ( err , "Could not extract rootfs" )
}
err = helpers . Tar ( rootfs , p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".package.tar" ) )
if err != nil {
return nil , errors . Wrap ( err , "Error met while creating package archive" )
}
2019-11-16 13:16:44 +00:00
Info ( pkgTag , " :white_check_mark: Done" )
2019-11-15 17:11:26 +00:00
artifact := NewPackageArtifact ( p . Rel ( p . GetPackage ( ) . GetFingerPrint ( ) + ".package.tar" ) )
artifact . SetCompileSpec ( p )
return artifact , nil
2019-11-13 08:42:52 +00:00
}
2019-11-15 23:38:07 +00:00
func ( cs * LuetCompiler ) ComputeDepTree ( p CompilationSpec ) ( solver . PackagesAssertions , error ) {
2019-11-11 23:13:03 +00:00
2019-11-15 23:38:07 +00:00
// Get build deps tree (ordered)
world , err := cs . Tree ( ) . World ( )
2019-11-12 07:48:07 +00:00
if err != nil {
2019-11-15 23:38:07 +00:00
return nil , errors . Wrap ( err , "While computing tree world" )
}
s := solver . NewSolver ( [ ] pkg . Package { } , world , cs . Database )
pack , err := cs . Tree ( ) . FindPackage ( p . GetPackage ( ) )
if err != nil {
return nil , errors . Wrap ( err , "While computing a solution for " + p . GetPackage ( ) . GetName ( ) )
2019-11-12 07:48:07 +00:00
}
2019-11-15 23:38:07 +00:00
solution , err := s . Install ( [ ] pkg . Package { pack } )
if err != nil {
return nil , errors . Wrap ( err , "While computing a solution for " + p . GetPackage ( ) . GetName ( ) )
}
dependencies := solution . Order ( p . GetPackage ( ) . GetFingerPrint ( ) )
assertions := solver . PackagesAssertions { }
for _ , assertion := range dependencies { //highly dependent on the order
if assertion . Value && assertion . Package . Flagged ( ) {
depPack , err := cs . Tree ( ) . FindPackage ( assertion . Package )
if err != nil {
return nil , errors . Wrap ( err , "While computing a solution for " + p . GetPackage ( ) . GetName ( ) )
}
nthsolution , err := s . Install ( [ ] pkg . Package { depPack } )
if err != nil {
return nil , errors . Wrap ( err , "While computing a solution for " + p . GetPackage ( ) . GetName ( ) )
}
assertion . Hash = solver . PackageHash {
BuildHash : nthsolution . Order ( depPack . GetFingerPrint ( ) ) . Drop ( depPack ) . AssertionHash ( ) ,
PackageHash : nthsolution . Order ( depPack . GetFingerPrint ( ) ) . AssertionHash ( ) ,
}
assertions = append ( assertions , assertion )
}
}
p . SetSourceAssertion ( assertions )
return assertions , nil
}
// Compile is non-parallel
func ( cs * LuetCompiler ) Compile ( concurrency int , keepPermissions bool , p CompilationSpec ) ( Artifact , error ) {
asserts , err := cs . ComputeDepTree ( p )
if err != nil {
panic ( err )
}
p . SetSourceAssertion ( asserts )
return cs . compile ( concurrency , keepPermissions , p )
}
func ( cs * LuetCompiler ) compile ( concurrency int , keepPermissions bool , p CompilationSpec ) ( Artifact , error ) {
2019-11-16 13:16:44 +00:00
Info ( ":package: Compiling" , p . GetPackage ( ) . GetName ( ) , "version" , p . GetPackage ( ) . GetVersion ( ) , ".... :coffee:" )
2019-11-12 07:48:07 +00:00
2019-11-11 23:13:03 +00:00
if len ( p . GetPackage ( ) . GetRequires ( ) ) == 0 && p . GetImage ( ) == "" {
Error ( "Package with no deps and no seed image supplied, bailing out" )
return nil , errors . New ( "Package " + p . GetPackage ( ) . GetFingerPrint ( ) + "with no deps and no seed image supplied, bailing out" )
}
2019-11-10 09:48:07 +00:00
2019-11-11 18:19:13 +00:00
// - If image is set we just generate a plain dockerfile
// Treat last case (easier) first. The image is provided and we just compute a plain dockerfile with the images listed as above
if p . GetImage ( ) != "" {
2019-11-13 08:42:52 +00:00
if p . ImageUnpack ( ) { // If it is just an entire image, create a package from it
return cs . packageFromImage ( p , "" , keepPermissions )
}
2019-11-11 18:19:13 +00:00
return cs . compileWithImage ( p . GetImage ( ) , "" , "" , concurrency , keepPermissions , p )
}
2019-11-12 16:31:50 +00:00
// - If image is not set, we read a base_image. Then we will build one image from it to kick-off our build based
// on how we compute the resolvable tree.
// This means to recursively build all the build-images needed to reach that tree part.
// - We later on compute an hash used to identify the image, so each similar deptree keeps the same build image.
2019-11-15 23:38:07 +00:00
dependencies := p . GetSourceAssertion ( ) . Drop ( p . GetPackage ( ) ) // at this point we should have a flattened list of deps to build, including all of them (with all constraints propagated already)
departifacts := [ ] Artifact { } // TODO: Return this somehow
2019-11-11 18:19:13 +00:00
deperrs := [ ] error { }
var lastHash string
2019-11-14 16:45:21 +00:00
depsN := 0
currentN := 0
2019-11-16 13:16:44 +00:00
Info ( ":deciduous_tree: Build dependencies for " + p . GetPackage ( ) . GetName ( ) )
2019-11-14 16:45:21 +00:00
for _ , assertion := range dependencies { //highly dependent on the order
2019-11-15 23:38:07 +00:00
depsN ++
2019-11-16 13:16:44 +00:00
Info ( " :arrow_right_hook:" , assertion . Package . GetName ( ) , ":leaves:" , assertion . Package . GetVersion ( ) , "(" , assertion . Package . GetCategory ( ) , ")" )
2019-11-15 23:38:07 +00:00
2019-11-14 16:45:21 +00:00
}
2019-11-11 18:19:13 +00:00
for _ , assertion := range dependencies { //highly dependent on the order
2019-11-15 23:38:07 +00:00
currentN ++
2019-11-16 13:16:44 +00:00
pkgTag := fmt . Sprintf ( ":package: %d/%d %s ⤑ %s" , currentN , depsN , p . GetPackage ( ) . GetName ( ) , assertion . Package . GetName ( ) )
Info ( pkgTag , " :zap: Building dependency" )
2019-11-15 23:38:07 +00:00
compileSpec , err := cs . FromPackage ( assertion . Package )
if err != nil {
return nil , errors . New ( "Error while generating compilespec for " + assertion . Package . GetName ( ) )
}
compileSpec . SetOutputPath ( p . GetOutputPath ( ) )
buildImageHash := "luet/cache:" + assertion . Hash . BuildHash
currentPackageImageHash := "luet/cache:" + assertion . Hash . PackageHash
2019-11-16 13:16:44 +00:00
Debug ( pkgTag , " :arrow_right_hook: :whale: Builder image name" , buildImageHash )
Debug ( pkgTag , " :arrow_right_hook: :whale: Package image name" , currentPackageImageHash )
2019-11-15 23:38:07 +00:00
lastHash = currentPackageImageHash
if compileSpec . GetImage ( ) != "" {
// TODO: Refactor this
2019-11-17 11:08:13 +00:00
if compileSpec . ImageUnpack ( ) { // If it is just an entire image, create a package from it
if compileSpec . GetImage ( ) == "" {
return nil , errors . New ( "No image defined for package: " + assertion . Package . GetName ( ) )
}
Info ( ":whale: Sourcing package from image" , compileSpec . GetImage ( ) )
artifact , err := cs . packageFromImage ( compileSpec , currentPackageImageHash , keepPermissions )
2019-11-11 18:19:13 +00:00
if err != nil {
deperrs = append ( deperrs , err )
break // stop at first error
}
departifacts = append ( departifacts , artifact )
continue
}
2019-11-16 13:16:44 +00:00
Debug ( pkgTag , " :wrench: Compiling " + compileSpec . GetPackage ( ) . GetFingerPrint ( ) + " from image" )
2019-11-15 23:38:07 +00:00
artifact , err := cs . compileWithImage ( compileSpec . GetImage ( ) , buildImageHash , currentPackageImageHash , concurrency , keepPermissions , compileSpec )
2019-11-11 18:19:13 +00:00
if err != nil {
2019-11-15 23:38:07 +00:00
deperrs = append ( deperrs , err )
break // stop at first error
2019-11-11 18:19:13 +00:00
}
departifacts = append ( departifacts , artifact )
2019-11-16 13:16:44 +00:00
Info ( pkgTag , ":white_check_mark: Done" )
2019-11-15 23:38:07 +00:00
continue
}
artifact , err := cs . compileWithImage ( buildImageHash , "" , currentPackageImageHash , concurrency , keepPermissions , compileSpec )
if err != nil {
return nil , errors . Wrap ( err , "Failed compiling " + compileSpec . GetPackage ( ) . GetName ( ) )
// deperrs = append(deperrs, err)
// break // stop at first error
2019-11-11 18:19:13 +00:00
}
2019-11-15 23:38:07 +00:00
departifacts = append ( departifacts , artifact )
2019-11-16 13:16:44 +00:00
Info ( pkgTag , ":collision: Done" )
2019-11-05 16:36:22 +00:00
}
2019-11-16 13:16:44 +00:00
Info ( ":package:" , p . GetPackage ( ) . GetName ( ) , ":cyclone: Building package target from:" , lastHash )
2019-11-15 17:11:26 +00:00
artifact , err := cs . compileWithImage ( lastHash , "" , "" , concurrency , keepPermissions , p )
if err != nil {
return artifact , err
}
artifact . SetDependencies ( departifacts )
2019-11-15 23:38:07 +00:00
artifact . SetSourceAssertion ( p . GetSourceAssertion ( ) )
2019-11-05 16:36:22 +00:00
2019-11-15 17:11:26 +00:00
return artifact , err
2019-11-04 16:16:13 +00:00
}
func ( cs * LuetCompiler ) FromPackage ( p pkg . Package ) ( CompilationSpec , error ) {
2019-11-12 16:26:00 +00:00
pack , err := cs . Tree ( ) . FindPackage ( p )
2019-11-04 16:16:13 +00:00
if err != nil {
return nil , err
}
2019-11-10 09:48:07 +00:00
2019-11-04 16:16:13 +00:00
buildFile := pack . Rel ( BuildFile )
if ! helpers . Exists ( buildFile ) {
return nil , errors . New ( "No build file present for " + p . GetFingerPrint ( ) )
}
dat , err := ioutil . ReadFile ( buildFile )
if err != nil {
return nil , err
}
2019-11-10 09:48:07 +00:00
return NewLuetCompilationSpec ( dat , pack )
2019-11-04 16:16:13 +00:00
}
2019-11-04 16:20:00 +00:00
func ( cs * LuetCompiler ) GetBackend ( ) CompilerBackend {
return cs . Backend
}
func ( cs * LuetCompiler ) SetBackend ( b CompilerBackend ) {
cs . Backend = b
}