This is an automated email from the ASF dual-hosted git repository.

magibney pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new 6046f56  SOLR-15455: Facilitate joint Solr/Lucene development via 
local dependency substitution (#304)
6046f56 is described below

commit 6046f561c92a70ab1c2e4358248f096ccc9b202b
Author: Dawid Weiss <[email protected]>
AuthorDate: Mon Oct 18 21:29:03 2021 +0200

    SOLR-15455: Facilitate joint Solr/Lucene development via local dependency 
substitution (#304)
---
 .gitignore                                         |   3 +
 build.gradle                                       |   5 +
 gradle/lucene-dev/lucene-dev-repo-composite.gradle | 142 +++++++++++++++++++++
 .../randomization/policies/solr-tests.policy       |   2 +
 gradle/validation/validate-source-patterns.gradle  |   1 +
 help/dependencies.txt                              |  34 +++++
 settings.gradle                                    |   4 +-
 solr/CHANGES.txt                                   |   2 +
 8 files changed, 192 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 03cd821..0ae4764 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,6 @@ __pycache__
 
 # Emacs backup
 *~
+
+# Ignore lucene included build
+lucene/
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index dafeae7..88d730c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -164,6 +164,9 @@ apply from: file('gradle/testing/profiling.gradle')
 apply from: file('gradle/testing/beasting.gradle')
 apply from: file('gradle/help.gradle')
 
+// Configures development for joint Lucene/ Solr composite build.
+apply from: file('gradle/lucene-dev/lucene-dev-repo-composite.gradle')
+
 // Ant-compatibility layer. ALL OF THESE SHOULD BE GONE at some point. They are
 // here so that we can coexist with current ant build but they are indicative
 // of potential problems with the build conventions, dependencies, etc.
@@ -190,3 +193,5 @@ apply from: file('gradle/solr/packaging.gradle')
 apply from: file('gradle/solr/solr-forbidden-apis.gradle')
 
 apply from: file('gradle/ant-compat/solr.post-jar.gradle')
+
+
diff --git a/gradle/lucene-dev/lucene-dev-repo-composite.gradle 
b/gradle/lucene-dev/lucene-dev-repo-composite.gradle
new file mode 100644
index 0000000..0ad6ee8
--- /dev/null
+++ b/gradle/lucene-dev/lucene-dev-repo-composite.gradle
@@ -0,0 +1,142 @@
+import java.util.function.BiFunction
+
+/*
+ * 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.
+ */
+
+// Local Lucene development repository resolution:
+//   1) A "-Plucene.dev.version=[version]" property, resolving Lucene 
artifacts from a local Maven repository.
+//   2) A non-empty property "-Plucene.dev.path=[path]" pointing to a local 
path. Relative paths
+//      are resolved against the root project directory.
+//   3) An auto-wired 'lucene' subfolder, if present. To skip auto-wiring, pass
+//      a blank value in step 2: "-Plucene.dev.path=".
+
+
+// This script is applied in settings.gradle and later at build time: these 
two contexts
+// are distinctively different and have separate (and limited) APIs.
+def configuringSettings = (rootProject instanceof 
org.gradle.api.initialization.ProjectDescriptor)
+
+// Accessor for -P properties from settings or at build time.
+BiFunction<String, String, String> resolvePropertyValue = { propertyName, 
defValue ->
+  if (configuringSettings) {
+    return 
settings.startParameter.projectProperties.getOrDefault(propertyName, defValue)
+  } else {
+    return project.properties.getOrDefault(propertyName, defValue)
+  }
+}
+
+def PROP_FORCE_VERSION="lucene.dev.version"
+def PROP_FORCE_PATH="lucene.dev.path"
+def READ_ACCESS_PROPERTY="lucene-dev-path.dir"
+
+
+def forcedLuceneVersion = resolvePropertyValue(PROP_FORCE_VERSION, null)
+if (forcedLuceneVersion != null) {
+  if (!configuringSettings) {
+    logger.lifecycle("Lucene version forced by 
-P${PROP_FORCE_VERSION}=${forcedLuceneVersion}")
+
+    allprojects {
+      repositories {
+        mavenLocal()
+      }
+
+      tasks.withType(Test) {
+        def userHome = System.properties.get('user.home')
+        systemProperty READ_ACCESS_PROPERTY, 
file("${userHome}/.m2/repository/org/apache/lucene").absolutePath
+      }
+
+      configurations.all {
+        resolutionStrategy.eachDependency {
+          if (requested.group == "org.apache.lucene") {
+            useVersion(forcedLuceneVersion)
+            because("Lucene version forced manually by 'lucene.dev.version' 
property.")
+          }
+        }
+      }
+    }
+  }
+
+  // Step 1: end resolution
+  return
+}
+
+def luceneDevRepo = null
+def defaultLuceneDevRepo = file("${rootDir}/lucene")
+String propertyValue = resolvePropertyValue(PROP_FORCE_PATH, null)
+if (propertyValue != null) {
+  // Step 2.
+  if (propertyValue.isBlank()) {
+    if (defaultLuceneDevRepo.exists() && configuringSettings) {
+      logger.lifecycle("Local Lucene development repository has been detected 
but won't be used.")
+    }
+  } else {
+    // For relative path `propertyValue` spec, `file(propertyValue)` at 
settings configuration time
+    // resolves relative to "${rootDir}/gradle/" (as opposed to 
"${rootDir}/"); so we use the Java
+    // Path API here for consistent relative path resolution at configuration 
and build time
+    luceneDevRepo = 
file(rootDir).toPath().resolve(propertyValue).normalize().toFile()
+    if (!luceneDevRepo.exists()) {
+      throw new GradleException("Lucene repository does not exist at: 
-P${PROP_FORCE_PATH}=${luceneDevRepo}.")
+    }
+  }
+} else if (defaultLuceneDevRepo.exists()) {
+  // Step 3
+  luceneDevRepo = defaultLuceneDevRepo
+}
+
+
+if (luceneDevRepo != null) {
+  // Allow turning off this auto-wiring via -Dlucene.dev.repo=false (can't be 
a -P property because
+  // at settings evaluation time we don't have project properties yet).
+  if (configuringSettings) {
+    // We substitute the exact version of Lucene we currently have in 
versions.props across all the dependencies.
+    // We can't just substitute all references without looking at the versoin 
because
+    // plugin dependencies then also get substituted and everything crashes.
+    String luceneVersion = (file("${rootDir}/versions.props").getText("UTF-8") 
=~ /org.apache.lucene:\*=(.+)/)[0][1]
+    logger.lifecycle("Local Lucene development repository will be used 
substituting ${luceneVersion}: ${luceneDevRepo}")
+
+    // Include Lucene repository as a composite and substitute module names.
+    includeBuild(luceneDevRepo) {
+      dependencySubstitution {
+        all {  DependencySubstitution dependency ->
+          if (dependency.requested instanceof ModuleComponentSelector) {
+            def moduleSelector = (ModuleComponentSelector) dependency.requested
+            if (moduleSelector.group == "org.apache.lucene" && 
moduleSelector.version == luceneVersion) {
+              // Map Maven artifact name to lucene module name.
+              def projectModuleName =
+                  moduleSelector.moduleIdentifier.name
+                      .replaceFirst("^lucene-analysis-", ":lucene:analysis:")
+                      .replaceFirst("^lucene-", ":lucene:")
+
+              logger.info("Substituting Lucene dependency ${moduleSelector} 
with an included build project: ${projectModuleName}")
+              dependency.useTarget(project(projectModuleName))
+            }
+          }
+        }
+      }
+    }
+  } else {
+    // We're being applied at build-time and Lucene development repository 
exists. Configure
+    // certain aspects of the build so that things work with it.
+
+    // Security policy requires read access to the repo path.
+    allprojects {
+      tasks.withType(Test) {
+        systemProperty READ_ACCESS_PROPERTY, luceneDevRepo.absolutePath
+      }
+    }
+  }
+}
+
diff --git a/gradle/testing/randomization/policies/solr-tests.policy 
b/gradle/testing/randomization/policies/solr-tests.policy
index 297647a..7232474 100644
--- a/gradle/testing/randomization/policies/solr-tests.policy
+++ b/gradle/testing/randomization/policies/solr-tests.policy
@@ -232,4 +232,6 @@ grant {
   permission java.io.FilePermission "${gradle.worker.jar}", "read";
   // Allow reading from classpath JARs (resources).
   permission java.io.FilePermission "${gradle.user.home}${/}-", "read";
+  // Allow read access to Lucene jars if "-Plucene.dev.version=" or 
"-Plucene.dev.path=" is used
+  permission java.io.FilePermission "${lucene-dev-path.dir}${/}-", "read";
 };
diff --git a/gradle/validation/validate-source-patterns.gradle 
b/gradle/validation/validate-source-patterns.gradle
index 284fd99..f9639d0 100644
--- a/gradle/validation/validate-source-patterns.gradle
+++ b/gradle/validation/validate-source-patterns.gradle
@@ -120,6 +120,7 @@ configure(rootProject) {
 
       // default excludes.
       exclude '**/build/**'
+      exclude '**/.idea/**'
       exclude 'dev-tools/solr-missing-doclet/src/**/*.java' // <-- TODO: 
remove once we allow "var" on master
 
       // ourselves :-)
diff --git a/help/dependencies.txt b/help/dependencies.txt
index f84a04d..d67130f 100644
--- a/help/dependencies.txt
+++ b/help/dependencies.txt
@@ -108,6 +108,40 @@ If you want to upgrade Lucene to a newer build proceed 
like the following:
 - Run: gradlew --write-locks (as described before)
 
 
+Lucene local dependency substitution
+-------------------------------
+
+Because of the fundamental nature of Solr's dependency on Lucene, Solr
+facilitates dependency substitution to support developing against a local
+Lucene version (e.g., for joint Solr and Lucene development).
+
+A local Lucene dependency substitution is resolved by evaluating the
+following conditions, in priority order:
+
+  1) A "-Plucene.dev.version=[version]" property, resolving Lucene artifacts
+     from a local Maven repository.
+  2) A non-empty property "-Plucene.dev.path=[path]" pointing to a local
+     path. Relative paths are resolved against the Solr root project
+     directory.
+  3) An auto-wired 'lucene' subdirectory, if present. To skip auto-wiring,
+     pass a blank value for condition 2: "-Plucene.dev.path=".
+
+Note: Lucene dependencies substituted via conditions 2 and 3 require the
+local Lucene repository to use the same Gradle version as the Solr root
+project.
+
+Local Maven repository Lucene artifacts (for use with the
+"-Plucene.dev.version" project property) may be created by running the
+following command from within a local Lucene project:
+
+  gradlew mavenToLocalRepo
+
+As is the case with project properties generally, the relevant properties
+can be invoked on the command line, or configured via the gradle.properties
+file (the latter approach is particularly useful for making IDEs aware of
+associated dependency substitutions).
+
+
 Inspecting current dependencies
 -------------------------------
 
diff --git a/settings.gradle b/settings.gradle
index 1f68a4a..a04cd7c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -45,7 +45,9 @@ include "solr:benchmark"
 include "solr:test-framework"
 include "solr:solr-ref-guide"
 include "solr:example"
-
 include "solr:documentation"
 include "solr:packaging"
 include "solr:docker"
+
+// Configures development for joint Lucene/ Solr composite build.
+apply from: file('gradle/lucene-dev/lucene-dev-repo-composite.gradle')
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 5dc9f7a..91f0eb6 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -370,6 +370,8 @@ Other Changes
 
 * SOLR-15692: Fix parsing of -zkHost flag for the bin/solr commands (janhoy)
 
+* SOLR-15455: Facilitate joint Solr/Lucene development via local dependency 
substitution (Dawid Weiss, Michael Gibney)
+
 Bug Fixes
 ---------------------
 * SOLR-14546: Fix for a relatively hard to hit issue in OverseerTaskProcessor 
that could lead to out of order execution

Reply via email to