#!/usr/bin/python """ This merges in changes from the branch specified below to trunk. I hold no responsibility if this destroys your tree, it works for me, but I haven't tested all possible uses, so use at your own risk """ import os import glob import curses import shutil from subprocess import Popen, PIPE branch='1.2_RC' files = [] p = Popen(['svn', 'status', '--ignore-externals'], stdout=PIPE) directories = [] trunk_files = [] for line in p.stdout: line = line.strip() if line[0] not in ('A', 'M'): continue mod_type = line[0] filename = line.split()[1].strip() if not filename.startswith('branches/%s' % branch): continue if mod_type == 'A': skip = False if os.path.isdir(filename): directories.append(filename) else: for directory in directories: skip = False if filename.startswith(directory): skip = True if skip: continue files.append([filename, None, mod_type]) def stop_curses(): curses.nocbreak() curses.echo() curses.endwin() def remove_svn(folder): for entry in os.listdir(folder): if entry == '.svn': shutil.rmtree(os.path.join(folder, entry)) if os.path.isdir(os.path.join(folder, entry)): remove_svn(os.path.join(folder, entry)) def apply_changes(files): directories = [] for filename, selected, mod_type in files: if not selected: continue trunk_filename = 'trunk' + filename[len('branches/%s' % branch):] if mod_type == 'M': diff = Popen(['diff', '-u', trunk_filename, filename], stdout=PIPE) patch = Popen(['patch', trunk_filename], stdin=diff.stdout, stdout=PIPE) exitcode = patch.wait() if exitcode == 0: print 'Patching %s successful' % trunk_filename else: print 'Failed to patch %s' % trunk_filename elif mod_type == 'A': if os.path.isdir(filename): shutil.copytree(filename, trunk_filename) remove_svn(trunk_filename) else: shutil.copy(filename, trunk_filename) add = Popen(['svn', 'add', trunk_filename], stdout=PIPE, stderr=PIPE) if add.wait() == 0: print 'Added %s to trunk' % os.path.basename(trunk_filename) else: print 'Unable to add %s to trunk' % trunk_filename # for some reason curses is reporting my enter key as 10, not 343 curses.KEY_ENTER = 10 try: screen = curses.initscr() curses.noecho() curses.cbreak() screen.clear() screen.addstr(0, 0, '*' * 60) screen.addstr(1, 0, 'WARNING: this will only work if the trunk file is unmodified') screen.addstr(2, 0,' when compared to the branch') screen.addstr(3, 0, '*' * 60) screen.refresh() window = curses.newwin(1000, 200, 5, 0) while 1: window.clear() index = 0 for index, merge_file in enumerate(files): selection = merge_file[1] or ' ' isdir = '' if os.path.isdir(merge_file[0]): isdir = ' (dir)' window.addstr(index, 4, '[%s] %d. %s %s%s' % (selection, index + 1, merge_file[2], merge_file[0], isdir)) window.addstr(index + 3, 0, 'Select file(s)') window.addstr(index + 4, 0, '* selects all files') window.refresh() key = window.getch() if key == curses.KEY_ENTER: screen.clear() stop_curses() apply_changes(files) break else: try: index = int(chr(key)) - 1 except: continue if index == -1: for merge_file in files: merge_file[1] = '*' else: if files[index][1] == '*': files[index][1] = False else: files[index][1] = '*' except Exception, e: stop_curses() raise e except KeyboardInterrupt: stop_curses() exit(0)