@@ -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,22 @@ 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+
95130 /** Helper method to write artifact information in the pom. */
96131 private def pomArtifactWriter (artifact : MavenCoordinate , tabCount : Int = 1 ): String = {
97132 var result = " \n " + " " * tabCount + s " <groupId> ${artifact.groupId}</groupId> "
@@ -121,15 +156,55 @@ private[deploy] object IvyTestUtils {
121156 " \n <dependencies>\n " + inside + " \n </dependencies>"
122157 }.getOrElse(" " )
123158 content += " \n </project>"
124- writeFile(dir, artifactName(artifact, " .pom" ), content.trim)
159+ writeFile(dir, artifactName(artifact, false , " .pom" ), content.trim)
160+ }
161+
162+ /** Helper method to write artifact information in the ivy.xml. */
163+ private def ivyArtifactWriter (artifact : MavenCoordinate ): String = {
164+ s """ <dependency org=" ${artifact.groupId}" name=" ${artifact.artifactId}"
165+ | rev=" ${artifact.version}" force="true"
166+ | conf="compile->compile(*),master(*);runtime->runtime(*)"/> """ .stripMargin
167+ }
168+
169+ /** Create a pom file for this artifact. */
170+ private def createIvyDescriptor (
171+ dir : File ,
172+ artifact : MavenCoordinate ,
173+ dependencies : Option [Seq [MavenCoordinate ]]): File = {
174+ var content = s """
175+ |<?xml version="1.0" encoding="UTF-8"?>
176+ |<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
177+ | <info organisation=" ${artifact.groupId}"
178+ | module=" ${artifact.artifactId}"
179+ | revision=" ${artifact.version}"
180+ | status="release" publication="20150405222456" />
181+ | <configurations>
182+ | <conf name="default" visibility="public" description="" extends="runtime,master"/>
183+ | <conf name="compile" visibility="public" description=""/>
184+ | <conf name="master" visibility="public" description=""/>
185+ | <conf name="runtime" visibility="public" description="" extends="compile"/>
186+ | <conf name="pom" visibility="public" description=""/>
187+ | </configurations>
188+ | <publications>
189+ | <artifact name=" ${artifactName(artifact, true , " " )}" type="jar" ext="jar"
190+ | conf="master"/>
191+ | </publications>
192+ """ .stripMargin.trim
193+ content += dependencies.map { deps =>
194+ val inside = deps.map(ivyArtifactWriter).mkString(" \n " )
195+ " \n <dependencies>\n " + inside + " \n </dependencies>"
196+ }.getOrElse(" " )
197+ content += " \n </ivy-module>"
198+ writeFile(dir, " ivy.xml" , content.trim)
125199 }
126200
127201 /** Create the jar for the given maven coordinate, using the supplied files. */
128202 private def packJar (
129203 dir : File ,
130204 artifact : MavenCoordinate ,
131- files : Seq [(String , File )]): File = {
132- val jarFile = new File (dir, artifactName(artifact))
205+ files : Seq [(String , File )],
206+ useIvyLayout : Boolean ): File = {
207+ val jarFile = new File (dir, artifactName(artifact, useIvyLayout))
133208 val jarFileStream = new FileOutputStream (jarFile)
134209 val jarStream = new JarOutputStream (jarFileStream, new java.util.jar.Manifest ())
135210
@@ -187,12 +262,10 @@ private[deploy] object IvyTestUtils {
187262 } else {
188263 Seq (javaFile)
189264 }
190- val jarFile = packJar(jarPath, artifact, allFiles)
265+ val jarFile = packJar(jarPath, artifact, allFiles, useIvyLayout )
191266 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" )
267+ val descriptor = createDescriptor(tempPath, artifact, dependencies, useIvyLayout)
268+ assert(descriptor.exists(), " Problem creating Pom file" )
196269 } finally {
197270 FileUtils .deleteDirectory(root)
198271 }
@@ -237,25 +310,40 @@ private[deploy] object IvyTestUtils {
237310 dependencies : Option [String ],
238311 rootDir : Option [File ],
239312 useIvyLayout : Boolean = false ,
240- withPython : Boolean = false )(f : String => Unit ): Unit = {
313+ withPython : Boolean = false ,
314+ ivySettings : IvySettings = new IvySettings )(f : String => Unit ): Unit = {
315+ val deps = dependencies.map(SparkSubmitUtils .extractMavenCoordinates)
316+ purgeLocalIvyCache(artifact, deps, ivySettings)
241317 val repo = createLocalRepositoryForTests(artifact, dependencies, rootDir, useIvyLayout,
242318 withPython)
243319 try {
244320 f(repo.toURI.toString)
245321 } finally {
246322 // Clean up
247323 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)))
324+ val groupDir = getBaseGroupDirectory(artifact, useIvyLayout)
325+ FileUtils .deleteDirectory(new File (repo, groupDir + File .separator + artifact.artifactId))
326+ deps.foreach { _.foreach { dep =>
327+ FileUtils .deleteDirectory(new File (repo, getBaseGroupDirectory(dep, useIvyLayout)))
254328 }
255329 }
256330 } else {
257331 FileUtils .deleteDirectory(repo)
258332 }
333+ purgeLocalIvyCache(artifact, deps, ivySettings)
334+ }
335+ }
336+
337+ /** Deletes the test packages from the ivy cache */
338+ private def purgeLocalIvyCache (
339+ artifact : MavenCoordinate ,
340+ dependencies : Option [Seq [MavenCoordinate ]],
341+ ivySettings : IvySettings ): Unit = {
342+ // delete the artifact from the cache as well if it already exists
343+ FileUtils .deleteDirectory(new File (ivySettings.getDefaultCache, artifact.groupId))
344+ dependencies.foreach { _.foreach { dep =>
345+ FileUtils .deleteDirectory(new File (ivySettings.getDefaultCache, dep.groupId))
346+ }
259347 }
260348 }
261349}
0 commit comments