Repository: iterative/dvc

Issue:
push: exception when remote is at the root of a GCS bucket
# Bug Report

## Description

When the remote is at the root of a GCS bucket, `dvc push` raises an exception. 

Thanks @pmrowla for diagnosing this on Discord.

### Reproduce

Pulling from the "Get Started" example, a complete example would be something like:

```bash
git init
dvc init
dvc remote add -d storage gs://mybucket/   # or without the trailing slash
dvc get https://github.com/iterative/dataset-registry get-started/data.xml -o data/data.xml
dvc add data/data.xml
git add data/data.xml.dvc data/.gitignore
git commit -m "Add raw data"
dvc push
```

In my case,
```
% dvc push -v     
2021-03-18 20:35:05,623 DEBUG: Check for update is enabled.
2021-03-18 20:35:06,219 DEBUG: Preparing to upload data to 'gs://mybucket/'
2021-03-18 20:35:06,219 DEBUG: Preparing to collect status from gs://mybucket/
2021-03-18 20:35:06,220 DEBUG: Collecting information from local cache...
2021-03-18 20:35:06,221 DEBUG: Collecting information from remote cache...                                                                               
2021-03-18 20:35:06,221 DEBUG: Querying 1 hashes via object_exists
2021-03-18 20:35:07,057 DEBUG: Indexing new .dir '997a185cf1ec1f6d2a653c9b54a61a63.dir' with '23' nested files                                           
2021-03-18 20:35:07,058 DEBUG: Matched '0' indexed hashes
2021-03-18 20:35:07,412 DEBUG: Estimated remote size: 4096 files                                                                                         
2021-03-18 20:35:07,413 DEBUG: Querying '20' hashes via traverse                                                                                         
2021-03-18 20:35:07,549 ERROR: unexpected error - not enough values to unpack (expected 2, got 1)                                                        
------------------------------------------------------------
Traceback (most recent call last):
  File "dvc/main.py", line 50, in main
  File "dvc/command/data_sync.py", line 66, in run
  File "dvc/repo/__init__.py", line 49, in wrapper
  File "dvc/repo/push.py", line 41, in push
  File "dvc/data_cloud.py", line 70, in push
  File "dvc/remote/base.py", line 56, in wrapper
  File "dvc/remote/base.py", line 471, in push
  File "dvc/remote/base.py", line 328, in _process
  File "dvc/remote/base.py", line 176, in _status
  File "dvc/remote/base.py", line 132, in hashes_exist
  File "dvc/objects/db/base.py", line 410, in hashes_exist
  File "dvc/objects/db/base.py", line 269, in list_hashes_traverse
  File "concurrent/futures/_base.py", line 598, in result_iterator
  File "concurrent/futures/_base.py", line 435, in result
  File "concurrent/futures/_base.py", line 384, in __get_result
  File "concurrent/futures/thread.py", line 57, in run
  File "dvc/objects/db/base.py", line 261, in list_with_update
  File "dvc/objects/db/base.py", line 150, in list_hashes
  File "dvc/objects/db/base.py", line 130, in _list_paths
  File "dvc/fs/fsspec_wrapper.py", line 97, in walk_files
  File "dvc/fs/fsspec_wrapper.py", line 83, in ls
  File "dvc/fs/fsspec_wrapper.py", line 50, in isdir
  File "dvc/fs/fsspec_wrapper.py", line 106, in info
  File "dvc/fs/fsspec_wrapper.py", line 22, in _strip_bucket
ValueError: not enough values to unpack (expected 2, got 1)
```

Where the config looks like:
```
[core]
    analytics = false
    remote = storage
['remote "storage"']
    url = gs://mybucket/
```

Moving each directory (`02`, `04`, `3a` ...) under `gs://mybucket/dvc` and then editing the config to match avoided the error.

### Expected

```
1 file pushed
```

### Environment information

**Output of `dvc doctor`:**

```console
DVC version: 2.0.6 (osxpkg)
---------------------------------
Platform: Python 3.7.10 on Darwin-20.3.0-x86_64-i386-64bit
Supports: All remotes
Cache types: reflink, hardlink, symlink
Cache directory: apfs on /dev/disk1s5s1
Caches: local
Remotes: gs
Workspace directory: apfs on /dev/disk1s5s1
Repo: dvc, git
```

discord context: https://discord.com/channels/485586884165107732/485596304961962003/822266284896550943


Discussion:

Resolving patch:
diff --git a/dvc/fs/fsspec_wrapper.py b/dvc/fs/fsspec_wrapper.py
--- a/dvc/fs/fsspec_wrapper.py
+++ b/dvc/fs/fsspec_wrapper.py
@@ -19,8 +19,14 @@ def _with_bucket(self, path):
         return path
 
     def _strip_bucket(self, entry):
-        _, entry = entry.split("/", 1)
-        return entry
+        try:
+            bucket, path = entry.split("/", 1)
+        except ValueError:
+            # If there is no path attached, only returns
+            # the bucket (top-level).
+            bucket, path = entry, None
+
+        return path or bucket
 
     def _strip_buckets(self, entries, detail, prefix=None):
         for entry in entries:


Test patch:
diff --git a/tests/func/test_fs.py b/tests/func/test_fs.py
--- a/tests/func/test_fs.py
+++ b/tests/func/test_fs.py
@@ -349,3 +349,23 @@ def test_fs_ls_with_etag(dvc, cloud):
             fs.info(path_info.replace(path=details["name"]))["etag"]
             == details["etag"]
         )
+
+
+@pytest.mark.parametrize(
+    "cloud", [pytest.lazy_fixture("azure"), pytest.lazy_fixture("gs")]
+)
+def test_fs_fsspec_path_management(dvc, cloud):
+    cloud.gen({"foo": "foo", "data": {"bar": "bar", "baz": {"foo": "foo"}}})
+    fs = get_cloud_fs(dvc, **cloud.config)
+
+    root = cloud.parents[len(cloud.parents) - 1]
+    bucket_details = fs.info(root)
+
+    # special conditions: name always points to the bucket name
+    assert bucket_details["name"] == root.bucket
+    assert bucket_details["type"] == "directory"
+
+    data = cloud / "data"
+    data_details = fs.info(data)
+    assert data_details["name"].rstrip("/") == data.path
+    assert data_details["type"] == "directory"