#!/opt/local/bin/python2.7
#
# Check/update default wiki pages from the Trac project website.
#
# Note: This is a development tool used in Trac packaging/QA, not something
#       particularly useful for end-users.
#
# Author: Daniel Lundin <daniel@edgewall.com>

import httplib
import re
import sys
import getopt

# Pages to include in distribution
wiki_pages = [
 "CamelCase",
 "InterMapTxt",
 "InterTrac",
 "InterWiki",
 "PageTemplates",
 "RecentChanges",
 "TitleIndex",
 "TracAccessibility",
 "TracAdmin",
 "TracBackup",
 "TracBatchModify",
 "TracBrowser",
 "TracCgi",
 "TracChangeset",
 "TracEnvironment",
 "TracFastCgi",
 "TracFineGrainedPermissions",
 "TracGuide",
 "TracImport",
 "TracIni",
 "TracInstall",
 "TracInterfaceCustomization",
 "TracLinks",
 "TracLogging",
 "TracModPython",
 "TracModWSGI",
 "TracNavigation",
 "TracNotification",
 "TracPermissions",
 "TracPlugins",
 "TracQuery",
 "TracReports",
 "TracRepositoryAdmin",
 "TracRevisionLog",
 "TracRoadmap",
 "TracRss",
 "TracSearch",
 "TracStandalone",
 "TracSupport",
 "TracSyntaxColoring",
 "TracTickets",
 "TracTicketsCustomFields",
 "TracTimeline",
 "TracUnicode",
 "TracUpgrade",
 "TracWiki",
 "TracWorkflow",
 "WikiDeletePage",
 "WikiFormatting",
 "WikiHtml",
 "WikiMacros",
 "WikiNewPage",
 "WikiPageNames",
 "WikiProcessors",
 "WikiRestructuredText",
 "WikiRestructuredTextLinks"
 ]

def get_page_from_file(prefix, pname):
    d = ''
    try:
        f = open(pname ,'r')
        d = f.read()
        f.close()
    except Exception:
        print "Missing page: %s" % pname
    return d

def get_page_from_web(prefix, pname):
    host = "trac.edgewall.org"
    rfile = "/wiki/%s%s?format=txt" % (prefix, pname)
    c = httplib.HTTPConnection(host)
    c.request("GET", rfile)
    print "Getting", rfile
    r = c.getresponse()
    d = r.read()
    if r.status == 200 and d:
        f = open(pname, 'w+')
        f.write(d.replace('\r\n', '\n'))
        f.close()
    else:
        print "Missing or empty page"
    c.close()
    return d

def check_links(data):
    def get_refs(t, refs=[]):
        r = "(?P<wikilink>(^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)"
        m = re.search (r, t)
        if not m:
            refs.sort()
            result = []
            orf = None
            for rf in refs:
                if rf != orf:
                    result.append(rf)
                    orf = rf
            return result
        refs.append(m.group())
        return get_refs( t[m.end():], refs)
    for p in data.keys():
        links = get_refs(data[p], [])
        for l in links:
            if l not in data.keys():
                print "Broken link:  %s -> %s" % (p, l)

if __name__ == '__main__':
    try:
        opts, args = getopt.getopt(sys.argv[1:], "dCp:")
    except getopt.GetoptError:
        # print help information and exit:
        print "%s [-d] [-C] [-p prefix] [PAGE ...]" % sys.argv[0]
        print "\t-d        -- Download pages from the main project wiki."
        print "\t-C        -- Try to check links (currently broken)"
        print "\t-p prefix -- When downloading, prepend 'prefix/' to the page."
        sys.exit()
    get_page = get_page_from_file
    prefix = ''
    check = False
    for o,a in opts:
        if o == '-d':
            get_page = get_page_from_web
        elif o == '-p':
            prefix = a+'/'
        elif o == '-C':
            check = True
    data = {}
    for p in args or wiki_pages:
        data[p] = get_page(prefix, p)
    if check:
        check_links(data)

