diff --git a/build.gradle b/build.gradle index 1781e46d22b..3adf267ca5d 100644 --- a/build.gradle +++ b/build.gradle @@ -26,12 +26,25 @@ plugins { id "de.undercouch.download" version "4.0.2" apply false } -// Project version and main properties. Applies to all projects. +// Project version. +version = "9.0.0-SNAPSHOT" + +// Propagate version and derived properties across projects. allprojects { - version = "9.0.0-SNAPSHOT" + version = rootProject.version } ext { + // "base" version is stripped of the qualifier. Compute it. + baseVersion = { + def m = (version =~ /^(\d+\.\d+\.\d+)(-(.+))?/) + if (!m) { + throw GradleException("Can't strip version to just x.y.z: " + rootProject.version) + } + return m[0][1] + }() + + // Build timestamp. def tstamp = ZonedDateTime.now() buildDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(tstamp) buildTime = DateTimeFormatter.ofPattern("HH:mm:ss").format(tstamp) @@ -70,6 +83,7 @@ apply from: file('gradle/testing/defaults-tests.gradle') apply from: file('gradle/testing/randomization.gradle') apply from: file('gradle/testing/fail-on-no-tests.gradle') apply from: file('gradle/testing/runtime-jvm-support.gradle') +apply from: file('gradle/jar-manifest.gradle') // Maven publishing. apply from: file('gradle/maven/defaults-maven.gradle') diff --git a/gradle/jar-manifest.gradle b/gradle/jar-manifest.gradle new file mode 100644 index 00000000000..bf8e6816223 --- /dev/null +++ b/gradle/jar-manifest.gradle @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Configures JAR manifest entries + +allprojects { + // Declare these inline for now. Don't know if it makes sense to declare them + // per-project. + def title; + def implementationTitle; + def legaleseDir; + if (project.path.startsWith(":lucene")) { + implementationTitle = "org.apache.lucene" + title = "Lucene Search Engine: ${project.name}" + legaleseDir = project(":lucene").projectDir + } else { + implementationTitle = "org.apache.solr" + title = "Apache Solr Search Server: ${project.name}" + legaleseDir = project(":solr").projectDir + } + + // Apply the manifest to any JAR or WAR file created by any project, + // excluding those explicitly listed. + tasks.withType(Jar) + .matching { t -> !["sourcesJar", "javadocJar"].contains(t.name) } + .configureEach { task -> + // Compute git status once on the root project prior to assembling manifest. + dependsOn ":gitStatus" + + // Because git status is a task we must defer computing this + // until status has been computed. We do this with a provider. + def implementationVersion = provider { + "${project.version} ${rootProject.gitRev} - ${System.properties['user.name']} - ${buildDate} ${buildTime}" + } + + manifest { + attributes([ + "Extension-Name" : implementationTitle, + + "Implementation-Vendor" : "The Apache Software Foundation", + "Implementation-Title" : implementationTitle, + "Implementation-Version": implementationVersion, + + "Specification-Vendor" : "The Apache Software Foundation", + "Specification-Version" : project.baseVersion, + "Specification-Title" : title, + + "X-Compile-Source-JDK" : "${project.sourceCompatibility}", + "X-Compile-Target-JDK" : "${project.targetCompatibility}", + + "X-Build-JDK" : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']})", + "X-Build-OS" : "${System.properties['os.name']} ${System.properties['os.arch']} ${System.properties['os.version']}" + ]) + } + + // Copy legalese into META-INF. + metaInf { + from(legaleseDir, { + include "LICENSE.txt" + include "NOTICE.txt" + }) + } + } +} \ No newline at end of file diff --git a/gradle/testing/randomization.gradle b/gradle/testing/randomization.gradle index 02fc9e8332f..0f36bae78fb 100644 --- a/gradle/testing/randomization.gradle +++ b/gradle/testing/randomization.gradle @@ -39,15 +39,6 @@ configure(rootProject) { rootSeed = propertyOrDefault('tests.seed', String.format("%08X", new Random().nextLong())) rootSeedLong = SeedUtils.parseSeedChain(rootSeed)[0] projectSeedLong = rootSeedLong ^ project.path.hashCode() - - // "base" version is stripped of the qualifier. Compute it. - baseVersion = { - def m = (rootProject.version =~ /^(\d+\.\d+\.\d+)(-(.+))?/) - if (!m) { - throw GradleException("Can't strip version to just x.y.z: " + rootProject.version) - } - return m[0][1] - }() } task randomizationInfo() { diff --git a/gradle/validation/git-status.gradle b/gradle/validation/git-status.gradle index 5706b0adc7f..79a26fa48be 100644 --- a/gradle/validation/git-status.gradle +++ b/gradle/validation/git-status.gradle @@ -31,30 +31,37 @@ buildscript { } } -def gitStatus(dir) { - try { - def repository = new FileRepositoryBuilder() - .setWorkTree(dir) - .setMustExist(true) - .build() - - def status = new Git(repository).status().call() - return status - } catch (RepositoryNotFoundException | NoWorkTreeException e) { - logger.warn("WARNING: Directory is not a valid GIT checkout (won't check dirty files): ${dir}") - return null - } catch (NotSupportedException e) { - throw new GradleException("jgit does not support git repository version at this location: ${dir}", e) - } -} - configure(rootProject) { + task gitStatus() { + doFirst { + try { + def repository = new FileRepositoryBuilder() + .setWorkTree(rootProject.projectDir) + .setMustExist(true) + .build() + + def ref = repository.findRef("HEAD").getObjectId() + project.ext.gitRev = ref.name() + project.ext.gitRevShort = ref.abbreviate(8).name() + project.ext.gitStatus = new Git(repository).status().call() + } catch (RepositoryNotFoundException | NoWorkTreeException e) { + project.ext.gitRev = "(not a git checkout)" + project.ext.gitRevShort = "(not a git checkout)" + project.ext.gitStatus = null + } catch (NotSupportedException e) { + throw new GradleException("jgit does not support git repository version at this location: ${dir}", e) + } + } + } + // Verify git working copy does not have any unstaged modified files. task checkWorkingCopyClean() { + dependsOn gitStatus doFirst { - def status = gitStatus(rootProject.projectDir) + def status = rootProject.ext.gitStatus if (status == null) { // Ignore the check. This isn't a git checkout. + logger.warn("WARNING: Directory is not a valid GIT checkout (won't check dirty files): ${rootProject.projectDir}") } else { def offenders = [ // Exclude staged changes. These are fine in precommit.