| #!/usr/bin/env python3 |
| # 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. |
| |
| |
| # For usage information, see: |
| # |
| # http://wiki.apache.org/lucene-java/ReleaseTodo#Generate_Backcompat_Indexes |
| |
| |
| import os |
| import sys |
| from pathlib import Path |
| |
| sys.path.append(os.path.dirname(__file__)) |
| import argparse |
| import re |
| import shutil |
| import urllib.error |
| import urllib.request |
| |
| import scriptutil |
| |
| |
| def create_and_add_index(source: str, indextype: str, index_version: scriptutil.Version, current_version: scriptutil.Version, temp_dir: str): |
| if not current_version.is_back_compat_with(index_version): |
| prefix = "unsupported" |
| else: |
| prefix = {"cfs": "index", "nocfs": "index", "sorted": "sorted", "int7_hnsw": "int7_hnsw", "moreterms": "moreterms", "dvupdates": "dvupdates", "emptyIndex": "empty"}[indextype] |
| if indextype in ("cfs", "nocfs"): |
| filename = "%s.%s-%s.zip" % (prefix, index_version, indextype) |
| else: |
| filename = "%s.%s.zip" % (prefix, index_version) |
| |
| print(" creating %s..." % filename, end="", flush=True) |
| module = "backward-codecs" |
| index_dir = os.path.join("lucene", module, "src/test/org/apache/lucene/backward_index") |
| if os.path.exists(os.path.join(index_dir, filename)): |
| print("uptodate") |
| return |
| |
| test = { |
| "cfs": "testCreateCFS", |
| "nocfs": "testCreateNoCFS", |
| "sorted": "testCreateSortedIndex", |
| "int7_hnsw": "testCreateInt7HNSWIndices", |
| "moreterms": "testCreateMoreTermsIndex", |
| "dvupdates": "testCreateIndexWithDocValuesUpdates", |
| "emptyIndex": "testCreateEmptyIndex", |
| }[indextype] |
| gradle_args = " ".join(["-p lucene/%s" % module, "test", "--tests TestGenerateBwcIndices.%s" % test, "-Dtests.bwcdir=%s" % temp_dir, "-Dtests.codec=default"]) |
| base_dir = os.getcwd() |
| bc_index_file = os.path.join(temp_dir, filename) |
| |
| if os.path.exists(bc_index_file): |
| print("alreadyexists") |
| else: |
| os.chdir(source) |
| scriptutil.run("./gradlew %s" % gradle_args) |
| if not os.path.exists(bc_index_file): |
| raise Exception("Expected file can't be found: %s" % bc_index_file) |
| print("done") |
| |
| print(" adding %s..." % filename, end="", flush=True) |
| scriptutil.run("cp %s %s" % (bc_index_file, os.path.join(base_dir, index_dir))) |
| os.chdir(base_dir) |
| print("done") |
| |
| |
| def update_backcompat_tests(index_version: scriptutil.Version, current_version: scriptutil.Version): |
| print(" adding new indexes to backcompat tests...", end="", flush=True) |
| module = "lucene/backward-codecs" |
| |
| filename = None |
| if not current_version.is_back_compat_with(index_version): |
| filename = "%s/src/test/org/apache/lucene/backward_index/unsupported_versions.txt" % module |
| else: |
| filename = "%s/src/test/org/apache/lucene/backward_index/versions.txt" % module |
| |
| strip_dash_suffix_re = re.compile(r"-.*") |
| |
| def find_version(x: str): |
| x = x.strip() |
| x = re.sub(strip_dash_suffix_re, "", x) # remove the -suffix if any |
| return scriptutil.Version.parse(x) |
| |
| def edit(buffer: list[str], _match: re.Match[str], line: str): |
| v = find_version(line) |
| changed = False |
| if v.on_or_after(index_version): |
| if not index_version.on_or_after(v): |
| buffer.append(("%s\n") % index_version) |
| changed = True |
| buffer.append(line) |
| return changed |
| |
| def append(buffer: list[str], changed: bool): |
| if changed: |
| return changed |
| if not buffer[len(buffer) - 1].endswith("\n"): |
| buffer.append("\n") |
| buffer.append(("%s\n") % index_version) |
| return True |
| |
| changed = scriptutil.update_file(filename, re.compile(r".*"), edit, append) |
| print("done" if changed else "uptodate") |
| |
| |
| def check_backcompat_tests(): |
| print(" checking backcompat tests...", end="", flush=True) |
| scriptutil.run("./gradlew -p lucene/backward-codecs test --tests TestGenerateBwcIndices") |
| print("ok") |
| |
| |
| def download_from_cdn(version: scriptutil.Version, remotename: str, localname: str): |
| url = "http://dlcdn.apache.org/lucene/java/%s/%s" % (version, remotename) |
| try: |
| urllib.request.urlretrieve(url, localname) |
| return True |
| except urllib.error.HTTPError as e: |
| if e.code == 404: |
| return False |
| raise e |
| |
| |
| def download_from_archives(version: scriptutil.Version, remotename: str, localname: str): |
| url = "http://archive.apache.org/dist/lucene/java/%s/%s" % (version, remotename) |
| try: |
| urllib.request.urlretrieve(url, localname) |
| return True |
| except urllib.error.HTTPError as e: |
| if e.code == 404: |
| return False |
| raise e |
| |
| |
| def download_release(version: scriptutil.Version, temp_dir: str, force: bool): |
| print(" downloading %s source release..." % version, end="", flush=True) |
| source = os.path.join(temp_dir, "lucene-%s" % version) |
| if os.path.exists(source): |
| if force: |
| shutil.rmtree(source) |
| else: |
| print("uptodate") |
| return source |
| |
| filename = "lucene-%s-src.tgz" % version |
| source_tgz = os.path.join(temp_dir, filename) |
| if not download_from_cdn(version, filename, source_tgz) and not download_from_archives(version, filename, source_tgz): |
| raise Exception("Could not find version %s in apache CDN or archives" % version) |
| |
| olddir = os.getcwd() |
| os.chdir(temp_dir) |
| scriptutil.run("tar -xvzf %s" % source_tgz) |
| os.chdir(olddir) |
| print("done") |
| return source |
| |
| |
| def read_config(): |
| parser = argparse.ArgumentParser( |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| description="""\ |
| Add backcompat index and test for new version. See: |
| http://wiki.apache.org/lucene-java/ReleaseTodo#Generate_Backcompat_Indexes |
| """, |
| ) |
| parser.add_argument("--force", action="store_true", default=False, help="Redownload the version and rebuild, even if it already exists") |
| parser.add_argument("--no-cleanup", dest="cleanup", action="store_false", default=True, help="Do not cleanup the built indexes, so that they can be reused " + "for adding to another branch") |
| parser.add_argument("--temp-dir", metavar="DIR", default="/tmp/lucenebwc", help="Temp directory to build backcompat indexes within") |
| parser.add_argument("version", type=scriptutil.Version.parse, help="Version to add, of the form X.Y.Z") |
| c = parser.parse_args() |
| |
| return c |
| |
| |
| def main(): |
| c = read_config() |
| if not os.path.exists(c.temp_dir): |
| Path(c.temp_dir).mkdir(parents=True) |
| |
| print("\nCreating backwards compatibility indexes") |
| source = download_release(c.version, c.temp_dir, c.force) |
| current_version = scriptutil.Version.parse(scriptutil.find_current_version()) |
| create_and_add_index(source, "cfs", c.version, current_version, c.temp_dir) |
| create_and_add_index(source, "nocfs", c.version, current_version, c.temp_dir) |
| create_and_add_index(source, "int7_hnsw", c.version, current_version, c.temp_dir) |
| should_make_sorted = current_version.is_back_compat_with(c.version) and (c.version.major > 6 or (c.version.major == 6 and c.version.minor >= 2)) |
| if should_make_sorted: |
| create_and_add_index(source, "sorted", c.version, current_version, c.temp_dir) |
| if c.version.minor == 0 and c.version.bugfix == 0 and current_version.is_back_compat_with(c.version): |
| create_and_add_index(source, "moreterms", c.version, current_version, c.temp_dir) |
| create_and_add_index(source, "dvupdates", c.version, current_version, c.temp_dir) |
| create_and_add_index(source, "emptyIndex", c.version, current_version, c.temp_dir) |
| print("\nMANUAL UPDATE REQUIRED: edit TestGenerateBwcIndices to enable moreterms, dvupdates, and empty index testing") |
| |
| print("\nAdding backwards compatibility tests") |
| update_backcompat_tests(c.version, current_version) |
| |
| print("\nTesting changes") |
| check_backcompat_tests() |
| |
| if c.cleanup: |
| print("\nCleaning up") |
| print(" deleting %s..." % c.temp_dir, end="", flush=True) |
| shutil.rmtree(c.temp_dir) |
| print("done") |
| |
| print() |
| |
| |
| if __name__ == "__main__": |
| try: |
| main() |
| except KeyboardInterrupt: |
| print("\nRecieved Ctrl-C, exiting early") |