1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Licensed to the Apache Software Foundation (ASF) under one or more 4# contributor license agreements. See the NOTICE file distributed with 5# this work for additional information regarding copyright ownership. 6# The ASF licenses this file to You under the Apache License, Version 2.0 7# (the "License"); you may not use this file except in compliance with 8# the License. You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18import sys 19import os 20sys.path.append(os.path.dirname(__file__)) 21from scriptutil import * 22import argparse 23import re 24 25# Pulls out all JIRAs mentioned at the beginning of bullet items 26# under the given version in the given CHANGES.txt file 27# and prints a regular expression that will match all of them 28# 29# Caveat: In ancient versions (Lucene v1.9 and older), 30# does not find Bugzilla bugs or JIRAs not mentioned at the beginning of 31# bullets or numbered entries. 32# 33def print_released_jiras_regex(version, filename): 34 release_boundary_re = re.compile(r'\s*====*\s+(.*)\s+===') 35 version_re = re.compile(r'%s(?:$|[^-])' % version) 36 bullet_re = re.compile(r'\s*(?:[-*]|\d+\.(?=(?:\s|(?:LUCENE)-)))(.*)') 37 jira_ptn = r'(?:LUCENE)-\d+' 38 jira_re = re.compile(jira_ptn) 39 jira_list_ptn = r'(?:[:,/()\s]*(?:%s))+' % jira_ptn 40 jira_list_re = re.compile(jira_list_ptn) 41 more_jiras_on_next_line_re = re.compile(r'%s\s*,\s*$' % jira_list_ptn) # JIRA list with trailing comma 42 under_requested_version = False 43 requested_version_found = False 44 more_jiras_on_next_line = False 45 lucene_jiras = [] 46 with open(filename, 'r') as changes: 47 for line in changes: 48 version_boundary = release_boundary_re.match(line) 49 if version_boundary is not None: 50 if under_requested_version: 51 break # No longer under the requested version - stop looking for JIRAs 52 else: 53 if version_re.search(version_boundary.group(1)): 54 under_requested_version = True # Start looking for JIRAs 55 requested_version_found = True 56 else: 57 if under_requested_version: 58 bullet_match = bullet_re.match(line) 59 if more_jiras_on_next_line or bullet_match is not None: 60 content = line if bullet_match is None else bullet_match.group(1) 61 jira_list_match = jira_list_re.match(content) 62 if jira_list_match is not None: 63 jira_match = jira_re.findall(jira_list_match.group(0)) 64 for jira in jira_match: 65 lucene_jiras.append(jira.rsplit('-', 1)[-1]) 66 more_jiras_on_next_line = more_jiras_on_next_line_re.match(content) 67 if not requested_version_found: 68 raise Exception('Could not find %s in %s' % (version, filename)) 69 print() 70 if (len(lucene_jiras) == 0): 71 print('(No JIRAs => no regex)', end='') 72 else: 73 print(r'LUCENE-(?:%s)\b' % '|'.join(lucene_jiras), end='') 74 print() 75 76def read_config(): 77 parser = argparse.ArgumentParser( 78 description='Prints a regex matching JIRAs fixed in the given version by parsing the given CHANGES.txt file') 79 parser.add_argument('version', type=Version.parse, help='Version of the form X.Y.Z') 80 parser.add_argument('changes', help='CHANGES.txt file to parse') 81 return parser.parse_args() 82 83def main(): 84 config = read_config() 85 print_released_jiras_regex(config.version, config.changes) 86 87if __name__ == '__main__': 88 try: 89 main() 90 except KeyboardInterrupt: 91 print('\nReceived Ctrl-C, exiting early') 92