@@ -24,6 +24,8 @@ import com.google.common.io.{Files, ByteStreams}
2424
2525import org .apache .commons .io .FileUtils
2626
27+ import org .apache .ivy .core .settings .IvySettings
28+
2729import org .apache .spark .TestUtils .{createCompiledClass , JavaSourceFromString }
2830import org .apache .spark .deploy .SparkSubmitUtils .MavenCoordinate
2931
@@ -44,13 +46,30 @@ private[deploy] object IvyTestUtils {
4446 if (! useIvyLayout) {
4547 Seq (groupDirs, artifactDirs, artifact.version).mkString(File .separator)
4648 } else {
47- Seq (groupDirs , artifactDirs, artifact.version, ext + " s" ).mkString(File .separator)
49+ Seq (artifact.groupId , artifactDirs, artifact.version, ext + " s" ).mkString(File .separator)
4850 }
4951 new File (prefix, artifactPath)
5052 }
5153
52- private def artifactName (artifact : MavenCoordinate , ext : String = " .jar" ): String = {
53- s " ${artifact.artifactId}- ${artifact.version}$ext"
54+ /** Returns the artifact naming based on standard ivy or maven format. */
55+ private def artifactName (
56+ artifact : MavenCoordinate ,
57+ useIvyLayout : Boolean ,
58+ ext : String = " .jar" ): String = {
59+ if (! useIvyLayout) {
60+ s " ${artifact.artifactId}- ${artifact.version}$ext"
61+ } else {
62+ s " ${artifact.artifactId}$ext"
63+ }
64+ }
65+
66+ /** Returns the directory for the given groupId based on standard ivy or maven format. */
67+ private def getBaseGroupDirectory (artifact : MavenCoordinate , useIvyLayout : Boolean ): String = {
68+ if (! useIvyLayout) {
69+ artifact.groupId.replace(" ." , File .separator)
70+ } else {
71+ artifact.groupId
72+ }
5473 }
5574
5675 /** Write the contents to a file to the supplied directory. */
@@ -92,6 +111,23 @@ private[deploy] object IvyTestUtils {
92111 createCompiledClass(className, dir, sourceFile, Seq .empty)
93112 }
94113
114+ private def createDescriptor (
115+ tempPath : File ,
116+ artifact : MavenCoordinate ,
117+ dependencies : Option [Seq [MavenCoordinate ]],
118+ useIvyLayout : Boolean ): File = {
119+ if (useIvyLayout) {
120+ val ivyXmlPath = pathFromCoordinate(artifact, tempPath, " ivy" , true )
121+ Files .createParentDirs(new File (ivyXmlPath, " dummy" ))
122+ createIvyDescriptor(ivyXmlPath, artifact, dependencies)
123+ } else {
124+ val pomPath = pathFromCoordinate(artifact, tempPath, " pom" , useIvyLayout)
125+ Files .createParentDirs(new File (pomPath, " dummy" ))
126+ createPom(pomPath, artifact, dependencies)
127+ }
128+ }
129+
130+
95131 /** Helper method to write artifact information in the pom. */
96132 private def pomArtifactWriter (artifact : MavenCoordinate , tabCount : Int = 1 ): String = {
97133 var result = " \n " + " " * tabCount + s " <groupId> ${artifact.groupId}</groupId> "
@@ -121,15 +157,55 @@ private[deploy] object IvyTestUtils {
121157 " \n <dependencies>\n " + inside + " \n </dependencies>"
122158 }.getOrElse(" " )
123159 content += " \n </project>"
124- writeFile(dir, artifactName(artifact, " .pom" ), content.trim)
160+ writeFile(dir, artifactName(artifact, false , " .pom" ), content.trim)
161+ }
162+
163+ /** Helper method to write artifact information in the ivy.xml. */
164+ private def ivyArtifactWriter (artifact : MavenCoordinate ): String = {
165+ s """ <dependency org=" ${artifact.groupId}" name=" ${artifact.artifactId}"
166+ | rev=" ${artifact.version}" force="true"
167+ | conf="compile->compile(*),master(*);runtime->runtime(*)"/> """ .stripMargin
168+ }
169+
170+ /** Create a pom file for this artifact. */
171+ private def createIvyDescriptor (
172+ dir : File ,
173+ artifact : MavenCoordinate ,
174+ dependencies : Option [Seq [MavenCoordinate ]]): File = {
175+ var content = s """
176+ |<?xml version="1.0" encoding="UTF-8"?>
177+ |<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
178+ | <info organisation=" ${artifact.groupId}"
179+ | module=" ${artifact.artifactId}"
180+ | revision=" ${artifact.version}"
181+ | status="release" publication="20150405222456" />
182+ | <configurations>
183+ | <conf name="default" visibility="public" description="" extends="runtime,master"/>
184+ | <conf name="compile" visibility="public" description=""/>
185+ | <conf name="master" visibility="public" description=""/>
186+ | <conf name="runtime" visibility="public" description="" extends="compile"/>
187+ | <conf name="pom" visibility="public" description=""/>
188+ | </configurations>
189+ | <publications>
190+ | <artifact name=" ${artifactName(artifact, true , " " )}" type="jar" ext="jar"
191+ | conf="master"/>
192+ | </publications>
193+ """ .stripMargin.trim
194+ content += dependencies.map { deps =>
195+ val inside = deps.map(ivyArtifactWriter).mkString(" \n " )
196+ " \n <dependencies>\n " + inside + " \n </dependencies>"
197+ }.getOrElse(" " )
198+ content += " \n </ivy-module>"
199+ writeFile(dir, " ivy.xml" , content.trim)
125200 }
126201
127202 /** Create the jar for the given maven coordinate, using the supplied files. */
128203 private def packJar (
129204 dir : File ,
130205 artifact : MavenCoordinate ,
131- files : Seq [(String , File )]): File = {
132- val jarFile = new File (dir, artifactName(artifact))
206+ files : Seq [(String , File )],
207+ useIvyLayout : Boolean ): File = {
208+ val jarFile = new File (dir, artifactName(artifact, useIvyLayout))
133209 val jarFileStream = new FileOutputStream (jarFile)
134210 val jarStream = new JarOutputStream (jarFileStream, new java.util.jar.Manifest ())
135211
@@ -187,12 +263,10 @@ private[deploy] object IvyTestUtils {
187263 } else {
188264 Seq (javaFile)
189265 }
190- val jarFile = packJar(jarPath, artifact, allFiles)
266+ val jarFile = packJar(jarPath, artifact, allFiles, useIvyLayout )
191267 assert(jarFile.exists(), " Problem creating Jar file" )
192- val pomPath = pathFromCoordinate(artifact, tempPath, " pom" , useIvyLayout)
193- Files .createParentDirs(new File (pomPath, " dummy" ))
194- val pomFile = createPom(pomPath, artifact, dependencies)
195- assert(pomFile.exists(), " Problem creating Pom file" )
268+ val descriptor = createDescriptor(tempPath, artifact, dependencies, useIvyLayout)
269+ assert(descriptor.exists(), " Problem creating Pom file" )
196270 } finally {
197271 FileUtils .deleteDirectory(root)
198272 }
@@ -237,25 +311,40 @@ private[deploy] object IvyTestUtils {
237311 dependencies : Option [String ],
238312 rootDir : Option [File ],
239313 useIvyLayout : Boolean = false ,
240- withPython : Boolean = false )(f : String => Unit ): Unit = {
314+ withPython : Boolean = false ,
315+ ivySettings : IvySettings = new IvySettings )(f : String => Unit ): Unit = {
316+ val deps = dependencies.map(SparkSubmitUtils .extractMavenCoordinates)
317+ purgeLocalIvyCache(artifact, deps, ivySettings)
241318 val repo = createLocalRepositoryForTests(artifact, dependencies, rootDir, useIvyLayout,
242319 withPython)
243320 try {
244321 f(repo.toURI.toString)
245322 } finally {
246323 // Clean up
247324 if (repo.toString.contains(" .m2" ) || repo.toString.contains(" .ivy2" )) {
248- FileUtils .deleteDirectory(new File (repo,
249- artifact.groupId.replace(" ." , File .separator) + File .separator + artifact.artifactId))
250- dependencies.map(SparkSubmitUtils .extractMavenCoordinates).foreach { seq =>
251- seq.foreach { dep =>
252- FileUtils .deleteDirectory(new File (repo,
253- dep.artifactId.replace(" ." , File .separator)))
254- }
325+ val groupDir = getBaseGroupDirectory(artifact, useIvyLayout)
326+ FileUtils .deleteDirectory(new File (repo, groupDir + File .separator + artifact.artifactId))
327+ deps.foreach { _.foreach { dep =>
328+ FileUtils .deleteDirectory(new File (repo, getBaseGroupDirectory(dep, useIvyLayout)))
329+ }
255330 }
256331 } else {
257332 FileUtils .deleteDirectory(repo)
258333 }
334+ purgeLocalIvyCache(artifact, deps, ivySettings)
335+ }
336+ }
337+
338+ /** Deletes the test packages from the ivy cache */
339+ private def purgeLocalIvyCache (
340+ artifact : MavenCoordinate ,
341+ dependencies : Option [Seq [MavenCoordinate ]],
342+ ivySettings : IvySettings ): Unit = {
343+ // delete the artifact from the cache as well if it already exists
344+ FileUtils .deleteDirectory(new File (ivySettings.getDefaultCache, artifact.groupId))
345+ dependencies.foreach { _.foreach { dep =>
346+ FileUtils .deleteDirectory(new File (ivySettings.getDefaultCache, dep.groupId))
347+ }
259348 }
260349 }
261350}
0 commit comments