LUCENE-5962: Rename diffSources.py to createPatch.py and make work it work with all text file types

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1626890 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Ryan Ernst 2014-09-22 20:46:08 +00:00
parent 34890299da
commit c599b96748
3 changed files with 134 additions and 72 deletions

View File

@ -0,0 +1,131 @@
# 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.
'''
Creates a unified diff, applyable by the patch tool, between two source checkouts.
Note that .gitignore or svn:ignore rules are used to filter out files that would normally
not be checked in.
While you could use this to make a committable patch from a branch,
that approach loses the svn history from the branch (better to use
"svn merge --reintegrate", for example). This diff output should
not be considered "authoritative" from a merging standpoint as it
does not reflect what svn will do on merge.
'''
from argparse import ArgumentParser, RawTextHelpFormatter
import os
import subprocess
import sys
def make_filter_func(src_dir):
if os.path.exists(os.path.join(src_dir, '.git')):
def git_filter(filename):
rc = subprocess.call('git --git-dir=%s check-ignore %s' % (src_dir, filename), shell=True)
return rc == 0
return git_filter
else:
def svn_filter(filename):
# we can't find if svn will ignore a file unless it exists...
created = False
if not os.path.exists(filename):
head,tail = os.path.split(filename)
# find a parent directory that already exists, so we
# can see if that is ignored by svn
while not os.path.exists(head):
filename = head
head,tail = os.path.split(filename)
created = True
subprocess.check_call('touch %s' % filename, shell=True)
try:
output = subprocess.check_output('svn status %s' % filename,
shell=True, stderr=subprocess.STDOUT).strip()
return output.startswith(b'I')
finally:
if created and os.path.exists(filename):
os.remove(filename)
return svn_filter
def print_filtered_output(output, should_filter):
filtering = False
line = output.readline()
while line:
if line.startswith(b'diff '):
fromfile, tofile = line.decode('utf-8').split()[-2:]
if os.path.exists(fromfile) or \
os.path.exists(tofile):
filtering = should_filter(fromfile)
else:
# If both files do not exist, then the filename must contain spaces,
# which breaks our split logic. In this case, just ignore, since
# patch cannot handle filenames with spaces anyways.
filtering = True
elif line.startswith(b'Binary files'):
filtering = True
if not filtering:
print(line.decode('utf-8'), end='')
line = output.readline()
def run_diff(from_dir, to_dir, skip_whitespace):
flags = '-ruN'
if skip_whitespace:
flags += 'bBw'
args = ['diff', flags]
for ignore in ('.svn', '.git', 'build', '.caches'):
args.append('-x')
args.append(ignore)
args.append(from_dir)
args.append(to_dir)
return subprocess.Popen(args, shell=False, stdout=subprocess.PIPE)
def parse_config():
parser = ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter)
parser.add_argument('--skip-whitespace', action='store_true', default=False,
help='Ignore whitespace differences')
parser.add_argument('from_dir', help='Source directory to diff from')
parser.add_argument('to_dir', help='Source directory to diff to')
c = parser.parse_args()
if not os.path.isdir(c.from_dir):
parser.error('\'from\' path %s is not a valid directory' % c.from_dir)
if not os.path.exists(os.path.join(c.from_dir, 'lucene', 'CHANGES.txt')):
parser.error('\'from\' path %s is not a valid lucene/solr checkout' % c.from_dir)
if not os.path.isdir(c.to_dir):
parser.error('\'to\' path %s is not a valid directory' % c.to_dir)
if not os.path.exists(os.path.join(c.to_dir, 'lucene', 'CHANGES.txt')):
parser.error('\'to\' path %s is not a valid lucene/solr checkout' % c.to_dir)
return c
def main():
c = parse_config()
p = run_diff(c.from_dir, c.to_dir, c.skip_whitespace)
should_filter = make_filter_func(c.from_dir)
print_filtered_output(p.stdout, should_filter)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nReceived Ctrl-C, exiting early')

View File

@ -1,72 +0,0 @@
# 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.
import subprocess
import sys
import os
# recursive, unified output format, treat missing files as present but empty
DIFF_FLAGS = '-ruN'
if '-skipWhitespace' in sys.argv:
sys.argv.remove('-skipWhitespace')
# ignores only whitespace changes
DIFF_FLAGS += 'bBw'
if len(sys.argv) != 3:
print
print 'Usage: python -u diffSources.py <dir1> <dir2> [-skipWhitespace]'
print
print '''This tool creates an applying patch between two directories.
While you could use this to make a committable patch from a branch, that approach loses
the svn history from the branch (better to use "svn merge --reintegrate", for example). This
diff output should not be considered "authoritative" from a merging standpoint as it does
not reflect what svn will do on merge.
'''
print
sys.exit(0)
p = subprocess.Popen(['diff', DIFF_FLAGS, '-x', '.svn', '-x', 'build', sys.argv[1], sys.argv[2]], shell=False, stdout=subprocess.PIPE)
keep = False
while True:
l = p.stdout.readline()
if l == '':
break
if l.endswith('\r\n'):
l = l[:-2]
elif l.endswith('\n'):
l = l[:-1]
if l.startswith('diff ') or l.startswith('Binary files '):
if l.endswith('timehints.txt') or l.find('/build/') != -1 or l.find('/.svn/') != -1:
keep = False
elif l.lower().startswith('Only in'):
keep = True
elif l.find('/META-INF/') != -1:
keep = True
else:
ext = os.path.splitext(l)[-1]
keep = ext in ('.xml', '.iml', '.html', '.template', '.py', '.g', '.properties', '.java')
if keep:
print
print
print l.strip()
elif keep:
print l
elif l.startswith('Only in'):
print l.strip()

View File

@ -193,6 +193,9 @@ Build
* LUCENE-5902: Add bumpVersion.py script to manage version increase after release branch is cut.
* LUCENE-5962: Rename diffSources.py to createPatch.py and make it work with all text file types.
(Ryan Ernst)
Other
* LUCENE-5563: Removed sep layout: which has fallen behind on features and doesn't