explodeModules takes a collection of build modules and concurrently reads their tar files. It assumes the modules were extracted with `buildpack.extractBuildpacks`, which when provided a flattened buildpack package containing N buildpacks, will return N modules: 1 module with a single tar containing
(kind, tmpDir string, additionalModules []buildpack.BuildModule, logger logging.Logger)
| 1326 | // explodeModules will split the module into N modules, each with a single tar containing a single buildpack. |
| 1327 | // In case a module with an empty tar file is found, it is ignored. |
| 1328 | func explodeModules(kind, tmpDir string, additionalModules []buildpack.BuildModule, logger logging.Logger) ([]moduleWithDiffID, []error) { |
| 1329 | modInfoChans := make([]chan modInfo, len(additionalModules)) |
| 1330 | for i := range modInfoChans { |
| 1331 | modInfoChans[i] = make(chan modInfo, 1) |
| 1332 | } |
| 1333 | |
| 1334 | // Explode modules concurrently |
| 1335 | for i, module := range additionalModules { |
| 1336 | go func(i int, module buildpack.BuildModule) { |
| 1337 | modTmpDir := filepath.Join(tmpDir, fmt.Sprintf("%s-%s", kind, strconv.Itoa(i))) |
| 1338 | if err := os.MkdirAll(modTmpDir, os.ModePerm); err != nil { |
| 1339 | modInfoChans[i] <- handleError(module, err, fmt.Sprintf("creating %s temp dir %s", kind, modTmpDir)) |
| 1340 | } |
| 1341 | moduleTars, err := buildpack.ToNLayerTar(modTmpDir, module) |
| 1342 | if err != nil { |
| 1343 | modInfoChans[i] <- handleError(module, err, fmt.Sprintf("creating %s tar file at path %s", module.Descriptor().Info().FullName(), modTmpDir)) |
| 1344 | } |
| 1345 | modInfoChans[i] <- modInfo{moduleTars: moduleTars} |
| 1346 | }(i, module) |
| 1347 | } |
| 1348 | |
| 1349 | // Iterate over modules sequentially, building up the result. |
| 1350 | var ( |
| 1351 | result []moduleWithDiffID |
| 1352 | errs []error |
| 1353 | ) |
| 1354 | for i, module := range additionalModules { |
| 1355 | mi := <-modInfoChans[i] |
| 1356 | if mi.err != nil { |
| 1357 | errs = append(errs, mi.err) |
| 1358 | continue |
| 1359 | } |
| 1360 | if len(mi.moduleTars) == 1 { |
| 1361 | // This entry is an individual buildpack or extension, or a module with empty tar |
| 1362 | moduleTar := mi.moduleTars[0] |
| 1363 | diffID, err := dist.LayerDiffID(moduleTar.Path()) |
| 1364 | if err != nil { |
| 1365 | errs = append(errs, errors.Wrapf(err, "calculating layer diffID for path %s", moduleTar.Path())) |
| 1366 | continue |
| 1367 | } |
| 1368 | if diffID.String() == emptyTarDiffID { |
| 1369 | logger.Debugf("%s %s is a component of a flattened buildpack that will be added elsewhere, skipping...", istrings.Title(kind), style.Symbol(moduleTar.Info().FullName())) |
| 1370 | continue // we don't need to keep modules with empty tars |
| 1371 | } |
| 1372 | result = append(result, moduleWithDiffID{ |
| 1373 | tarPath: moduleTar.Path(), |
| 1374 | diffID: diffID.String(), |
| 1375 | module: module, |
| 1376 | }) |
| 1377 | } else { |
| 1378 | // This entry is a flattened buildpack that was exploded, we need to add each exploded buildpack to the result in order |
| 1379 | for _, moduleTar := range mi.moduleTars { |
| 1380 | diffID, err := dist.LayerDiffID(moduleTar.Path()) |
| 1381 | if err != nil { |
| 1382 | errs = append(errs, errors.Wrapf(err, "calculating layer diffID for path %s", moduleTar.Path())) |
| 1383 | continue |
| 1384 | } |
| 1385 | explodedMod := moduleWithDiffID{ |
no test coverage detected