tools/gitwash_dumper.tpy
#!/usr/bin/env python
''' Checkout gitwash repo into directory and do search replace on name '''
from __future__ import (absolute_import, division, print_function)
import os
from os.path import join as pjoin
import shutil
import sys
import re
import glob
import fnmatch
import tempfile
from subprocess import call
from optparse import OptionParser
verbose = False
def clone_repo(url, branch):
cwd = os.getcwd()
tmpdir = tempfile.mkdtemp()
try:
cmd = 'git clone %s %s' % (url, tmpdir)
call(cmd, shell=True)
os.chdir(tmpdir)
cmd = 'git checkout %s' % branch
call(cmd, shell=True)
except:
shutil.rmtree(tmpdir)
raise
finally:
os.chdir(cwd)
return tmpdir
def cp_files(in_path, globs, out_path):
try:
os.makedirs(out_path)
except OSError:
pass
out_fnames = []
for in_glob in globs:
in_glob_path = pjoin(in_path, in_glob)
for in_fname in glob.glob(in_glob_path):
out_fname = in_fname.replace(in_path, out_path)
pth, _ = os.path.split(out_fname)
if not os.path.isdir(pth):
os.makedirs(pth)
shutil.copyfile(in_fname, out_fname)
out_fnames.append(out_fname)
return out_fnames
def filename_search_replace(sr_pairs, filename, backup=False):
''' Search and replace for expressions in files
'''
with open(filename, 'rt') as in_fh:
in_txt = in_fh.read(-1)
out_txt = in_txt[:]
for in_exp, out_exp in sr_pairs:
in_exp = re.compile(in_exp)
out_txt = in_exp.sub(out_exp, out_txt)
if in_txt == out_txt:
return False
with open(filename, 'wt') as out_fh:
out_fh.write(out_txt)
if backup:
with open(filename + '.bak', 'wt') as bak_fh:
bak_fh.write(in_txt)
return True
def copy_replace(replace_pairs,
repo_path,
out_path,
cp_globs=('*',),
rep_globs=('*',),
renames = ()):
out_fnames = cp_files(repo_path, cp_globs, out_path)
renames = [(re.compile(in_exp), out_exp) for in_exp, out_exp in renames]
fnames = []
for rep_glob in rep_globs:
fnames += fnmatch.filter(out_fnames, rep_glob)
if verbose:
print('\n'.join(fnames))
for fname in fnames:
filename_search_replace(replace_pairs, fname, False)
for in_exp, out_exp in renames:
new_fname, n = in_exp.subn(out_exp, fname)
if n:
os.rename(fname, new_fname)
break
def make_link_targets(proj_name,
user_name,
repo_name,
known_link_fname,
out_link_fname,
url=None,
ml_url=None):
""" Check and make link targets
If url is None or ml_url is None, check if there are links present for these
in `known_link_fname`. If not, raise error. The check is:
Look for a target `proj_name`.
Look for a target `proj_name` + ' mailing list'
Also, look for a target `proj_name` + 'github'. If this exists, don't write
this target into the new file below.
If we are writing any of the url, ml_url, or github address, then write new
file with these links, of form:
.. _`proj_name`
.. _`proj_name`: url
.. _`proj_name` mailing list: url
"""
with open(known_link_fname, 'rt') as link_fh:
link_contents = link_fh.readlines()
have_url = not url is None
have_ml_url = not ml_url is None
have_gh_url = None
for line in link_contents:
if not have_url:
match = re.match(r'..\s+_`%s`:\s+' % proj_name, line)
if match:
have_url = True
if not have_ml_url:
match = re.match(r'..\s+_`%s mailing list`:\s+' % proj_name, line)
if match:
have_ml_url = True
if not have_gh_url:
match = re.match(r'..\s+_`%s github`:\s+' % proj_name, line)
if match:
have_gh_url = True
if not have_url or not have_ml_url:
raise RuntimeError('Need command line or known project '
'and / or mailing list URLs')
lines = []
if not url is None:
lines.append('.. _`%s`: %s\n' % (proj_name, url))
if not have_gh_url:
gh_url = 'https://github.com/%s/%s\n' % (user_name, repo_name)
lines.append('.. _`%s github`: %s\n' % (proj_name, gh_url))
if not ml_url is None:
lines.append('.. _`%s mailing list`: %s\n' % (proj_name, ml_url))
if len(lines) == 0:
# Nothing to do
return
# A neat little header line
lines = ['.. %s\n' % proj_name] + lines
with open(out_link_fname, 'wt') as out_links:
out_links.writelines(lines)
USAGE = ''' <output_directory> <project_name>
If not set with options, the repository name is the same as the <project
name>
If not set with options, the main github user is the same as the
repository name.'''
GITWASH_CENTRAL = 'git://github.com/matthew-brett/gitwash.git'
GITWASH_BRANCH = 'master'
def main():
parser = OptionParser()
parser.set_usage(parser.get_usage().strip() + USAGE)
parser.add_option("--repo-name", dest="repo_name",
help="repository name - e.g. nitime",
metavar="REPO_NAME")
parser.add_option("--github-user", dest="main_gh_user",
help="github username for main repo - e.g fperez",
metavar="MAIN_GH_USER")
parser.add_option("--gitwash-url", dest="gitwash_url",
help="URL to gitwash repository - default %s"
% GITWASH_CENTRAL,
default=GITWASH_CENTRAL,
metavar="GITWASH_URL")
parser.add_option("--gitwash-branch", dest="gitwash_branch",
help="branch in gitwash repository - default %s"
% GITWASH_BRANCH,
default=GITWASH_BRANCH,
metavar="GITWASH_BRANCH")
parser.add_option("--source-suffix", dest="source_suffix",
help="suffix of ReST source files - default '.rst'",
default='.rst',
metavar="SOURCE_SUFFIX")
parser.add_option("--project-url", dest="project_url",
help="URL for project web pages",
default=None,
metavar="PROJECT_URL")
parser.add_option("--project-ml-url", dest="project_ml_url",
help="URL for project mailing list",
default=None,
metavar="PROJECT_ML_URL")
(options, args) = parser.parse_args()
if len(args) < 2:
parser.print_help()
sys.exit()
out_path, project_name = args
if options.repo_name is None:
options.repo_name = project_name
if options.main_gh_user is None:
options.main_gh_user = options.repo_name
repo_path = clone_repo(options.gitwash_url, options.gitwash_branch)
try:
copy_replace((('PROJECTNAME', project_name),
('REPONAME', options.repo_name),
('MAIN_GH_USER', options.main_gh_user)),
repo_path,
out_path,
cp_globs=(pjoin('gitwash', '*'),),
rep_globs=('*.rst',),
renames=(('\.rst$', options.source_suffix),))
make_link_targets(project_name,
options.main_gh_user,
options.repo_name,
pjoin(out_path, 'gitwash', 'known_projects.inc'),
pjoin(out_path, 'gitwash', 'this_project.inc'),
options.project_url,
options.project_ml_url)
finally:
shutil.rmtree(repo_path)
if __name__ == '__main__':
main()