Implemented push, pull and clone from and to freenet:USK@ and USK@ uris.
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py --- a/infocalypse/__init__.py +++ b/infocalypse/__init__.py @@ -356,7 +356,8 @@ import os from commands import * -from mercurial import commands +from mercurial import commands, extensions, util, hg, dispatch +from mercurial.i18n import _ import freenetrepo @@ -382,12 +383,14 @@ NOSEARCH_OPT = [('', 'nosearch', None, ' # Allow mercurial naming convention for command table. # pylint: disable-msg=C0103 +PULL_OPTS = [('', 'hash', [], 'repo hash of repository to pull from'), + ('', 'onlytrusted', None, 'only use repo announcements from ' + + 'known users')] + cmdtable = { "fn-pull": (infocalypse_pull, - [('', 'uri', '', 'request URI to pull from'), - ('', 'hash', [], 'repo hash of repository to pull from'), - ('', 'onlytrusted', None, 'only use repo announcements from ' - + 'known users')] + [('', 'uri', '', 'request URI to pull from')] + + PULL_OPTS + FCP_OPTS + NOSEARCH_OPT + AGGRESSIVE_OPT, @@ -512,3 +515,115 @@ commands.norepo += ' fn-setup' commands.norepo += ' fn-setupfms' commands.norepo += ' fn-genkey' commands.norepo += ' fn-archive' + + +## Wrap core commands for use with freenet keys. + +def freenetpathtouri(path): + 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): + ui, repo, path = parsepushargs(*args) + if not path: + path = ui.expandpath('default', 'default-push') + # 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) + +def freenetpush(orig, *args, **opts): + ui, repo, path = parsepushargs(*args) + if not path: + path = ui.expandpath('default-push', 'default') + # 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) + +def freenetclone(orig, *args, **opts): + ui, source, dest = parsepushargs(*args) + # only act differently, if dest or source is an infocalypse repo. + if not isfreenetpath(source) and not isfreenetpath(dest): + return orig(*args, **opts) + + if not dest: + if not isfreenetpath(source): + dest = hg.defaultdest(source) + else: # this is a freenet key. It has a /# at the end and + # could contain .R1 or .R0 as pure technical identifiers + # which we do not need in the local name. + dest = source.split("/")[-2] + if dest.endswith(".R1") or dest.endswith(".R0"): + dest = dest[:-3] + + # check whether to create, pull or copy + pulluri, pushuri = None, None + if isfreenetpath(source): + pulluri = freenetpathtouri(source) + if isfreenetpath(dest): + pushuri = freenetpathtouri(dest) + + # decide which infocalypse command to use. + if pulluri and pushuri: + action = "copy" + elif pulluri: + action = "pull" + elif pushuri: + action = "create" + else: + 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) + + if action == "create": + opts["uri"] = pushuri + return infocalypse_create(ui, repo, **opts) + + if action == "pull": + if os.path.exists(dest): + raise util.Abort(_("destination " + dest + " already exists.")) + # create the repo + req = dispatch.request(["init", dest], ui=ui) + dispatch.dispatch(req) + # pull the data from freenet + origdest = ui.expandpath(dest) + dest, branch = hg.parseurl(origdest) + destrepo = hg.repository(ui, dest) + infocalypse_pull(ui, destrepo, aggressive=True, hash=None, uri=pulluri, **opts) + # store the request uri for future updates + with destrepo.opener("hgrc", "a", text=True) as f: + f.write("""[paths] +default = freenet://""" + pulluri + "\n") + # and update the repo + return hg.update(destrepo, None) + + +# really wrap the command +entry = extensions.wrapcommand(commands.table, "push", freenetpush) +entry[1].extend(FCP_OPTS) +entry = extensions.wrapcommand(commands.table, "pull", freenetpull) +entry[1].extend(PULL_OPTS) +entry[1].extend(FCP_OPTS) +entry = extensions.wrapcommand(commands.table, "clone", freenetclone) +entry[1].extend(FCP_OPTS)