|
18 | 18 | */ |
19 | 19 | package com.here.bom.internal |
20 | 20 |
|
| 21 | +import lmcoursier.internal.shaded.coursier.core.shaded.geny.Generator.from |
21 | 22 | import sbt.File |
22 | 23 | import sbt.util.Logger |
23 | 24 |
|
| 25 | +import java.net.{URI, URL} |
24 | 26 | import java.io.FileInputStream |
25 | 27 | import java.util.Properties |
26 | 28 | import scala.collection.JavaConverters.* |
@@ -106,75 +108,96 @@ class IvyPomLocator(resolver: DependencyResolutionProxy, ivyHome: File, logger: |
106 | 108 | } |
107 | 109 | } |
108 | 110 |
|
109 | | - def findLocalPomFile(moduleId: NormalizedArtifact): Option[File] = { |
110 | | - /* |
111 | | - If the artifact was resolved by Ivy, the pom file will be stored under .ivy2 directory. |
112 | | - But if it was previously resolved by Maven, Ivy will not download it second time and just store the reference |
113 | | - Original POM file could be under either .ivy or .m2 directory: |
114 | | -
|
115 | | - Examples: |
116 | | - 1) Pom file under .ivy directory: |
117 | | - $ ~/s/vsvu-utils (batch-support)> cat ~/.ivy2/cache/com.here.platform/sdk-dep-common_2.12/ivydata-1.0.46.properties |
118 | | - #ivy cached data file for com.here.platform#sdk-dep-common_2.12;1.0.46 |
119 | | - #Mon Jan 17 12:20:26 CET 2022 |
120 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691773007.location=~/.m2/repository/com/here/platform/sdk-dep-common_2.12/1.0.46/sdk-dep-common_2.12-1.0.46.pom |
121 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691773007.is-local=true |
122 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691773007.exists=true |
123 | | - artifact\:ivy\#ivy\#xml\#-1235680096.exists=true |
124 | | - artifact\:ivy\#ivy\#xml\#-1235680096.location=~/.m2/repository/com/here/platform/sdk-dep-common_2.12/1.0.46/sdk-dep-common_2.12-1.0.46.pom |
125 | | - resolver=sbt-chain |
126 | | - artifact\:ivy\#ivy\#xml\#-1235680096.is-local=true |
127 | | - 2) Pom file downloaded by Maven first: |
128 | | - $ ~/s/vsvu-utils (batch-support)> cat ~/.ivy2/cache/com.here.platform/sdk-dep-common_2.12/ivydata-1.0.47.properties |
129 | | - #ivy cached data file for com.here.platform#sdk-dep-common_2.12;1.0.47 |
130 | | - #Thu Jan 06 12:38:21 CET 2022 |
131 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691766754.is-local=false |
132 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691766754.exists=true |
133 | | - artifact\:ivy\#ivy\#xml\#-1235673843.exists=true |
134 | | - artifact\:ivy\#ivy\#xml\#-1235673843.location=https\://artifactory.in.here.com/artifactory/here-olp-sit/com/here/platform/sdk-dep-common_2.12/1.0.47/sdk-dep-common_2.12-1.0.47.pom |
135 | | - artifact\:ivy\#ivy\#xml\#-1235673843.is-local=false |
136 | | - artifact\:sdk-dep-common_2.12\#pom.original\#pom\#-691766754.location=https\://artifactory.in.here.com/artifactory/here-olp-sit/com/here/platform/sdk-dep-common_2.12/1.0.47/sdk-dep-common_2.12-1.0.47.pom |
137 | | - */ |
138 | | - val localIvyPomLocation = new File( |
| 111 | + private def findLocalPomFile(moduleId: NormalizedArtifact): Option[File] = |
| 112 | + resolvePomUrl(moduleId).flatMap(urlToLocalFile) |
| 113 | + |
| 114 | + def getPomUrl(moduleId: NormalizedArtifact): Option[URL] = |
| 115 | + resolvePomUrl(moduleId) |
| 116 | + |
| 117 | + /** Canonical local ivy original path (if Ivy materialized it). */ |
| 118 | + private def ivyOriginalPath(moduleId: NormalizedArtifact): File = |
| 119 | + new File( |
139 | 120 | ivyHome, |
140 | 121 | s"/cache/${moduleId.group}/${moduleId.name}/ivy-${moduleId.version}.xml.original" |
141 | 122 | ) |
142 | | - if (localIvyPomLocation.exists()) { |
143 | | - logger.debug(f"Found local pom file: $localIvyPomLocation") |
144 | | - Some(localIvyPomLocation) |
145 | | - } else { |
146 | | - val ivyPropsFile = new File( |
147 | | - ivyHome, |
148 | | - s"/cache/${moduleId.group}/${moduleId.name}/ivydata-${moduleId.version}.properties" |
149 | | - ) |
150 | | - logger.debug(f"Trying to load local pom file: $ivyPropsFile") |
151 | | - referencedPomLocation(ivyPropsFile) |
152 | | - } |
| 123 | + |
| 124 | + /** ivydata-<ver>.properties path. */ |
| 125 | + private def ivyDataPath(moduleId: NormalizedArtifact): File = |
| 126 | + new File( |
| 127 | + ivyHome, |
| 128 | + s"/cache/${moduleId.group}/${moduleId.name}/ivydata-${moduleId.version}.properties" |
| 129 | + ) |
| 130 | + |
| 131 | + /** Convert URL → File only for file: scheme. */ |
| 132 | + private def urlToLocalFile(u: URL): Option[File] = |
| 133 | + if (u.getProtocol.equalsIgnoreCase("file")) Some(new File(u.toURI)) else None |
| 134 | + |
| 135 | + /** |
| 136 | + * If the artifact was resolved by Ivy, the POM will be under ~/.ivy2/cache/... as |
| 137 | + * ivy-<ver>.xml.original. If it was previously resolved by Maven, Ivy may not download it again |
| 138 | + * and only store a reference in ivydata-<ver>.properties. That .location can be a local |
| 139 | + * filesystem path (~/.m2/...) or a remote URL (https://...). |
| 140 | + * |
| 141 | + * Examples: 1) Local POM (ivy): |
| 142 | + * ~/.ivy2/cache/com.here.platform/sdk-dep-common_2.12/ivydata-1.0.46.properties |
| 143 | + * artifact:...pom.original...location=~/.m2/repository/.../sdk-dep-common_2.12-1.0.46.pom ... |
| 144 | + * is-local=true |
| 145 | + * |
| 146 | + * 2) Remote POM (downloaded by Maven first): |
| 147 | + * ~/.ivy2/cache/com.here.platform/sdk-dep-common_2.12/ivydata-1.0.47.properties |
| 148 | + * artifact:...pom.original...location=https://artifactory.../sdk-dep-common_2.12-1.0.47.pom ... |
| 149 | + * is-local=false |
| 150 | + * |
| 151 | + * Resolution strategy: |
| 152 | + * - If ivy-<ver>.xml.original exists => return its file: URL. |
| 153 | + * - Else read ivydata .location: * if it parses as URL with scheme => return that URL (handles |
| 154 | + * https:// or file:/) * else if it's a filesystem path that exists => return file: URL * else |
| 155 | + * \=> None |
| 156 | + */ |
| 157 | + |
| 158 | + private def resolvePomUrl(moduleId: NormalizedArtifact): Option[URL] = { |
| 159 | + val local = ivyOriginalPath(moduleId) |
| 160 | + if (local.exists()) return Some(local.toURI.toURL) |
| 161 | + referencedPomUrl(ivyDataPath(moduleId)) |
153 | 162 | } |
154 | 163 |
|
155 | | - private def referencedPomLocation(ivyPropertyFile: File): Option[File] = { |
| 164 | + /** Read a usable URL from ivydata (normalizes “https\://”, handles file paths). */ |
| 165 | + private def referencedPomUrl(ivyPropertyFile: File): Option[URL] = { |
| 166 | + if (!ivyPropertyFile.exists()) return None |
| 167 | + |
156 | 168 | val properties = new Properties() |
157 | | - if (ivyPropertyFile.exists()) { |
158 | | - val is = new FileInputStream(ivyPropertyFile) |
159 | | - try { |
160 | | - properties.load(is) |
161 | | - } finally { |
162 | | - is.close() |
163 | | - } |
| 169 | + val is = new FileInputStream(ivyPropertyFile) |
| 170 | + try properties.load(is) |
| 171 | + finally is.close() |
| 172 | + |
| 173 | + val locationKeyOpt: Option[String] = |
| 174 | + properties |
| 175 | + .keys() |
| 176 | + .asScala |
| 177 | + .collect { case s: String if s.endsWith(".location") => s } |
| 178 | + .headOption |
| 179 | + |
| 180 | + locationKeyOpt.flatMap { locationKey => |
| 181 | + val rawLocation0 = properties.getProperty(locationKey) |
| 182 | + val rawLocation = Option(rawLocation0).map(_.replace("\\:", ":")) |
164 | 183 |
|
165 | | - val locationKey = |
166 | | - properties.keys().asScala.find(key => key.asInstanceOf[String].endsWith(".location")) |
167 | | - if (locationKey.isEmpty) { |
168 | | - logger.warn(f"No *.location entry in the file $ivyPropertyFile") |
| 184 | + rawLocation.flatMap { loc => |
| 185 | + // Prefer interpreting as a URI; if it has a scheme, we’re done. |
| 186 | + try { |
| 187 | + val uri = new URI(loc) |
| 188 | + if (uri.getScheme != null) Some(uri.toURL) |
| 189 | + else { |
| 190 | + // No scheme => treat as filesystem path and require it to exist. |
| 191 | + val file = new File(loc) |
| 192 | + if (file.exists()) Some(file.toURI.toURL) else None |
| 193 | + } |
| 194 | + } catch { |
| 195 | + case _: Exception => |
| 196 | + // Fallback: treat as filesystem path if valid & exists. |
| 197 | + val file = new File(loc) |
| 198 | + if (file.exists()) Some(file.toURI.toURL) else None |
| 199 | + } |
169 | 200 | } |
170 | | - locationKey.map(k => { |
171 | | - val f = new File(properties.getProperty(k.asInstanceOf[String])) |
172 | | - require(f.exists(), s"File $f doesn't exist, is artifact cache corrupted?") |
173 | | - f |
174 | | - }) |
175 | | - } else { |
176 | | - logger.debug(f"File: $ivyPropertyFile not exists") |
177 | | - None |
178 | 201 | } |
179 | 202 | } |
180 | 203 | } |
0 commit comments