hg site extension
 
(Arne Babenhauserheide)
2011-10-06: overview should work.

overview should work.

diff --git a/static.py b/static.py
new file mode 100644
--- /dev/null
+++ b/static.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+"""static
+
+Create and/or upload a static copy of the repository.
+
+The main goal is sharing Mercurial on servers with only FTP access and
+statically served files, while providing the same information as hg
+serve and full solutions like bitbucket and gitorious (naturally
+without the interactivity).
+"""
+
+__plan__ = """
+
+* Create the static-dir in the repo:
+  - Overview: Readme + commits + template
+  - Changes: Commit-Log + each commit as changeset/<hex>
+  - source: a filetree, shown as sourcecode: src/<path> and raw/<path>
+  - if b is used: a bugtracker: issue/<id>/<name>
+  - fork-/clone-info for each entry in [paths] with its incoming data (if it has some):
+    clone/<pathname>/ → commit log + possibly an associated issue in b.
+
+* Usage:
+  - hg static [--name] [-r] [folder] → parse the static folder for the current revision.
+    Mimic pull and clone wherever possible: This is a clone to <repo>/static
+  - hg static --upload <FTP-path> [folder] → update and upload the folder == clone/push
+
+* Idea: hg clone/push ftp://host.tld/path/to/repo → hg static --upload
+
+* Setup a new static repo or update an existing one: hg static --upload ftp://host.tld/path/to/repo
+
+"""
+
+import os
+from os.path import join, isdir, isfile
+import shutil
+import mercurial.cmdutil
+from mercurial import commands
+
+_staticidentifier = ".statichgrepo"
+
+templates = {
+    "head": """<!DOCTYPE html>
+<html><head>
+    <meta charset="utf-8" />
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <!--duplicate for older browsers-->
+    <link rel="stylesheet" href="style.css" type="text/css" media="screen" />
+    <link rel="stylesheet" href="print.css" type="text/css" media="print" />
+    <title>REPO_NAME</title>
+</head>
+<body>
+""",
+    "foot": "</body></html>",
+    "screenstyle": """ """,
+    "printstyle": """ """
+}
+
+
+def parsereadme(filepath):
+    """Parse the readme file"""
+    with open(filepath) as r:
+        return r.read()
+
+
+def parsesite(ui, repo, target, **opts):
+    """Create the static folder."""
+    idfile = join(target, _staticidentifier)
+    if not isdir(target):
+        # make sure the target exists
+        os.makedirs(target)
+    else: # make sure it is a staticrepo
+        if not isfile(idfile):
+            if not ui.prompt("The target folder exists is no static repo. Really use it?", default="n").lower() in ["y", "yes"]:
+                return
+    with open(idfile, "w") as i:
+        i.write("")
+
+    # first the stylesheets
+    screenstyle = opts["screenstyle"]
+    if screenstyle:
+        shutil.copyfile(screenstyle, join(target, "style.css"))
+    else:
+        with open(join(target, "style.css"), "w") as f:
+            f.write(templates["screenstyle"])
+    printstyle = opts["printstyle"]
+    if printstyle:
+        shutil.copyfile(printstyle, join(target, "print.css"))
+    else:
+        with open(join(target, "print.css"), "w") as f:
+            f.write(templates["printstyle"])
+
+    # then the overview
+    overview = open(join(target, "index.html"), "w")
+    overview.write(templates["head"])
+    # add a readme, if it exists # TODO: Parse different types of readme files
+    for f in os.listdir(target):
+        if f.lower().startswith("readme"):
+            overview.write(parsereadme(f))
+    # now add the 5 most recent log entries
+    # divert all following ui output to a string, so we can just use standard functions
+    #ui.pushbuffer()
+    commands.log(ui, repo, template="""<div style='float: right; padding-left: 0.5em'><em>({author|person})</em></div>
+
+g<p><strong> {date|shortdate}: <a href='commits/{node}.html'>{desc|strip|fill68|firstline}</a> <span style='font-size: xx-small'>{branches} {tags}</span></p><p>{desc|escape}</p>""", date="")
+    #overview.write(ui.popbuffer())
+    # finish the overview
+    overview.write(templates["foot"])
+
+
+
+def static(ui, repo, target=None, **opts):
+    """Create a static copy of the repository and/or upload it to an FTP server."""
+    if not target:
+        target = "static"
+    parsesite(ui, repo, target, **opts)
+
+
+
+cmdtable = {
+    # "command-name": (function-call, options-list, help-string)
+    "static": (static,
+                     [('r', 'rev', None, 'parse the given revision'),
+                      ('a', 'all', None, 'parse all revisions (requires much space)'),
+                      ('n', 'name', None, 'the repo name. Default: folder or last segment of the repo-path.'),
+                      ('u', 'upload', None, 'upload the repo'),
+                      ('s', 'screenstyle', None, 'use a custom stylesheet for display on screen'),
+                      ('p', 'printstyle', None, 'use a custom stylesheet for printing')],
+                     "[options] [folder]")
+}