hg site extension
 
(Arne Babenhauserheide)
2011-10-20: also add source files and manifest infos.

also add source files and manifest infos.

diff --git a/static.py b/static.py
--- a/static.py
+++ b/static.py
@@ -26,6 +26,7 @@ without the interactivity).
   - fork-/clone-info for each entry in [paths] with its incoming data (if it has some):
     clone/<pathname>/ → incoming log (commits) + possibly an associated issue in b.
   - More complex Readme parsing.
+  - Treat branch heads specially: link on the main page.
 
 * Usage:
   - hg static [--name] [-r] [folder] → parse the static folder for the current revision.
@@ -39,7 +40,7 @@ without the interactivity).
 """
 
 import os
-from os.path import join, isdir, isfile, basename
+from os.path import join, isdir, isfile, basename, dirname
 import shutil
 import re
 import mercurial
@@ -62,7 +63,11 @@ templates = {
 """,
     "foot": "</body></html>",
     "screenstyle": """ """,
-    "printstyle": """ """
+    "printstyle": """ """,
+    "manifesthead": """<h2>Commit: {hex} </h2>
+<p>{desc}</p><p>{user}</p>
+    <h2>Files changed</h2>"""
+
 }
 
 _indexregexp = re.compile("^\\.*index.html$")
@@ -178,15 +183,80 @@ def escapename(filename):
     """escape index.html as .index.html and .ind… as ..ind… and so fort."""
     if _indexregexp.match(filename) is not None:
         return "." + filename
+    else: return filename
 
 
-def writesourcetree(ui, repo, target, name):
+def parsesrcdata(data):
+    """Parse a src file into a html file."""
+    return "<pre>"+data.replace("<", "<")+"</pre>"
+
+def srcpath(target, ctx, filename):
+    """Get the relative path to the static sourcefile for an already escaped filename."""
+    return join(target,"src",ctx.hex(),filename+".html")
+
+def createindex(target, ctx):
+    """Create an index page for the changecontext: the commit message + the user + all files in the changecontext."""
+    # first the head
+    index = templates["manifesthead"].replace(
+        "{hex}", ctx.hex()).replace(
+        "{desc}", ctx.description()).replace(
+            "{user}", ctx.user())
+    # then the files
+    index += "<ul>"
+    for filename in ctx:
+        filectx = ctx[filename]
+        lasteditctx = filectx.filectx(filectx.filerev())
+        index += "<li><a href='../../../"+ srcpath(target, lasteditctx, escapename(filename)) + "'>" + filename + "</a></li>"
+    index += "</ul>"
+    return index
+
+
+def writesourcetree(ui, repo, target, name, force):
     """Write manifests for all commits and websites for all files.
 
     * For each file, write sites for all revisions where the file was changed: under src/<hex>/path as html site (with linenumbers and maybe colored source), under raw/<hex>/<path> as plain files. If there is an index.html file, write it as .index.html. If there also is .index.html, turn it to ..index.html, …
     * For each commit write an index with links to the included files at their latest revisions before/at the commit.
     """
-    pass
+    # first write all files in all commits.
+    for c in range(len(repo.changelog)):
+        ctx = repo.changectx(str(c))
+        for filename in ctx.files():
+            filectx = ctx[filename]
+            # first write the raw data
+            filepath = join(target,"raw",ctx.hex(),filectx.path())
+            # skip already existing files
+            if not force and isfile(filepath):
+                continue
+            try:
+                os.makedirs(dirname(filepath))
+            except OSError: pass # exists
+            with open(filepath, "w") as f:
+                f.write(filectx.data())
+            # then write it as html
+            _filenameescaped = escapename(filectx.path())
+            filepath = srcpath(target,ctx,_filenameescaped)
+            try:
+                os.makedirs(dirname(filepath))
+            except OSError: pass # exists
+            with open(filepath, "w") as f:
+                f.write(templates["head"].replace("{reponame}", name))
+                f.write(parsesrcdata(filectx.data()))
+                f.write(templates["foot"].replace("{reponame}", name))
+    # then write manifests for all commits
+    for c in range(len(repo.changelog)):
+        ctx = repo.changectx(str(c))
+        filepath = join(target,"src",ctx.hex(),"index.html")
+        # skip already existing files
+        if not force and isfile(filepath):
+            continue
+        try:
+            os.makedirs(dirname(filepath))
+        except OSError: pass # exists
+        with open(filepath, "w") as f:
+            f.write(templates["head"].replace("{reponame}", name))
+            f.write(createindex(target, ctx))
+            f.write(templates["foot"].replace("{reponame}", name))
+
 
 def parsesite(ui, repo, target, **opts):
     """Create the static folder."""
@@ -229,6 +299,9 @@ def parsesite(ui, repo, target, **opts):
     # and all commit files
     writecommits(ui, repo, target, name, force=opts["force"])
 
+    # and all file data
+    writesourcetree(ui, repo, target, name, force=opts["force"])
+
 
 def addrepo(ui, repo, target):
     """Add the repo to the target and make sure it is up to date."""