(Steve Dougherty)
2013-06-25: Add more work on freenet:// path resolution for WoT. Add more work on freenet:// path resolution for WoT.
diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py
--- a/infocalypse/__init__.py
+++ b/infocalypse/__init__.py
@@ -554,6 +554,13 @@ extensions.wrapfunction(discovery, 'find
def freenetpathtouri(ui, path, pull=True):
+ """
+ Return a usable request or insert URI. Expects a freenet:// or freenet:
+ protocol to be specified.
+
+ If the key is not a USK it will be resolved as a WoT identity. In this
+ case if the resolution fails, print an error message and return None.
+ """
# TODO: Is this the only URL encoding that may happen? Why not use a more
# semantically meaningful function?
path = path.replace("%7E", "~").replace("%2C", ",")
@@ -632,6 +639,8 @@ def freenetpush(orig, *args, **opts):
if not isfreenetpath(path):
return orig(*args, **opts)
uri = freenetpathtouri(ui, path, pull=False)
+ if uri is None:
+ return
# if the uri is the short form (USK@/name/#), generate the key and preprocess the uri.
if uri.startswith("USK@/"):
ui.status("creating a new key for the repo. For a new repo with an existing key, use clone.\n")
diff --git a/infocalypse/keys.py b/infocalypse/keys.py
new file mode 100644
--- /dev/null
+++ b/infocalypse/keys.py
@@ -0,0 +1,15 @@
+from string import split
+
+
+class USK:
+ def __init__(self, path):
+ components = split(path, '/')
+ # Expecting USK@key/name/edition
+ assert len(components) == 3
+
+ self.key = components[0]
+ self.name = components[1]
+ self.edition = components[2]
+
+ def __str__(self):
+ return self.key + '/' + self.name + '/' + self.edition
\ No newline at end of file
diff --git a/infocalypse/wot.py b/infocalypse/wot.py
--- a/infocalypse/wot.py
+++ b/infocalypse/wot.py
@@ -6,6 +6,7 @@ from defusedxml.ElementTree import froms
import smtplib
from base64 import b32encode
from fcp.node import base64decode
+from keys import USK
def send_pull_request(ui, from_identity, to_identity):
@@ -67,10 +68,31 @@ def update_repo_listing(ui, for_identity
ui.status("Updated repository listing:\n{0}\n".format(uri))
+def find_repo(ui, truster, wot_identifier, repo_name):
+ """
+ Return a request URI for a repo of the given name published by an
+ identity matching the given identifier.
+ Print an error message and return None on failure.
+ """
+ listing = read_repo_listing(ui, truster, wot_identifier)
+
+ if listing is None:
+ return
+
+ if repo_name not in listing:
+ # TODO: Perhaps resolve again; print full nick / key?
+ # TODO: Maybe print key found in the resolve_*identity?
+ ui.warn("{0} does not publish a repo named '{1}'\n".format(
+ wot_identifier, repo_name))
+ return
+
+ return listing[repo_name]
+
+
def read_repo_listing(ui, truster, wot_identifier):
"""
Read a repo listing for a given identity.
- Return a dictionary of repository URIs keyed by name.
+ Return a dictionary of repository request URIs keyed by name.
"""
identity = resolve_identity(ui, truster, wot_identifier)
if identity is None:
@@ -85,6 +107,8 @@ def read_repo_listing(ui, truster, wot_i
# TODO: Set and read vcs edition property.
node = fcp.FCPNode()
ui.status("Fetching {0}\n".format(uri))
+ # TODO: What exception can this throw on failure? Catch it,
+ # print its description, and return None.
mime_type, repo_xml, msg = node.get(uri, priority=1)
ui.status("Parsing.\n")
@@ -121,17 +145,7 @@ def resolve_pull_uri(ui, path, truster):
# TODO: How to handle redundancy? Does Infocalypse automatically try
# an R0 if an R1 fails?
- repositories = read_repo_listing(ui, truster, wot_id)
-
- if repositories is None:
- return
-
- if repo_name not in repositories:
- ui.warn("Could not find repository named \"{0}\".\n"
- .format(repo_name))
- return
-
- return repositories[repo_name]
+ return find_repo(ui, truster, wot_id, repo_name)
def resolve_push_uri(ui, path):
@@ -140,17 +154,34 @@ def resolve_push_uri(ui, path):
Print an error message and return None on failure.
:param ui: For feedback.
- :param path: path describing a repo: nick@key/reponame,
+ :param path: path describing a repo - nick@key/repo_name,
where the identity is a local one. (Such that the insert URI is known.)
"""
- # Expecting <id stuff>/reponame
- # TODO: Duplcate with resolve_pull
+ # Expecting <id stuff>/repo_name
+ # TODO: Duplicate with resolve_pull
wot_id, repo_name = path.split('/', 1)
- local_id = resolve_local_identity(ui, )
+ local_id = resolve_local_identity(ui, wot_id)
- # Get edition by checking one's own repo list.
- repositories = read_repo_listing(ui, )
+ if local_id is None:
+ return
+
+ insert_uri = USK(local_id['InsertURI'])
+
+ identifier = local_id['Nickname'] + '@' + local_id['Identity']
+
+ repo = find_repo(ui, local_id['Identity'], identifier, repo_name)
+
+ if repo is None:
+ return
+
+ # Request URI
+ repo_uri = USK(repo)
+
+ # Maintains path, edition.
+ repo_uri.key = insert_uri.key
+
+ return str(repo_uri)
# Support for querying WoT for own identities and identities meeting various
# criteria.