infocalypse
 
(Steve Dougherty)
2013-08-30: Prompt to remove existing name conflicts.

Prompt to remove existing name conflicts. Duplicate names make references to repositories ambiguous.

diff --git a/.bugs/bugs b/.bugs/bugs
--- a/.bugs/bugs
+++ b/.bugs/bugs
@@ -4,7 +4,7 @@ Update USK hgrc paths                   
 Add command to reinsert repo list.                           | owner:, open:False, id:2dcc27c850209062080906368530b4b9202271d0, time:1373407233.84
 pull fails, because config.get_wot_identity requests self.defaults['DEFAULT_TRUSTER'] which is not in defaults. | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:31beb672d404944a4655a546b21c95c7baa91002, time:1371735138.39
 cloning from a freenet:// uri does not work right now.       | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:35584408d800bb895d52dcf86cfba12c5b3237dd, time:1373100583.27
-Perform sanity check for multiple repos of the same name.    | owner:Steve Dougherty <steve@asksteved.com>, open:True, id:4160157833020b1a33d2e6b05dc12c848c891d03, time:1375733375.04
+Perform sanity check for multiple repos of the same name.    | owner:Steve Dougherty <steve@asksteved.com>, open:False, id:4160157833020b1a33d2e6b05dc12c848c891d03, time:1375733375.04
 Preserve non-Infocalypse repositories in the repository list. | owner:Steve Dougherty <steve@asksteved.com>, open:True, id:4d63383a07faa29083fb0b61846ab6cc3d3151be, time:1375733323.42
 set the timezone to UTC on cloning a freenet repo to avoid timezone-based attacks. | owner:Arne Babenhauserheide <bab@draketo.de>, open:True, id:4dfc4cc28a7fa69f040776a7138da78ee89ec819, time:1355764180.36
 mime-type problems                                           | owner:Arne Babenhauserheide <bab@draketo.de>, open:False, id:5916e6e8328e20d8b0276b76b7116dd432730778, time:1353463866.97
diff --git a/.bugs/details/4d63383a07faa29083fb0b61846ab6cc3d3151be.txt b/.bugs/details/4d63383a07faa29083fb0b61846ab6cc3d3151be.txt
new file mode 100644
--- /dev/null
+++ b/.bugs/details/4d63383a07faa29083fb0b61846ab6cc3d3151be.txt
@@ -0,0 +1,27 @@
+# Lines starting with '#' and sections without content
+# are not displayed by a call to 'details'
+#
+[paths]
+# Paths related to this bug.
+# suggested format: REPO_PATH:LINENUMBERS
+
+
+[details]
+# Additional details
+If the repo list cannot be fetched first, barring additional complication
+to persist them, repos inserted with different DVCS would be dropped.
+
+[expected]
+# The expected result
+
+
+[actual]
+# What happened instead
+
+
+[reproduce]
+# Reproduction steps
+
+
+[comments]
+# Comments and updates - leave your name
diff --git a/infocalypse/commands.py b/infocalypse/commands.py
--- a/infocalypse/commands.py
+++ b/infocalypse/commands.py
@@ -13,7 +13,7 @@ from wikicmds import execute_wiki, execu
 from arccmds import execute_arc_create, execute_arc_pull, execute_arc_push, \
     execute_arc_reinsert
 
-from config import read_freesite_cfg, Config
+from config import read_freesite_cfg, Config, normalize
 from validate import is_hex_string, is_fms_id
 
 import os
@@ -49,7 +49,7 @@ def infocalypse_update_repo_list(ui, **o
 
 def infocalypse_create(ui_, repo, local_identity=None, **opts):
     """ Create a new Infocalypse repository in Freenet.
-    :type local_identity: WoT_ID
+    :type local_identity: Local_WoT_ID
     :param local_identity: If specified the new repository is associated with
                            that identity.
     """
@@ -84,6 +84,44 @@ def infocalypse_create(ui_, repo, local_
 
     # This is a WoT repository.
     if local_identity:
+        # Prompt whether to replace in the case of conflicting names.
+        from wot import build_repo_list
+
+        request_usks = build_repo_list(ui_, local_identity)
+        names = map(lambda x: USK(x).get_repo_name(), request_usks)
+        new_name = USK(insert_uri).get_repo_name()
+
+        if new_name in names:
+            replace = ui_.prompt("A repository with the name '{0}' is already"
+                                 " published by {1}. Replace it? [y/N]"
+                                 .format(new_name, local_identity),
+                                 default='n')
+
+            if replace.lower() != 'y':
+                raise util.Abort("A repository with this name already exists.")
+
+            # Remove the existing repository from each configuration section.
+            existing_usk = request_usks[names.index(new_name)]
+
+            existing_dir = None
+            for directory, request_usk in stored_cfg.request_usks.iteritems():
+                if request_usk == existing_usk:
+                    if existing_dir:
+                        raise util.Abort("Configuration lists the same "
+                                         "request USK multiple times.")
+                    existing_dir = directory
+
+            assert existing_dir
+
+            existing_hash = normalize(existing_usk)
+
+            # Config file changes will not be written until a successful insert
+            # below.
+            del stored_cfg.version_table[existing_hash]
+            del stored_cfg.request_usks[existing_dir]
+            del stored_cfg.insert_usks[existing_hash]
+            del stored_cfg.wot_identities[existing_hash]
+
         # Add "vcs" context. No-op if the identity already has it.
         msg_params = {'Message': 'AddContext',
                       'Identity': local_identity.identity_id,
@@ -107,7 +145,6 @@ def infocalypse_create(ui_, repo, local_
     inserted_to = execute_create(ui_, repo, params, stored_cfg)
 
     if inserted_to and local_identity:
-        # TODO: Would it be friendlier to include the nickname as well?
         # creation returns a list of request URIs; use the first.
         stored_cfg.set_wot_identity(inserted_to[0], local_identity)
         Config.to_file(stored_cfg)