infocalypse
 
(Steve Dougherty)
2013-08-02: Fix "clone" requiring the target repository exist.

Fix "clone" requiring the target repository exist. When looking up a push URI for a clone operation the edition lookup is now skipped.

diff --git a/infocalypse/__init__.py b/infocalypse/__init__.py
--- a/infocalypse/__init__.py
+++ b/infocalypse/__init__.py
@@ -568,12 +568,24 @@ extensions.wrapfunction(discovery, 'find
 # wrap the commands
 
 
-def freenetpathtouri(ui, path, repo=None, pull=True):
+def freenetpathtouri(ui, path, operation, repo=None):
     """
     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.
+
+
+    :param repo: Mercurial localrepository, used to resolve the truster set
+                 for the repository.
+    :param operation: A string name of the operation the URI will be used to
+                      perform. Used to return the appropriate result with
+                      WoT-integrated URI resolution. Valid operations are:
+                       * "pull" - request URI for existing repository.
+                       * "push" - insert URI for existing repository.
+                       * "clone-push" - insert URI for repository that might
+                                        not exist. (Skips looking up
+                                        published name and edition.)
     """
     # TODO: Is this the only URL encoding that may happen? Why not use a more
     # semantically meaningful function?
@@ -587,11 +599,16 @@ def freenetpathtouri(ui, path, repo=None
     # nick to be "USK", but this is a corner case. Using --wot will still work.
     if not path.startswith("USK"):
         import wot
-        if pull:
+        if operation == "pull":
             truster = get_truster(ui, repo)
             return wot.resolve_pull_uri(ui, path, truster)
+        elif operation == "push":
+            return wot.resolve_push_uri(ui, path)
+        elif operation == "clone-push":
+            return wot.resolve_push_uri(ui, path, resolve_edition=False)
         else:
-            return wot.resolve_push_uri(ui, path)
+            raise util.Abort("Internal error: invalid operation '{0}' when "
+                             "resolving WoT-integrated URI.".format(operation))
     else:
         return path
 
@@ -613,7 +630,7 @@ def freenetpull(orig, *args, **opts):
     # only act differently, if the target is an infocalypse repo.
     if not isfreenetpath(path):
         return orig(*args, **opts)
-    uri = freenetpathtouri(ui, path, repo)
+    uri = freenetpathtouri(ui, path, "pull", repo)
     opts["uri"] = uri
     opts["aggressive"] = True # always search for the latest revision.
     return infocalypse_pull(ui, repo, **opts)
@@ -650,7 +667,7 @@ def freenetpush(orig, *args, **opts):
     # only act differently, if the target is an infocalypse repo.
     if not isfreenetpath(path):
         return orig(*args, **opts)
-    uri = parse_repo_path(freenetpathtouri(ui, path, repo, pull=False))
+    uri = parse_repo_path(freenetpathtouri(ui, path, "push", repo))
     if uri is None:
         return
     # if the uri is the short form (USK@/name/#), generate the key and preprocess the uri.
@@ -706,10 +723,10 @@ def freenetclone(orig, *args, **opts):
     # check whether to create, pull or copy
     pulluri, pushuri = None, None
     if isfreenetpath(source):
-        pulluri = parse_repo_path(freenetpathtouri(ui, source))
+        pulluri = parse_repo_path(freenetpathtouri(ui, source, "pull"))
 
     if isfreenetpath(dest):
-        pushuri = parse_repo_path(freenetpathtouri(ui, dest, pull=False),
+        pushuri = parse_repo_path(freenetpathtouri(ui, dest, "clone-push"),
                                   assume_redundancy=True)
 
     # decide which infocalypse command to use.
diff --git a/infocalypse/wot.py b/infocalypse/wot.py
--- a/infocalypse/wot.py
+++ b/infocalypse/wot.py
@@ -423,11 +423,16 @@ def resolve_pull_uri(ui, path, truster):
         return find_repo(ui, identity, repo_name)
 
 
-def resolve_push_uri(ui, path):
+def resolve_push_uri(ui, path, resolve_edition=True):
     """
     Return a push URI for the given path.
     Raise util.Abort if unable to resolve identity or repository.
 
+    :param resolve_edition: Defaults to True. If False, skips resolving the
+                            repository, uses the edition number 0. and does
+                            not modify the repository name. This is useful
+                            for finding a push URI for a repository that does
+                            not already exist.
     :param ui: For feedback.
     :param path: path describing a repo - nick@key/repo_name,
     where the identity is a local one. (Such that the insert URI is known.)
@@ -437,17 +442,25 @@ def resolve_push_uri(ui, path):
 
     local_id = Local_WoT_ID(wot_id)
 
-    # TODO: find_repo should make it clearer that it returns a request URI,
-    # and return a USK.
-    repo = find_repo(ui, local_id, repo_name)
+    if resolve_edition:
+        # TODO: find_repo should make it clearer that it returns a request URI,
+        # and return a USK.
+        repo = find_repo(ui, local_id, repo_name)
 
-    # Request URI
-    repo_uri = USK(repo)
+        # Request URI
+        repo_uri = USK(repo)
 
-    # Maintains name, edition.
-    repo_uri.key = local_id.insert_uri.key
+        # Maintains name, edition.
+        repo_uri.key = local_id.insert_uri.key
 
-    return str(repo_uri)
+        return str(repo_uri)
+    else:
+        repo_uri = local_id.insert_uri.clone()
+
+        repo_uri.name = repo_name
+        repo_uri.edition = 0
+
+        return str(repo_uri)
 
 
 def execute_setup_wot(ui_, local_id):