supermario/bin/deepen

86 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
from os import path, makedirs, walk, listdir, remove, stat, chmod
from shutil import copy, rmtree
from subprocess import run
from shlex import quote
from folder import folder
def make_executable(path): # thanks to Jonathon Reinhart on SO
mode = stat(path).st_mode
mode |= (mode & 0o444) >> 2 # copy R bits to X
chmod(path, mode)
def relpath(dest, src):
return path.relpath(path.abspath(dest), path.abspath(src))
def path_to_script(script_name, from_worktree):
script_path = path.join(path.dirname(__file__), script_name)
return relpath(script_path, from_worktree)
parser = argparse.ArgumentParser(description='''
Expand a patchset into a git repository (based on git-am)
''')
parser.add_argument('patchset', metavar='PATCHSET', action='store', type=lambda x: folder('patchset', x), help='Patchset (assumed in ../patchset/)')
parser.add_argument('worktree', metavar='WORKTREE', action='store', type=lambda x: folder('worktree', x), help='Destination worktree (assumed in ../worktree/)')
group = parser.add_mutually_exclusive_group()
group.add_argument('--base', metavar='SRC', action='store', default='SuperMarioProj.1994-02-09', type=lambda x: folder('base', x), help='Base source tree (default=SuperMarioProj.1994-02-09, assumed in ../base/)')
args = parser.parse_args()
assert path.exists(args.patchset)
assert not path.exists(path.join(args.patchset, '.git')) # protect against argument swap
horst = ['-c', 'user.name=Horst Beepmanh', '-c', 'user.email=<>']
def git(*gitargs):
run(['git', *horst, *gitargs], cwd=args.worktree, check=True)
try:
rmtree(args.worktree)
except FileNotFoundError:
pass
makedirs(args.worktree)
with open(path.join(args.worktree, '.gitignore'), 'a') as f:
f.write('.*\n*.dmg\nBuild*/\n')
with open(path.join(args.worktree, '.build'), 'w') as f:
print('#!/bin/sh', file=f)
print('exec ' + quote(path_to_script('build', args.worktree)) + ' . "$@"', file=f)
make_executable(f.name)
with open(path.join(args.worktree, '.flatten'), 'w') as f:
print('#!/bin/sh', file=f)
print('exec ' + quote(path_to_script('flatten', args.worktree)) + ' . ' + relpath(args.patchset, args.worktree) + ' "$@"', file=f)
make_executable(f.name)
git('init')
git('add', '-f', '.gitignore', '.build', '.flatten')
git('commit', '-m', 'Useful non-source things')
for walk_base, walk_dirs, walk_files in walk(args.base):
walk_dirs[:] = [x for x in walk_dirs if not x.startswith('.')]
walk_files[:] = [x for x in walk_files if not x.startswith('.')]
other_dir = path.join(args.worktree, path.relpath(walk_base, args.base))
makedirs(other_dir, exist_ok=True)
for this_file in walk_files:
copy(path.join(walk_base, this_file), other_dir)
git('add', '.')
git('commit', '-m', path.basename(args.base))
git('tag', 'patchset-base')
patchfiles = [path.join(args.patchset, x) for x in sorted(listdir(args.patchset)) if path.splitext(x)[1].lower() == '.patch']
git('am', *patchfiles)