import subprocess, sys, re, os sys.stdout.reconfigure(encoding='utf-8') res = subprocess.run(['git', '-c', 'core.quotepath=false', 'diff', '-U5', '0054b5ac..3cd61cad'], capture_output=True, text=True, encoding='utf-8') diff_text = res.stdout file_diffs = diff_text.split('diff --git ') print(f"Total files modified in 3cd61cad: {len(file_diffs)-1}") possible_duplicates_found = [] for fd in file_diffs[1:]: lines = fd.split('\n') header = lines[0] filename = header.split(' ')[0][2:] if "2026년_건설공사_표준품셈.md" in filename: continue # Check split files only # Read full content of current file with open(filename, 'r', encoding='utf-8') as f: file_lines = f.readlines() raw_hunks = re.split(r'\n@@\s+[^@]+\s+@@\n', fd)[1:] for h_idx, h in enumerate(raw_hunks): h_lines = h.split('\n') # Get added lines (starting with +) added_lines = [l[1:].strip() for l in h_lines if l.startswith('+') and l[1:].strip().startswith('|') and not all(re.match(r'^:?-+:?$', c) for c in [x.strip() for x in l[1:].strip().split('|')[1:-1]] if c)] # Get deleted lines (starting with -) del_lines = [l[1:].strip() for l in h_lines if l.startswith('-') and l[1:].strip().startswith('|')] if not added_lines: continue # Find where added_lines appear in file_lines first_added = added_lines[0] match_idx = -1 for idx, fl in enumerate(file_lines): if fl.strip() == first_added: match_idx = idx break if match_idx == -1: continue # Check 40 lines above and 40 lines below match_idx # for duplicate table data added_content_words = set(w for l in added_lines for w in re.findall(r'[가-힣A-Za-z0-9]+', l) if len(w) > 1 and w not in ["인부", "보통인부", "특별인부"]) added_nums = set(n for l in added_lines for n in re.findall(r'\b\d+(?:\.\d+)?\b', l)) # Check above lines (match_idx - 40 to match_idx - 1) above_start = max(0, match_idx - 50) above_lines = [file_lines[i].strip() for i in range(above_start, match_idx) if file_lines[i].strip().startswith('|')] # Check below lines (match_idx + len(added_lines) to match_idx + len(added_lines) + 50) below_start = match_idx + len(added_lines) below_end = min(len(file_lines), below_start + 50) below_lines = [file_lines[i].strip() for i in range(below_start, below_end) if file_lines[i].strip().startswith('|')] # Check if above or below contains significant overlap with added_lines for region_name, r_lines in [('above', above_lines), ('below', below_lines)]: overlap_rows = 0 for rl in r_lines: rl_words = set(w for w in re.findall(r'[가-힣A-Za-z0-9]+', rl) if len(w) > 1 and w not in ["인부", "보통인부", "특별인부"]) rl_nums = set(re.findall(r'\b\d+(?:\.\d+)?\b', rl)) common_w = added_content_words.intersection(rl_words) common_n = added_nums.intersection(rl_nums) if len(common_w) >= 2 and len(common_n) >= 1: overlap_rows += 1 if overlap_rows >= 3: possible_duplicates_found.append({ 'file': os.path.basename(filename), 'hunk': h_idx, 'line': match_idx + 1, 'region': region_name, 'overlap_rows': overlap_rows, 'added_sample': added_lines[0], 'region_sample': r_lines[0] if r_lines else '' }) print(f"\nPossible duplicated / overlapping fixes: {len(possible_duplicates_found)}") for p in possible_duplicates_found: print(f"[{p['file']}:L{p['line']}] Hunk {p['hunk']} overlaps with {p['region']} ({p['overlap_rows']} rows)") print(f" Added: {p['added_sample']}") print(f" {p['region']}: {p['region_sample']}")