#!/usr/bin/python import os import sys from pprint import pprint from collections import defaultdict print 'using newsmerge' result = [] base = sys.argv[1] local = sys.argv[2] other = sys.argv[3] output = sys.argv[5] print base, local, other, output # states empty_line = 0 file_header = 1 section_header = 2 news_entry = 3 def parse_news(fname): """ Parse a Misc/NEWS file and return a list of [section, list_of_news] for the latest/topmost Python release. """ status = empty_line sections = [] with open(fname) as f: prev_line = '' for full_line in f: line = full_line.strip() if set(line) == set('+'): if status == empty_line: status = file_header else: status = empty_line elif status == empty_line: if not line: continue if line.startswith('- '): status = news_entry news = [full_line] else: status = section_header elif status == section_header: if set(line) == set('-'): section_news = [] sections.append([prev_line, section_news]) elif set(line) == set('=') and sections: break status = empty_line elif status == news_entry: if line: news.append(line) else: section_news.append(news) status = empty_line prev_line = line #pprint(sections) return sections base_content = parse_news(base) local_content = parse_news(local) other_content = parse_news(other) base_sections = [section for section, news in base_content] local_sections = [section for section, news in local_content] other_sections = [section for section, news in other_content if section in base_sections] # base = common ancestor (e.g. previous 3.4 changeset) # local = working copy we want to modify (e.g. default) # other = files that we already modified (e.g. cs we just made on 3.4) # make a diff between base and other, to find what news entries have been # added in the previous changeset (other). Take those entries and add # them to local. If local already has additional entries (e.g. in case # of heads merge on the same branch) they won't be affected. base_content_dict = dict(base_content) other_content_dict = dict(other_content) new_entries = defaultdict(list) for section in other_sections: base_section = base_content_dict[section] other_section = other_content_dict[section] for entry in other_section: if entry not in base_section: new_entries[section].append(entry) #print new_entries with open(local) as fr, open(output, 'w') as fw: entries_buffer = [] for full_line in fr: fw.write(full_line) if not new_entries and not entries_buffer: continue # all the news have been added already line = full_line.strip() if line and line in new_entries: print '*** found', line # assume all the sections already exist in local entries_buffer = new_entries.pop(line) elif not line and entries_buffer: print '*** writing:', entries_buffer for entry in entries_buffer: fw.writelines(entry) fw.write(full_line) entries_buffer = []