infocalypse
 
(Steve Dougherty)
2013-06-13: Add repository names lookup from WoT repo list.

Add repository names lookup from WoT repo list. One can now pull a repository with hg fn-pull --wot AnID/reponame

diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py
--- a/infocalypse/__init__.py
+++ b/infocalypse/__init__.py
@@ -529,8 +529,11 @@ def infocalypse_pull(ui_, repo, **opts):
         # it up from the XML.
         # TODO: Insert XML.
 
-        # Expecting <id stuff>/reponame.R1/edition
-        wot_id, repo_path = opts['wot'].split('/', 1)
+        # Expecting <id stuff>/reponame
+        wot_id, repo_name = opts['wot'].split('/', 1)
+
+        # TODO: How to handle redundancy? Does Infocalypse automatically try
+        # an R0 if an R1 fails?
 
         nickname_prefix = ''
         key_prefix=''
@@ -541,25 +544,14 @@ def infocalypse_pull(ui_, repo, **opts):
         if len(split) == 2:
             key_prefix = split[1]
 
-        attributes = wot.resolve_identity(ui_,
-                                          truster=truster,
-                                          nickname_prefix=nickname_prefix,
-                                          key_prefix=key_prefix)
-        if attributes is None:
+        repositories = wot.read_repo_listing(ui_, truster,
+                                             nickname_prefix=nickname_prefix,
+                                             key_prefix=key_prefix)
+        if repo_name not in repositories:
+            ui_.warn("Could not find repository named \"{0}\".\n".format(repo_name))
             return
 
-        # Expecting [freenet:]?USK@key/WebOfTrust/edition
-        request_uri = attributes['RequestURI']
-        # See similar note in fn-create: trim off LCWoT URI prefix.
-        # TODO: Semantically meaningful key classes.
-        prefix = "freenet:"
-        if request_uri.startswith(prefix):
-            request_uri = request_uri[len(prefix):]
-
-        request_uri = request_uri.split('/', 1)[0]
-
-        request_uri = request_uri + '/' + repo_path
-
+        request_uri = repositories[repo_name]
     else:
         request_uri = opts['uri']
 
diff --git a/infocalypse/wot.py b/infocalypse/wot.py
--- a/infocalypse/wot.py
+++ b/infocalypse/wot.py
@@ -1,6 +1,7 @@
 import fcp
 from config import Config
 import xml.etree.ElementTree as ET
+from defusedxml.ElementTree import fromstring
 
 def update_repo_listing(ui, for_identity):
     # TODO: WoT property containing edition. Used when requesting.
@@ -32,6 +33,37 @@ def update_repo_listing(ui, for_identity
     else:
         ui.status("Updated repository listing:\n{0}\n".format(uri))
 
+def read_repo_listing(ui, truster, nickname_prefix=None, key_prefix=''):
+    """
+    Read a repo listing for a given identity.
+    Return a dictionary of repository URIs keyed by name.
+    """
+    identity = resolve_identity(ui, truster, nickname_prefix=nickname_prefix,
+                                key_prefix=key_prefix)
+    if identity is None:
+        return
+
+    uri = identity['RequestURI']
+    uri = uri.split('/', 1)[0] + '/vcs/0'
+
+    # TODO: Set and read vcs edition property.
+    node = fcp.FCPNode()
+    ui.status("Fetching {0}\n".format(uri))
+    mime_type, repo_xml, msg = node.get(uri)
+
+    ui.status("Parsing.\n")
+    repositories = {}
+    root = fromstring(repo_xml)
+    for repository in root.iterfind('repository'):
+        if repository.get('vcs') == 'Infocalypse':
+            uri = repository.text
+            # Expecting key/reponame.R<num>/edition
+            name = uri.split('/')[1].split('.')[0]
+            ui.status("Found repository \"{0}\" at {1}\n".format(name, uri))
+            repositories[name] = uri
+
+    return repositories
+
 # Support for querying WoT for own identities and identities meeting various
 # criteria.
 # TODO: "cmds" suffix to module name to fit fms, arc, inf?
@@ -150,6 +182,9 @@ def resolve_identity(ui, truster, nickna
 
     # Test for GetIdentitiesByPartialNickname support. currently LCWoT-only.
     # https://github.com/tmarkus/LessCrappyWebOfTrust/blob/master/src/main/java/plugins/WebOfTrust/fcp/GetIdentitiesByPartialNickname.java
+    # TODO: LCWoT allows limiting by context, but how to make sure otherwise?
+    # TODO: Should this manually ensure an identity has a vcs context
+    # otherwise?
     params = {'Message': 'GetIdentitiesByPartialNickname',
               'Truster': truster,
               'PartialNickname': nickname_prefix,
@@ -223,10 +258,12 @@ def read_identity(message, id_num):
     #property_prefix = "Replies.Properties{0}".format(id_num)
 
     # Add contexts for the identity too.
+    # TODO: Unflattening WoT response? Several places check for prefix like
+    # this.
     prefix = "Replies.Contexts{0}.Context".format(id_num)
     for key in message.iterkeys():
         if key.startswith(prefix):
             num = key[len(prefix):]
             result["Context{0}".format(num)] = message[key]
 
-    return result
+    return result
\ No newline at end of file