now pushing and pulling works with keys in the .hg/hgrc (prefixed with freenet://)
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py --- a/infocalypse/__init__.py +++ b/infocalypse/__init__.py @@ -356,7 +356,7 @@ import os from commands import * -from mercurial import commands, extensions, util, hg, dispatch +from mercurial import commands, extensions, util, hg, dispatch, discovery from mercurial.i18n import _ import freenetrepo @@ -518,47 +518,83 @@ commands.norepo += ' fn-archive' ## Wrap core commands for use with freenet keys. +## 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 +# the new function: gets the original function as first argument and the originals args and kwds. +def findcommonoutgoing(orig, *args, **opts): + repo = args[0] + remoterepo = args[1] + capable = getattr(remoterepo, 'capable', lambda x: False) + if capable('infocalypse'): + class fakeoutgoing(object): + def __init__(self): + self.excluded = [] + self.missing = repo.heads() + self.missingheads = [] + self.commonheads = [] + return fakeoutgoing() + else: + return orig(*args, **opts) +# really wrap the functions +extensions.wrapfunction(discovery, 'findcommonoutgoing', findcommonoutgoing) + +# wrap the commands def freenetpathtouri(path): + path = path.replace("%7E", "~").replace("%2C", ",") if path.startswith("freenet://"): return path[len("freenet://"):] if path.startswith("freenet:"): return path[len("freenet:"):] return path -def isfreenetpath(path): - if path and path.startswith("freenet:") or path.startswith("USK@"): - return True - return False - -def parsepushargs(ui, repo, path=None): - return ui, repo, path - def freenetpull(orig, *args, **opts): + def parsepushargs(ui, repo, path=None): + return ui, repo, path + def isfreenetpath(path): + if path and path.startswith("freenet:") or path.startswith("USK@"): + return True + return False ui, repo, path = parsepushargs(*args) if not path: path = ui.expandpath('default', 'default-push') + else: + path = ui.expandpath(path) # only act differently, if the target is an infocalypse repo. if not isfreenetpath(path): return orig(*args, **opts) uri = freenetpathtouri(path) opts["uri"] = uri opts["aggressive"] = True # always search for the latest revision. - infocalypse_pull(ui, repo, **opts) + return infocalypse_pull(ui, repo, **opts) def freenetpush(orig, *args, **opts): + def parsepushargs(ui, repo, path=None): + return ui, repo, path + def isfreenetpath(path): + if path and path.startswith("freenet:") or path.startswith("USK@"): + return True + return False ui, repo, path = parsepushargs(*args) if not path: path = ui.expandpath('default-push', 'default') + else: + path = ui.expandpath(path) # only act differently, if the target is an infocalypse repo. if not isfreenetpath(path): return orig(*args, **opts) uri = freenetpathtouri(path) opts["uri"] = uri opts["aggressive"] = True # always search for the latest revision. - infocalypse_push(ui, repo, **opts) + return infocalypse_push(ui, repo, **opts) def freenetclone(orig, *args, **opts): + def parsepushargs(ui, repo, path=None): + return ui, repo, path + def isfreenetpath(path): + if path and path.startswith("freenet:") or path.startswith("USK@"): + return True + return False ui, source, dest = parsepushargs(*args) # only act differently, if dest or source is an infocalypse repo. if not isfreenetpath(source) and not isfreenetpath(dest): @@ -592,12 +628,11 @@ def freenetclone(orig, *args, **opts): raise util.Abort("""Can't clone without source and target. This message should not be reached. If you see it, this is a bug.""") if action == "copy": - opts["requesturi"] = pulluri - opts["inserturi"] = pushuri - return infocalypse_copy(ui, repo, **opts) + raise util.Abort("""Cloning without intermediate local repo not yet supported in the simplified commands. Use fn-copy directly.""") if action == "create": opts["uri"] = pushuri + repo = hg.repository(ui, ui.expandpath(source)) return infocalypse_create(ui, repo, **opts) if action == "pull": @@ -614,7 +649,12 @@ def freenetclone(orig, *args, **opts): # store the request uri for future updates with destrepo.opener("hgrc", "a", text=True) as f: f.write("""[paths] -default = freenet://""" + pulluri + "\n") +default = freenet://""" + pulluri + """ + +[ui] +username = anonymous +""" ) + ui.warn("As basic protection, infocalypse automatically set the username 'anonymous' for commits in this repo. To change this, edit " + str(os.path.join(destrepo.root, ".hg", "hgrc"))) # and update the repo return hg.update(destrepo, None) @@ -627,3 +667,76 @@ entry[1].extend(PULL_OPTS) entry[1].extend(FCP_OPTS) entry = extensions.wrapcommand(commands.table, "clone", freenetclone) entry[1].extend(FCP_OPTS) + + +# 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 InfocalypseRepository(repo.repository): + def __init__(self, ui, path, create): + self.create = create + self.ui = ui + self.path = path + self.capabilities = set(["infocalypse"]) + self.branchmap = {} + + def lock(self): + """We cannot really lock Infocalypse 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 Infocalypse 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 Infocalypse repositories') + + def pull(self, remote, heads=[], force=False): + raise util.Abort('command pull unavailable for Infocalypse repositories') + + def findoutgoing(self, remote, base=None, heads=None, force=False): + raise util.Abort('command findoutgoing unavailable for Infocalypse repositories') + + +class RepoContainer(object): + def __init__(self): + pass + + def __repr__(self): + return '<InfocalypseRepository>' + + def instance(self, ui, url, create): + # Should this use urlmod.url(), or is manual parsing better? + #context = {} + return InfocalypseRepository(ui, url, create) + +hg.schemes["freenet"] = RepoContainer()