Index: subversion/include/svn_path.h
===================================================================
--- subversion/include/svn_path.h	(revision 10031)
+++ subversion/include/svn_path.h	(working copy)
@@ -171,6 +171,12 @@
  */
 const char *svn_path_canonicalize (const char *path, apr_pool_t *pool);
 
+/** remove multiple adjacent slashes (e.g: "//" or "///") in @a url,
+ * (except for the first few /'s following the protocol) and
+ * returns the new URL. use @a pool for temporary allocations.
+ */
+const char *svn_path_url_remove_multiple_slashes (const char *url,
+                                                  apr_pool_t *pool);
 
 /** Return an integer greater than, equal to, or less than 0, according
  * as @a path1 is greater than, equal to, or less than @a path2.
Index: subversion/libsvn_subr/path.c
===================================================================
--- subversion/libsvn_subr/path.c	(revision 10031)
+++ subversion/libsvn_subr/path.c	(working copy)
@@ -133,6 +133,80 @@
   return apr_pstrmemdup (pool, path, len);
 }
 
+const char *svn_path_url_remove_multiple_slashes (const char *url,
+                                                  apr_pool_t *pool)
+{
+  int num_slashes_to_remove = 0;
+  const char * p = url;
+  char * ret;
+  char * ret_p;
+  size_t ret_len;
+
+  /* First skip the "proto:///" part */
+  while (*p && (*p != ':'))
+    p++;
+  
+  if (*p == ':')
+    {
+      p++;
+      while(*p == '/')
+        p++;
+      while (*p)
+        {
+          /* The p++ is not always executed because if there are duplicate
+           * slashes, the pointer will stop after the string of slashes
+           * terminates, so it's not needed there. (And could be harmful if
+           * a '\0' is eminent.) */
+          if ((p[0] == '/') && (p[1] == '/'))
+            {
+              p++;
+              while (*p == '/')
+                {
+                  num_slashes_to_remove++;
+                  p++;
+                }
+            }
+          else
+              p++;
+        }
+    }
+
+  /* If there's nothing to change - return the original string. */
+  if (num_slashes_to_remove == 0)
+    return url;
+
+  ret = apr_palloc(pool, (p - url) - num_slashes_to_remove + 1);
+  ret_p = ret;
+  p = url;
+  
+  while (*p && (*p != ':'))
+    *(ret_p++) = *(p++);
+  
+  if (*p == ':')
+    {
+      *(ret_p++) = *(p++);
+      while(*p == '/')
+        *(ret_p++) = *(p++);
+      
+      while (*p)
+        {
+          *(ret_p++) = *p;
+          if ((p[0] == '/') && (p[1] == '/'))
+            {
+              p++;
+              while (*p == '/')
+                  p++;
+            }
+          else
+              p++;
+        }
+    }
+
+  *(ret_p) = '\0';
+  return ret;
+}
+
+
 
 #ifndef NDEBUG
 static svn_boolean_t
Index: subversion/libsvn_client/copy.c
===================================================================
--- subversion/libsvn_client/copy.c	(revision 10031)
+++ subversion/libsvn_client/copy.c	(working copy)
@@ -1022,6 +1022,15 @@
        _("Cannot copy path '%s' into its own child '%s'"),
        src_path, dst_path);
 
+  /* Remove double slashes in URLs which can cause problems later
+   * on (Issue #1901). */
+
+  if (src_is_url)
+    src_path = svn_path_url_remove_multiple_slashes(src_path, pool);
+
+  if (dst_is_url)
+    dst_path = svn_path_url_remove_multiple_slashes(dst_path, pool);
+
   if (is_move)
     {
       if (src_is_url == dst_is_url)
Index: subversion/tests/libsvn_subr/path-test.c
===================================================================
--- subversion/tests/libsvn_subr/path-test.c	(revision 10031)
+++ subversion/tests/libsvn_subr/path-test.c	(working copy)
@@ -561,6 +561,54 @@
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_url_remove_multiple_slashes (const char **msg,
+                                  svn_boolean_t msg_only,
+                                  apr_pool_t *pool)
+{
+  const char *paths[][2] = {
+    { "file:///var/svn/",               "file:///var/svn/" },
+    { "file:///var/svn//hello",         "file:///var/svn/hello" },
+    { "file:///var/svn/hello//",        "file:///var/svn/hello/" },
+    { "file:///var/svn///hello/",       "file:///var/svn/hello/" },
+    { "file:///var////svn/",            "file:///var/svn/" },
+    { "http://localhost/svn/",          "http://localhost/svn/" },
+    { "http://localhost/svn//",         "http://localhost/svn/" },
+    { "http://localhost/svn//hello/",   "http://localhost/svn/hello/" },
+    { "http://localhost/svn///hello/",  "http://localhost/svn/hello/" },
+    { NULL, NULL }
+  };
+  int i;
+
+  *msg = "test svn_path_url_remove_multiple_slashes";
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  i = 0;
+  while (paths[i][0])
+    {
+      const char *deslashed =
+          svn_path_url_remove_multiple_slashes (paths[i][0], pool);
+
+      if (strcmp (deslashed, paths[i][1]))
+        return svn_error_createf (SVN_ERR_TEST_FAILED, NULL,
+                                  "svn_path_url_remove_multiple_slashes"
+                                  "(\"%s\") returned "
+                                  "\"%s\" expected \"%s\"",
+                                  paths[i][0], deslashed, paths[i][1]);
+
+      if (strcmp (paths[i][0], paths[i][1]) == 0 && deslashed != paths[i][0])
+        return svn_error_createf (SVN_ERR_TEST_FAILED, NULL,
+                                  "svn_path_url_remove_multiple_slashes"
+                                  "(\"%s\") alloc'd",
+                                  paths[i][0]);
+
+      ++i;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 
 /* The test table.  */
 
@@ -576,5 +624,6 @@
     SVN_TEST_PASS (test_basename),
     SVN_TEST_PASS (test_decompose),
     SVN_TEST_PASS (test_canonicalize),
+    SVN_TEST_PASS (test_url_remove_multiple_slashes),
     SVN_TEST_NULL
   };
Index: subversion/tests/clients/cmdline/copy_tests.py
===================================================================
--- subversion/tests/clients/cmdline/copy_tests.py	(revision 10031)
+++ subversion/tests/clients/cmdline/copy_tests.py	(working copy)
@@ -1310,8 +1310,34 @@
     })
   svntest.actions.run_and_verify_status (wc_dir, expected_status)
 
+#----------------------------------------------------------------------
+# Regression test for issue 1901:
+# Check that copying a URL with a double slash after the repos part 
+# does not crash the client.
 
+def copy_with_double_slash_1901(sbox):
+  "copy a URL with double slash after the repos part"
 
+  sbox.build()
+  wc_dir = sbox.wc_dir
+
+  # Note the double slash after the repo_url
+  iota_repos_path = svntest.main.current_repo_url + '//iota'
+  new_iota_repos_path = svntest.main.current_repo_url + '//A/C/new.iota'
+
+  # Let's do the copy.
+  svntest.actions.run_and_verify_svn(None, None, [], 'cp', '-m', '', 
+                                     iota_repos_path, new_iota_repos_path)
+  # If the bug exists we should get a crash here, and the test will exit
+  # with an exception.
+
+  # Now just to make sure the file was copied correctly.
+  new_good_iota_repos_path = svntest.main.current_repo_url + '/A/C/new.iota'
+  svntest.actions.run_and_verify_svn(None, ["This is the file 'iota'."], None,
+                                     'cat', new_good_iota_repos_path)
+
+
+
 ########################################################################
 # Run the tests
 
@@ -1340,6 +1366,7 @@
               revision_kinds_local_source,
               copy_over_missing_file,
               repos_to_wc_1634,
+              copy_with_double_slash_1901,
              ]
 
 if __name__ == '__main__':


