File indexing completed on 2024-04-21 05:42:43
0001 #!/usr/bin/env python 0002 0003 # SPDX-FileCopyrightText: 2002-2007 Joachim Eibl, joachim.eibl at gmx.de 0004 # SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 import argparse 0007 import glob 0008 import os 0009 import subprocess as sp 0010 import sys 0011 0012 # Prior to this python for windows still uses legancy non uft-8 encoding by default. 0013 assert sys.version_info >= (3, 7) 0014 0015 parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, 0016 description='Generate input files for alignmenttest from the files merged for each merge commit in a git repository.\n\n' + 0017 'This script finds all merge commits in the clone where it is run, checks which files were modified in both\n' + 0018 'parents of the merge commit and then finds the common ancestor of these files to get the merge base.\n\n' 0019 'Example:\n' 0020 ' cd ~/git/linux\n' 0021 f' ~/kdiff3/test/{os.path.basename(sys.argv[0])} -d ~/kdiff3/test/testdata/linux\n') 0022 0023 parser.add_argument('-d', metavar='destination_path', nargs=1, default=['testdata_from_git/'], 0024 help='specify the folder where to save the test input files. If the folder does not exist it will be created.') 0025 args = parser.parse_args() 0026 dirname = args.d[0] 0027 0028 print(f'Generating input files in {dirname} ...') 0029 sys.stdout.flush() 0030 0031 if not os.path.exists(dirname): 0032 os.makedirs(dirname) 0033 0034 merges = sp.check_output('git rev-list --merges --parents master'.split()).strip().decode() 0035 0036 for entry in merges.splitlines(): 0037 fields = entry.split() 0038 0039 if len(fields) > 3: 0040 print(f'merge {fields[0]} had more than 2 parents: {fields}') 0041 merge, contrib1, contrib2 = fields[:3] 0042 0043 if glob.glob(f'{dirname}/{merge}_*'): 0044 print(f'skipping merge {merge} because files for this merge already present') 0045 continue 0046 0047 base = sp.check_output((f'git merge-base {contrib1} {contrib2}').split()).strip().decode() 0048 0049 fileschanged1 = sp.check_output((f'git diff --name-only {base} {contrib1}').split()).strip().decode().splitlines() 0050 fileschanged2 = sp.check_output((f'git diff --name-only {base} {contrib2}').split()).strip().decode().splitlines() 0051 0052 fileschangedboth = set(fileschanged1) & set(fileschanged2) 0053 0054 if not fileschangedboth: 0055 print(f'No files overlapped for merge {merge}') 0056 else: 0057 print(f'Overlapping files for merge {merge} with base {base}: {fileschangedboth}') 0058 for filename in fileschangedboth: 0059 simplified_filename = filename.replace('/', '_').replace('.', '_') 0060 0061 try: 0062 base_content = sp.check_output((f'git show {base}:{filename}').split()) 0063 contrib1_content = sp.check_output((f'git show {contrib1}:{filename}').split()) 0064 contrib2_content = sp.check_output((f'git show {contrib2}:{filename}').split()) 0065 0066 if base_content in [contrib1_content, contrib2_content] or \ 0067 contrib1_content == contrib2_content: 0068 print('this merge was trivial. Skipping.') 0069 else: 0070 basefilename = f'{dirname}/{merge}_{simplified_filename}_base.txt' 0071 contrib1filename = f'{dirname}/{merge}_{simplified_filename}_contrib1.txt' 0072 contrib2filename = f'{dirname}/{merge}_{simplified_filename}_contrib2.txt' 0073 0074 for filename, content in [(basefilename, base_content), 0075 (contrib1filename, contrib1_content), 0076 (contrib2filename, contrib2_content)]: 0077 with open(filename, 'wb') as f: 0078 f.write(content) 0079 0080 with open(f'{dirname}/{merge}_{simplified_filename}_expected_result.txt', 'a') as f: 0081 pass 0082 0083 except sp.CalledProcessError: 0084 print('error from git show, continuing with next file') 0085 0086 print('Input files generated.') 0087 print('') 0088 print(f'To create a reference set of expected_result.txt files, run alignmenttest and copy/move all {dirname}/*_actual_result.txt files to {dirname}/*_expected_result.txt:') 0089 print(' ./alignmenttest > /dev/null') 0090 print(f' cd {dirname}') 0091 print(' for file in *_actual_result.txt; do mv ${file} ${file/actual/expected}; done') 0092 print("If you've already modified the algorithm, you can run the alignment test of an older version of kdiff3 and copy those result files over")