Skip to content

Instantly share code, notes, and snippets.

@yellow-sky
Created November 4, 2013 21:34
Show Gist options
  • Save yellow-sky/7309541 to your computer and use it in GitHub Desktop.
Save yellow-sky/7309541 to your computer and use it in GitHub Desktop.
Trac Wiki to Bitbucket Wiki simple converter. Based on https://gist.github.com/sgk/1286682
#!/usr/bin/python
# coding=utf-8
import sqlite3
import re
import sys
from os import path, rename, walk, mkdir
import shutil
PAGE_QUERY = '''
select
name, version, time, author, text
from
wiki w
where
version = (select max(version) from wiki where name = w.name)
and author <> 'trac'
'''
ATTACH_QUERY = '''
select
id, filename, description
from
attachment a
where
id = '%s'
'''
def rename_home(parent_path):
"""
rename WikiStart.md -> Home.md (Bitbucket start wiki page)
"""
rename(path.join(parent_path, 'WikiStart.md'), path.join(parent_path, 'Home.md'))
def copy_attachments(track_path, out_path):
"""
Copy all attachments from track dir to output dir
"""
for (dirpath, dirnames, filenames) in walk(path.join(track_path, 'attachments')):
for filename in filenames:
shutil.copyfile(path.join(dirpath, filename), path.join(out_path, filename))
def convert_pages(track_path, out_path):
"""
Convert pages from track db to Markdown Bitbucket
"""
conn = sqlite3.connect(path.join(track_path, 'db', 'trac.db'))
result = conn.execute(PAGE_QUERY)
for row in result:
name = row[0]
text = row[4]
text = re.sub('\[\[BR\]\]', '\n', text)
text = re.sub('\r\n', '\n', text)
text = re.sub(r'{{{(.*?)}}}', r'`\1`', text)
def indent4(m):
return '\n ' + m.group(1).replace('\n', '\n ')
text = re.sub(r'(?sm){{{\n(.*?)\n}}}', indent4, text)
text = re.sub(r'(?m)^====\s+(.*?)\s+====$', r'#### \1', text)
text = re.sub(r'(?m)^===\s+(.*?)\s+===$', r'### \1', text)
text = re.sub(r'(?m)^==\s+(.*?)\s+==$', r'## \1', text)
text = re.sub(r'(?m)^=\s+(.*?)\s+=$', r'# \1', text)
text = re.sub(r'^ * ', r'****', text)
text = re.sub(r'^ * ', r'***', text)
text = re.sub(r'^ * ', r'**', text)
text = re.sub(r'^ * ', r'*', text)
text = re.sub(r'^ \d+. ', r'1.', text)
a = []
for line in text.split('\n'):
if not line.startswith(' '):
line = re.sub(r'\[(https?://[^\s\[\]]+)\s([^\[\]]+)\]', r'[\2](\1)', line)
line = re.sub(r'\[wiki:([^\s\[\]]+)\s([^\[\]]+)\]', r'[\2](\1)', line)
line = re.sub(r'\[wiki:([^\s\[\]]+)\]', r'[\1](\1)', line)
line = re.sub(r'\!(([A-Z][a-z0-9]+){2,})', r'\1', line)
line = re.sub(r'\'\'\'(.*?)\'\'\'', r'*\1*', line)
line = re.sub(r'\'\'(.*?)\'\'', r'_\1_', line)
a.append(line)
text = '\n'.join(a)
#attaches
att_text = ''
attaches = conn.execute(ATTACH_QUERY % name)
for att in attaches:
att_filename = att[1]
att_desc = att[2]
att_text += '\n\n [%s](attachments/%s) *%s*' % (att_filename, att_filename, att_desc)
fp = file(path.join(out_path, '%s.md' % name), 'w')
fp.write(text.encode('utf-8'))
if att_text:
fp.write('\n\n\n\n***Attachments:***')
fp.write(att_text.encode('utf-8'))
fp.close()
def main(args):
"""
Main func
"""
trac_path = args[1]
out_wiki_path = args[2]
out_attach_path = path.join(out_wiki_path, 'attachments')
# need check
if not path.exists(out_wiki_path):
mkdir(out_wiki_path)
if not path.exists(out_attach_path):
mkdir(out_attach_path)
convert_pages(trac_path, out_wiki_path)
rename_home(out_wiki_path)
copy_attachments(trac_path, out_attach_path)
if __name__ == '__main__':
args = sys.argv
if len(args) < 3:
print ('Usage: trac2bitbucket.py trac_path out_wiki_path')
sys.exit(-1)
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment