{
    "file_diffs": [
        {
            "old_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Helper for RIA stores\n\n\"\"\"\n\n\nclass UnknownLayoutVersion(Exception):\n    pass\n\n\n# TODO: Make versions a tuple of (label, description)?\n# Object tree versions we introduced so far. This is about the layout within a\n# dataset in a RIA store\nknown_versions_objt = ['1', '2']\n# Dataset tree versions we introduced so far. This is about the layout of\n# datasets in a RIA store\nknown_versions_dst = ['1']\n\n\n# TODO: This is wrong and should consider both versions (store+dataset)\ndef get_layout_locations(version, base_path, dsid):\n    \"\"\"Return dataset-related path in a RIA store\n\n    Parameters\n    ----------\n    version : int\n      Layout version of the store.\n    base_path : Path\n      Base path of the store.\n    dsid : str\n      Dataset ID\n\n    Returns\n    -------\n    Path, Path, Path\n      The location of the bare dataset repository in the store,\n      the directory with archive files for the dataset, and the\n      annex object directory are return in that order.\n    \"\"\"\n    if version == 1:\n        dsgit_dir = base_path / dsid[:3] / dsid[3:]\n        archive_dir = dsgit_dir / 'archives'\n        dsobj_dir = dsgit_dir / 'annex' / 'objects'\n        return dsgit_dir, archive_dir, dsobj_dir\n    else:\n        raise ValueError(\"Unknown layout version: {}. Supported: {}\"\n                         \"\".format(version, known_versions_dst))\n\n\ndef verify_ria_url(url, cfg):\n    \"\"\"Verify and decode ria url\n\n    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to\n    decode potential host and base path for the store from it. Additionally\n    raises if `url` is considered invalid.\n\n    ria+ssh://somehost:/path/to/store\n    ria+file:///path/to/store\n\n    Parameters\n    ----------\n    url : str\n      URL to verify an decode.\n    cfg : dict-like\n      Configuration settings for rewrite_url()\n\n    Raises\n    ------\n    ValueError\n\n    Returns\n    -------\n    tuple\n      (host, base-path, rewritten url)\n    \"\"\"\n    from datalad.config import rewrite_url\n    from datalad.support.network import URL\n\n    if not url:\n        raise ValueError(\"Got no URL\")\n\n    url = rewrite_url(cfg, url)\n    url_ri = URL(url)\n    if not url_ri.scheme.startswith('ria+'):\n        raise ValueError(\"Missing ria+ prefix in final URL: %s\" % url)\n    if url_ri.fragment:\n        raise ValueError(\n            \"Unexpected fragment in RIA-store URL: %s\" % url_ri.fragment)\n    protocol = url_ri.scheme[4:]\n    if protocol not in ['ssh', 'file', 'http', 'https']:\n        raise ValueError(\"Unsupported protocol: %s. \"\n                         \"Supported: ssh, file, http(s)\" %\n                         protocol)\n\n    return url_ri.hostname if protocol != 'file' else None, \\\n        url_ri.path if url_ri.path else '/', \\\n        url\n\n\ndef _ensure_version(io, base_path, version):\n    \"\"\"Check a store or dataset version and make sure it is declared\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n    base_path: Path\n      root path of a store or dataset\n    version: str\n      target layout version of the store (dataset tree)\n    \"\"\"\n    version_file = base_path / 'ria-layout-version'\n    if io.exists(version_file):\n        existing_version = io.read_file(version_file).split('|')[0].strip()\n        if existing_version != version.split('|')[0]:\n            # We have an already existing location with a conflicting version on\n            # record.\n            # Note, that a config flag after pipe symbol is fine.\n            raise ValueError(\"Conflicting version found at target: {}\"\n                             .format(existing_version))\n        else:\n            # already exists, recorded version fits - nothing to do\n            return\n    # Note, that the following does create the base-path dir as well, since\n    # mkdir has parents=True:\n    io.mkdir(base_path)\n    io.write_file(version_file, version)\n\n\ndef create_store(io, base_path, version):\n    \"\"\"Helper to create a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to dedicated command or option for\n    create-sibling-ria.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    version: str\n      layout version of the store (dataset tree)\n    \"\"\"\n\n    # At store level the only version we know as of now is 1.\n    if version not in known_versions_dst:\n        raise UnknownLayoutVersion(\"RIA store layout version unknown: {}.\"\n                                   \"Supported versions: {}\"\n                                   .format(version, known_versions_dst))\n    _ensure_version(io, base_path, version)\n    error_logs = base_path / 'error_logs'\n    io.mkdir(error_logs)\n\n\ndef create_ds_in_store(io, base_path, dsid, obj_version, store_version):\n    \"\"\"Helper to create a dataset in a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to a version option for create-sibling-ria\n    in conjunction with a store creation command/option.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    dsid: str\n      dataset id\n    store_version: str\n      layout version of the store (dataset tree)\n    obj_version: str\n      layout version of the dataset itself (object tree)\n    \"\"\"\n\n    # TODO: Note for RF'ing, that this is about setting up a valid target\n    #       for the special remote not a replacement for create-sibling-ria.\n    #       There's currently no git (bare) repo created.\n\n    try:\n        # TODO: This is currently store layout version!\n        #       Too entangled by current get_layout_locations.\n        dsgit_dir, archive_dir, dsobj_dir = \\\n            get_layout_locations(int(store_version), base_path, dsid)\n    except ValueError as e:\n        raise UnknownLayoutVersion(str(e))\n\n    if obj_version not in known_versions_objt:\n        raise UnknownLayoutVersion(\"Dataset layout version unknown: {}. \"\n                                   \"Supported: {}\"\n                                   .format(obj_version, known_versions_objt))\n\n    _ensure_version(io, dsgit_dir, obj_version)\n\n    io.mkdir(archive_dir)\n    io.mkdir(dsobj_dir)\n",
            "new_file_content": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Helper for RIA stores\n\n\"\"\"\n\n\nclass UnknownLayoutVersion(Exception):\n    pass\n\n\n# TODO: Make versions a tuple of (label, description)?\n# Object tree versions we introduced so far. This is about the layout within a\n# dataset in a RIA store\nknown_versions_objt = ['1', '2']\n# Dataset tree versions we introduced so far. This is about the layout of\n# datasets in a RIA store\nknown_versions_dst = ['1']\n\n\n# TODO: This is wrong and should consider both versions (store+dataset)\ndef get_layout_locations(version, base_path, dsid):\n    \"\"\"Return dataset-related path in a RIA store\n\n    Parameters\n    ----------\n    version : int\n      Layout version of the store.\n    base_path : Path\n      Base path of the store.\n    dsid : str\n      Dataset ID\n\n    Returns\n    -------\n    Path, Path, Path\n      The location of the bare dataset repository in the store,\n      the directory with archive files for the dataset, and the\n      annex object directory are return in that order.\n    \"\"\"\n    if version == 1:\n        dsgit_dir = base_path / dsid[:3] / dsid[3:]\n        archive_dir = dsgit_dir / 'archives'\n        dsobj_dir = dsgit_dir / 'annex' / 'objects'\n        return dsgit_dir, archive_dir, dsobj_dir\n    else:\n        raise ValueError(\"Unknown layout version: {}. Supported: {}\"\n                         \"\".format(version, known_versions_dst))\n\n\ndef verify_ria_url(url, cfg):\n    \"\"\"Verify and decode ria url\n\n    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to\n    decode potential host and base path for the store from it. Additionally\n    raises if `url` is considered invalid.\n\n    ria+ssh://somehost:/path/to/store\n    ria+file:///path/to/store\n\n    Parameters\n    ----------\n    url : str\n      URL to verify an decode.\n    cfg : dict-like\n      Configuration settings for rewrite_url()\n\n    Raises\n    ------\n    ValueError\n\n    Returns\n    -------\n    tuple\n      (host, base-path, rewritten url)\n      `host` is not just a hostname, but may also contain username, password,\n      and port, if specified in a given URL.\n    \"\"\"\n    from datalad.config import rewrite_url\n    from datalad.support.network import URL\n\n    if not url:\n        raise ValueError(\"Got no URL\")\n\n    url = rewrite_url(cfg, url)\n    url_ri = URL(url)\n    if not url_ri.scheme.startswith('ria+'):\n        raise ValueError(\"Missing ria+ prefix in final URL: %s\" % url)\n    if url_ri.fragment:\n        raise ValueError(\n            \"Unexpected fragment in RIA-store URL: %s\" % url_ri.fragment)\n    protocol = url_ri.scheme[4:]\n    if protocol not in ['ssh', 'file', 'http', 'https']:\n        raise ValueError(\"Unsupported protocol: %s. \"\n                         \"Supported: ssh, file, http(s)\" %\n                         protocol)\n\n    host = '{user}{pdelim}{passwd}{udelim}{hostname}{portdelim}{port}'.format(\n        user=url_ri.username or '',\n        pdelim=':' if url_ri.password else '',\n        passwd=url_ri.password or '',\n        udelim='@' if url_ri.username else '',\n        hostname=url_ri.hostname or '',\n        portdelim=':' if url_ri.port else '',\n        port=url_ri.port or '',\n    )\n    return host if protocol != 'file' else None, \\\n        url_ri.path if url_ri.path else '/', \\\n        url\n\n\ndef _ensure_version(io, base_path, version):\n    \"\"\"Check a store or dataset version and make sure it is declared\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n    base_path: Path\n      root path of a store or dataset\n    version: str\n      target layout version of the store (dataset tree)\n    \"\"\"\n    version_file = base_path / 'ria-layout-version'\n    if io.exists(version_file):\n        existing_version = io.read_file(version_file).split('|')[0].strip()\n        if existing_version != version.split('|')[0]:\n            # We have an already existing location with a conflicting version on\n            # record.\n            # Note, that a config flag after pipe symbol is fine.\n            raise ValueError(\"Conflicting version found at target: {}\"\n                             .format(existing_version))\n        else:\n            # already exists, recorded version fits - nothing to do\n            return\n    # Note, that the following does create the base-path dir as well, since\n    # mkdir has parents=True:\n    io.mkdir(base_path)\n    io.write_file(version_file, version)\n\n\ndef create_store(io, base_path, version):\n    \"\"\"Helper to create a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to dedicated command or option for\n    create-sibling-ria.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    version: str\n      layout version of the store (dataset tree)\n    \"\"\"\n\n    # At store level the only version we know as of now is 1.\n    if version not in known_versions_dst:\n        raise UnknownLayoutVersion(\"RIA store layout version unknown: {}.\"\n                                   \"Supported versions: {}\"\n                                   .format(version, known_versions_dst))\n    _ensure_version(io, base_path, version)\n    error_logs = base_path / 'error_logs'\n    io.mkdir(error_logs)\n\n\ndef create_ds_in_store(io, base_path, dsid, obj_version, store_version):\n    \"\"\"Helper to create a dataset in a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to a version option for create-sibling-ria\n    in conjunction with a store creation command/option.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    dsid: str\n      dataset id\n    store_version: str\n      layout version of the store (dataset tree)\n    obj_version: str\n      layout version of the dataset itself (object tree)\n    \"\"\"\n\n    # TODO: Note for RF'ing, that this is about setting up a valid target\n    #       for the special remote not a replacement for create-sibling-ria.\n    #       There's currently no git (bare) repo created.\n\n    try:\n        # TODO: This is currently store layout version!\n        #       Too entangled by current get_layout_locations.\n        dsgit_dir, archive_dir, dsobj_dir = \\\n            get_layout_locations(int(store_version), base_path, dsid)\n    except ValueError as e:\n        raise UnknownLayoutVersion(str(e))\n\n    if obj_version not in known_versions_objt:\n        raise UnknownLayoutVersion(\"Dataset layout version unknown: {}. \"\n                                   \"Supported: {}\"\n                                   .format(obj_version, known_versions_objt))\n\n    _ensure_version(io, dsgit_dir, obj_version)\n\n    io.mkdir(archive_dir)\n    io.mkdir(dsobj_dir)\n",
            "header": {
                "file": {
                    "path": "datalad/customremotes/ria_utils.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "3795d6952",
                "new_commit_hash": "0b629bdc0",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/customremotes/ria_utils.py"
            },
            "plus_file": {
                "path": "b/datalad/customremotes/ria_utils.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 79,
                            "length": 6
                        },
                        "new_range": {
                            "start": 79,
                            "length": 8
                        },
                        "section": "def verify_ria_url(url, cfg):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    -------",
                                "type": "context"
                            },
                            {
                                "content": "    tuple",
                                "type": "context"
                            },
                            {
                                "content": "      (host, base-path, rewritten url)",
                                "type": "context"
                            },
                            {
                                "content": "      `host` is not just a hostname, but may also contain username, password,",
                                "type": "added"
                            },
                            {
                                "content": "      and port, if specified in a given URL.",
                                "type": "added"
                            },
                            {
                                "content": "    \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "    from datalad.config import rewrite_url",
                                "type": "context"
                            },
                            {
                                "content": "    from datalad.support.network import URL",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/customremotes/ria_utils.py",
                            "type": "function",
                            "name": "verify_ria_url",
                            "content": "def verify_ria_url(url, cfg):\n    \"\"\"Verify and decode ria url\n\n    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to\n    decode potential host and base path for the store from it. Additionally\n    raises if `url` is considered invalid.\n\n    ria+ssh://somehost:/path/to/store\n    ria+file:///path/to/store\n\n    Parameters\n    ----------\n    url : str\n      URL to verify an decode.\n    cfg : dict-like\n      Configuration settings for rewrite_url()\n\n    Raises\n    ------\n    ValueError\n\n    Returns\n    -------\n    tuple\n      (host, base-path, rewritten url)\n      `host` is not just a hostname, but may also contain username, password,\n      and port, if specified in a given URL.\n    \"\"\"\n    from datalad.config import rewrite_url\n    from datalad.support.network import URL\n\n    if not url:\n        raise ValueError(\"Got no URL\")\n\n    url = rewrite_url(cfg, url)\n    url_ri = URL(url)\n    if not url_ri.scheme.startswith('ria+'):\n        raise ValueError(\"Missing ria+ prefix in final URL: %s\" % url)\n    if url_ri.fragment:\n        raise ValueError(\n            \"Unexpected fragment in RIA-store URL: %s\" % url_ri.fragment)\n    protocol = url_ri.scheme[4:]\n    if protocol not in ['ssh', 'file', 'http', 'https']:\n        raise ValueError(\"Unsupported protocol: %s. \"\n                         \"Supported: ssh, file, http(s)\" %\n                         protocol)\n\n    host = '{user}{pdelim}{passwd}{udelim}{hostname}{portdelim}{port}'.format(\n        user=url_ri.username or '',\n        pdelim=':' if url_ri.password else '',\n        passwd=url_ri.password or '',\n        udelim='@' if url_ri.username else '',\n        hostname=url_ri.hostname or '',\n        portdelim=':' if url_ri.port else '',\n        port=url_ri.port or '',\n    )\n    return host if protocol != 'file' else None, \\\n        url_ri.path if url_ri.path else '/', \\\n        url",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 57,
                            "end_lineno": 115,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 99,
                            "length": 7
                        },
                        "new_range": {
                            "start": 101,
                            "length": 16
                        },
                        "section": "def verify_ria_url(url, cfg):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "                         \"Supported: ssh, file, http(s)\" %",
                                "type": "context"
                            },
                            {
                                "content": "                         protocol)",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "    return url_ri.hostname if protocol != 'file' else None, \\",
                                "type": "deleted"
                            },
                            {
                                "content": "    host = '{user}{pdelim}{passwd}{udelim}{hostname}{portdelim}{port}'.format(",
                                "type": "added"
                            },
                            {
                                "content": "        user=url_ri.username or '',",
                                "type": "added"
                            },
                            {
                                "content": "        pdelim=':' if url_ri.password else '',",
                                "type": "added"
                            },
                            {
                                "content": "        passwd=url_ri.password or '',",
                                "type": "added"
                            },
                            {
                                "content": "        udelim='@' if url_ri.username else '',",
                                "type": "added"
                            },
                            {
                                "content": "        hostname=url_ri.hostname or '',",
                                "type": "added"
                            },
                            {
                                "content": "        portdelim=':' if url_ri.port else '',",
                                "type": "added"
                            },
                            {
                                "content": "        port=url_ri.port or '',",
                                "type": "added"
                            },
                            {
                                "content": "    )",
                                "type": "added"
                            },
                            {
                                "content": "    return host if protocol != 'file' else None, \\",
                                "type": "added"
                            },
                            {
                                "content": "        url_ri.path if url_ri.path else '/', \\",
                                "type": "context"
                            },
                            {
                                "content": "        url",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/customremotes/ria_utils.py",
                            "type": "function",
                            "name": "verify_ria_url",
                            "content": "def verify_ria_url(url, cfg):\n    \"\"\"Verify and decode ria url\n\n    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to\n    decode potential host and base path for the store from it. Additionally\n    raises if `url` is considered invalid.\n\n    ria+ssh://somehost:/path/to/store\n    ria+file:///path/to/store\n\n    Parameters\n    ----------\n    url : str\n      URL to verify an decode.\n    cfg : dict-like\n      Configuration settings for rewrite_url()\n\n    Raises\n    ------\n    ValueError\n\n    Returns\n    -------\n    tuple\n      (host, base-path, rewritten url)\n    \"\"\"\n    from datalad.config import rewrite_url\n    from datalad.support.network import URL\n\n    if not url:\n        raise ValueError(\"Got no URL\")\n\n    url = rewrite_url(cfg, url)\n    url_ri = URL(url)\n    if not url_ri.scheme.startswith('ria+'):\n        raise ValueError(\"Missing ria+ prefix in final URL: %s\" % url)\n    if url_ri.fragment:\n        raise ValueError(\n            \"Unexpected fragment in RIA-store URL: %s\" % url_ri.fragment)\n    protocol = url_ri.scheme[4:]\n    if protocol not in ['ssh', 'file', 'http', 'https']:\n        raise ValueError(\"Unsupported protocol: %s. \"\n                         \"Supported: ssh, file, http(s)\" %\n                         protocol)\n\n    return url_ri.hostname if protocol != 'file' else None, \\\n        url_ri.path if url_ri.path else '/', \\\n        url",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 57,
                            "end_lineno": 104,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from datalad.distributed.ora_remote import (\n    LocalIO,\n    SSHRemoteIO\n)\nfrom datalad.customremotes.ria_utils import (\n    create_store,\n    create_ds_in_store,\n    verify_ria_url,\n    UnknownLayoutVersion\n)\nfrom datalad.utils import (\n    on_windows,\n    Path,\n)\nfrom datalad.tests.utils import (\n    assert_equal,\n    assert_raises,\n    assert_true,\n    rmtree,\n    skip_ssh,\n    with_tempfile,\n    SkipTest,\n)\n\n\n@with_tempfile\ndef _test_setup_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    version_file = store / 'ria-layout-version'\n    error_logs = store / 'error_logs'\n\n    # invalid version raises:\n    assert_raises(UnknownLayoutVersion, create_store, io, store, '2')\n\n    # non-existing path should work:\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # empty target directory should work as well:\n    rmtree(str(store))\n    store.mkdir(exist_ok=False)\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # re-execution also fine:\n    create_store(io, store, '1')\n\n    # but version conflict with existing target isn't:\n    version_file.write_text(\"2|unknownflags\\n\")\n    assert_raises(ValueError, create_store, io, store, '1')\n    # TODO: check output reporting conflicting version \"2\"\n\n\ndef test_setup_store():\n\n    yield _test_setup_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_store), SSHRemoteIO, ['datalad-test']\n\n\n@with_tempfile\ndef _test_setup_ds_in_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    # ATM create_ds_in_store doesn't care what kind of ID is provided\n    dsid = \"abc123456\"\n\n    ds_path = store / dsid[:3] / dsid[3:]  # store layout version 1\n    version_file = ds_path / 'ria-layout-version'\n    archives = ds_path / 'archives'\n    objects = ds_path / 'annex' / 'objects'\n    git_config = ds_path / 'config'\n\n    # invalid store version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, '1', 'abc')\n\n    # invalid obj version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, 'abc', '1')\n\n    # version 1\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '1', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"1\\n\")\n\n    # conflicting version exists at target:\n    assert_raises(ValueError, create_ds_in_store, io, store, dsid, '2', '1')\n\n    # version 2\n    # Note: The only difference between version 1 and 2 are supposed to be the\n    #       key paths (dirhashlower vs mixed), which has nothing to do with\n    #       setup routine.\n    rmtree(str(store))\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '2', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"2\\n\")\n\n\ndef test_setup_ds_in_store():\n\n    yield _test_setup_ds_in_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_ds_in_store), SSHRemoteIO, ['datalad-test']\n\n\ndef test_verify_ria_url():\n    # unsupported protocol\n    assert_raises(ValueError, verify_ria_url, 'ria+ftp://localhost/tmp/this', {})\n    # bunch of caes that should work\n    cases = {\n        'ria+file:///tmp/this': (None, '/tmp/this'),\n        # no normalization\n        'ria+file:///tmp/this/': (None, '/tmp/this/'),\n        # with hosts\n        'ria+ssh://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+http://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),\n        # with username\n        'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),\n    }\n    for i, o in cases.items():\n        # we are not testing the URL rewriting here\n        assert_equal(o, verify_ria_url(i, {})[:2])\n",
            "new_file_content": "from datalad.distributed.ora_remote import (\n    LocalIO,\n    SSHRemoteIO\n)\nfrom datalad.customremotes.ria_utils import (\n    create_store,\n    create_ds_in_store,\n    verify_ria_url,\n    UnknownLayoutVersion\n)\nfrom datalad.utils import (\n    on_windows,\n    Path,\n)\nfrom datalad.tests.utils import (\n    assert_equal,\n    assert_raises,\n    assert_true,\n    rmtree,\n    skip_ssh,\n    with_tempfile,\n    SkipTest,\n)\n\n\n@with_tempfile\ndef _test_setup_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    version_file = store / 'ria-layout-version'\n    error_logs = store / 'error_logs'\n\n    # invalid version raises:\n    assert_raises(UnknownLayoutVersion, create_store, io, store, '2')\n\n    # non-existing path should work:\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # empty target directory should work as well:\n    rmtree(str(store))\n    store.mkdir(exist_ok=False)\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # re-execution also fine:\n    create_store(io, store, '1')\n\n    # but version conflict with existing target isn't:\n    version_file.write_text(\"2|unknownflags\\n\")\n    assert_raises(ValueError, create_store, io, store, '1')\n    # TODO: check output reporting conflicting version \"2\"\n\n\ndef test_setup_store():\n\n    yield _test_setup_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_store), SSHRemoteIO, ['datalad-test']\n\n\n@with_tempfile\ndef _test_setup_ds_in_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    # ATM create_ds_in_store doesn't care what kind of ID is provided\n    dsid = \"abc123456\"\n\n    ds_path = store / dsid[:3] / dsid[3:]  # store layout version 1\n    version_file = ds_path / 'ria-layout-version'\n    archives = ds_path / 'archives'\n    objects = ds_path / 'annex' / 'objects'\n    git_config = ds_path / 'config'\n\n    # invalid store version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, '1', 'abc')\n\n    # invalid obj version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, 'abc', '1')\n\n    # version 1\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '1', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"1\\n\")\n\n    # conflicting version exists at target:\n    assert_raises(ValueError, create_ds_in_store, io, store, dsid, '2', '1')\n\n    # version 2\n    # Note: The only difference between version 1 and 2 are supposed to be the\n    #       key paths (dirhashlower vs mixed), which has nothing to do with\n    #       setup routine.\n    rmtree(str(store))\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '2', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"2\\n\")\n\n\ndef test_setup_ds_in_store():\n\n    yield _test_setup_ds_in_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_ds_in_store), SSHRemoteIO, ['datalad-test']\n\n\ndef test_verify_ria_url():\n    # unsupported protocol\n    assert_raises(ValueError, verify_ria_url, 'ria+ftp://localhost/tmp/this', {})\n    # bunch of caes that should work\n    cases = {\n        'ria+file:///tmp/this': (None, '/tmp/this'),\n        # no normalization\n        'ria+file:///tmp/this/': (None, '/tmp/this/'),\n        # with hosts\n        'ria+ssh://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+http://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),\n        # with username\n        'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),\n        # with port\n        'ria+ssh://humbug@localhost:2222/tmp/this': ('humbug@localhost:2222', '/tmp/this'),\n        'ria+ssh://localhost:2200/tmp/this': ('localhost:2200', '/tmp/this'),\n        # with password\n        'ria+https://humbug:1234@localhost:8080/tmp/this': ('humbug:1234@localhost:8080', '/tmp/this'),\n        # document a strange (MIH thinks undesirable), but pre-existing behavior\n        # an 'ssh example.com' would end up in the user HOME, not in '/'\n        'ria+ssh://example.com': ('example.com', '/')\n    }\n    for i, o in cases.items():\n        # we are not testing the URL rewriting here\n        assert_equal(o, verify_ria_url(i, {})[:2])\n",
            "header": {
                "file": {
                    "path": "datalad/customremotes/tests/test_ria_utils.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "90feebf78",
                "new_commit_hash": "1bc077672",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/customremotes/tests/test_ria_utils.py"
            },
            "plus_file": {
                "path": "b/datalad/customremotes/tests/test_ria_utils.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 139,
                            "length": 6
                        },
                        "new_range": {
                            "start": 139,
                            "length": 14
                        },
                        "section": "def test_verify_ria_url():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),",
                                "type": "context"
                            },
                            {
                                "content": "        # with username",
                                "type": "context"
                            },
                            {
                                "content": "        'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),",
                                "type": "context"
                            },
                            {
                                "content": "        # with port",
                                "type": "added"
                            },
                            {
                                "content": "        'ria+ssh://humbug@localhost:2222/tmp/this': ('humbug@localhost:2222', '/tmp/this'),",
                                "type": "added"
                            },
                            {
                                "content": "        'ria+ssh://localhost:2200/tmp/this': ('localhost:2200', '/tmp/this'),",
                                "type": "added"
                            },
                            {
                                "content": "        # with password",
                                "type": "added"
                            },
                            {
                                "content": "        'ria+https://humbug:1234@localhost:8080/tmp/this': ('humbug:1234@localhost:8080', '/tmp/this'),",
                                "type": "added"
                            },
                            {
                                "content": "        # document a strange (MIH thinks undesirable), but pre-existing behavior",
                                "type": "added"
                            },
                            {
                                "content": "        # an 'ssh example.com' would end up in the user HOME, not in '/'",
                                "type": "added"
                            },
                            {
                                "content": "        'ria+ssh://example.com': ('example.com', '/')",
                                "type": "added"
                            },
                            {
                                "content": "    }",
                                "type": "context"
                            },
                            {
                                "content": "    for i, o in cases.items():",
                                "type": "context"
                            },
                            {
                                "content": "        # we are not testing the URL rewriting here",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/customremotes/tests/test_ria_utils.py",
                            "type": "function",
                            "name": "test_verify_ria_url",
                            "content": "def test_verify_ria_url():\n    # unsupported protocol\n    assert_raises(ValueError, verify_ria_url, 'ria+ftp://localhost/tmp/this', {})\n    # bunch of caes that should work\n    cases = {\n        'ria+file:///tmp/this': (None, '/tmp/this'),\n        # no normalization\n        'ria+file:///tmp/this/': (None, '/tmp/this/'),\n        # with hosts\n        'ria+ssh://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+http://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),\n        # with username\n        'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),\n        # with port\n        'ria+ssh://humbug@localhost:2222/tmp/this': ('humbug@localhost:2222', '/tmp/this'),\n        'ria+ssh://localhost:2200/tmp/this': ('localhost:2200', '/tmp/this'),\n        # with password\n        'ria+https://humbug:1234@localhost:8080/tmp/this': ('humbug:1234@localhost:8080', '/tmp/this'),\n        # document a strange (MIH thinks undesirable), but pre-existing behavior\n        # an 'ssh example.com' would end up in the user HOME, not in '/'\n        'ria+ssh://example.com': ('example.com', '/')\n    }\n    for i, o in cases.items():\n        # we are not testing the URL rewriting here\n        assert_equal(o, verify_ria_url(i, {})[:2])",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 128,
                            "end_lineno": 153,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "947a0110b48ef9ad82a3a710a5f8bd6297c11f51^",
    "new_commit_hash": "947a0110b48ef9ad82a3a710a5f8bd6297c11f51",
    "commit_message": "Support username, password and port specification in RIA URLs\n\nPreviously only the hostname was retained for performing, e.g. SSH-based\nlogins, making it required to use an appropriate SSH config.\n\nWhile not using such properties in RIA URLs is advisable, silently\nstripping such information is a bug. Moreover, other mechanisms such\nas HTTP (or a future FTP support) may not have equivalent configuration\nanalogs. Using such a core helper as `verify_ria_url()` to silently\nremove information seems inappropriate.\n\nA more comprehensive test is included.\n\nFixes datalad/datalad#5475",
    "commit_date": "2021-08-16T18:26:28+02:00",
    "metadata": {}
}
{
    "repo_name": "datalad",
    "new_commit_hash": "947a0110b48ef9ad82a3a710a5f8bd6297c11f51",
    "test_file_codes": [
        "from datalad.distributed.ora_remote import (\n    LocalIO,\n    SSHRemoteIO\n)\nfrom datalad.customremotes.ria_utils import (\n    create_store,\n    create_ds_in_store,\n    verify_ria_url,\n    UnknownLayoutVersion\n)\nfrom datalad.utils import (\n    on_windows,\n    Path,\n)\nfrom datalad.tests.utils import (\n    assert_equal,\n    assert_raises,\n    assert_true,\n    rmtree,\n    skip_ssh,\n    with_tempfile,\n    SkipTest,\n)\n\n\n@with_tempfile\ndef _test_setup_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    version_file = store / 'ria-layout-version'\n    error_logs = store / 'error_logs'\n\n    # invalid version raises:\n    assert_raises(UnknownLayoutVersion, create_store, io, store, '2')\n\n    # non-existing path should work:\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # empty target directory should work as well:\n    rmtree(str(store))\n    store.mkdir(exist_ok=False)\n    create_store(io, store, '1')\n    assert_true(version_file.exists())\n    assert_true(error_logs.exists())\n    assert_true(error_logs.is_dir())\n    assert_equal([f for f in error_logs.iterdir()], [])\n\n    # re-execution also fine:\n    create_store(io, store, '1')\n\n    # but version conflict with existing target isn't:\n    version_file.write_text(\"2|unknownflags\\n\")\n    assert_raises(ValueError, create_store, io, store, '1')\n    # TODO: check output reporting conflicting version \"2\"\n\n\ndef test_setup_store():\n\n    yield _test_setup_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_store), SSHRemoteIO, ['datalad-test']\n\n\n@with_tempfile\ndef _test_setup_ds_in_store(io_cls, io_args, store):\n    io = io_cls(*io_args)\n    store = Path(store)\n    # ATM create_ds_in_store doesn't care what kind of ID is provided\n    dsid = \"abc123456\"\n\n    ds_path = store / dsid[:3] / dsid[3:]  # store layout version 1\n    version_file = ds_path / 'ria-layout-version'\n    archives = ds_path / 'archives'\n    objects = ds_path / 'annex' / 'objects'\n    git_config = ds_path / 'config'\n\n    # invalid store version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, '1', 'abc')\n\n    # invalid obj version:\n    assert_raises(UnknownLayoutVersion,\n                  create_ds_in_store, io, store, dsid, 'abc', '1')\n\n    # version 1\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '1', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"1\\n\")\n\n    # conflicting version exists at target:\n    assert_raises(ValueError, create_ds_in_store, io, store, dsid, '2', '1')\n\n    # version 2\n    # Note: The only difference between version 1 and 2 are supposed to be the\n    #       key paths (dirhashlower vs mixed), which has nothing to do with\n    #       setup routine.\n    rmtree(str(store))\n    create_store(io, store, '1')\n    create_ds_in_store(io, store, dsid, '2', '1')\n    for p in [ds_path, archives, objects]:\n        assert_true(p.is_dir(), msg=\"Not a directory: %s\" % str(p))\n    for p in [version_file]:\n        assert_true(p.is_file(), msg=\"Not a file: %s\" % str(p))\n    assert_equal(version_file.read_text(), \"2\\n\")\n\n\ndef test_setup_ds_in_store():\n\n    yield _test_setup_ds_in_store, LocalIO, []\n\n    if on_windows:\n        raise SkipTest('ora_remote.SSHRemoteIO stalls on Windows')\n\n    yield skip_ssh(_test_setup_ds_in_store), SSHRemoteIO, ['datalad-test']\n\n\ndef test_verify_ria_url():\n    # unsupported protocol\n    assert_raises(ValueError, verify_ria_url, 'ria+ftp://localhost/tmp/this', {})\n    # bunch of caes that should work\n    cases = {\n        'ria+file:///tmp/this': (None, '/tmp/this'),\n        # no normalization\n        'ria+file:///tmp/this/': (None, '/tmp/this/'),\n        # with hosts\n        'ria+ssh://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+http://localhost/tmp/this': ('localhost', '/tmp/this'),\n        'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),\n        # with username\n        'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),\n        # with port\n        'ria+ssh://humbug@localhost:2222/tmp/this': ('humbug@localhost:2222', '/tmp/this'),\n        'ria+ssh://localhost:2200/tmp/this': ('localhost:2200', '/tmp/this'),\n        # with password\n        'ria+https://humbug:1234@localhost:8080/tmp/this': ('humbug:1234@localhost:8080', '/tmp/this'),\n        # document a strange (MIH thinks undesirable), but pre-existing behavior\n        # an 'ssh example.com' would end up in the user HOME, not in '/'\n        'ria+ssh://example.com': ('example.com', '/')\n    }\n    for i, o in cases.items():\n        # we are not testing the URL rewriting here\n        assert_equal(o, verify_ria_url(i, {})[:2])\n",
        "import pytest\nimport tempfile\nimport os\n\n\n@pytest.fixture\ndef path():\n    with tempfile.TemporaryDirectory() as tmpdir:\n        yield tmpdir\n\n\n@pytest.fixture(autouse=True)\ndef setup_git_config():\n    with tempfile.TemporaryDirectory() as home:\n        old_home = os.environ.get(\"HOME\")\n        os.environ[\"HOME\"] = home\n        os.system('git config --global user.name \"DataLad Tester\"')\n        os.system('git config --global user.email \"test@example.com\"')\n        yield\n        if old_home:\n            os.environ[\"HOME\"] = old_home\n"
    ],
    "test_file_names": [
        "test_1.py",
        "conftest.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "Starting Datalad installation attempts...\nVerifying installation...\nDatalad version: 0.14.7+21.g947a0110b\n✅ Installation successful!\nSuccessfully installed Datalad using Python 3.9\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 25 packages in 128ms\nInstalled 25 packages in 3.53s\n + coverage==7.6.10\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + grabbit==0.2.6\n + importlib-resources==6.4.5\n + iniconfig==2.0.0\n + nibabel==5.3.2\n + num2words==0.5.14\n + numpy==2.0.2\n + packaging==24.2\n + pandas==2.2.3\n + patsy==1.0.1\n + pluggy==1.5.0\n + pybids==0.6.5\n + pytest==8.3.4\n + pytest-cov==6.0.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.13.1\n + setuptools==75.6.0\n + six==1.17.0\n + tomli==2.2.1\n + typing-extensions==4.12.2\n + tzdata==2024.2\n + zipp==3.21.0\nResolved 66 packages in 4.34s\nPrepared 1 package in 5.13s\nInstalled 60 packages in 289ms\n + annexremote==1.6.6\n + appdirs==1.4.4\n + argcomplete==3.5.3\n + backports-tarfile==1.2.0\n + beautifulsoup4==4.12.3\n + boto==2.49.0\n + certifi==2024.12.14\n + cffi==1.17.1\n + chardet==5.2.0\n + charset-normalizer==3.4.1\n + citeproc-py==0.6.0\n + cryptography==44.0.0\n + datalad==0.14.7+21.g947a0110b (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_947a0110b48ef9ad82a3a710a5f8bd6297c11f51)\n + deprecated==1.2.15\n + distro==1.9.0\n + duecredit==0.10.2\n + exifread==3.0.0\n + fasteners==0.19\n + httpretty==1.1.4\n + humanize==4.11.0\n + idna==3.10\n + importlib-metadata==8.5.0\n + iso8601==2.1.0\n + jaraco-classes==3.4.0\n + jaraco-context==6.0.1\n + jaraco-functools==4.1.0\n + jeepney==0.8.0\n + jsmin==3.0.1\n + keyring==25.6.0\n + keyrings-alt==5.0.2\n + looseversion==1.3.0\n + lxml==5.3.0\n + more-itertools==10.5.0\n + msgpack==1.1.0\n + multidict==6.1.0\n + mutagen==1.47.0\n + nose==1.3.7\n + patool==1.15.0\n + pillow==11.0.0\n + propcache==0.2.1\n + pycparser==2.22\n + pygithub==2.5.0\n + pyjwt==2.10.1\n + pynacl==1.5.0\n + pyperclip==1.9.0\n + python-gitlab==5.3.0\n + python-xmp-toolkit==2.0.2\n + pyyaml==6.0.2\n + requests==2.32.3\n + requests-ftp==0.3.1\n + requests-toolbelt==1.0.0\n + secretstorage==3.3.3\n + simplejson==3.19.3\n + soupsieve==2.6\n + tqdm==4.67.1\n + urllib3==1.26.20\n + vcrpy==7.0.0\n + whoosh==2.7.4\n + wrapt==1.17.0\n + yarl==1.18.3\nResolved 100 packages in 285ms\nInstalled 32 packages in 864ms\n + alabaster==0.7.16\n + asv==0.6.4\n + asv-runner==0.2.1\n + babel==2.16.0\n + build==1.2.2.post1\n + distlib==0.3.9\n + docutils==0.21.2\n + filelock==3.16.1\n + gprof2dot==2024.6.6\n + imagesize==1.4.1\n + jinja2==3.1.5\n + json5==0.10.0\n + markupsafe==3.0.2\n + nose-timer==1.0.1\n + platformdirs==4.3.6\n + psutil==6.1.1\n + pygments==2.18.0\n + pympler==1.1\n + pypandoc==1.14\n + pyproject-hooks==1.2.0\n + snowballstemmer==2.2.0\n + sphinx==7.4.7\n + sphinx-rtd-theme==3.0.2\n + sphinxcontrib-applehelp==2.0.0\n + sphinxcontrib-devhelp==2.0.0\n + sphinxcontrib-htmlhelp==2.1.0\n + sphinxcontrib-jquery==4.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==2.0.0\n + sphinxcontrib-serializinghtml==2.0.0\n + tabulate==0.9.0\n + virtualenv==20.28.0\n",
    "new_commit_res_code": 0,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_947a0110b48ef9ad82a3a710a5f8bd6297c11f51\nconfigfile: pyproject.toml\nplugins: cov-6.0.0\ncollected 3 items\n\nr2e_tests/test_1.py xx.                                                  [100%]\n\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_verify_ria_url\nXFAIL r2e_tests/test_1.py::test_setup_store - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_setup_store will be ignored\nXFAIL r2e_tests/test_1.py::test_setup_ds_in_store - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_setup_ds_in_store will be ignored\n========================= 1 passed, 2 xfailed in 3.94s =========================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.9.21, pytest-8.3.4, pluggy-1.5.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_947a0110b48ef9ad82a3a710a5f8bd6297c11f51\nconfigfile: pyproject.toml\nplugins: cov-6.0.0\ncollected 3 items\n\nr2e_tests/test_1.py xxF                                                  [100%]\n\n=================================== FAILURES ===================================\n_____________________________ test_verify_ria_url ______________________________\n\n    def test_verify_ria_url():\n        # unsupported protocol\n        assert_raises(ValueError, verify_ria_url, 'ria+ftp://localhost/tmp/this', {})\n        # bunch of caes that should work\n        cases = {\n            'ria+file:///tmp/this': (None, '/tmp/this'),\n            # no normalization\n            'ria+file:///tmp/this/': (None, '/tmp/this/'),\n            # with hosts\n            'ria+ssh://localhost/tmp/this': ('localhost', '/tmp/this'),\n            'ria+http://localhost/tmp/this': ('localhost', '/tmp/this'),\n            'ria+https://localhost/tmp/this': ('localhost', '/tmp/this'),\n            # with username\n            'ria+ssh://humbug@localhost/tmp/this': ('humbug@localhost', '/tmp/this'),\n            # with port\n            'ria+ssh://humbug@localhost:2222/tmp/this': ('humbug@localhost:2222', '/tmp/this'),\n            'ria+ssh://localhost:2200/tmp/this': ('localhost:2200', '/tmp/this'),\n            # with password\n            'ria+https://humbug:1234@localhost:8080/tmp/this': ('humbug:1234@localhost:8080', '/tmp/this'),\n            # document a strange (MIH thinks undesirable), but pre-existing behavior\n            # an 'ssh example.com' would end up in the user HOME, not in '/'\n            'ria+ssh://example.com': ('example.com', '/')\n        }\n        for i, o in cases.items():\n            # we are not testing the URL rewriting here\n>           assert_equal(o, verify_ria_url(i, {})[:2])\n\nr2e_tests/test_1.py:153: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py:837: in assertEqual\n    assertion_func(first, second, msg=msg)\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py:1054: in assertTupleEqual\n    self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py:1025: in assertSequenceEqual\n    self.fail(msg)\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\nself = <nose.tools.trivial.Dummy testMethod=nop>\nmsg = \"Tuples differ: ('humbug@localhost', '/tmp/this') != ('localhost', '/tmp/this')\\n\\nFirst differing element 0:\\n'humbug@localhost'\\n'localhost'\\n\\n- ('humbug@localhost', '/tmp/this')\\n?   -------\\n\\n+ ('localhost', '/tmp/this')\"\n\n    def fail(self, msg=None):\n        \"\"\"Fail immediately, with the given message.\"\"\"\n>       raise self.failureException(msg)\nE       AssertionError: Tuples differ: ('humbug@localhost', '/tmp/this') != ('localhost', '/tmp/this')\nE       \nE       First differing element 0:\nE       'humbug@localhost'\nE       'localhost'\nE       \nE       - ('humbug@localhost', '/tmp/this')\nE       ?   -------\nE       \nE       + ('localhost', '/tmp/this')\n\n../../../../.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py:676: AssertionError\n=========================== short test summary info ============================\nXFAIL r2e_tests/test_1.py::test_setup_store - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_setup_store will be ignored\nXFAIL r2e_tests/test_1.py::test_setup_ds_in_store - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_setup_ds_in_store will be ignored\nFAILED r2e_tests/test_1.py::test_verify_ria_url - AssertionError: Tuples diff...\n========================= 1 failed, 2 xfailed in 0.82s =========================\n",
    "old_commit_res_stderr": ""
}
datalad/customremotes/ria_utils.py datalad/customremotes/tests/test_ria_utils.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `verify_ria_url` Function Strips Username and Port from RIA URLs

**Description:**
When providing RIA URLs that include a username and port, the `verify_ria_url` function incorrectly strips this information, retaining only the hostname. This behavior prevents the usage of URLs with specified usernames and ports, which are necessary for protocols like SSH and HTTP.

**Example Code:**
```python
url = 'ria+ssh://humbug@localhost:2222/tmp/this'
host, path, rewritten_url = verify_ria_url(url, {})
print(host)  # Expected: 'humbug@localhost:2222'
```

**Expected Behavior:**
The `verify_ria_url` function should retain the username and port information from the RIA URL. For the given example, the `host` should be `'humbug@localhost:2222'`, accurately reflecting the provided URL components.

**Actual Behavior:**
The function currently strips the username and port, resulting in `host` being `'localhost'` instead of `'humbug@localhost:2222'`. This causes authentication and connection issues when using SSH or other protocols that rely on these URL components.
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### datalad/customremotes/ria_utils.py
# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
# ex: set sts=4 ts=4 sw=4 noet:
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the datalad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Helper for RIA stores

"""


class UnknownLayoutVersion(Exception):
    pass


# TODO: Make versions a tuple of (label, description)?
# Object tree versions we introduced so far. This is about the layout within a
# dataset in a RIA store
known_versions_objt = ['1', '2']
# Dataset tree versions we introduced so far. This is about the layout of
# datasets in a RIA store
known_versions_dst = ['1']


# TODO: This is wrong and should consider both versions (store+dataset)
def get_layout_locations(version, base_path, dsid):
    """Return dataset-related path in a RIA store

    Parameters
    ----------
    version : int
      Layout version of the store.
    base_path : Path
      Base path of the store.
    dsid : str
      Dataset ID

    Returns
    -------
    Path, Path, Path
      The location of the bare dataset repository in the store,
      the directory with archive files for the dataset, and the
      annex object directory are return in that order.
    """
    if version == 1:
        dsgit_dir = base_path / dsid[:3] / dsid[3:]
        archive_dir = dsgit_dir / 'archives'
        dsobj_dir = dsgit_dir / 'annex' / 'objects'
        return dsgit_dir, archive_dir, dsobj_dir
    else:
        raise ValueError("Unknown layout version: {}. Supported: {}"
                         "".format(version, known_versions_dst))


def verify_ria_url(url, cfg):
    """Verify and decode ria url

    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to
    decode potential host and base path for the store from it. Additionally
    raises if `url` is considered invalid.

    ria+ssh://somehost:/path/to/store
    ria+file:///path/to/store

    Parameters
    ----------
    url : str
      URL to verify an decode.
    cfg : dict-like
      Configuration settings for rewrite_url()

    Raises
    ------
    ValueError

    Returns
    -------
    tuple
      (host, base-path, rewritten url)
    """
    from datalad.config import rewrite_url
    from datalad.support.network import URL

    if not url:
        raise ValueError("Got no URL")

    url = rewrite_url(cfg, url)
    url_ri = URL(url)
    if not url_ri.scheme.startswith('ria+'):
        raise ValueError("Missing ria+ prefix in final URL: %s" % url)
    if url_ri.fragment:
        raise ValueError(
            "Unexpected fragment in RIA-store URL: %s" % url_ri.fragment)
    protocol = url_ri.scheme[4:]
    if protocol not in ['ssh', 'file', 'http', 'https']:
        raise ValueError("Unsupported protocol: %s. "
                         "Supported: ssh, file, http(s)" %
                         protocol)

    return url_ri.hostname if protocol != 'file' else None, \
        url_ri.path if url_ri.path else '/', \
        url


def _ensure_version(io, base_path, version):
    """Check a store or dataset version and make sure it is declared

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
    base_path: Path
      root path of a store or dataset
    version: str
      target layout version of the store (dataset tree)
    """
    version_file = base_path / 'ria-layout-version'
    if io.exists(version_file):
        existing_version = io.read_file(version_file).split('|')[0].strip()
        if existing_version != version.split('|')[0]:
            # We have an already existing location with a conflicting version on
            # record.
            # Note, that a config flag after pipe symbol is fine.
            raise ValueError("Conflicting version found at target: {}"
                             .format(existing_version))
        else:
            # already exists, recorded version fits - nothing to do
            return
    # Note, that the following does create the base-path dir as well, since
    # mkdir has parents=True:
    io.mkdir(base_path)
    io.write_file(version_file, version)


def create_store(io, base_path, version):
    """Helper to create a RIA store

    Note, that this is meant as an internal helper and part of intermediate
    RF'ing. Ultimately should lead to dedicated command or option for
    create-sibling-ria.

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
      Respective execution instance.
      Note: To be replaced by proper command abstraction
    base_path: Path
      root path of the store
    version: str
      layout version of the store (dataset tree)
    """

    # At store level the only version we know as of now is 1.
    if version not in known_versions_dst:
        raise UnknownLayoutVersion("RIA store layout version unknown: {}."
                                   "Supported versions: {}"
                                   .format(version, known_versions_dst))
    _ensure_version(io, base_path, version)
    error_logs = base_path / 'error_logs'
    io.mkdir(error_logs)


def create_ds_in_store(io, base_path, dsid, obj_version, store_version):
    """Helper to create a dataset in a RIA store

    Note, that this is meant as an internal helper and part of intermediate
    RF'ing. Ultimately should lead to a version option for create-sibling-ria
    in conjunction with a store creation command/option.

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
      Respective execution instance.
      Note: To be replaced by proper command abstraction
    base_path: Path
      root path of the store
    dsid: str
      dataset id
    store_version: str
      layout version of the store (dataset tree)
    obj_version: str
      layout version of the dataset itself (object tree)
    """

    # TODO: Note for RF'ing, that this is about setting up a valid target
    #       for the special remote not a replacement for create-sibling-ria.
    #       There's currently no git (bare) repo created.

    try:
        # TODO: This is currently store layout version!
        #       Too entangled by current get_layout_locations.
        dsgit_dir, archive_dir, dsobj_dir = \
            get_layout_locations(int(store_version), base_path, dsid)
    except ValueError as e:
        raise UnknownLayoutVersion(str(e))

    if obj_version not in known_versions_objt:
        raise UnknownLayoutVersion("Dataset layout version unknown: {}. "
                                   "Supported: {}"
                                   .format(obj_version, known_versions_objt))

    _ensure_version(io, dsgit_dir, obj_version)

    io.mkdir(archive_dir)
    io.mkdir(dsobj_dir)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** `verify_ria_url` Function Strips Username and Port from RIA URLs

**Description:**
When providing RIA URLs that include a username and port, the `verify_ria_url` function incorrectly strips this information, retaining only the hostname. This behavior prevents the usage of URLs with specified usernames and ports, which are necessary for protocols like SSH and HTTP.

**Example Code:**
```python
url = 'ria+ssh://humbug@localhost:2222/tmp/this'
host, path, rewritten_url = verify_ria_url(url, {})
print(host)  # Expected: 'humbug@localhost:2222'
```

**Expected Behavior:**
The `verify_ria_url` function should retain the username and port information from the RIA URL. For the given example, the `host` should be `'humbug@localhost:2222'`, accurately reflecting the provided URL components.

**Actual Behavior:**
The function currently strips the username and port, resulting in `host` being `'localhost'` instead of `'humbug@localhost:2222'`. This causes authentication and connection issues when using SSH or other protocols that rely on these URL components.
[/ISSUE]
{
    "test_verify_ria_url": "PASSED"
}
diff --git a/datalad/customremotes/ria_utils.py b/datalad/customremotes/ria_utils.py
index 3795d6952..0b629bdc0 100644
--- a/datalad/customremotes/ria_utils.py
+++ b/datalad/customremotes/ria_utils.py
@@ -79,6 +79,8 @@ def verify_ria_url(url, cfg):
     -------
     tuple
       (host, base-path, rewritten url)
+      `host` is not just a hostname, but may also contain username, password,
+      and port, if specified in a given URL.
     """
     from datalad.config import rewrite_url
     from datalad.support.network import URL
@@ -99,7 +101,16 @@ def verify_ria_url(url, cfg):
                          "Supported: ssh, file, http(s)" %
                          protocol)
 
-    return url_ri.hostname if protocol != 'file' else None, \
+    host = '{user}{pdelim}{passwd}{udelim}{hostname}{portdelim}{port}'.format(
+        user=url_ri.username or '',
+        pdelim=':' if url_ri.password else '',
+        passwd=url_ri.password or '',
+        udelim='@' if url_ri.username else '',
+        hostname=url_ri.hostname or '',
+        portdelim=':' if url_ri.port else '',
+        port=url_ri.port or '',
+    )
+    return host if protocol != 'file' else None, \
         url_ri.path if url_ri.path else '/', \
         url
 

{"datalad/customremotes/ria_utils.py": "# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-\n# ex: set sts=4 ts=4 sw=4 noet:\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n#\n#   See COPYING file distributed along with the datalad package for the\n#   copyright and license terms.\n#\n# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##\n\"\"\"Helper for RIA stores\n\n\"\"\"\n\n\nclass UnknownLayoutVersion(Exception):\n    pass\n\n\n# TODO: Make versions a tuple of (label, description)?\n# Object tree versions we introduced so far. This is about the layout within a\n# dataset in a RIA store\nknown_versions_objt = ['1', '2']\n# Dataset tree versions we introduced so far. This is about the layout of\n# datasets in a RIA store\nknown_versions_dst = ['1']\n\n\n# TODO: This is wrong and should consider both versions (store+dataset)\ndef get_layout_locations(version, base_path, dsid):\n    \"\"\"Return dataset-related path in a RIA store\n\n    Parameters\n    ----------\n    version : int\n      Layout version of the store.\n    base_path : Path\n      Base path of the store.\n    dsid : str\n      Dataset ID\n\n    Returns\n    -------\n    Path, Path, Path\n      The location of the bare dataset repository in the store,\n      the directory with archive files for the dataset, and the\n      annex object directory are return in that order.\n    \"\"\"\n    if version == 1:\n        dsgit_dir = base_path / dsid[:3] / dsid[3:]\n        archive_dir = dsgit_dir / 'archives'\n        dsobj_dir = dsgit_dir / 'annex' / 'objects'\n        return dsgit_dir, archive_dir, dsobj_dir\n    else:\n        raise ValueError(\"Unknown layout version: {}. Supported: {}\"\n                         \"\".format(version, known_versions_dst))\n\n\ndef verify_ria_url(url, cfg):\n    \"\"\"Verify and decode ria url\n\n    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to\n    decode potential host and base path for the store from it. Additionally\n    raises if `url` is considered invalid.\n\n    ria+ssh://somehost:/path/to/store\n    ria+file:///path/to/store\n\n    Parameters\n    ----------\n    url : str\n      URL to verify an decode.\n    cfg : dict-like\n      Configuration settings for rewrite_url()\n\n    Raises\n    ------\n    ValueError\n\n    Returns\n    -------\n    tuple\n      (host, base-path, rewritten url)\n    \"\"\"\n    from datalad.config import rewrite_url\n    from datalad.support.network import URL\n\n    if not url:\n        raise ValueError(\"Got no URL\")\n\n    url = rewrite_url(cfg, url)\n    url_ri = URL(url)\n    if not url_ri.scheme.startswith('ria+'):\n        raise ValueError(\"Missing ria+ prefix in final URL: %s\" % url)\n    if url_ri.fragment:\n        raise ValueError(\n            \"Unexpected fragment in RIA-store URL: %s\" % url_ri.fragment)\n    protocol = url_ri.scheme[4:]\n    if protocol not in ['ssh', 'file', 'http', 'https']:\n        raise ValueError(\"Unsupported protocol: %s. \"\n                         \"Supported: ssh, file, http(s)\" %\n                         protocol)\n\n    return url_ri.hostname if protocol != 'file' else None, \\\n        url_ri.path if url_ri.path else '/', \\\n        url\n\n\ndef _ensure_version(io, base_path, version):\n    \"\"\"Check a store or dataset version and make sure it is declared\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n    base_path: Path\n      root path of a store or dataset\n    version: str\n      target layout version of the store (dataset tree)\n    \"\"\"\n    version_file = base_path / 'ria-layout-version'\n    if io.exists(version_file):\n        existing_version = io.read_file(version_file).split('|')[0].strip()\n        if existing_version != version.split('|')[0]:\n            # We have an already existing location with a conflicting version on\n            # record.\n            # Note, that a config flag after pipe symbol is fine.\n            raise ValueError(\"Conflicting version found at target: {}\"\n                             .format(existing_version))\n        else:\n            # already exists, recorded version fits - nothing to do\n            return\n    # Note, that the following does create the base-path dir as well, since\n    # mkdir has parents=True:\n    io.mkdir(base_path)\n    io.write_file(version_file, version)\n\n\ndef create_store(io, base_path, version):\n    \"\"\"Helper to create a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to dedicated command or option for\n    create-sibling-ria.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    version: str\n      layout version of the store (dataset tree)\n    \"\"\"\n\n    # At store level the only version we know as of now is 1.\n    if version not in known_versions_dst:\n        raise UnknownLayoutVersion(\"RIA store layout version unknown: {}.\"\n                                   \"Supported versions: {}\"\n                                   .format(version, known_versions_dst))\n    _ensure_version(io, base_path, version)\n    error_logs = base_path / 'error_logs'\n    io.mkdir(error_logs)\n\n\ndef create_ds_in_store(io, base_path, dsid, obj_version, store_version):\n    \"\"\"Helper to create a dataset in a RIA store\n\n    Note, that this is meant as an internal helper and part of intermediate\n    RF'ing. Ultimately should lead to a version option for create-sibling-ria\n    in conjunction with a store creation command/option.\n\n    Parameters\n    ----------\n    io: SSHRemoteIO or LocalIO\n      Respective execution instance.\n      Note: To be replaced by proper command abstraction\n    base_path: Path\n      root path of the store\n    dsid: str\n      dataset id\n    store_version: str\n      layout version of the store (dataset tree)\n    obj_version: str\n      layout version of the dataset itself (object tree)\n    \"\"\"\n\n    # TODO: Note for RF'ing, that this is about setting up a valid target\n    #       for the special remote not a replacement for create-sibling-ria.\n    #       There's currently no git (bare) repo created.\n\n    try:\n        # TODO: This is currently store layout version!\n        #       Too entangled by current get_layout_locations.\n        dsgit_dir, archive_dir, dsobj_dir = \\\n            get_layout_locations(int(store_version), base_path, dsid)\n    except ValueError as e:\n        raise UnknownLayoutVersion(str(e))\n\n    if obj_version not in known_versions_objt:\n        raise UnknownLayoutVersion(\"Dataset layout version unknown: {}. \"\n                                   \"Supported: {}\"\n                                   .format(obj_version, known_versions_objt))\n\n    _ensure_version(io, dsgit_dir, obj_version)\n\n    io.mkdir(archive_dir)\n    io.mkdir(dsobj_dir)\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `verify_ria_url` Function Strips Username and Port from RIA URLs

**Description:**
When providing RIA URLs that include a username and port, the `verify_ria_url` function incorrectly strips this information, retaining only the hostname. This behavior prevents the usage of URLs with specified usernames and ports, which are necessary for protocols like SSH and HTTP.

**Example Code:**
```python
url = 'ria+ssh://humbug@localhost:2222/tmp/this'
host, path, rewritten_url = verify_ria_url(url, {})
print(host)  # Expected: 'humbug@localhost:2222'
```

**Expected Behavior:**
The `verify_ria_url` function should retain the username and port information from the RIA URL. For the given example, the `host` should be `'humbug@localhost:2222'`, accurately reflecting the provided URL components.

**Actual Behavior:**
The function currently strips the username and port, resulting in `host` being `'localhost'` instead of `'humbug@localhost:2222'`. This causes authentication and connection issues when using SSH or other protocols that rely on these URL components.
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### datalad/customremotes/ria_utils.py
# emacs: -*- mode: python; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
# ex: set sts=4 ts=4 sw=4 noet:
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
#
#   See COPYING file distributed along with the datalad package for the
#   copyright and license terms.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Helper for RIA stores

"""


class UnknownLayoutVersion(Exception):
    pass


# TODO: Make versions a tuple of (label, description)?
# Object tree versions we introduced so far. This is about the layout within a
# dataset in a RIA store
known_versions_objt = ['1', '2']
# Dataset tree versions we introduced so far. This is about the layout of
# datasets in a RIA store
known_versions_dst = ['1']


# TODO: This is wrong and should consider both versions (store+dataset)
def get_layout_locations(version, base_path, dsid):
    """Return dataset-related path in a RIA store

    Parameters
    ----------
    version : int
      Layout version of the store.
    base_path : Path
      Base path of the store.
    dsid : str
      Dataset ID

    Returns
    -------
    Path, Path, Path
      The location of the bare dataset repository in the store,
      the directory with archive files for the dataset, and the
      annex object directory are return in that order.
    """
    if version == 1:
        dsgit_dir = base_path / dsid[:3] / dsid[3:]
        archive_dir = dsgit_dir / 'archives'
        dsobj_dir = dsgit_dir / 'annex' / 'objects'
        return dsgit_dir, archive_dir, dsobj_dir
    else:
        raise ValueError("Unknown layout version: {}. Supported: {}"
                         "".format(version, known_versions_dst))


def verify_ria_url(url, cfg):
    """Verify and decode ria url

    Expects a ria-URL pointing to a RIA store, applies rewrites and tries to
    decode potential host and base path for the store from it. Additionally
    raises if `url` is considered invalid.

    ria+ssh://somehost:/path/to/store
    ria+file:///path/to/store

    Parameters
    ----------
    url : str
      URL to verify an decode.
    cfg : dict-like
      Configuration settings for rewrite_url()

    Raises
    ------
    ValueError

    Returns
    -------
    tuple
      (host, base-path, rewritten url)
    """
    from datalad.config import rewrite_url
    from datalad.support.network import URL

    if not url:
        raise ValueError("Got no URL")

    url = rewrite_url(cfg, url)
    url_ri = URL(url)
    if not url_ri.scheme.startswith('ria+'):
        raise ValueError("Missing ria+ prefix in final URL: %s" % url)
    if url_ri.fragment:
        raise ValueError(
            "Unexpected fragment in RIA-store URL: %s" % url_ri.fragment)
    protocol = url_ri.scheme[4:]
    if protocol not in ['ssh', 'file', 'http', 'https']:
        raise ValueError("Unsupported protocol: %s. "
                         "Supported: ssh, file, http(s)" %
                         protocol)

    return url_ri.hostname if protocol != 'file' else None, \
        url_ri.path if url_ri.path else '/', \
        url


def _ensure_version(io, base_path, version):
    """Check a store or dataset version and make sure it is declared

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
    base_path: Path
      root path of a store or dataset
    version: str
      target layout version of the store (dataset tree)
    """
    version_file = base_path / 'ria-layout-version'
    if io.exists(version_file):
        existing_version = io.read_file(version_file).split('|')[0].strip()
        if existing_version != version.split('|')[0]:
            # We have an already existing location with a conflicting version on
            # record.
            # Note, that a config flag after pipe symbol is fine.
            raise ValueError("Conflicting version found at target: {}"
                             .format(existing_version))
        else:
            # already exists, recorded version fits - nothing to do
            return
    # Note, that the following does create the base-path dir as well, since
    # mkdir has parents=True:
    io.mkdir(base_path)
    io.write_file(version_file, version)


def create_store(io, base_path, version):
    """Helper to create a RIA store

    Note, that this is meant as an internal helper and part of intermediate
    RF'ing. Ultimately should lead to dedicated command or option for
    create-sibling-ria.

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
      Respective execution instance.
      Note: To be replaced by proper command abstraction
    base_path: Path
      root path of the store
    version: str
      layout version of the store (dataset tree)
    """

    # At store level the only version we know as of now is 1.
    if version not in known_versions_dst:
        raise UnknownLayoutVersion("RIA store layout version unknown: {}."
                                   "Supported versions: {}"
                                   .format(version, known_versions_dst))
    _ensure_version(io, base_path, version)
    error_logs = base_path / 'error_logs'
    io.mkdir(error_logs)


def create_ds_in_store(io, base_path, dsid, obj_version, store_version):
    """Helper to create a dataset in a RIA store

    Note, that this is meant as an internal helper and part of intermediate
    RF'ing. Ultimately should lead to a version option for create-sibling-ria
    in conjunction with a store creation command/option.

    Parameters
    ----------
    io: SSHRemoteIO or LocalIO
      Respective execution instance.
      Note: To be replaced by proper command abstraction
    base_path: Path
      root path of the store
    dsid: str
      dataset id
    store_version: str
      layout version of the store (dataset tree)
    obj_version: str
      layout version of the dataset itself (object tree)
    """

    # TODO: Note for RF'ing, that this is about setting up a valid target
    #       for the special remote not a replacement for create-sibling-ria.
    #       There's currently no git (bare) repo created.

    try:
        # TODO: This is currently store layout version!
        #       Too entangled by current get_layout_locations.
        dsgit_dir, archive_dir, dsobj_dir = \
            get_layout_locations(int(store_version), base_path, dsid)
    except ValueError as e:
        raise UnknownLayoutVersion(str(e))

    if obj_version not in known_versions_objt:
        raise UnknownLayoutVersion("Dataset layout version unknown: {}. "
                                   "Supported: {}"
                                   .format(obj_version, known_versions_objt))

    _ensure_version(io, dsgit_dir, obj_version)

    io.mkdir(archive_dir)
    io.mkdir(dsobj_dir)

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user