(Arne Babenhauserheide)
2012-06-24: rename site.py to staticsite.py to avoid import conflicts with the rename site.py to staticsite.py to avoid import conflicts with the python site module. Also add FTP push support.
diff --git a/site.py b/staticsite.py
rename from site.py
rename to staticsite.py
--- a/site.py
+++ b/staticsite.py
@@ -28,7 +28,7 @@ import datetime
from mercurial import cmdutil, util, scmutil
from mercurial import commands, dispatch
from mercurial.i18n import _
-from mercurial import hg, discovery
+from mercurial import hg, discovery, util, extensions
_staticidentifier = ".statichgrepo"
@@ -563,8 +563,13 @@ def addrepo(ui, repo, target, bookmarks)
def upload(ui, repo, target, ftpstring, force):
"""upload the repo to the FTP server identified by the ftp string."""
- user, password = ftpstring.split("@")[0].split(":")
- serverandpath = "@".join(ftpstring.split("@")[1:])
+ try:
+ user, password = ftpstring.split("@")[0].split(":")
+ serverandpath = "@".join(ftpstring.split("@")[1:])
+ except ValueError:
+ ui.warn(_("FTP-upload: No @ in FTP-Url. We try anonymous access.\n"))
+ user, password = "anonymous", ""
+ serverandpath = ftpstring # no @, so we just take the whole string
server = serverandpath.split("/")[0]
ftppath = "/".join(serverandpath.split("/")[1:])
timeout = 10
@@ -671,8 +676,8 @@ def staticsite(ui, repo, target=None, **
# add the hg repo to the static site
# currently we need to either include all bookmarks or not, because we don’t have the remote repo when parsing the site.
# TODO: I don’t know if that is the correct way to go. Maybe always push all.
- bookmarks = opts["bookmarks"]
- addrepo(ui, repo, target, bookmarks)
+ bookmark = opts["bookmark"]
+ addrepo(ui, repo, target, bookmark)
# first: just create the site.
parsesite(ui, repo, target, **opts)
if opts["upload"]:
@@ -691,6 +696,119 @@ cmdtable = {
('f', 'force', False, 'force recreating all commit files. Slow.'),
('s', 'screenstyle', "", 'use a custom stylesheet for display on screen'),
('p', 'printstyle', "", 'use a custom stylesheet for printing'),
- ('B', 'bookmarks', False, 'include the bookmarks')],
+ ('B', 'bookmark', False, 'include the bookmarks')],
"[options] [folder]")
}
+
+## add ftp as scheme to be handled by this plugin.
+
+wrapcmds = { # cmd: generic, target, fixdoc, ppopts, opts
+ 'push': (False, None, False, False, [
+ ('', 'staticsite', None, 'show parent svn revision instead'),
+ ])
+}
+
+## Explicitely wrap functions to change local commands in case the remote repo is an FTP repo. See mercurial.extensions for more information.
+# Get the module which holds the functions to wrap
+#from mercurial import discovery
+# the new function: gets the original function as first argument and the originals args and kwds.
+#def findcommonoutgoing(orig, *args, **opts):
+# capable = getattr(args[1], 'capable', lambda x: False)
+# if capable('ftp'):
+# return []#orig(*args, **opts)
+# else:
+# return orig(*args, **opts)
+# really wrap the function
+#extensions.wrapfunction(discovery, 'findcommonoutgoing', findcommonoutgoing)
+
+# explicitely wrap commands in case the remote repo is an FTP repo.
+def ftppush(orig, *args, **opts):
+ print args, opts
+ ui, repo, path = args
+ # only act differently, if the target is an FTP repo.
+ if not path.startswith("ftp"):
+ return orig(*args, **opts)
+ # first create the site at ._site
+ target = "._site"
+ ftpstring = path.replace("ftp://", "")
+ if not "name" in opts:
+ opts["name"] = None
+ opts["screenstyle"] = ""
+ opts["printstyle"] = ""
+ opts["upload"] = ftpstring
+ opts["force"] = False
+ staticsite(ui, repo, target, **opts)
+
+# really wrap the command
+entry = extensions.wrapcommand(commands.table, "push", ftppush)
+
+# Starting an FTP repo. Not yet used, except for throwing errors for missing commands and faking the lock.
+
+from mercurial import repo, util
+try:
+ from mercurial.error import RepoError
+except ImportError:
+ from mercurial.repo import RepoError
+
+class FTPRepository(repo.repository):
+ def __init__(self, ui, path, create):
+ self.create = create
+ self.ui = ui
+ self.path = path
+ self.capabilities = set(["ftp"])
+
+ def lock(self):
+ """We cannot really lock FTP repos, yet.
+
+ TODO: Implement as locking the repo in the static site folder."""
+ class DummyLock:
+ def release(self):
+ pass
+ l = DummyLock()
+ return l
+
+ def url(self):
+ return self.path
+
+ def lookup(self, key):
+ return key
+
+ def cancopy(self):
+ return False
+
+ def heads(self, *args, **opts):
+ """
+ Whenever this function is hit, we abort. The traceback is useful for
+ figuring out where to intercept the functionality.
+ """
+ raise util.Abort('command heads unavailable for FTP repositories')
+
+ def pushkey(self, namespace, key, old, new):
+ return False
+
+ def listkeys(self, namespace):
+ return {}
+
+ def push(self, remote, force=False, revs=None, newbranch=None):
+ raise util.Abort('command push unavailable for FTP repositories')
+
+ def pull(self, remote, heads=[], force=False):
+ raise util.Abort('command pull unavailable for FTP repositories')
+
+ def findoutgoing(self, remote, base=None, heads=None, force=False):
+ raise util.Abort('command findoutgoing unavailable for FTP repositories')
+
+
+class RepoContainer(object):
+ def __init__(self):
+ pass
+
+ def __repr__(self):
+ return '<FTPRepository>'
+
+ def instance(self, ui, url, create):
+ # Should this use urlmod.url(), or is manual parsing better?
+ #context = {}
+ return FTPRepository(ui, url, create)
+
+hg.schemes["ftp"] = RepoContainer()