Repository: datalad/datalad

Issue:
clone: over ssh - (default) target directory contains `:` causing git to error out
could probably add to confusion in #5829 but that one has other issues preventing it even to get there,  but would be seen there too eventually

`maint`:

```
$> datalad clone smaug:datalad                          
[ERROR  ] Failed to clone from any candidate source URL. Encountered errors per each url were:            
| - smaug:datalad
  CommandError: 'git -c diff.ignoreSubmodules=none clone --progress smaug:datalad /tmp/smaug:datalad' failed with exitcode 128 [err: 'Cloning into '/tmp/smaug:datalad'...
done.
fatal: update_ref failed for ref 'HEAD': cannot update ref 'refs/heads/master': trying to write ref 'refs/heads/master' with nonexistent object 010db68540fe0940a3e857f1ec5640c2978d5eaa'] [install(/tmp/smaug:datalad)] 
install(error): /tmp/smaug:datalad (dataset) [Failed to clone from any candidate source URL. Encountered errors per each url were:
- smaug:datalad
  CommandError: 'git -c diff.ignoreSubmodules=none clone --progress smaug:datalad /tmp/smaug:datalad' failed with exitcode 128 [err: 'Cloning into '/tmp/smaug:datalad'...
done.
fatal: update_ref failed for ref 'HEAD': cannot update ref 'refs/heads/master': trying to write ref 'refs/heads/master' with nonexistent object 010db68540fe0940a3e857f1ec5640c2978d5eaa']]
```

master:

```
lena:/tmp
$> datalad clone smaug:datalad
[ERROR  ] Failed to clone from any candidate source URL. Encountered errors per each url were:            
| - smaug:datalad
   [install(/tmp/smaug:datalad)] 
install(error): /tmp/smaug:datalad (dataset) [Failed to clone from any candidate source URL. Encountered errors per each url were:
- smaug:datalad
  ]
```

more informative `maint` dump of errors is really confusing but does give a hint: `/tmp/smaug:datalad`  as a target dir, which if you try

```
$> git clone smaug:datalad /tmp/smaug:datalad
Cloning into '/tmp/smaug:datalad'...
done.
fatal: update_ref failed for ref 'HEAD': cannot update ref 'refs/heads/master': trying to write ref 'refs/heads/master' with nonexistent object 010db68540fe0940a3e857f1ec5640c2978d5eaa
(dev3) 1 26922 ->128 [1].....................................:Mon 09 Aug 2021 02:43:33 PM EDT:.
lena:/tmp
$> fatal: the remote end hung up unexpectedly
```
you get that error msg.

I think here we should follow `git` behavior and do not use any portion of the host name for the target directory... will try to work out a fix now

Comments:

Patch:
diff --git a/datalad/core/distributed/clone.py b/datalad/core/distributed/clone.py
index 12482f09f..62888b1f6 100644
--- a/datalad/core/distributed/clone.py
+++ b/datalad/core/distributed/clone.py
@@ -48,13 +48,14 @@ from datalad.support.constraints import (
 from datalad.support.exceptions import DownloadError
 from datalad.support.param import Parameter
 from datalad.support.network import (
-    get_local_file_url,
-    download_url,
-    is_url,
-    URL,
-    RI,
     DataLadRI,
     PathRI,
+    RI,
+    SSHRI,
+    URL,
+    download_url,
+    get_local_file_url,
+    is_url,
 )
 from datalad.dochelpers import (
     exc_str,
@@ -1206,7 +1207,7 @@ def _get_installationpath_from_url(url):
     from a URL, analog to what `git clone` does.
     """
     ri = RI(url)
-    if isinstance(ri, (URL, DataLadRI)):  # decode only if URL
+    if isinstance(ri, (URL, DataLadRI, SSHRI)):  # decode only if URL
         path = ri.path.rstrip('/')
         path = urlunquote(path) if path else ri.hostname
         if '/' in path:


Test patch:
diff --git a/datalad/core/distributed/tests/test_clone.py b/datalad/core/distributed/tests/test_clone.py
index a087c0a6d..08753a707 100644
--- a/datalad/core/distributed/tests/test_clone.py
+++ b/datalad/core/distributed/tests/test_clone.py
@@ -532,24 +532,41 @@ def test_clone_autoenable_msg_handles_sameas(repo, clone_path):
 
 
 def test_installationpath_from_url():
-    cases = (
+    # cases for all OSes
+    cases = [
         'http://example.com/lastbit',
         'http://example.com/lastbit.git',
         'http://lastbit:8000',
-    ) + (
+        # SSH
+        'hostname:lastbit',
+        'hostname:lastbit/',
+        'hostname:subd/lastbit',
+        'hostname:/full/path/lastbit',
+        'hostname:lastbit/.git',
+        'hostname:lastbit/.git/',
+        'hostname:/full/path/lastbit/.git',
+        'full.hostname.com:lastbit/.git',
+        'user@full.hostname.com:lastbit/.git',
+        'ssh://user:passw@full.hostname.com/full/path/lastbit',
+        'ssh://user:passw@full.hostname.com/full/path/lastbit/',
+        'ssh://user:passw@full.hostname.com/full/path/lastbit/.git',
+    ]
+    # OS specific cases
+    cases += [
         'C:\\Users\\mih\\AppData\\Local\\Temp\\lastbit',
         'C:\\Users\\mih\\AppData\\Local\\Temp\\lastbit\\',
         'Temp\\lastbit',
         'Temp\\lastbit\\',
         'lastbit.git',
         'lastbit.git\\',
-    ) if on_windows else (
+    ] if on_windows else [
         'lastbit',
         'lastbit/',
         '/lastbit',
         'lastbit.git',
         'lastbit.git/',
-    )
+    ]
+
     for p in cases:
         eq_(_get_installationpath_from_url(p), 'lastbit')
     # we need to deal with quoted urls