diff --git a/cmd/build.go b/cmd/build.go index 899779a7..83b9d641 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -78,6 +78,7 @@ var buildCmd = &cobra.Command{ nodeps := viper.GetBool("nodeps") onlydeps := viper.GetBool("onlydeps") keepExportedImages := viper.GetBool("keep-exported-images") + full := viper.GetBool("full") compilerSpecs := compiler.NewLuetCompilationspecs() var compilerBackend compiler.CompilerBackend @@ -146,7 +147,15 @@ var buildCmd = &cobra.Command{ luetCompiler := compiler.NewLuetCompiler(compilerBackend, generalRecipe.GetDatabase(), opts) luetCompiler.SetConcurrency(concurrency) luetCompiler.SetCompressionType(compiler.CompressionImplementation(compressionType)) - if !all { + if full { + specs, err := luetCompiler.FromDatabase(generalRecipe.GetDatabase(), true, dst) + if err != nil { + Fatal(err.Error()) + } + for _, spec := range specs { + compilerSpecs.Add(spec) + } + } else if !all { for _, a := range args { pack, err := helpers.ParsePackageStr(a) @@ -208,7 +217,9 @@ func init() { buildCmd.Flags().Bool("privileged", false, "Privileged (Keep permissions)") buildCmd.Flags().String("database", "memory", "database used for solving (memory,boltdb)") buildCmd.Flags().Bool("revdeps", false, "Build with revdeps") - buildCmd.Flags().Bool("all", false, "Build all packages in the tree") + buildCmd.Flags().Bool("all", false, "Build all specfiles in the tree") + buildCmd.Flags().Bool("full", false, "Build all packages (optimized)") + buildCmd.Flags().String("destination", path, "Destination folder") buildCmd.Flags().String("compression", "none", "Compression alg: none, gzip") buildCmd.Flags().String("image-repository", "luet/cache", "Default base image string for generated image") diff --git a/pkg/compiler/compiler.go b/pkg/compiler/compiler.go index f633a6c6..a6ad398a 100644 --- a/pkg/compiler/compiler.go +++ b/pkg/compiler/compiler.go @@ -448,6 +448,53 @@ func (cs *LuetCompiler) compileWithImage(image, buildertaggedImage, packageImage return artifact, nil } +func (cs *LuetCompiler) FromDatabase(db pkg.PackageDatabase, minimum bool, dst string) ([]CompilationSpec, error) { + compilerSpecs := NewLuetCompilationspecs() + + w := db.World() + + for _, p := range w { + spec, err := cs.FromPackage(p) + if err != nil { + return nil, err + } + if dst != "" { + spec.SetOutputPath(dst) + } + compilerSpecs.Add(spec) + } + + switch minimum { + case true: + return cs.ComputeMinimumCompilableSet(compilerSpecs.Unique().All()...) + default: + return compilerSpecs.Unique().All(), nil + } +} + +// ComputeMinimumCompilableSet strips specs that are eventually compiled by leafs +func (cs *LuetCompiler) ComputeMinimumCompilableSet(p ...CompilationSpec) ([]CompilationSpec, error) { + // Generate a set with all the deps of the provided specs + // we will use that set to remove the deps from the list of provided compilation specs + allDependencies := solver.PackagesAssertions{} // Get all packages that will be in deps + result := []CompilationSpec{} + for _, spec := range p { + ass, err := cs.ComputeDepTree(spec) + if err != nil { + return result, errors.Wrap(err, "computin specs deptree") + } + + allDependencies = append(allDependencies, ass.Drop(spec.GetPackage())...) + } + + for _, spec := range p { + if found := allDependencies.Search(spec.GetPackage().GetFingerPrint()); found == nil { + result = append(result, spec) + } + } + return result, nil +} + func (cs *LuetCompiler) ComputeDepTree(p CompilationSpec) (solver.PackagesAssertions, error) { s := solver.NewResolver(pkg.NewInMemoryDatabase(false), cs.Database, pkg.NewInMemoryDatabase(false), cs.Options.SolverOptions.Resolver()) diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index 36f65de6..0fefe3af 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -706,6 +706,25 @@ var _ = Describe("Compiler", func() { }) }) + Context("Compilation of whole tree", func() { + It("doesn't include dependencies that would be compiled anyway", func() { + // As some specs are dependent from each other, don't pull it in if they would + // be eventually + generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) + + err := generalRecipe.Load("../../tests/fixtures/includeimage") + Expect(err).ToNot(HaveOccurred()) + Expect(len(generalRecipe.GetDatabase().GetPackages())).To(Equal(2)) + compiler := NewLuetCompiler(sd.NewSimpleDockerBackend(), generalRecipe.GetDatabase(), NewDefaultCompilerOptions()) + + specs, err := compiler.FromDatabase(generalRecipe.GetDatabase(), true, "") + Expect(err).ToNot(HaveOccurred()) + Expect(len(specs)).To(Equal(1)) + + Expect(specs[0].GetPackage().GetFingerPrint()).To(Equal("b-test-1.0")) + }) + }) + Context("File list", func() { It("is generated after the compilation process and annotated in the metadata", func() { generalRecipe := tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false)) diff --git a/pkg/compiler/interface.go b/pkg/compiler/interface.go index 44298ca2..4c5f3b52 100644 --- a/pkg/compiler/interface.go +++ b/pkg/compiler/interface.go @@ -28,9 +28,10 @@ type Compiler interface { CompileParallel(keepPermissions bool, ps CompilationSpecs) ([]Artifact, []error) CompileWithReverseDeps(keepPermissions bool, ps CompilationSpecs) ([]Artifact, []error) ComputeDepTree(p CompilationSpec) (solver.PackagesAssertions, error) + ComputeMinimumCompilableSet(p ...CompilationSpec) ([]CompilationSpec, error) SetConcurrency(i int) FromPackage(pkg.Package) (CompilationSpec, error) - + FromDatabase(db pkg.PackageDatabase, minimum bool, dst string) ([]CompilationSpec, error) SetBackend(CompilerBackend) GetBackend() CompilerBackend SetCompressionType(t CompressionImplementation)