(Arne Babenhauserheide)
2012-10-30: merged default into stable for release. releases 0.2 merged default into stable for release.
diff --git a/.bugs/bugs b/.bugs/bugs --- a/.bugs/bugs +++ b/.bugs/bugs @@ -8,14 +8,16 @@ get mtimes from the repo instead of quer FIX: revision 0 is omitted: change that :) | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:29396f1753e45b5a37ffa0ce04d96c876d6b6722, time:1319209563.68 parse the pushed repo, not the local one. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:2c26d62b62e3656ebcce43e7a24f627594911fb5, time:1322115065.37 revisions more structured, as list or similar. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:39cacfc83da6f6beecafdb745823d7f01018206b, time:1322159357.88 +tags do not have a heading on the overview anymore | owner:, open:True, id:485d0b451f18b5eae517b34466622b0d52340d8e, time:1351620233.63 only write .statichgrepo print.css style.css and index.html when their data changed \(or \-\-force\) → read them and compare the contents. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:4f02149269a60fca85aa040116b2789d98c906f2, time:1319212903.98 sort tags in reverse order | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:61d256ab154e64597be604d6298daa545d4a96c7, time:1322159250.01 add proper caching of every ftp directory listing. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:750692931106d78ffc38c1ed63013c4dac4099dd, time:1319175393.07 -fork-/clone-info for each entry in [paths] with its incoming data (if it has some): | owner:, open:True, id:8621575e4016752e8987c8b294dfa9166f77eff3, time:1319147671.39 +fork-/clone-info for each entry in [paths] with its incoming data (if it has some): | owner:, open:False, id:8621575e4016752e8987c8b294dfa9166f77eff3, time:1319147671.39 +partial localization of strings - files to Dateien - is worse than none. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:921fb80eb2a2fbf57e0f6db0a949ead872624f8f, time:1351635128.79 More complex Readme parsing. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:94fbade896adbf6f696cfdb331021437dff3f30e, time:1319147671.39 -make the link from the /commit/*.html pages to the /src/*/[index.html] pages more obvious | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:ad936eaaba1693f7c44bd59916a19e6f3b3db27e, time:1319209748.93 +make the link from the /commit/*.html pages to the /src/*/[index.html] pages more obvious | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:ad936eaaba1693f7c44bd59916a19e6f3b3db27e, time:1319209748.93 cache FTP directory listings for much faster upload of already existing sites. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:b1f6dfdaccc0346adaf0d42d361bbc2de00ee176, time:1319208814.12 -Idea: hg clone/push ftp://host.tld/path/to/repo → hg site --upload | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:b4693d2677e0a2b4ef9ee5dfbbe8c4742924604c, time:1319147779.76 +Idea: hg clone/push ftp://host.tld/path/to/repo → hg site --upload | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:b4693d2677e0a2b4ef9ee5dfbbe8c4742924604c, time:1319147779.76 add linenumbers to the src files. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, 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 @@ -24,4 +26,5 @@ check the hgweb templating for parsing t 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:True, id:f4232c8a52fff730a4c63525ad597c063135e576, time:1332936115.69 Treat branch heads specially: link on the main page. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:f531c27b38f9ea1749ded312f4f468c9ac33b930, time:1319147696.96 +do not show closed branches | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:fbae7e95ed65dc314770126b614fe40d52e61f89, time:1351633799.8 allow setting user, password, server and path vie .hg/hgrc. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:fc575156316d56b70fda64725984b66cc8a2cfde, time:1322118134.69 diff --git a/README.txt b/README.txt --- a/README.txt +++ b/README.txt @@ -4,13 +4,13 @@ Create and/or upload a static copy of th You can get it via `hg clone http://draketo.de/proj/hgsite/` -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). +The main goal is sharing code with Mercurial on servers who only offer +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). -Only changed files are uploaded, based on the time they were last -modified, so uploads can be reasonably fast. +On upload, only changed files are uploaded, based on the time they +were last modified, so uploads can be reasonably fast. Install: @@ -22,10 +22,13 @@ Install: Usage: -$ hg site [-n sitename] -u user:password@ftp.host.tld/path/to/dir -→ that’s how this site gets created. +$ hg push [-f] --sitename "sitename" ftp://user:password@ftp.host.tld/path/to/dir +→ that’s how this site gets created. + With -f it is reuploaded completely, + otherwise only the changes get uploaded. + defining the ftp://… in [paths] in .hg/hgrc works. -To upload the site when you push, you can use a hook in .hg/hgrc. This is what I use: +To upload the site when you push it anywhere, you can use a hook in .hg/hgrc. This is what I use: [hooks] post-push = hg site -n site -u user:password@ftp.host.tld/path/to/dir diff --git a/staticsite.py b/staticsite.py --- a/staticsite.py +++ b/staticsite.py @@ -11,7 +11,7 @@ serve and full solutions like bitbucket without the interactivity). """ -__copyright__ = """Copyright 2011 Arne Babenhauserheide +__copyright__ = """Copyright 2012 Arne Babenhauserheide This software may be used and distributed according to the terms of the GNU General Public License version 2 or any later version. @@ -65,7 +65,20 @@ templates = { <h1>{forkname} <small>(fork of <a href="../../">{reponame}</a>, found at {forkuri})</small></h1> """, "foot": "</body></html>\n", - "screenstyle": """ """, + "screenstyle": """ +.bugnumbers { + font-size: x-small; + vertical-align: super; +} +.openbugnumber, .openbugnumber a { + color: #f00; + text-decoration: none; +} +.resolvedbugnumber, .resolvedbugnumber a { + color: #00f; + text-decoration: none; +} +""", "printstyle": """ """, "manifesthead": """<h2>""" + _("Commit (click to see the diff)")+""": <a href='../../commit/{hex}.html'>{hex}</a></h2> <p>{desc}</p><p>{user}</p> @@ -95,6 +108,76 @@ def contentequals(filepath, content): except IOError: return False # file does not exist. Empty != not existing. # TODO: check: return True if content is None? +def bisenabled(): + """Check if the b extension is enabled to decide if we want to add + a bug listing.""" + enabled = extensions.enabled() + if "b" in enabled: + return True + +def splitbugline(line): + """Split a b extension bug line into the ID and the description.""" + try: + bugid = line.split("-")[0].strip() + except IndexError: + return "", line + description = "".join(line.split("-")[1:]).lstrip() + return bugid, description + +def getbugdetails(ui, repo, bugid): + """Get the details for a bug.""" + # first get the details + ui.pushbuffer() + req = dispatch.request(["b", "details", bugid], ui=ui, repo=repo) + dispatch.dispatch(req) + return ui.popbuffer() + +def getbugfullid(details, bugid): + """Get the real ID of a bug from its detailed info. If it’s not available, just give the short bugid""" + try: + idline = [i for i in details.splitlines() if i.startswith("ID: ")][0] + except IndexError: # no id line + return bugid + realid = idline[4:].strip() + return realid + +class BBug(object): + """A b-extension bug.""" + def __init__(self, shortid, fullid, description, state, details=""): + self.shortid, self.fullid, self.description, self.state, self.details = shortid, fullid, description, state, details + +def getbuginfo(ui, repo, bugline): + """Get information about a bug from its bugline.""" + shortid, description = splitbugline(bugline) + details = getbugdetails(ui, repo, shortid) + fullid = getbugfullid(details, shortid) + return shortid, fullid, description, details + +def getbugs(ui, repo): + """Get all bugs.""" + if not bisenabled(): + return [], [] + # run the b command to get all open bugs + ui.pushbuffer() + req = dispatch.request(["b"], ui=ui, repo=repo) + dispatch.dispatch(req) + openbuglines = [line for line in ui.popbuffer().splitlines() if "-" in line] + # similarly get all resolved bugs + ui.pushbuffer() + req = dispatch.request(["b", "list", "-r"], ui=ui, repo=repo) + dispatch.dispatch(req) + resolvedbuglines = [line for line in ui.popbuffer().splitlines() if "-" in line] + # now turn them into a list of bugs + openbugs = [] + for bugline in openbuglines: + bugid, fullid, description, details = getbuginfo(ui, repo, bugline) + openbugs.append(BBug(bugid, fullid, description, "open", details)) + resolvedbugs = [] + for bugline in resolvedbuglines: + bugid, fullid, description, details = getbuginfo(ui, repo, bugline) + resolvedbugs.append(BBug(bugid, fullid, description, "resolved", details)) + return openbugs, resolvedbugs + def parsereadme(filepath, truncated=False): """Parse the readme file""" with open(filepath) as r: @@ -114,7 +197,6 @@ def overviewlogstring(ui, repo, revs, te t.show(ctx) return ui.popbuffer() - def writeoverview(ui, repo, target, name): """Create the overview page""" overview = "" @@ -132,7 +214,17 @@ def writeoverview(ui, repo, target, name overview += "</div>" break # now the links to the log and the files. - overview += "\n<p id='nav'><a href='commits'>changelog</a> | <a href='src/" + repo["tip"].hex() + "/'>files</a>" + overview += "\n<p id='nav'><a href='commits'>" + _("changelog") + "</a> | <a href='src/" + repo["tip"].hex() + "/'>" + _("files") + "</a>" + # and the bugs + openbugs, resolvedbugs = getbugs(ui, repo) + if openbugs or resolvedbugs: + overview += " | <a href=\"bugs\">" + _("bugs") + "</a>" + if openbugs: + overview += " <span class=\"bugnumbers\">(<span class=\"openbugnumber\"><a href=\"bugs#open\">" + str(len(openbugs)) + "!</a></span> " + else: + overview += " <span class=\"bugnumber openbugnumberzero\">0</span>" + overview += "<span class=\"bugnumber resolvedbugnumber\"><a href=\"bugs#resolved\">" + str(len(resolvedbugs)) + "√</a></span>)</span>" + # and the forks forks = getforkinfo(ui, target) if forks: @@ -143,9 +235,9 @@ def writeoverview(ui, repo, target, name overview += "<small>(" + str(len(incoming)) outgoing, fn, localother = getoutgoing(ui, repo, otheruri=forkuri, othername=forkname) overview += "<small>↓↑</small>" + str(len(outgoing)) + ")</small> " - + overview += "</p>" - + # now add the 5 most recent log entries # divert all following ui output to a string, so we can just use standard functions overview += "\n<div id='shortlog'><h2>Changes (<a href='commits'>full changelog</a>)</h2>\n" @@ -163,8 +255,9 @@ def writeoverview(ui, repo, target, name for branch, heads in repo.branchmap().items(): if branch and branch != "default": # not default branches.extend(heads) - + try: + # FIXME: For some reason this does not seem to give the tags anymore. tags = repo._tags except AttributeError: tags = [] @@ -203,7 +296,7 @@ def writeoverview(ui, repo, target, name overview += "<div id='readme'><h2>"+_("Readme")+"</h2>\n" overview += readme overview += "</div>" - + # finish the overview overview += templates["foot"] indexfile = os.path.join(target, "index.html") @@ -214,7 +307,7 @@ def writeoverview(ui, repo, target, name def writelog(ui, repo, target, name): """Write the full changelog, in steps of 100.""" commits = os.path.join(target, "commits") - + # create the folders if not os.path.isdir(commits): os.makedirs(commits) @@ -222,7 +315,7 @@ def writelog(ui, repo, target, name): d = commits+"-"+str(i+1)+"00" if not os.path.isdir(d): os.makedirs(d) - + # create the log files t = cmdutil.changeset_templater(ui, repo, patch=False, diffopts=None, mapfile=None, buffered=False) t.use_template(templates["commitlog"].replace("{relativepath}", "../")) @@ -243,13 +336,13 @@ def writelog(ui, repo, target, name): else: d = commits logs.append([os.path.join(d, "index.html"), ""]) - + logs[-1][-1] += templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name) for c in range(ck*100+1, min(len(repo.changelog)+1, (ck+1)*100)): ctx = repo.changectx(str(-c)) t.show(ctx) logs[-1][-1] += ui.popbuffer() - + for filepath,data in logs: data += templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>") if not contentequals(filepath,data): @@ -258,7 +351,7 @@ def writelog(ui, repo, target, name): def getlocalother(repo, ui, otheruri, othername): """Get a local clone of the repo identified by uri and name within .hg/paths. - + This creates that local clone! """ # if we cannot get the changes via bundlerepo, we create a @@ -296,7 +389,7 @@ def getincoming(ui, repo, otheruri, othe if isftpuri or isfreenetpriv: chlist = [] return chlist, cleanupfn, other - + if not other: other = hg.peer(repo, {}, otheruri) ui.pushbuffer() # ignore ui events @@ -326,10 +419,10 @@ def getoutgoing(ui, repo, otheruri, othe if isftpuri or isfreenetpriv: chlist = [] return chlist, cleanupfn, other - + if not other: other = hg.peer(repo, {}, otheruri) - + def outgoingchanges(repo, other): from mercurial import discovery fco = discovery.findcommonoutgoing @@ -342,7 +435,7 @@ def getoutgoing(ui, repo, otheruri, othe return o other.ui.pushbuffer() # ignore ui events - + try: chlist = outgoingchanges(repo, other) except (AttributeError, util.Abort): @@ -350,11 +443,10 @@ def getoutgoing(ui, repo, otheruri, othe other = getlocalother(repo, ui, otheruri, othername) other.ui.pushbuffer() chlist = outgoingchanges(repo, other) - + other.ui.popbuffer() return chlist, cleanupfn, other - def getforkinfo(ui, target): """Name and Uri of all forks.""" forks = dict(ui.configitems("paths")) @@ -378,18 +470,18 @@ def getforkdata(ui, repo, target, name, """Write the site for a single fork.""" # make sure the forkdir exists. other = hg.peer(repo, {}, forkuri) - + # incrementally build the html html = templates["forkhead"].replace( "{forkname}", forkname).replace( "{reponame}", name).replace( "{forkuri}", safeuri(forkuri)) - + # 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}", "../")) - + # Add incoming commits html += "<div id='incoming'><h2>Incoming commits</h2>" chlist, cleanupfn, localother = getincoming(ui, repo, otheruri=forkuri, other=other, othername=forkname) @@ -400,11 +492,11 @@ 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) - + ui.pushbuffer() for ch in chlist: ctx = repo.changectx(ch) @@ -421,7 +513,7 @@ def getforkdir(target, forkname): def writeforks(ui, repo, target, name): """Write an info-page for each fork, defined in hg paths. - + relevant data: incoming commits, outgoing commits, branches and bookmarks not in fork or not in repo. Short: incoming (commits, branches, bookmarks), outgoing (incoming first means, we consider this repo to be the main repo). """ forkinfo = getforkinfo(ui, target) @@ -436,15 +528,14 @@ def writeforks(ui, repo, target, name): f.write( getforkdata(ui, repo, target, name, forkname, forkuri)) - def writecommits(ui, repo, target, name, 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)): @@ -462,6 +553,54 @@ def writecommits(ui, repo, target, name, cf.write("<pre>"+ui.popbuffer().replace("<", "<")+"</pre>") cf.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>")) +#: html escape codes thanks to http://wiki.python.org/moin/EscapingHtml +htmlescapetable = { + "&": "&", + '"': """, + "'": "'", + ">": ">", + "<": "<", + } + +def htmlescape(text): + """Produce entities within text.""" + return "".join(htmlescapetable.get(c,c) for c in text) + +def writebugs(ui, repo, target, name): + """Write bug information, a listing and the details for each bug.""" + bugdir = os.path.join(target, "bugs") + + # create the bugs folder + if not os.path.isdir(bugdir): + os.makedirs(bugdir) + + # get all bugs + openbugs, resolvedbugs = getbugs(ui, repo) + # write the bugs list + bugslist = os.path.join(bugdir, "index.html") + content = "<h2 id=\"open\">Open Bugs</h2>\n<ul>" + for bug in openbugs: + content += "<li><a href=\"" + bug.fullid + ".html\">" + bug.shortid + "</a> - " + htmlescape(bug.description) + "</li>\n" + content += "</ul>\n" + content += "<h2 id=\"resolved\">Resolved Bugs</h2>\n<ul>" + for bug in resolvedbugs: + content += "<li><a href=\"" + bug.fullid + ".html\">" + bug.shortid + "</a> - " + htmlescape(bug.description) + "</li>\n" + content += "</ul>\n" + with open(bugslist, "w") as f: + f.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name)) + f.write(content) + f.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>")) + # write all bug details + for bug in openbugs + resolvedbugs: + bugsfile = bugslist = os.path.join(bugdir, bug.fullid + ".html") + content = "<h2>" + bug.description + "</h2>\n" + content += "<pre>" + bug.details + "</pre>\n" + content += "<hr>" + content += "- <a href=\"index.html\">" + _("all bugs") + "</a> -" + with open(bugsfile, "w") as bf: + bf.write(templates["head"].replace("{reponame}", "<a href='../'>"+name+"</a>").replace("{title}", name)) + bf.write(content) + bf.write(templates["foot"].replace("{reponame}", "<a href='../'>"+name+"</a>")) def escapename(filename): """escape index.html as .index.html and .ind… as ..ind… and so fort.""" @@ -469,7 +608,6 @@ def escapename(filename): return "." + filename else: return filename - def parsesrcdata(data): """Parse a src file into a html file.""" return "<pre>"+data.replace("<", "<")+"</pre>" @@ -484,7 +622,10 @@ def rawpath(target, ctx, filename): def ctxdiffstat(ui, repo, ctx): """Get the diffstat of a change context.""" - command = "log -r " + ctx.hex() + " --stat --color=never" + if "color" in extensions.enabled(): + command = "log -r " + ctx.hex() + " --stat --color=never" + else: + command = "log -r " + ctx.hex() + " --stat" req = dispatch.request(command.split(), ui=ui, repo=repo) ui.pushbuffer() dispatch.dispatch(req) @@ -496,6 +637,7 @@ def ctxdiffstat(ui, repo, ctx): "[0;31m", "").replace( "[0m","") + def createindex(ui, repo, target, ctx): """Create an index page for the changecontext: the commit message + the user + all files in the changecontext.""" # first the head @@ -515,7 +657,7 @@ def createindex(ui, repo, target, ctx): 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. """ @@ -577,12 +719,12 @@ def parsesite(ui, repo, target, **opts): return with open(idfile, "w") as i: i.write("") - + if opts["sitename"]: name = opts["sitename"] elif target != "static": name = target else: name = os.path.basename(repo.root) - + # first the stylesheets screenstyle = opts["screenstyle"] screenfile = os.path.join(target, "style.css") @@ -598,22 +740,24 @@ def parsesite(ui, repo, target, **opts): elif not contentequals(printfile, templates["printstyle"]): with open(printfile, "w") as f: f.write(templates["printstyle"]) - + # then the overview writeoverview(ui, repo, target, name) - + # and the log writelog(ui, repo, target, name) - + # and all commit files writecommits(ui, repo, target, name, force=opts["force"]) - + # and all file data writesourcetree(ui, repo, target, name, force=opts["force"]) - + # and all forks writeforks(ui, repo, target, name) - + + # and all bugs + writebugs(ui, repo, target, name) def addrepo(ui, repo, target, bookmarks, force): """Add the repo to the target and make sure it is up to date.""" @@ -622,7 +766,7 @@ def addrepo(ui, repo, target, bookmarks, except mercurial.error.RepoError, e: # already exists pass - + ui.pushbuffer() if bookmarks: commands.push(ui, repo, dest=target, bookmark=repo._bookmarks, force=force) @@ -630,7 +774,6 @@ def addrepo(ui, repo, target, bookmarks, commands.push(ui, repo, dest=target, force=force) ui.popbuffer() - def upload(ui, repo, target, ftpstring, force): """upload the repo to the FTP server identified by the ftp string.""" try: @@ -648,9 +791,9 @@ def upload(ui, repo, target, ftpstring, except socket.timeout: ui.warn(_("connection to "), server, _(" timed out after "), timeout, _(" seconds.\n")) return - + ui.status(ftp.getwelcome(), "\n") - + # create the target dir. serverdir = os.path.dirname(ftppath) serverdirparts = ftppath.split("/") @@ -662,26 +805,26 @@ def upload(ui, repo, target, ftpstring, sd = os.path.join(sd, sdp) if not sd in ftp.nlst(sdo): ftp.mkd(sd) - - + + ftp.cwd(ftppath) if not ftp.pwd() == "/" + ftppath: ui.warn(_("not in the correct ftp directory. Cowardly bailing out.\n")) return - + #ftp.dir() #return ftpfeatures = ftp.sendcmd("FEAT") featuremtime = " MDTM" in ftpfeatures.splitlines() _ftplistcache = set() - + for d, dirnames, filenames in os.walk(target): for filename in filenames: localfile = os.path.join(d, filename) serverfile = localfile[len(target)+1:] serverdir = os.path.dirname(serverfile) serverdirparts = serverdir.split("/") -# print serverdirparts, serverfile + # print serverdirparts, serverfile with open(localfile, "rb") as f: sd = serverdirparts[0] if sd and not sd in _ftplistcache: # should happen only once per superdir @@ -694,7 +837,7 @@ def upload(ui, repo, target, ftpstring, except ftplib.error_perm, resp: ui.warn(_("could not create directory "), sd, ": " , resp, "\n") else: _ftplistcache.add(sd) - + for sdp in serverdirparts[1:]: sdold = sd sd = os.path.join(sd, sdp) @@ -710,7 +853,7 @@ def upload(ui, repo, target, ftpstring, except ftplib.error_perm, resp: ui.warn(_("could not create directory "), sd, ": " , resp, "\n") - + if not serverfile in _ftplistcache: # should happen for existing files only once per dir. _ftplistcache.update(set(ftp.nlst(serverdir))) if not serverfile in _ftplistcache or force: @@ -720,7 +863,7 @@ def upload(ui, repo, target, ftpstring, else: ui.status(_("uploading "), serverfile, _(" because it is not yet online.\n")) - + ftp.storbinary("STOR "+ serverfile, f) else: # reupload the file if the file on the server is older than the local file. @@ -734,8 +877,6 @@ def upload(ui, repo, target, ftpstring, _(" because it is newer than the file on the FTP server.\n")) ftp.storbinary("STOR "+ serverfile, f) - - def staticsite(ui, repo, target=None, **opts): """Create a static copy of the repository and/or upload it to an FTP server.""" if repo.root == target: @@ -754,7 +895,6 @@ def staticsite(ui, repo, target=None, ** # upload the repo upload(ui, repo, target, opts["upload"], opts["force"]) - cmdtable = { # "command-name": (function-call, options-list, help-string) "site": (staticsite, @@ -912,10 +1052,10 @@ def test(): showcall(["hg", "--config", "extensions.site="+__file__, "site", "-B", "-n", "mysite"]) # check if uploading works: Only a valid test, if you have a # post-push hook which does the uploading - showcall(["hg", "--config", "extensions.site="+__file__, "push"]) + # showcall(["hg", "--config", "extensions.site="+__file__, "push"]) # check if push directly to ftp works. Requires the path draketo # to be set up in .hg/hgrc as ftp://user:password/path - showcall(["hg", "--config", "extensions.site="+__file__, "push", "draketo", "--sitename", "site extension"]) + # showcall(["hg", "--config", "extensions.site="+__file__, "push", "draketo", "--sitename", "hg site extension"]) if __name__ == "__main__": test()