infocalypse
 
(Steve Dougherty)
2013-08-09: Add tolerance for remote repository list problems.

Add tolerance for remote repository list problems. - Add USK support for "repo name," which excludes any redundancy. - Use highest edition for a key if more than one is specified. - Ignore repos listed with multiple different keys or complete names.

diff --git a/infocalypse/keys.py b/infocalypse/keys.py
--- a/infocalypse/keys.py
+++ b/infocalypse/keys.py
@@ -18,6 +18,28 @@ class USK:
         elif self.key.startswith('freenet://'):
             self.key = self.key[len('freenet://'):]
 
+    def get_repo_name(self):
+        """
+        Return name with the redundancy level, if any, removed.
+
+        # TODO: tests. Use in detecting duplicate names. (Also
+        # determining repo names from URI.)
+
+        >>> USK('USK@.../name/5').get_repo_name()
+        'name'
+        >>> USK('USK@.../name.R1/5').get_repo_name()
+        'name'
+        >>> USK('USK@.../name.R0/5').get_repo_name()
+        'name'
+        >>> USK('USK@.../name.something/5').get_repo_name()
+        'name.something'
+        >>> USK('USK@.../name.R2/5').get_repo_name()
+        'name.R2'
+        """
+        if self.name.endswith('.R1') or self.name.endswith('.R0'):
+            return self.name[:-3]
+        return self.name
+
     def clone(self):
         return USK(str(self))
 
diff --git a/infocalypse/wot.py b/infocalypse/wot.py
--- a/infocalypse/wot.py
+++ b/infocalypse/wot.py
@@ -387,14 +387,43 @@ def read_repo_listing(ui, identity):
     Config.to_file(cfg)
 
     repositories = {}
+    ambiguous = []
     root = fromstring(repo_xml)
     for repository in root.iterfind('repository'):
         if repository.get('vcs') == VCS_NAME:
-            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
+            uri = USK(repository.text)
+            name = uri.get_repo_name()
+            if name not in repositories:
+                repositories[name] = uri
+            else:
+                existing = repositories[name]
+                if uri.key == existing.key and uri.name == existing.name:
+                    # Different edition of same key and complete name.
+                    # Use the latest edition.
+                    if uri.edition > existing.edition:
+                        repositories[name] = uri
+                else:
+                    # Different key or complete name. Later remove and give
+                    # warning.
+                    ambiguous.append(name)
+
+    for name in ambiguous:
+        # Same repo name but different key or exact name.
+        ui.warn("\"{0}\" refers ambiguously to multiple paths. Ignoring.\n"
+                .format(name))
+        del repositories[name]
+
+    # TODO: Would it make sense to mention those for which multiple editions
+    # are specified? It has no practical impact from this perspective,
+    # and these problems should be pointed out (or prevented) for local repo
+    # lists.
+
+    for name in repositories.iterkeys():
+        ui.status("Found repository \"{0}\".\n".format(name))
+
+    # Convert values from USKs to strings - USKs are not expected elsewhere.
+    for key in repositories.keys():
+        repositories[key] = str(repositories[key])
 
     return repositories