123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- #!/usr/bin/env python3
- import fnmatch
- import hashlib
- import json
- import os
- import shutil
- import sqlite3
- import sys
- import time
- import urllib.parse
- import argparse
- import trac2md
- wiki_query = '''
- SELECT
- name,
- author,
- version,
- time / 1000000 AS time,
- text
- FROM wiki
- ORDER BY
- name, version
- '''
- attachment_query = '''
- SELECT
- id,
- filename,
- size,
- author,
- description,
- ipnr,
- time / 1000000 AS createdtime
- FROM
- attachment
- WHERE
- type = 'wiki'
- ORDER BY
- filename, time
- '''
- def attachment_link(row):
- h = lambda whatever: hashlib.sha1(whatever.encode()).hexdigest()
- h1 = h(row.id)
- h2 = h(row.filename)
- fn2 = os.path.splitext(row["filename"])[1]
- return \
- os.path.join("attachments", "wiki", h1[:3], h1, h2 + fn2), \
- os.path.join("pelican", "content", row.id, row.filename)
- class Filter:
- def __init__(self, filename = "tools/filter.json"):
- with open(filename) as f:
- filter = json.load(f)
- if not all(action in "-+" for action, pattern in filter):
- sys.exit("Bad action \"{}\" in filter".format(action))
- self.filter = tuple((action == "+", pattern) for action, pattern in filter)
- def __call__(self, name):
- for action, pattern in self.filter:
- if fnmatch.fnmatch(name, pattern):
- return action
- return True
- class Row(sqlite3.Row):
- def __getattr__(self, name):
- return self[name]
- @property
- def isotime(self):
- return time.strftime("%Y-%m-%d %H:%M", time.gmtime(self.time))
- def markdown_header(row, first_published):
- if row.name in first_published:
- modtime = "Modified: {}\n".format(row.isotime)
- else:
- modtime = ""
- first_published[row.name] = row.isotime
- return "Title: {}\nAuthor: {}\nDate: {}\n{}\n".format(row.name, row.author, first_published[row.name], modtime)
- def main():
- ap = argparse.ArgumentParser()
- ap.add_argument("--source-url")
- args = ap.parse_args()
- for dn in ("wiki", "pelican"):
- if os.path.exists(dn):
- shutil.rmtree(dn)
- for dn in ("wiki", "pelican/content"):
- os.makedirs(dn)
- os.link("pelicanconf.py", "pelican/pelicanconf.py")
- wiki_to_markdown = trac2md.Trac2Markdown(args.source_url)
- keep = Filter()
- first_published = {}
- db = sqlite3.connect("trac.db")
- db.row_factory = Row
- for row in db.execute(wiki_query):
- if keep(row.name):
- with open("wiki/{}.trac".format(urllib.parse.quote(row.name, "")), "w") as f:
- f.write(row.text)
- md = markdown_header(row, first_published) + wiki_to_markdown(row.text, row.name)
- fn = "pelican/content/{}.md".format(row.name)
- dn = os.path.dirname(fn)
- if not os.path.exists(dn):
- os.makedirs(dn)
- with open(fn, "w") as f:
- f.write(md)
- for row in db.execute(attachment_query):
- src, dst = attachment_link(row)
- #print("{} => {}".format(dst, src))
- if not os.path.isdir(os.path.dirname(dst)):
- os.makedirs(os.path.dirname(dst))
- os.link(src, dst)
- db.close()
- if __name__ == "__main__":
- main()
|