@@ -266,7 +266,7 @@ object DependencyResolver extends Logging {
266266 }
267267
268268 // Read a config file from a built target. Extract dependencies 'writtenPath'.
269- def getSparseDependencyInfo (configPath : String ): List [String ] = {
269+ def getSparseDependencyInfo (configPath : String ): ( List [String ], String ) = {
270270 try {
271271 val yamlText = IO .read(IO .uri(configPath))
272272 val json = Convert .textToJson(yamlText, configPath)
@@ -275,15 +275,18 @@ object DependencyResolver extends Logging {
275275 val dependencies =
276276 if (legacyMode) {
277277 val jsonVec = json.hcursor.downField(" functionality" ).downField(" dependencies" ).focus.flatMap(_.asArray).get
278- jsonVec.flatMap(_.hcursor.downField(" writtenPath" ).as[String ].toOption).toList
278+ val depList = jsonVec.flatMap(_.hcursor.downField(" writtenPath" ).as[String ].toOption).toList
279+ (depList, " " )
279280 }
280281 else {
281282 val jsonVec = json.hcursor.downField(" build_info" ).downField(" dependencies" ).focus.flatMap(_.asArray).get
282- jsonVec.flatMap(_.hcursor.as[String ].toOption).toList
283+ val depList = jsonVec.flatMap(_.hcursor.as[String ].toOption).toList
284+ val outputPath = json.hcursor.downField(" build_info" ).downField(" output" ).as[String ].toOption.get
285+ (depList, outputPath)
283286 }
284287 dependencies
285288 } catch {
286- case _ : Throwable => Nil
289+ case _ : Throwable => ( Nil , " " )
287290 }
288291 }
289292
@@ -296,19 +299,38 @@ object DependencyResolver extends Logging {
296299 }
297300
298301 // Handle dependencies of dependencies. For a given already built component, get their dependencies, copy them to our new target folder and recurse into these.
299- def recurseBuiltDependencies (output : Path , repoPath : Path , builtDependencyPath : String , dependency : Dependency , depth : Int = 0 ): Unit = {
302+ def recurseBuiltDependencies (output : Path , repoPath : Path , builtDependencyPath : String , dependency : Dependency , dependencySourcePath : Option [Path ] = None , depth : Int = 0 ): Unit = {
303+ import scala .jdk .CollectionConverters ._
300304
301305 // Limit recursion depth to prevent infinite loops in e.g. cross dependencies (TODO)
302306 if (depth > 10 )
303307 throw new RuntimeException (" Copying dependencies traces too deep. Possibibly caused by a cross dependency." )
304308
305309 // this returns paths relative to `repoPath` of dependencies to be copied to `output`
306- val dependencyPaths = getSparseDependencyInfo(builtDependencyPath + " /.config.vsh.yaml" )
310+ val (dependencyPaths, relativeOutput) = getSparseDependencyInfo(builtDependencyPath + " /.config.vsh.yaml" )
311+ logger.debug(s " Paths to relativize: dependencySourcePath: $dependencySourcePath, relativeOutput: $relativeOutput" )
312+
313+ // remove the trailing path parts as far as relativeOutputPath matches the dependencySourcePath
314+ // baseDependencySourcePath: a/b/c/d/e
315+ // relativeOutputPath: c'/d/e
316+ // output: a/b/c & c'
317+ val dependencySourceParts = dependencySourcePath.map { dsp =>
318+ val dspParts = dsp.iterator().asScala.toList.map(p => Some (p)).reverse
319+ val relativeOutputPath = Paths .get(relativeOutput).iterator().asScala.toList.map(p => Some (p)).reverse
320+ // Find the first part that is not in the relative output path
321+ val commonParts = dspParts.zipAll(relativeOutputPath, None , None ).dropWhile{ case (a, b) => a == b }
322+
323+ val leftPath = commonParts.flatMap(_._1).reverse.fold(dsp.getRoot())((p1, p2) => p1.resolve(p2))
324+ val rightPath = commonParts.flatMap(_._2).reverse.reduce((p1, p2) => p1.resolve(p2))
325+
326+ (leftPath, rightPath)
327+ }
328+ logger.debug(s " dependencySourceParts: $dependencySourceParts" )
307329
308330 for (dp <- dependencyPaths) {
309331 // Get the source & destination path for the dependency, functionality depends whether it was a previous dependency or not.
310332 // Paths are relativized depending the original dependency.
311- val (sourcePath, destPath) = Dependency .getSourceAndDestinationFromWrittenPath(dp, output, repoPath, dependency)
333+ val (sourcePath, destPath) = Dependency .getSourceAndDestinationFromWrittenPath(dp, output, repoPath, dependency, dependencySourceParts )
312334
313335 // Make sure the destination is clean so first remove the destination folder if it exists
314336 if (destPath.toFile().exists())
@@ -319,7 +341,7 @@ object DependencyResolver extends Logging {
319341 IO .copyFolder(sourcePath, destPath)
320342
321343 // Check for more dependencies
322- recurseBuiltDependencies(output, repoPath, destPath.toString(), dependency, depth + 1 )
344+ recurseBuiltDependencies(output, repoPath, destPath.toString(), dependency, Some (sourcePath), depth + 1 )
323345 }
324346 }
325347
0 commit comments