# HG changeset patch # User Doug Simon # Date 1341498258 -7200 # Node ID 613a3ddb9a7146275f3043181a2482573764cfcc # Parent 25e37b01b92aa6669851eed55b1bee270f71920e moved core site functionality into mx.py diff -r 25e37b01b92a -r 613a3ddb9a71 mx/commands.py --- a/mx/commands.py Thu Jul 05 11:18:12 2012 +0200 +++ b/mx/commands.py Thu Jul 05 16:24:18 2012 +0200 @@ -969,142 +969,13 @@ mx.abort('jacocoreport takes only one argument : an output directory') mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) -def _fix_overview_summary(path, topLink): - """ - Processes an "overview-summary.html" generated by javadoc to put the complete - summary text above the Packages table. - """ - - # This uses scraping and so will break if the relevant content produced by javadoc changes in any way! - with open(path) as fp: - content = fp.read() - - class Chunk: - def __init__(self, content, ldelim, rdelim): - lindex = content.find(ldelim) - rindex = content.find(rdelim) - self.ldelim = ldelim - self.rdelim = rdelim - if lindex != -1 and rindex != -1 and rindex > lindex: - self.text = content[lindex + len(ldelim):rindex] - else: - self.text = None - - def replace(self, content, repl): - lindex = content.find(self.ldelim) - rindex = content.find(self.rdelim) - old = content[lindex:rindex + len(self.rdelim)] - return content.replace(old, repl) - - chunk1 = Chunk(content, """
-
-
""", """
-
-

See: Description

-
""") - - chunk2 = Chunk(content, """ -""") - - assert chunk1.text, 'Could not find header section in ' + path - assert chunk2.text, 'Could not find footer section in ' + path - - content = chunk1.replace(content, '
' + topLink + chunk2.text +'
') - content = chunk2.replace(content, '') - - with open(path, 'w') as fp: - fp.write(content) - def site(args): """creates a website containing javadoc and the project dependency graph""" - parser = ArgumentParser(prog='site') - parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='') - - args = parser.parse_args(args) - - args.base = os.path.abspath(args.base) - tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base)) - unified = join(tmpbase, 'all') - - try: - # Create javadoc for each project - mx.javadoc(['--base', tmpbase]) - - # Create unified javadoc for all projects - mx.javadoc(['--base', tmpbase, - '--unified', - '--arg', '@-windowtitle', '--arg', '@Graal OpenJDK Project Documentation', - '--arg', '@-doctitle', '--arg', '@Graal OpenJDK Project Documentation', - '--arg', '@-overview', '--arg', '@' + join(_graal_home, 'graal', 'overview.html')]) - os.rename(join(tmpbase, 'javadoc'), unified) - - # Generate dependency graph with Graphviz - _, tmp = tempfile.mkstemp() - try: - svg = join(tmpbase, 'all', 'modules.svg') - jpg = join(tmpbase, 'all', 'modules.jpg') - with open(tmp, 'w') as fp: - print >> fp, 'digraph projects {' - print >> fp, 'rankdir=BT;' - print >> fp, 'size = "13,13";' - print >> fp, 'node [shape=rect, fontcolor="blue"];' - #print >> fp, 'edge [color="green"];' - for p in mx.projects(): - print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' - for dep in p.canonical_deps(): - if mx.project(dep, False): - print >> fp, '"' + p.name + '" -> "' + dep + '"' - depths = dict() - for p in mx.projects(): - d = p.max_depth() - depths.setdefault(d, list()).append(p.name) - for d, names in depths.iteritems(): - print >> fp, '{ rank = same; "' + '"; "'.join(names) + '"; }' - print >> fp, '}' - - mx.run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, tmp]) - - finally: - os.remove(tmp) - - # Post-process generated SVG to remove title elements which most browsers - # render as redundant (and annoying) tooltips. - with open(svg, 'r') as fp: - content = fp.read() - content = re.sub('.*', '', content) - content = re.sub('xlink:title="[^"]*"', '', content) - with open(svg, 'w') as fp: - fp.write(content) - - # Post-process generated overview-summary.html files - top = join(tmpbase, 'all', 'overview-summary.html') - for root, _, files in os.walk(tmpbase): - for f in files: - if f == 'overview-summary.html': - path = join(root, f) - topLink = '' - if top != path: - link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path)) - topLink = '

[return to the overall Graal documentation]

' - _fix_overview_summary(path, topLink) - - - if exists(args.base): - shutil.rmtree(args.base) - shutil.move(tmpbase, args.base) - - print 'Created website - root is ' + join(args.base, 'all', 'index.html') - - finally: - if exists(tmpbase): - shutil.rmtree(tmpbase) + return mx.site(['--name', 'Graal', + '--overview', join(_graal_home, 'graal', 'overview.html'), + '--title', 'Graal OpenJDK Project Documentation', + '--dot-output-base', 'modules'] + args) def mx_init(): _vmbuild = 'product' diff -r 25e37b01b92a -r 613a3ddb9a71 mxtool/mx.py --- a/mxtool/mx.py Thu Jul 05 11:18:12 2012 +0200 +++ b/mxtool/mx.py Thu Jul 05 16:24:18 2012 +0200 @@ -1993,6 +1993,7 @@ parser.add_argument('--arg', action='append', dest='extra_args', help='extra Javadoc arguments (e.g. --arg @-use)', metavar='@', default=[]) parser.add_argument('-m', '--memory', action='store', help='-Xmx value to pass to underlying JVM') parser.add_argument('--packages', action='store', help='comma separated packages to process (omit to process all packages)') + parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude') args = parser.parse_args(args) @@ -2006,6 +2007,10 @@ if args.packages is not None: packages = [name for name in args.packages.split(',')] + exclude_packages = [] + if args.exclude_packages is not None: + exclude_packages = [name for name in args.exclude_packages.split(',')] + def outDir(p): if args.base is None: return join(p.dir, docDir) @@ -2039,7 +2044,8 @@ if len([name for name in files if name.endswith('.java')]) != 0: pkg = root[len(sourceDir) + 1:].replace(os.sep,'.') if len(packages) == 0 or pkg in packages: - pkgs.add(pkg) + if len(exclude_packages) == 0 or not pkg in exclude_packages: + pkgs.add(pkg) return pkgs extraArgs = [a.lstrip('@') for a in args.extra_args] @@ -2066,26 +2072,33 @@ cp = classpath(p.name, includeSelf=True) sp = os.pathsep.join(p.source_dirs()) overviewFile = join(p.dir, 'overview.html') - overview = [] - if exists(overviewFile): - overview = ['-overview', overviewFile] + delOverviewFile = False + if not exists(overviewFile): + with open(overviewFile, 'w') as fp: + print >> fp, 'Documentation for the ' + p.name + ' project.' + delOverviewFile = True nowarnAPI = [] if not args.warnAPI: nowarnAPI.append('-XDignore.symbol.file') - log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) - run([java().javadoc, memory, - '-windowtitle', p.name + ' javadoc', - '-XDignore.symbol.file', - '-classpath', cp, - '-quiet', - '-d', out, - '-sourcepath', sp] + - links + - extraArgs + - overview + - nowarnAPI + - list(pkgs)) - log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) + try: + log('Generating {2} for {0} in {1}'.format(p.name, out, docDir)) + run([java().javadoc, memory, + '-windowtitle', p.name + ' javadoc', + '-XDignore.symbol.file', + '-classpath', cp, + '-quiet', + '-d', out, + '-overview', overviewFile, + '-sourcepath', sp] + + links + + extraArgs + + nowarnAPI + + list(pkgs)) + log('Generated {2} for {0} in {1}'.format(p.name, out, docDir)) + finally: + if delOverviewFile: + os.remove(overviewFile) + else: # The projects must be built to ensure javadoc can find class files for all referenced classes build(['--no-native']) @@ -2119,6 +2132,156 @@ list(pkgs)) log('Generated {2} for {0} in {1}'.format(', '.join(names), out, docDir)) +def site(args): + """creates a website containing javadoc and the project dependency graph""" + + parser = ArgumentParser(prog='site') + parser.add_argument('-d', '--base', action='store', help='directory for generated site', required=True, metavar='') + parser.add_argument('--name', action='store', help='name of overall documentation', required=True, metavar='') + parser.add_argument('--overview', action='store', help='path to the overview content for overall documentation', required=True, metavar='') + parser.add_argument('--projects', action='store', help='comma separated projects to process (omit to process all projects)') + parser.add_argument('--exclude-packages', action='store', help='comma separated packages to exclude', metavar='') + parser.add_argument('--dot-output-base', action='store', help='base file name (relative to /all) for project dependency graph .svg and .jpg files generated by dot (omit to disable dot generation)', metavar='') + parser.add_argument('--title', action='store', help='value used for -windowtitle and -doctitle javadoc args for overall documentation (default: "")', metavar='') + args = parser.parse_args(args) + + args.base = os.path.abspath(args.base) + tmpbase = tempfile.mkdtemp(prefix=basename(args.base) + '.', dir=dirname(args.base)) + unified = join(tmpbase, 'all') + + exclude_packages_arg = [] + if args.exclude_packages is not None: + exclude_packages_arg = ['--exclude-packages', args.exclude_packages] + + projects = sorted_deps() + projects_arg = [] + if args.projects is not None: + projects_arg = ['--projects', args.projects] + projects = [project(name) for name in args.projects.split(',')] + + try: + # Create javadoc for each project + javadoc(['--base', tmpbase] + exclude_packages_arg + projects_arg) + + # Create unified javadoc for all projects + title = args.title if args.title is not None else args.name + javadoc(['--base', tmpbase, + '--unified', + '--arg', '@-windowtitle', '--arg', '@' + title, + '--arg', '@-doctitle', '--arg', '@' + title, + '--arg', '@-overview', '--arg', '@' + args.overview] + exclude_packages_arg + projects_arg) + os.rename(join(tmpbase, 'javadoc'), unified) + + # Generate dependency graph with Graphviz + if args.dot_output_base is not None: + dot = join(tmpbase, 'all', str(args.dot_output_base) + '.dot') + svg = join(tmpbase, 'all', str(args.dot_output_base) + '.svg') + jpg = join(tmpbase, 'all', str(args.dot_output_base) + '.jpg') + with open(dot, 'w') as fp: + dim = len(projects) + print >> fp, 'digraph projects {' + print >> fp, 'rankdir=BT;' + print >> fp, 'size = "' + str(dim) + ',' + str(dim) + '";' + print >> fp, 'node [shape=rect, fontcolor="blue"];' + #print >> fp, 'edge [color="green"];' + for p in projects: + print >> fp, '"' + p.name + '" [URL = "../' + p.name + '/javadoc/index.html", target = "_top"]' + for dep in p.canonical_deps(): + if dep in [proj.name for proj in projects]: + print >> fp, '"' + p.name + '" -> "' + dep + '"' + depths = dict() + for p in projects: + d = p.max_depth() + depths.setdefault(d, list()).append(p.name) + print >> fp, '}' + + run(['dot', '-Tsvg', '-o' + svg, '-Tjpg', '-o' + jpg, dot]) + + # Post-process generated SVG to remove title elements which most browsers + # render as redundant (and annoying) tooltips. + with open(svg, 'r') as fp: + content = fp.read() + content = re.sub('<title>.*', '', content) + content = re.sub('xlink:title="[^"]*"', '', content) + with open(svg, 'w') as fp: + fp.write(content) + + # Post-process generated overview-summary.html files + + def fix_overview_summary(path, topLink): + """ + Processes an "overview-summary.html" generated by javadoc to put the complete + summary text above the Packages table. + """ + + # This uses scraping and so will break if the relevant content produced by javadoc changes in any way! + with open(path) as fp: + content = fp.read() + + class Chunk: + def __init__(self, content, ldelim, rdelim): + lindex = content.find(ldelim) + rindex = content.find(rdelim) + self.ldelim = ldelim + self.rdelim = rdelim + if lindex != -1 and rindex != -1 and rindex > lindex: + self.text = content[lindex + len(ldelim):rindex] + else: + self.text = None + + def replace(self, content, repl): + lindex = content.find(self.ldelim) + rindex = content.find(self.rdelim) + old = content[lindex:rindex + len(self.rdelim)] + return content.replace(old, repl) + + chunk1 = Chunk(content, """
+
+
""", """
+
+

See: Description

+
""") + + chunk2 = Chunk(content, """ +""") + + assert chunk1.text, 'Could not find header section in ' + path + assert chunk2.text, 'Could not find footer section in ' + path + + content = chunk1.replace(content, '
' + topLink + chunk2.text +'
') + content = chunk2.replace(content, '') + + with open(path, 'w') as fp: + fp.write(content) + + top = join(tmpbase, 'all', 'overview-summary.html') + for root, _, files in os.walk(tmpbase): + for f in files: + if f == 'overview-summary.html': + path = join(root, f) + topLink = '' + if top != path: + link = os.path.relpath(join(tmpbase, 'all', 'index.html'), dirname(path)) + topLink = '

[return to the overall ' + args.name + ' documentation]

' + fix_overview_summary(path, topLink) + + + if exists(args.base): + shutil.rmtree(args.base) + shutil.move(tmpbase, args.base) + + print 'Created website - root is ' + join(args.base, 'all', 'index.html') + + finally: + if exists(tmpbase): + shutil.rmtree(tmpbase) + def findclass(args): """find all classes matching a given substring""" @@ -2181,6 +2344,7 @@ 'projectgraph': [projectgraph, ''], 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'], + 'site': [site, '[options]'], 'netbeansinit': [netbeansinit, ''], 'projects': [show_projects, ''], }