hg site extension
 
(Arne Babenhauserheide)
2013-04-13: merge default into releases for release. releases 0.3

merge default into releases for release.

diff --git a/.bugs/bugs b/.bugs/bugs
--- a/.bugs/bugs
+++ b/.bugs/bugs
@@ -2,6 +2,7 @@ push all bookmarks too                  
 add sourcecode coloring to the src files.                    | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:09715a67cfabe2de0901f0472610c2285626e0e7, time:1319147685.11
 offer different and customizeable ways to parse a site, including to just call an external applications. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:0ed55f757a6352bc3b2674153a3dc8eda91db843, time:1332932026.35
 Add a list of branches, heads and tags to the summary page.  | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:0fde104c4206be8245ff0716ee2e91ea3971db8f, time:1319147651.17
+include incoming commits, so I can easily check if I should pull a fork - and visitors can see what they can find in the fork. | owner:, open:False, id:14e7a48faa8965f947695744cc40d0f2bc25023b, time:1365863785.15
 if b is used: a bugtracker: issue/<id>/<name>                | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:1d631d51ff06b3bdca50e21da3d6a00bcb801c85, time:1319147632.52
 add css classes and ids everywhere, so this can be styled with CSS. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:2699812cf02c803fa338daf9ae039c43a30a0b5f, time:1322090683.01
 get mtimes from the repo instead of querying the FTP server. We know which files were changed. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:29210503551d0eafca67dda8d6fffbd40bf837dc, time:1319213074.57
@@ -24,7 +25,9 @@ Idea: hg clone/push ftp://host.tld/path/
 add linenumbers to the src files.                            | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:b7bab6f46da7d224f97d0dac55a617d3a464d301, time:1319147678.56
 commits as commit/<rev>/ for long term viability. .html as suffix is not as long lived as a simple dirname. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:baaad4bdc13d7155048ce6a9dde92dc857b6a1ac, time:1319148414.16
 clone/<pathname>/ → incoming log (commits) + possibly an associated issue in b. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:c58557260a47597ac5057703e26a94df190a2a5d, time:1319147661.8
+only write bug files if their content differs from the content on disk to avoid reuploading them without need | owner:, open:True, id:c7b2cf5fdbc68160530a08e1d651c23a1f49fc01, time:1365865229.49
 no longer create raw files, since they can’t be served by all webservers and waste bandwidth and space (they are no longer linked anyway). | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:d1010e1933648f65af37d969bfb45f8d834fc8bb, time:1319148721.49
+add a footer which links back to hgsite                      | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:ed55d92709329e81b8d619c4d2a9aa97361fefd8, time:1365863559.31
 check the hgweb templating for parsing the site.             | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:ef17f01dbe8ee58536fa8b345eb18d1efc639f15, time:1319208643.38
 maybe more advanced bookmarks pushing.                       | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:ef8c12bfcc99686efc1f685a9be0be0c78922ca5, time:1322115049.48
 crashes on missing readme.                                   | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:f4232c8a52fff730a4c63525ad597c063135e576, time:1332936115.69
diff --git a/staticsite.py b/staticsite.py
--- a/staticsite.py
+++ b/staticsite.py
@@ -30,6 +30,7 @@ from mercurial.i18n import _
 from mercurial import hg, discovery, util, extensions
 
 _staticidentifier = ".statichgrepo"
+_freenetprivkeystring = "AQECAAE/"
 
 templates = {
     "head": """<!DOCTYPE html>
@@ -393,7 +394,7 @@ def getincoming(ui, repo, otheruri, othe
     # cannot do that for ftp or freenet insertion uris (freenet
     # separates insertion and retrieval by private/public key)
     isftpuri = otheruri.startswith("ftp://")
-    isfreenetpriv = "AQECAAE/" in otheruri
+    isfreenetpriv = _freenetprivkeystring in otheruri
     if isftpuri or isfreenetpriv:
         chlist = []
         return chlist, cleanupfn, other
@@ -434,8 +435,8 @@ def getoutgoing(ui, repo, otheruri, othe
     def outgoingchanges(repo, other):
         from mercurial import discovery
         fco = discovery.findcommonoutgoing
+        og = fco(repo, other, force=True)
         try:
-            og = fco(repo, other, force=True)
             return og.missing
         except AttributeError: # old client
             common, outheads = og
@@ -469,9 +470,8 @@ def getforkinfo(ui, target):
 def safeuri(uri):
     """Shareable uris: Hide password + hide freenet insert keys."""
     uri = util.hidepassword(uri)
-    freenetpriv = "AQECAAE/"
-    if "USK@" in uri and freenetpriv in uri:
-        uri = "freenet://USK@******" + uri[uri.index(freenetpriv)+len(freenetpriv)-1:]
+    if "USK@" in uri and _freenetprivkeystring in uri:
+        uri = "freenet://USK@******" + uri[uri.index(_freenetprivkeystring)+len(_freenetprivkeystring)-1:]
     return uri
 
 def getforkdata(ui, repo, target, name, forkname, forkuri):
@@ -488,11 +488,22 @@ def getforkdata(ui, repo, target, name, 
     # prepare the log templater
     t = cmdutil.changeset_templater(ui, repo, patch=False, diffopts=None, mapfile=None, buffered=False)
     t.use_template(templates["commitlog"].replace(
-            "{relativepath}", "../"))
+            "{relativepath}", "../../"))
     
     # Add incoming commits
     html += "<div id='incoming'><h2>Incoming commits</h2>"
     chlist, cleanupfn, localother = getincoming(ui, repo, otheruri=forkuri, other=other, othername=forkname)
+
+    # write all missing incoming commits directly from the incoming repo
+    if chlist:
+        try:
+            writecommitsforchlist(ui, localother, target, name, chlist)
+            writesourcetreeforchlist(ui, localother, target, name, chlist, force=False)
+        except AttributeError:
+            if not hasattr(localother, "changelog"):
+                print "Cannot write commits from fork", forkname, "because the repository type does not support getting the changelog."
+            else:
+                raise
     
     ui.pushbuffer()
     for ch in chlist:
@@ -500,7 +511,7 @@ def getforkdata(ui, repo, target, name, 
         t.show(ctx)
     html += ui.popbuffer()
     cleanupfn()
-    
+        
     # add outgoing commits
     html += "<div id='outgoing'><h2>Outgoing commits</h2>"
     chlist, cleanupfn, localother = getoutgoing(ui, repo, forkuri, other=other, othername=forkname)
@@ -536,17 +547,18 @@ def writeforks(ui, repo, target, name):
             f.write(
                 getforkdata(ui, repo, target, name, forkname, forkuri))
 
-def writecommits(ui, repo, target, name, force=False):
+def writecommitsforchlist(ui, repo, target, name, chlist, force=False):
     """Write all not yet existing commit files."""
     commit = os.path.join(target, "commit")
     
     # create the folders
     if not os.path.isdir(commit):
         os.makedirs(commit)
-        
+    
     t = cmdutil.changeset_templater(ui, repo, patch=False, diffopts=None, mapfile=None, buffered=False)
     t.use_template(templates["commitlog"].replace("{relativepath}", "../"))
-    for c in range(len(repo.changelog)):
+
+    for c in chlist:
         ctx = repo.changectx(str(c))
         cpath = os.path.join(commit, ctx.hex() + ".html")
         if not force and os.path.isfile(cpath):
@@ -561,6 +573,11 @@ def writecommits(ui, repo, target, name,
             cf.write("<pre>"+ui.popbuffer().replace("<", "<")+"</pre>")
             cf.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>"))
 
+def writecommits(ui, repo, target, name, force=False):
+    """Write all not yet existing commit files."""
+    chlist = range(len(repo.changelog))
+    return writecommitsforchlist(ui, repo, target, name, chlist, force=force)
+
 #: html escape codes thanks to http://wiki.python.org/moin/EscapingHtml
 htmlescapetable = {
     "&": "&",
@@ -663,14 +680,14 @@ def createindex(ui, repo, target, ctx):
     index += "</ul>"
     return index
 
-def writesourcetree(ui, repo, target, name, force, rawfiles=False):
+def writesourcetreeforchlist(ui, repo, target, name, chlist, force=False, rawfiles=False):
     """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.
     """
     # first write all files in all commits.
-    for c in range(len(repo.changelog)):
+    for c in chlist:
         ctx = repo.changectx(str(c))
         for filename in ctx.files():
             try:
@@ -702,7 +719,7 @@ def writesourcetree(ui, repo, target, na
                 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)):
+    for c in chlist:
         ctx = repo.changectx(str(c))
         filepath = os.path.join(target,"src",ctx.hex(),"index.html")
         # skip already existing files
@@ -716,6 +733,16 @@ def writesourcetree(ui, repo, target, na
             f.write(createindex(ui, repo, target, ctx))
             f.write(templates["foot"].replace("{reponame}", "<a href='../../'>"+name+"</a>"))
 
+
+def writesourcetree(ui, repo, target, name, force, rawfiles=False):
+    """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.
+    """
+    chlist = range(len(repo.changelog))
+    return writesourcetreeforchlist(ui, repo, target, name, chlist, force=force, rawfiles=rawfiles)
+
 def parsesite(ui, repo, target, **opts):
     """Create the static folder."""
     idfile = os.path.join(target, _staticidentifier)