func (c *Compilator) isPackageCompiled(pkg *model.Package) (bool, error) { // If compiled package exists on hard disk compiledPackagePath := pkg.GetPackageCompiledDir(c.hostWorkDir) compiledPackagePathExists, err := validatePath(compiledPackagePath, true, "package path") if err != nil { return false, err } if !compiledPackagePathExists { return false, nil } compiledDirEmpty, err := isDirEmpty(compiledPackagePath) if err != nil { return false, err } return !compiledDirEmpty, nil }
func (c *Compilator) getSourcePackageDir(pkg *model.Package) string { return filepath.Join(pkg.GetTargetPackageSourcesDir(c.hostWorkDir), "var", "vcap", "source") }
func (c *Compilator) compilePackage(pkg *model.Package) (err error) { // Prepare input dir (package plus deps) if err := c.createCompilationDirStructure(pkg); err != nil { return err } if err := c.copyDependencies(pkg); err != nil { return err } // Generate a compilation script targetScriptName := "compile.sh" hostScriptPath := filepath.Join(pkg.GetTargetPackageSourcesDir(c.hostWorkDir), targetScriptName) containerScriptPath := filepath.Join(docker.ContainerInPath, targetScriptName) if err := compilation.SaveScript(c.baseType, compilation.CompilationScript, hostScriptPath); err != nil { return err } // Extract package extractDir := c.getSourcePackageDir(pkg) if _, err := pkg.Extract(extractDir); err != nil { return err } // Run compilation in container containerName := c.getPackageContainerName(pkg) // in-memory buffer of the log log := new(bytes.Buffer) stdoutWriter := docker.NewFormattingWriter( log, func(line string) string { return color.GreenString("compilation-%s > %s", color.MagentaString("%s", pkg.Name), color.WhiteString("%s", line)) }, ) stderrWriter := docker.NewFormattingWriter( log, func(line string) string { return color.GreenString("compilation-%s > %s", color.MagentaString("%s", pkg.Name), color.RedString("%s", line)) }, ) sourceMountName := fmt.Sprintf("source_mount-%s", uuid.New()) mounts := map[string]string{ pkg.GetTargetPackageSourcesDir(c.hostWorkDir): docker.ContainerInPath, pkg.GetPackageCompiledTempDir(c.hostWorkDir): docker.ContainerOutPath, // Add the volume mount to work around AUFS issues. We will clean // the volume up (as long as we're not trying to keep the container // around for debugging). We don't give it an actual directory to mount // from, so it will be in some docker-maintained storage. sourceMountName: ContainerSourceDir, } exitCode, container, err := c.dockerManager.RunInContainer(docker.RunInContainerOpts{ ContainerName: containerName, ImageName: c.BaseImageName(), Cmd: []string{"bash", containerScriptPath, pkg.Name, pkg.Version}, Mounts: mounts, Volumes: map[string]map[string]string{sourceMountName: nil}, KeepContainer: c.keepContainer, StdoutWriter: stdoutWriter, StderrWriter: stderrWriter, }) if container != nil && (!c.keepContainer || err == nil || exitCode == 0) { // Attention. While the assignments to 'err' in the // deferal below take effect after the 'return' // statements coming later they are visible to the // caller, i.e. override the 'return'ed value, // because 'err' is a __named__ return parameter. defer func() { // Remove container - dockerManager.RemoveContainer does a force-rm if removeErr := c.dockerManager.RemoveContainer(container.ID); removeErr != nil { if err == nil { err = removeErr } else { err = fmt.Errorf("Error compiling package: %s. Error removing package: %s", err.Error(), removeErr.Error()) } } if removeErr := c.dockerManager.RemoveVolumes(container); removeErr != nil { if err == nil { err = removeErr } else { err = fmt.Errorf("%s: Error removing volumes for package %s: %s", err, pkg.Name, removeErr) } } }() } if err != nil { log.WriteTo(c.ui) return fmt.Errorf("Error compiling package %s: %s", pkg.Name, err.Error()) } if exitCode != 0 { log.WriteTo(c.ui) return fmt.Errorf("Error - compilation for package %s exited with code %d", pkg.Name, exitCode) } return os.Rename( pkg.GetPackageCompiledTempDir(c.hostWorkDir), pkg.GetPackageCompiledDir(c.hostWorkDir)) }