{
    "file_diffs": [
        {
            "old_file_content": "# 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\"\"\"Test install action\n\n\"\"\"\n\nfrom datalad.tests.utils import known_failure_v6\nfrom datalad.tests.utils import known_failure_direct_mode\n\n\nimport logging\nimport os\n\nfrom os.path import join as opj\nfrom os.path import isdir\nfrom os.path import exists\nfrom os.path import realpath\nfrom os.path import basename\nfrom os.path import dirname\n\nfrom mock import patch\n\nfrom datalad.utils import getpwd\n\nfrom datalad.api import create\nfrom datalad.api import install\nfrom datalad.api import get\nfrom datalad import consts\nfrom datalad.utils import chpwd\nfrom datalad.interface.results import YieldDatasets\nfrom datalad.interface.results import YieldRelativePaths\nfrom datalad.support.exceptions import InsufficientArgumentsError\nfrom datalad.support.exceptions import InstallFailedError\nfrom datalad.support.exceptions import IncompleteResultsError\nfrom datalad.support.gitrepo import GitRepo\nfrom datalad.support.gitrepo import GitCommandError\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.cmd import Runner\nfrom datalad.tests.utils import create_tree\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import with_tree\nfrom datalad.tests.utils import with_testrepos\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import ok_\nfrom datalad.tests.utils import assert_false\nfrom datalad.tests.utils import ok_file_has_content\nfrom datalad.tests.utils import assert_not_in\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_is_instance\nfrom datalad.tests.utils import assert_result_count\nfrom datalad.tests.utils import assert_status\nfrom datalad.tests.utils import assert_in_results\nfrom datalad.tests.utils import assert_not_in_results\nfrom datalad.tests.utils import ok_startswith\nfrom datalad.tests.utils import ok_clean_git\nfrom datalad.tests.utils import serve_path_via_http\nfrom datalad.tests.utils import swallow_logs\nfrom datalad.tests.utils import use_cassette\nfrom datalad.tests.utils import skip_if_no_network\nfrom datalad.tests.utils import put_file_under_git\nfrom datalad.tests.utils import integration\nfrom datalad.tests.utils import slow\nfrom datalad.tests.utils import usecase\nfrom datalad.tests.utils import get_datasets_topdir\nfrom datalad.utils import _path_\nfrom datalad.utils import rmtree\n\nfrom ..dataset import Dataset\nfrom ..utils import _get_installationpath_from_url\nfrom ..utils import _get_git_url_from_source\n\n###############\n# Test helpers:\n###############\n\n\ndef test_installationpath_from_url():\n    for p in ('lastbit',\n              'lastbit/',\n              '/lastbit',\n              'lastbit.git',\n              'lastbit.git/',\n              'http://example.com/lastbit',\n              'http://example.com/lastbit.git',\n              ):\n        eq_(_get_installationpath_from_url(p), 'lastbit')\n\n\ndef test_get_git_url_from_source():\n\n    # resolves datalad RIs:\n    eq_(_get_git_url_from_source('///subds'), consts.DATASETS_TOPURL + 'subds')\n    assert_raises(NotImplementedError, _get_git_url_from_source,\n                  '//custom/subds')\n\n    # doesn't harm others:\n    eq_(_get_git_url_from_source('http://example.com'), 'http://example.com')\n    eq_(_get_git_url_from_source('/absolute/path'), '/absolute/path')\n    eq_(_get_git_url_from_source('file://localhost/some'),\n        'file://localhost/some')\n    eq_(_get_git_url_from_source('localhost/another/path'),\n        'localhost/another/path')\n    eq_(_get_git_url_from_source('user@someho.st/mydir'),\n        'user@someho.st/mydir')\n    eq_(_get_git_url_from_source('ssh://somewhe.re/else'),\n        'ssh://somewhe.re/else')\n    eq_(_get_git_url_from_source('git://github.com/datalad/testrepo--basic--r1'),\n        'git://github.com/datalad/testrepo--basic--r1')\n\n\n@with_tree(tree={'file.txt': '123'})\n@serve_path_via_http\n@with_tempfile\ndef _test_guess_dot_git(annex, path, url, tdir):\n    repo = (AnnexRepo if annex else GitRepo)(path, create=True)\n    repo.add('file.txt', commit=True, git=not annex)\n\n    # we need to prepare to be served via http, otherwise it must fail\n    with swallow_logs() as cml:\n        assert_raises(IncompleteResultsError, install, path=tdir, source=url)\n    ok_(not exists(tdir))\n\n    Runner(cwd=path)(['git', 'update-server-info'])\n\n    with swallow_logs() as cml:\n        installed = install(tdir, source=url)\n        assert_not_in(\"Failed to get annex.uuid\", cml.out)\n    eq_(realpath(installed.path), realpath(tdir))\n    ok_(exists(tdir))\n    ok_clean_git(tdir, annex=annex)\n\n\ndef test_guess_dot_git():\n    for annex in False, True:\n        yield _test_guess_dot_git, annex\n\n\n######################\n# Test actual Install:\n######################\n\ndef test_insufficient_args():\n    assert_raises(InsufficientArgumentsError, install)\n    assert_raises(InsufficientArgumentsError, install, description=\"some\")\n    assert_raises(InsufficientArgumentsError, install, None)\n    assert_raises(InsufficientArgumentsError, install, None, description=\"some\")\n\n\n@with_tempfile(mkdir=True)\ndef test_invalid_args(path):\n    assert_raises(IncompleteResultsError, install, 'Zoidberg', source='Zoidberg')\n    # install to an invalid URL\n    assert_raises(ValueError, install, 'ssh://mars:Zoidberg', source='Zoidberg')\n    # install to a remote location\n    assert_raises(ValueError, install, 'ssh://mars/Zoidberg', source='Zoidberg')\n    # make fake dataset\n    ds = create(path)\n    assert_raises(IncompleteResultsError, install, '/higherup.', 'Zoidberg', dataset=ds)\n\n\n# This test caused a mysterious segvault in gh-1350. I reimplementation of\n# the same test functionality in test_clone.py:test_clone_crcns that uses\n# `clone` instead of `install` passes without showing this behavior\n# This test is disabled until some insight into the cause of the issue\n# materializes.\n#@skip_if_no_network\n#@use_cassette('test_install_crcns')\n#@with_tempfile(mkdir=True)\n#@with_tempfile(mkdir=True)\n#def test_install_crcns(tdir, ds_path):\n#    with chpwd(tdir):\n#        with swallow_logs(new_level=logging.INFO) as cml:\n#            install(\"all-nonrecursive\", source='///')\n#            # since we didn't log decorations such as log level atm while\n#            # swallowing so lets check if exit code is returned or not\n#            # I will test both\n#            assert_not_in('ERROR', cml.out)\n#            # below one must not fail alone! ;)\n#            assert_not_in('with exit code', cml.out)\n#\n#        # should not hang in infinite recursion\n#        with chpwd('all-nonrecursive'):\n#            get(\"crcns\")\n#        ok_(exists(_path_(\"all-nonrecursive/crcns/.git/config\")))\n#        # and we could repeat installation and get the same result\n#        ds1 = install(_path_(\"all-nonrecursive/crcns\"))\n#        ok_(ds1.is_installed())\n#        ds2 = Dataset('all-nonrecursive').install('crcns')\n#        eq_(ds1, ds2)\n#        eq_(ds1.path, ds2.path)  # to make sure they are a single dataset\n#\n#    # again, but into existing dataset:\n#    ds = create(ds_path)\n#    crcns = ds.install(\"///crcns\")\n#    ok_(crcns.is_installed())\n#    eq_(crcns.path, opj(ds_path, \"crcns\"))\n#    assert_in(crcns.path, ds.get_subdatasets(absolute=True))\n\n\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tree(tree={'sub': {}})\ndef test_install_datasets_root(tdir):\n    with chpwd(tdir):\n        ds = install(\"///\")\n        ok_(ds.is_installed())\n        eq_(ds.path, opj(tdir, get_datasets_topdir()))\n\n        # do it a second time:\n        result = install(\"///\", result_xfm=None, return_type='list')\n        assert_status('notneeded', result)\n        eq_(YieldDatasets()(result[0]), ds)\n\n        # and a third time into an existing something, that is not a dataset:\n        with open(opj(tdir, 'sub', 'a_file.txt'), 'w') as f:\n            f.write(\"something\")\n\n        with assert_raises(IncompleteResultsError) as cme:\n            install(\"sub\", source='///')\n        assert_in(\"already exists and not empty\", str(cme.exception))\n\n\n@known_failure_v6  #FIXME\n@with_testrepos('.*basic.*', flavors=['local-url', 'network', 'local'])\n@with_tempfile(mkdir=True)\ndef test_install_simple_local(src, path):\n    origin = Dataset(path)\n\n    # now install it somewhere else\n    ds = install(path, source=src, description='mydummy')\n    eq_(ds.path, path)\n    ok_(ds.is_installed())\n    if not isinstance(origin.repo, AnnexRepo):\n        # this means it is a GitRepo\n        ok_(isinstance(origin.repo, GitRepo))\n        # stays plain Git repo\n        ok_(isinstance(ds.repo, GitRepo))\n        ok_(not isinstance(ds.repo, AnnexRepo))\n        ok_(GitRepo.is_valid_repo(ds.path))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt'})\n        ok_clean_git(path, annex=False)\n    else:\n        # must be an annex\n        ok_(isinstance(ds.repo, AnnexRepo))\n        ok_(AnnexRepo.is_valid_repo(ds.path, allow_noninitialized=False))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt', 'test-annex.dat'})\n        ok_clean_git(path, annex=True)\n        # no content was installed:\n        ok_(not ds.repo.file_has_content('test-annex.dat'))\n        uuid_before = ds.repo.uuid\n        eq_(ds.repo.get_description(), 'mydummy')\n\n    # installing it again, shouldn't matter:\n    res = install(path, source=src, result_xfm=None, return_type='list')\n    assert_status('notneeded', res)\n    ok_(ds.is_installed())\n    if isinstance(origin.repo, AnnexRepo):\n        eq_(uuid_before, ds.repo.uuid)\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local-url', 'network', 'local'])\n@with_tempfile\ndef test_install_dataset_from_just_source(url, path):\n    with chpwd(path, mkdir=True):\n        ds = install(source=url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_dataset_from_instance(src, dst):\n    origin = Dataset(src)\n    clone = install(source=origin, path=dst)\n\n    assert_is_instance(clone, Dataset)\n    ok_startswith(clone.path, dst)\n    ok_(clone.is_installed())\n    ok_(GitRepo.is_valid_repo(clone.path))\n    ok_clean_git(clone.path, annex=None)\n    assert_in('INFO.txt', clone.repo.get_indexed_files())\n\n\n@with_testrepos(flavors=['network'])\n@with_tempfile\n@known_failure_v6  #FIXME\ndef test_install_dataset_from_just_source_via_path(url, path):\n    # for remote urls only, the source could be given to `path`\n    # to allows for simplistic cmdline calls\n    # Q (ben): remote urls only? Sure? => TODO\n\n    with chpwd(path, mkdir=True):\n        ds = install(url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@with_tree(tree={\n    'ds': {'test.txt': 'some'},\n    })\n@serve_path_via_http\n@with_tempfile(mkdir=True)\ndef test_install_dataladri(src, topurl, path):\n    # make plain git repo\n    ds_path = opj(src, 'ds')\n    gr = GitRepo(ds_path, create=True)\n    gr.add('test.txt')\n    gr.commit('demo')\n    Runner(cwd=gr.path)(['git', 'update-server-info'])\n    # now install it somewhere else\n    with patch('datalad.consts.DATASETS_TOPURL', topurl), \\\n            swallow_logs():\n        ds = install(path, source='///ds')\n    eq_(ds.path, path)\n    ok_clean_git(path, annex=False)\n    ok_file_has_content(opj(path, 'test.txt'), 'some')\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\ndef test_install_recursive(src, path_nr, path_r):\n    # first install non-recursive:\n    ds = install(path_nr, source=src, recursive=False)\n    ok_(ds.is_installed())\n    for sub in ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(not sub.is_installed(),\n            \"Unintentionally installed: %s\" % (sub,))\n    # this also means, subdatasets to be listed as not fulfilled:\n    eq_(set(ds.subdatasets(recursive=True, fulfilled=False, result_xfm='relpaths')),\n        {'subm 1', '2'})\n\n    # now recursively:\n    # don't filter implicit results so we can inspect them\n    ds_list = install(path_r, source=src, recursive=True, result_filter=None)\n    # installed a dataset and two subdatasets\n    eq_(len(ds_list), 3)\n    eq_(sum([isinstance(i, Dataset) for i in ds_list]), 3)\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(ds_list[0].path, path_r)\n    top_ds = ds_list[0]\n    ok_(top_ds.is_installed())\n\n    # the subdatasets are contained in returned list:\n    # (Note: Until we provide proper (singleton) instances for Datasets,\n    # need to check for their paths)\n    assert_in(opj(top_ds.path, 'subm 1'), [i.path for i in ds_list])\n    assert_in(opj(top_ds.path, '2'), [i.path for i in ds_list])\n\n    eq_(len(top_ds.subdatasets(recursive=True)), 2)\n\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(),\n            \"Not installed: %s\" % (subds,))\n        # no content was installed:\n        ok_(not any(subds.repo.file_has_content(\n            subds.repo.get_annexed_files())))\n    # no unfulfilled subdatasets:\n    ok_(top_ds.subdatasets(recursive=True, fulfilled=False) == [])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_recursive_with_data(src, path):\n\n    # now again; with data:\n    res = install(path, source=src, recursive=True, get_data=True,\n                  result_filter=None, result_xfm=None)\n    assert_status('ok', res)\n    # installed a dataset and two subdatasets, and one file with content in\n    # each, plus the report that we got all content in each dataset's root dir\n    eq_(len(res), 9)\n    assert_result_count(res, 3, type='dataset')\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(res[0]['path'], path)\n    top_ds = YieldDatasets()(res[0])\n    ok_(top_ds.is_installed())\n    if isinstance(top_ds.repo, AnnexRepo):\n        ok_(all(top_ds.repo.file_has_content(top_ds.repo.get_annexed_files())))\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(), \"Not installed: %s\" % (subds,))\n        if isinstance(subds.repo, AnnexRepo):\n            ok_(all(subds.repo.file_has_content(subds.repo.get_annexed_files())))\n\n\n# @known_failure_direct_mode  #FIXME:\n# If we use all testrepos, we get a mixed hierarchy. Therefore ok_clean_git\n# fails if we are in direct mode and run into a plain git beneath an annex, due\n# to currently impossible recursion of `AnnexRepo._submodules_dirty_direct_mode`\n\n@slow  # 88.0869s  because of going through multiple test repos, ~8sec each time\n@with_testrepos('.*annex.*', flavors=['local'])\n# 'local-url', 'network'\n# TODO: Somehow annex gets confused while initializing installed ds, whose\n# .git/config show a submodule url \"file:///aaa/bbb%20b/...\"\n# this is delivered by with_testrepos as the url to clone\n@with_tempfile\ndef test_install_into_dataset(source, top_path):\n\n    ds = create(top_path)\n    ok_clean_git(ds.path)\n\n    subds = ds.install(\"sub\", source=source, save=False)\n    if isinstance(subds.repo, AnnexRepo) and subds.repo.is_direct_mode():\n        ok_(exists(opj(subds.path, '.git')))\n    else:\n        ok_(isdir(opj(subds.path, '.git')))\n    ok_(subds.is_installed())\n    assert_in('sub', ds.subdatasets(result_xfm='relpaths'))\n    # sub is clean:\n    ok_clean_git(subds.path, annex=None)\n    # top is too:\n    ok_clean_git(ds.path, annex=None)\n    ds.save('addsub')\n    # now it is:\n    ok_clean_git(ds.path, annex=None)\n\n    # but we could also save while installing and there should be no side-effect\n    # of saving any other changes if we state to not auto-save changes\n    # Create a dummy change\n    create_tree(ds.path, {'dummy.txt': 'buga'})\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n    subds_ = ds.install(\"sub2\", source=source)\n    eq_(subds_.path, opj(ds.path, \"sub2\"))  # for paranoid yoh ;)\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n    # and we should achieve the same behavior if we create a dataset\n    # and then decide to add it\n    create(_path_(top_path, 'sub3'))\n    ok_clean_git(ds.path, untracked=['dummy.txt', 'sub3/'])\n    ds.add('sub3')\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n\n@usecase  # 39.3074s\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_failed_install_multiple(top_path):\n    ds = create(top_path)\n\n    create(_path_(top_path, 'ds1'))\n    create(_path_(top_path, 'ds3'))\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n\n    # specify install with multiple paths and one non-existing\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(['ds1', 'ds2', '///crcns', '///nonexisting', 'ds3'],\n                   on_failure='continue')\n\n    # install doesn't add existing submodules -- add does that\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n    ds.add(['ds1', 'ds3'])\n    ok_clean_git(ds.path, annex=None)\n    # those which succeeded should be saved now\n    eq_(ds.subdatasets(result_xfm='relpaths'), ['crcns', 'ds1', 'ds3'])\n    # and those which didn't -- listed\n    eq_(set(r.get('source_url', r['path']) for r in cme.exception.failed),\n        {'///nonexisting', _path_(top_path, 'ds2')})\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\ndef test_install_known_subdataset(src, path):\n\n    # get the superdataset:\n    ds = install(path, source=src)\n    # subdataset not installed:\n    subds = Dataset(opj(path, 'subm 1'))\n    assert_false(subds.is_installed())\n    assert_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n    # install it:\n    ds.install('subm 1')\n    ok_(subds.is_installed())\n    ok_(AnnexRepo.is_valid_repo(subds.path, allow_noninitialized=False))\n    # Verify that it is the correct submodule installed and not\n    # new repository initiated\n    eq_(set(subds.repo.get_indexed_files()),\n        {'test.dat', 'INFO.txt', 'test-annex.dat'})\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n\n    # now, get the data by reinstalling with -g:\n    ok_(subds.repo.file_has_content('test-annex.dat') is False)\n    with chpwd(ds.path):\n        result = get(path='subm 1', dataset=os.curdir)\n        assert_in_results(result, path=opj(subds.path, 'test-annex.dat'))\n        ok_(subds.repo.file_has_content('test-annex.dat') is True)\n        ok_(subds.is_installed())\n\n\n@slow  # 46.3650s\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_implicit_install(src, dst):\n\n    origin_top = create(src)\n    origin_sub = origin_top.create(\"sub\")\n    origin_subsub = origin_sub.create(\"subsub\")\n    with open(opj(origin_top.path, \"file1.txt\"), \"w\") as f:\n        f.write(\"content1\")\n    origin_top.add(\"file1.txt\")\n    with open(opj(origin_sub.path, \"file2.txt\"), \"w\") as f:\n        f.write(\"content2\")\n    origin_sub.add(\"file2.txt\")\n    with open(opj(origin_subsub.path, \"file3.txt\"), \"w\") as f:\n        f.write(\"content3\")\n    origin_subsub.add(\"file3.txt\")\n    origin_top.save(recursive=True)\n\n    # first, install toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # fail on obscure non-existing one\n    assert_raises(IncompleteResultsError, ds.install, source='obscure')\n\n    # install 3rd level and therefore implicitly the 2nd:\n    result = ds.install(path=opj(\"sub\", \"subsub\"))\n    ok_(sub.is_installed())\n    ok_(subsub.is_installed())\n    # but by default implicit results are not reported\n    eq_(result, subsub)\n\n    # fail on obscure non-existing one in subds\n    assert_raises(IncompleteResultsError, ds.install, source=opj('sub', 'obscure'))\n\n    # clean up, the nasty way\n    rmtree(dst, chmod_files=True)\n    ok_(not exists(dst))\n\n    # again first toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # now implicit but without an explicit dataset to install into\n    # (deriving from CWD):\n    with chpwd(dst):\n        # don't ask for the file content to make return value comparison\n        # simpler\n        result = get(path=opj(\"sub\", \"subsub\"), get_data=False, result_xfm='datasets')\n        ok_(sub.is_installed())\n        ok_(subsub.is_installed())\n        eq_(result, [sub, subsub])\n\n\n@with_tempfile(mkdir=True)\ndef test_failed_install(dspath):\n    ds = create(dspath)\n    assert_raises(IncompleteResultsError,\n                  ds.install,\n                  \"sub\",\n                  source=\"http://nonexistingreallyanything.datalad.org/bla\")\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_list(path, top_path):\n\n    # we want to be able to install several things, if these are known\n    # (no 'source' allowed). Therefore first toplevel:\n    ds = install(top_path, source=path, recursive=False)\n    assert_not_in('annex.hardlink', ds.config)\n    ok_(ds.is_installed())\n    sub1 = Dataset(opj(top_path, 'subm 1'))\n    sub2 = Dataset(opj(top_path, '2'))\n    ok_(not sub1.is_installed())\n    ok_(not sub2.is_installed())\n\n    # fails, when `source` is passed:\n    assert_raises(ValueError, ds.install,\n                  path=['subm 1', '2'],\n                  source='something')\n\n    # now should work:\n    result = ds.install(path=['subm 1', '2'], result_xfm='paths')\n    ok_(sub1.is_installed())\n    ok_(sub2.is_installed())\n    eq_(set(result), {sub1.path, sub2.path})\n    # and if we request it again via get, result should be empty\n    get_result = ds.get(path=['subm 1', '2'], get_data=False)\n    assert_status('notneeded', get_result)\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_reckless(path, top_path):\n    ds = install(top_path, source=path, reckless=True)\n    eq_(ds.config.get('annex.hardlink', None), 'true')\n    eq_(ds.repo.repo_info()['untrusted repositories'][0]['here'], True)\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_install_recursive_repeat(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n    ok_clean_git(top_src.path)\n\n    # install top level:\n    top_ds = install(path, source=src)\n    ok_(top_ds.is_installed() is True)\n    sub1 = Dataset(opj(path, 'sub 1'))\n    ok_(sub1.is_installed() is False)\n    sub2 = Dataset(opj(path, 'sub 2'))\n    ok_(sub2.is_installed() is False)\n    subsub = Dataset(opj(path, 'sub 1', 'subsub'))\n    ok_(subsub.is_installed() is False)\n\n    # install again, now with data and recursive, but recursion_limit 1:\n    result = get(os.curdir, dataset=path, recursive=True, recursion_limit=1,\n                 result_xfm='datasets')\n    # top-level dataset was not reobtained\n    assert_not_in(top_ds, result)\n    assert_in(sub1, result)\n    assert_in(sub2, result)\n    assert_not_in(subsub, result)\n    ok_(top_ds.repo.file_has_content('top_file.txt') is True)\n    ok_(sub1.repo.file_has_content('sub1file.txt') is True)\n    ok_(sub2.repo.file_has_content('sub2file.txt') is True)\n\n    # install sub1 again, recursively and with data\n    top_ds.install('sub 1', recursive=True, get_data=True)\n    ok_(subsub.is_installed())\n    ok_(subsub.repo.file_has_content('subsubfile.txt'))\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\n@with_tempfile\ndef test_install_skip_list_arguments(src, path, path_outside):\n    ds = install(path, source=src)\n    ok_(ds.is_installed())\n\n    # install a list with valid and invalid items:\n    result = ds.install(\n        path=['subm 1', 'not_existing', path_outside, '2'],\n        get_data=False,\n        on_failure='ignore', result_xfm=None, return_type='list')\n    # good and bad results together\n    ok_(isinstance(result, list))\n    eq_(len(result), 4)\n    # check that we have an 'impossible' status for both invalid args\n    # but all the other tasks have been accomplished\n    for skipped, msg in [(opj(ds.path, 'not_existing'), \"path does not exist\"),\n                         (path_outside, \"path not associated with any dataset\")]:\n        assert_result_count(\n            result, 1, status='impossible', message=msg, path=skipped)\n    for sub in [Dataset(opj(path, 'subm 1')), Dataset(opj(path, '2'))]:\n        assert_result_count(\n            result, 1, status='ok',\n            message=('Installed subdataset in order to get %s', sub.path))\n        ok_(sub.is_installed())\n\n    # return of get is always a list, by default, even if just one thing was gotten\n    # in this case 'subm1' was already obtained above, so this will get this\n    # content of the subdataset\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(path=['subm 1', 'not_existing'])\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.get(path=['subm 1', 'not_existing'])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_skip_failed_recursive(src, path):\n\n    # install top level:\n    ds = install(path, source=src)\n    sub1 = Dataset(opj(path, 'subm 1'))\n    sub2 = Dataset(opj(path, '2'))\n    # sabotage recursive installation of 'subm 1' by polluting the target:\n    with open(opj(path, 'subm 1', 'blocking.txt'), \"w\") as f:\n        f.write(\"sdfdsf\")\n\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        result = ds.get(\n            os.curdir, recursive=True,\n            on_failure='ignore', result_xfm=None)\n        # toplevel dataset was in the house already\n        assert_result_count(\n            result, 0, path=ds.path, type='dataset')\n        # subm 1 should fail to install. [1] since comes after '2' submodule\n        assert_in_results(result, status='error', path=sub1.path)\n        assert_in_results(result, status='ok', path=sub2.path)\n\n        cml.assert_logged(\n            msg=\"target path already exists and not empty\".format(sub1.path),\n            regex=False, level='ERROR')\n    # this is not in effect that this message is not propagated up\n    # assert_in(\n    #     \"destination path '{}' already exists and is not an empty directory\".format(\n    #         sub1.path),\n    #     result[0]['message'][2])\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\ndef test_install_noautoget_data(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n\n    # install top level:\n    # don't filter implicitly installed subdataset to check them for content\n    cdss = install(path, source=src, recursive=True, result_filter=None)\n    # there should only be datasets in the list of installed items,\n    # and none of those should have any data for their annexed files yet\n    for ds in cdss:\n        assert_false(any(ds.repo.file_has_content(ds.repo.get_annexed_files())))\n\n\n@with_tempfile\n@with_tempfile\ndef test_install_source_relpath(src, dest):\n    ds1 = create(src)\n    src_ = basename(src)\n    with chpwd(dirname(src)):\n        ds2 = install(dest, source=src_)\n\n\n@integration  # 41.2043s\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_install_consistent_state(src, dest, dest2, dest3):\n    # if we install a dataset, where sub-dataset \"went ahead\" in that branch,\n    # while super-dataset was not yet updated (e.g. we installed super before)\n    # then it is desired to get that default installed branch to get to the\n    # position where previous location was pointing to.\n    # It is indeed a mere heuristic which might not hold the assumption in some\n    # cases, but it would work for most simple and thus mostly used ones\n    ds1 = create(src)\n    sub1 = ds1.create('sub1')\n\n    def check_consistent_installation(ds):\n        datasets = [ds] + list(\n            map(Dataset, ds.subdatasets(recursive=True, fulfilled=True,\n                                        result_xfm='paths')))\n        assert len(datasets) == 2  # in this test\n        for ds in datasets:\n            # all of them should be in master branch\n            eq_(ds.repo.get_active_branch(), \"master\")\n            # all of them should be clean, so sub should be installed in a \"version\"\n            # as pointed by the super\n            ok_(not ds.repo.dirty)\n\n    dest_ds = install(dest, source=src)\n    # now we progress sub1 by adding sub2\n    subsub2 = sub1.create('sub2')\n\n    # and progress subsub2 forward to stay really thorough\n    put_file_under_git(subsub2.path, 'file.dat', content=\"data\")\n    subsub2.save(\"added a file\")  # above function does not commit\n\n    # just installing a submodule -- apparently different code/logic\n    # but also the same story should hold - we should install the version pointed\n    # by the super, and stay all clean\n    dest_sub1 = dest_ds.install('sub1')\n    check_consistent_installation(dest_ds)\n\n    # So now we have source super-dataset \"dirty\" with sub1 progressed forward\n    # Our install should try to \"retain\" consistency of the installation\n    # whenever possible.\n\n    # install entire hierarchy without specifying dataset\n    # no filter, we want full report\n    dest2_ds = install(dest2, source=src, recursive=True, result_filter=None)\n    check_consistent_installation(dest2_ds[0])  # [1] is the subdataset\n\n    # install entire hierarchy by first installing top level ds\n    # and then specifying sub-dataset\n    dest3_ds = install(dest3, source=src, recursive=False)\n    # and then install both submodules recursively while pointing\n    # to it based on dest3_ds\n    dest3_ds.install('sub1', recursive=True)\n    check_consistent_installation(dest3_ds)\n\n    # TODO: makes a nice use-case for an update operation\n\n\nfrom datalad.tests.utils import skip_ssh\n\n@skip_ssh\n@with_tempfile\n@with_tempfile\ndef test_install_subds_with_space(opath, tpath):\n    ds = create(opath)\n    ds.create('sub ds')\n    # works even now, boring\n    # install(tpath, source=opath, recursive=True)\n    # do via ssh!\n    install(tpath, source=\"localhost:\" + opath, recursive=True)\n    assert Dataset(opj(tpath, 'sub ds')).is_installed()\n\n\n@skip_ssh\n@usecase\n@with_tempfile(mkdir=True)\ndef test_install_subds_from_another_remote(topdir):\n    # https://github.com/datalad/datalad/issues/1905\n    with chpwd(topdir):\n        origin_ = 'origin'\n        clone1_ = 'clone1'\n        clone2_ = 'clone2'\n\n        origin = create(origin_, no_annex=True)\n        clone1 = install(source=origin, path=clone1_)\n        # print(\"Initial clone\")\n        clone1.create_sibling('ssh://localhost%s/%s' % (getpwd(), clone2_), name=clone2_)\n\n        # print(\"Creating clone2\")\n        clone1.publish(to=clone2_)\n        clone2 = Dataset(clone2_)\n        # print(\"Initiating subdataset\")\n        clone2.create('subds1')\n\n        # print(\"Updating\")\n        clone1.update(merge=True, sibling=clone2_)\n        # print(\"Installing within updated dataset -- should be able to install from clone2\")\n        clone1.install('subds1')",
            "new_file_content": "# 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\"\"\"Test install action\n\n\"\"\"\n\nfrom datalad.tests.utils import known_failure_v6\nfrom datalad.tests.utils import known_failure_direct_mode\n\n\nimport logging\nimport os\n\nfrom os.path import join as opj\nfrom os.path import isdir\nfrom os.path import exists\nfrom os.path import realpath\nfrom os.path import basename\nfrom os.path import dirname\n\nfrom mock import patch\n\nfrom datalad.utils import getpwd\n\nfrom datalad.api import create\nfrom datalad.api import install\nfrom datalad.api import get\nfrom datalad import consts\nfrom datalad.utils import chpwd\nfrom datalad.interface.results import YieldDatasets\nfrom datalad.interface.results import YieldRelativePaths\nfrom datalad.support.exceptions import InsufficientArgumentsError\nfrom datalad.support.exceptions import InstallFailedError\nfrom datalad.support.exceptions import IncompleteResultsError\nfrom datalad.support.gitrepo import GitRepo\nfrom datalad.support.gitrepo import GitCommandError\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.cmd import Runner\nfrom datalad.tests.utils import create_tree\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import with_tree\nfrom datalad.tests.utils import with_testrepos\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import ok_\nfrom datalad.tests.utils import assert_false\nfrom datalad.tests.utils import ok_file_has_content\nfrom datalad.tests.utils import assert_not_in\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_is_instance\nfrom datalad.tests.utils import assert_result_count\nfrom datalad.tests.utils import assert_status\nfrom datalad.tests.utils import assert_in_results\nfrom datalad.tests.utils import assert_not_in_results\nfrom datalad.tests.utils import ok_startswith\nfrom datalad.tests.utils import ok_clean_git\nfrom datalad.tests.utils import serve_path_via_http\nfrom datalad.tests.utils import swallow_logs\nfrom datalad.tests.utils import use_cassette\nfrom datalad.tests.utils import skip_if_no_network\nfrom datalad.tests.utils import put_file_under_git\nfrom datalad.tests.utils import integration\nfrom datalad.tests.utils import slow\nfrom datalad.tests.utils import usecase\nfrom datalad.tests.utils import get_datasets_topdir\nfrom datalad.utils import _path_\nfrom datalad.utils import rmtree\n\nfrom ..dataset import Dataset\nfrom ..utils import _get_installationpath_from_url\nfrom ..utils import _get_git_url_from_source\n\n###############\n# Test helpers:\n###############\n\n\ndef test_installationpath_from_url():\n    for p in ('lastbit',\n              'lastbit/',\n              '/lastbit',\n              'lastbit.git',\n              'lastbit.git/',\n              'http://example.com/lastbit',\n              'http://example.com/lastbit.git',\n              'http://lastbit:8000'\n              ):\n        eq_(_get_installationpath_from_url(p), 'lastbit')\n    # we need to deal with quoted urls\n    for url in (\n        # although some docs say that space could've been replaced with +\n        'http://localhost:8000/+last%20bit',\n        'http://localhost:8000/%2Blast%20bit',\n        '///%2Blast%20bit',\n        '///d1/%2Blast%20bit',\n        '///d1/+last bit',\n    ):\n        eq_(_get_installationpath_from_url(url), '+last bit')\n\n\ndef test_get_git_url_from_source():\n\n    # resolves datalad RIs:\n    eq_(_get_git_url_from_source('///subds'), consts.DATASETS_TOPURL + 'subds')\n    assert_raises(NotImplementedError, _get_git_url_from_source,\n                  '//custom/subds')\n\n    # doesn't harm others:\n    eq_(_get_git_url_from_source('http://example.com'), 'http://example.com')\n    eq_(_get_git_url_from_source('/absolute/path'), '/absolute/path')\n    eq_(_get_git_url_from_source('file://localhost/some'),\n        'file://localhost/some')\n    eq_(_get_git_url_from_source('localhost/another/path'),\n        'localhost/another/path')\n    eq_(_get_git_url_from_source('user@someho.st/mydir'),\n        'user@someho.st/mydir')\n    eq_(_get_git_url_from_source('ssh://somewhe.re/else'),\n        'ssh://somewhe.re/else')\n    eq_(_get_git_url_from_source('git://github.com/datalad/testrepo--basic--r1'),\n        'git://github.com/datalad/testrepo--basic--r1')\n\n\n@with_tree(tree={'file.txt': '123'})\n@serve_path_via_http\n@with_tempfile\ndef _test_guess_dot_git(annex, path, url, tdir):\n    repo = (AnnexRepo if annex else GitRepo)(path, create=True)\n    repo.add('file.txt', commit=True, git=not annex)\n\n    # we need to prepare to be served via http, otherwise it must fail\n    with swallow_logs() as cml:\n        assert_raises(IncompleteResultsError, install, path=tdir, source=url)\n    ok_(not exists(tdir))\n\n    Runner(cwd=path)(['git', 'update-server-info'])\n\n    with swallow_logs() as cml:\n        installed = install(tdir, source=url)\n        assert_not_in(\"Failed to get annex.uuid\", cml.out)\n    eq_(realpath(installed.path), realpath(tdir))\n    ok_(exists(tdir))\n    ok_clean_git(tdir, annex=annex)\n\n\ndef test_guess_dot_git():\n    for annex in False, True:\n        yield _test_guess_dot_git, annex\n\n\n######################\n# Test actual Install:\n######################\n\ndef test_insufficient_args():\n    assert_raises(InsufficientArgumentsError, install)\n    assert_raises(InsufficientArgumentsError, install, description=\"some\")\n    assert_raises(InsufficientArgumentsError, install, None)\n    assert_raises(InsufficientArgumentsError, install, None, description=\"some\")\n\n\n@with_tempfile(mkdir=True)\ndef test_invalid_args(path):\n    assert_raises(IncompleteResultsError, install, 'Zoidberg', source='Zoidberg')\n    # install to an invalid URL\n    assert_raises(ValueError, install, 'ssh://mars:Zoidberg', source='Zoidberg')\n    # install to a remote location\n    assert_raises(ValueError, install, 'ssh://mars/Zoidberg', source='Zoidberg')\n    # make fake dataset\n    ds = create(path)\n    assert_raises(IncompleteResultsError, install, '/higherup.', 'Zoidberg', dataset=ds)\n\n\n# This test caused a mysterious segvault in gh-1350. I reimplementation of\n# the same test functionality in test_clone.py:test_clone_crcns that uses\n# `clone` instead of `install` passes without showing this behavior\n# This test is disabled until some insight into the cause of the issue\n# materializes.\n#@skip_if_no_network\n#@use_cassette('test_install_crcns')\n#@with_tempfile(mkdir=True)\n#@with_tempfile(mkdir=True)\n#def test_install_crcns(tdir, ds_path):\n#    with chpwd(tdir):\n#        with swallow_logs(new_level=logging.INFO) as cml:\n#            install(\"all-nonrecursive\", source='///')\n#            # since we didn't log decorations such as log level atm while\n#            # swallowing so lets check if exit code is returned or not\n#            # I will test both\n#            assert_not_in('ERROR', cml.out)\n#            # below one must not fail alone! ;)\n#            assert_not_in('with exit code', cml.out)\n#\n#        # should not hang in infinite recursion\n#        with chpwd('all-nonrecursive'):\n#            get(\"crcns\")\n#        ok_(exists(_path_(\"all-nonrecursive/crcns/.git/config\")))\n#        # and we could repeat installation and get the same result\n#        ds1 = install(_path_(\"all-nonrecursive/crcns\"))\n#        ok_(ds1.is_installed())\n#        ds2 = Dataset('all-nonrecursive').install('crcns')\n#        eq_(ds1, ds2)\n#        eq_(ds1.path, ds2.path)  # to make sure they are a single dataset\n#\n#    # again, but into existing dataset:\n#    ds = create(ds_path)\n#    crcns = ds.install(\"///crcns\")\n#    ok_(crcns.is_installed())\n#    eq_(crcns.path, opj(ds_path, \"crcns\"))\n#    assert_in(crcns.path, ds.get_subdatasets(absolute=True))\n\n\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tree(tree={'sub': {}})\ndef test_install_datasets_root(tdir):\n    with chpwd(tdir):\n        ds = install(\"///\")\n        ok_(ds.is_installed())\n        eq_(ds.path, opj(tdir, get_datasets_topdir()))\n\n        # do it a second time:\n        result = install(\"///\", result_xfm=None, return_type='list')\n        assert_status('notneeded', result)\n        eq_(YieldDatasets()(result[0]), ds)\n\n        # and a third time into an existing something, that is not a dataset:\n        with open(opj(tdir, 'sub', 'a_file.txt'), 'w') as f:\n            f.write(\"something\")\n\n        with assert_raises(IncompleteResultsError) as cme:\n            install(\"sub\", source='///')\n        assert_in(\"already exists and not empty\", str(cme.exception))\n\n\n@known_failure_v6  #FIXME\n@with_testrepos('.*basic.*', flavors=['local-url', 'network', 'local'])\n@with_tempfile(mkdir=True)\ndef test_install_simple_local(src, path):\n    origin = Dataset(path)\n\n    # now install it somewhere else\n    ds = install(path, source=src, description='mydummy')\n    eq_(ds.path, path)\n    ok_(ds.is_installed())\n    if not isinstance(origin.repo, AnnexRepo):\n        # this means it is a GitRepo\n        ok_(isinstance(origin.repo, GitRepo))\n        # stays plain Git repo\n        ok_(isinstance(ds.repo, GitRepo))\n        ok_(not isinstance(ds.repo, AnnexRepo))\n        ok_(GitRepo.is_valid_repo(ds.path))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt'})\n        ok_clean_git(path, annex=False)\n    else:\n        # must be an annex\n        ok_(isinstance(ds.repo, AnnexRepo))\n        ok_(AnnexRepo.is_valid_repo(ds.path, allow_noninitialized=False))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt', 'test-annex.dat'})\n        ok_clean_git(path, annex=True)\n        # no content was installed:\n        ok_(not ds.repo.file_has_content('test-annex.dat'))\n        uuid_before = ds.repo.uuid\n        eq_(ds.repo.get_description(), 'mydummy')\n\n    # installing it again, shouldn't matter:\n    res = install(path, source=src, result_xfm=None, return_type='list')\n    assert_status('notneeded', res)\n    ok_(ds.is_installed())\n    if isinstance(origin.repo, AnnexRepo):\n        eq_(uuid_before, ds.repo.uuid)\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local-url', 'network', 'local'])\n@with_tempfile\ndef test_install_dataset_from_just_source(url, path):\n    with chpwd(path, mkdir=True):\n        ds = install(source=url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_dataset_from_instance(src, dst):\n    origin = Dataset(src)\n    clone = install(source=origin, path=dst)\n\n    assert_is_instance(clone, Dataset)\n    ok_startswith(clone.path, dst)\n    ok_(clone.is_installed())\n    ok_(GitRepo.is_valid_repo(clone.path))\n    ok_clean_git(clone.path, annex=None)\n    assert_in('INFO.txt', clone.repo.get_indexed_files())\n\n\n@with_testrepos(flavors=['network'])\n@with_tempfile\n@known_failure_v6  #FIXME\ndef test_install_dataset_from_just_source_via_path(url, path):\n    # for remote urls only, the source could be given to `path`\n    # to allows for simplistic cmdline calls\n    # Q (ben): remote urls only? Sure? => TODO\n\n    with chpwd(path, mkdir=True):\n        ds = install(url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@with_tree(tree={\n    'ds': {'test.txt': 'some'},\n    })\n@serve_path_via_http\n@with_tempfile(mkdir=True)\ndef test_install_dataladri(src, topurl, path):\n    # make plain git repo\n    ds_path = opj(src, 'ds')\n    gr = GitRepo(ds_path, create=True)\n    gr.add('test.txt')\n    gr.commit('demo')\n    Runner(cwd=gr.path)(['git', 'update-server-info'])\n    # now install it somewhere else\n    with patch('datalad.consts.DATASETS_TOPURL', topurl), \\\n            swallow_logs():\n        ds = install(path, source='///ds')\n    eq_(ds.path, path)\n    ok_clean_git(path, annex=False)\n    ok_file_has_content(opj(path, 'test.txt'), 'some')\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\ndef test_install_recursive(src, path_nr, path_r):\n    # first install non-recursive:\n    ds = install(path_nr, source=src, recursive=False)\n    ok_(ds.is_installed())\n    for sub in ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(not sub.is_installed(),\n            \"Unintentionally installed: %s\" % (sub,))\n    # this also means, subdatasets to be listed as not fulfilled:\n    eq_(set(ds.subdatasets(recursive=True, fulfilled=False, result_xfm='relpaths')),\n        {'subm 1', '2'})\n\n    # now recursively:\n    # don't filter implicit results so we can inspect them\n    ds_list = install(path_r, source=src, recursive=True, result_filter=None)\n    # installed a dataset and two subdatasets\n    eq_(len(ds_list), 3)\n    eq_(sum([isinstance(i, Dataset) for i in ds_list]), 3)\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(ds_list[0].path, path_r)\n    top_ds = ds_list[0]\n    ok_(top_ds.is_installed())\n\n    # the subdatasets are contained in returned list:\n    # (Note: Until we provide proper (singleton) instances for Datasets,\n    # need to check for their paths)\n    assert_in(opj(top_ds.path, 'subm 1'), [i.path for i in ds_list])\n    assert_in(opj(top_ds.path, '2'), [i.path for i in ds_list])\n\n    eq_(len(top_ds.subdatasets(recursive=True)), 2)\n\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(),\n            \"Not installed: %s\" % (subds,))\n        # no content was installed:\n        ok_(not any(subds.repo.file_has_content(\n            subds.repo.get_annexed_files())))\n    # no unfulfilled subdatasets:\n    ok_(top_ds.subdatasets(recursive=True, fulfilled=False) == [])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_recursive_with_data(src, path):\n\n    # now again; with data:\n    res = install(path, source=src, recursive=True, get_data=True,\n                  result_filter=None, result_xfm=None)\n    assert_status('ok', res)\n    # installed a dataset and two subdatasets, and one file with content in\n    # each, plus the report that we got all content in each dataset's root dir\n    eq_(len(res), 9)\n    assert_result_count(res, 3, type='dataset')\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(res[0]['path'], path)\n    top_ds = YieldDatasets()(res[0])\n    ok_(top_ds.is_installed())\n    if isinstance(top_ds.repo, AnnexRepo):\n        ok_(all(top_ds.repo.file_has_content(top_ds.repo.get_annexed_files())))\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(), \"Not installed: %s\" % (subds,))\n        if isinstance(subds.repo, AnnexRepo):\n            ok_(all(subds.repo.file_has_content(subds.repo.get_annexed_files())))\n\n\n# @known_failure_direct_mode  #FIXME:\n# If we use all testrepos, we get a mixed hierarchy. Therefore ok_clean_git\n# fails if we are in direct mode and run into a plain git beneath an annex, due\n# to currently impossible recursion of `AnnexRepo._submodules_dirty_direct_mode`\n\n@slow  # 88.0869s  because of going through multiple test repos, ~8sec each time\n@with_testrepos('.*annex.*', flavors=['local'])\n# 'local-url', 'network'\n# TODO: Somehow annex gets confused while initializing installed ds, whose\n# .git/config show a submodule url \"file:///aaa/bbb%20b/...\"\n# this is delivered by with_testrepos as the url to clone\n@with_tempfile\ndef test_install_into_dataset(source, top_path):\n\n    ds = create(top_path)\n    ok_clean_git(ds.path)\n\n    subds = ds.install(\"sub\", source=source, save=False)\n    if isinstance(subds.repo, AnnexRepo) and subds.repo.is_direct_mode():\n        ok_(exists(opj(subds.path, '.git')))\n    else:\n        ok_(isdir(opj(subds.path, '.git')))\n    ok_(subds.is_installed())\n    assert_in('sub', ds.subdatasets(result_xfm='relpaths'))\n    # sub is clean:\n    ok_clean_git(subds.path, annex=None)\n    # top is too:\n    ok_clean_git(ds.path, annex=None)\n    ds.save('addsub')\n    # now it is:\n    ok_clean_git(ds.path, annex=None)\n\n    # but we could also save while installing and there should be no side-effect\n    # of saving any other changes if we state to not auto-save changes\n    # Create a dummy change\n    create_tree(ds.path, {'dummy.txt': 'buga'})\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n    subds_ = ds.install(\"sub2\", source=source)\n    eq_(subds_.path, opj(ds.path, \"sub2\"))  # for paranoid yoh ;)\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n    # and we should achieve the same behavior if we create a dataset\n    # and then decide to add it\n    create(_path_(top_path, 'sub3'))\n    ok_clean_git(ds.path, untracked=['dummy.txt', 'sub3/'])\n    ds.add('sub3')\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n\n@usecase  # 39.3074s\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_failed_install_multiple(top_path):\n    ds = create(top_path)\n\n    create(_path_(top_path, 'ds1'))\n    create(_path_(top_path, 'ds3'))\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n\n    # specify install with multiple paths and one non-existing\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(['ds1', 'ds2', '///crcns', '///nonexisting', 'ds3'],\n                   on_failure='continue')\n\n    # install doesn't add existing submodules -- add does that\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n    ds.add(['ds1', 'ds3'])\n    ok_clean_git(ds.path, annex=None)\n    # those which succeeded should be saved now\n    eq_(ds.subdatasets(result_xfm='relpaths'), ['crcns', 'ds1', 'ds3'])\n    # and those which didn't -- listed\n    eq_(set(r.get('source_url', r['path']) for r in cme.exception.failed),\n        {'///nonexisting', _path_(top_path, 'ds2')})\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\ndef test_install_known_subdataset(src, path):\n\n    # get the superdataset:\n    ds = install(path, source=src)\n    # subdataset not installed:\n    subds = Dataset(opj(path, 'subm 1'))\n    assert_false(subds.is_installed())\n    assert_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n    # install it:\n    ds.install('subm 1')\n    ok_(subds.is_installed())\n    ok_(AnnexRepo.is_valid_repo(subds.path, allow_noninitialized=False))\n    # Verify that it is the correct submodule installed and not\n    # new repository initiated\n    eq_(set(subds.repo.get_indexed_files()),\n        {'test.dat', 'INFO.txt', 'test-annex.dat'})\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n\n    # now, get the data by reinstalling with -g:\n    ok_(subds.repo.file_has_content('test-annex.dat') is False)\n    with chpwd(ds.path):\n        result = get(path='subm 1', dataset=os.curdir)\n        assert_in_results(result, path=opj(subds.path, 'test-annex.dat'))\n        ok_(subds.repo.file_has_content('test-annex.dat') is True)\n        ok_(subds.is_installed())\n\n\n@slow  # 46.3650s\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_implicit_install(src, dst):\n\n    origin_top = create(src)\n    origin_sub = origin_top.create(\"sub\")\n    origin_subsub = origin_sub.create(\"subsub\")\n    with open(opj(origin_top.path, \"file1.txt\"), \"w\") as f:\n        f.write(\"content1\")\n    origin_top.add(\"file1.txt\")\n    with open(opj(origin_sub.path, \"file2.txt\"), \"w\") as f:\n        f.write(\"content2\")\n    origin_sub.add(\"file2.txt\")\n    with open(opj(origin_subsub.path, \"file3.txt\"), \"w\") as f:\n        f.write(\"content3\")\n    origin_subsub.add(\"file3.txt\")\n    origin_top.save(recursive=True)\n\n    # first, install toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # fail on obscure non-existing one\n    assert_raises(IncompleteResultsError, ds.install, source='obscure')\n\n    # install 3rd level and therefore implicitly the 2nd:\n    result = ds.install(path=opj(\"sub\", \"subsub\"))\n    ok_(sub.is_installed())\n    ok_(subsub.is_installed())\n    # but by default implicit results are not reported\n    eq_(result, subsub)\n\n    # fail on obscure non-existing one in subds\n    assert_raises(IncompleteResultsError, ds.install, source=opj('sub', 'obscure'))\n\n    # clean up, the nasty way\n    rmtree(dst, chmod_files=True)\n    ok_(not exists(dst))\n\n    # again first toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # now implicit but without an explicit dataset to install into\n    # (deriving from CWD):\n    with chpwd(dst):\n        # don't ask for the file content to make return value comparison\n        # simpler\n        result = get(path=opj(\"sub\", \"subsub\"), get_data=False, result_xfm='datasets')\n        ok_(sub.is_installed())\n        ok_(subsub.is_installed())\n        eq_(result, [sub, subsub])\n\n\n@with_tempfile(mkdir=True)\ndef test_failed_install(dspath):\n    ds = create(dspath)\n    assert_raises(IncompleteResultsError,\n                  ds.install,\n                  \"sub\",\n                  source=\"http://nonexistingreallyanything.datalad.org/bla\")\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_list(path, top_path):\n\n    # we want to be able to install several things, if these are known\n    # (no 'source' allowed). Therefore first toplevel:\n    ds = install(top_path, source=path, recursive=False)\n    assert_not_in('annex.hardlink', ds.config)\n    ok_(ds.is_installed())\n    sub1 = Dataset(opj(top_path, 'subm 1'))\n    sub2 = Dataset(opj(top_path, '2'))\n    ok_(not sub1.is_installed())\n    ok_(not sub2.is_installed())\n\n    # fails, when `source` is passed:\n    assert_raises(ValueError, ds.install,\n                  path=['subm 1', '2'],\n                  source='something')\n\n    # now should work:\n    result = ds.install(path=['subm 1', '2'], result_xfm='paths')\n    ok_(sub1.is_installed())\n    ok_(sub2.is_installed())\n    eq_(set(result), {sub1.path, sub2.path})\n    # and if we request it again via get, result should be empty\n    get_result = ds.get(path=['subm 1', '2'], get_data=False)\n    assert_status('notneeded', get_result)\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_reckless(path, top_path):\n    ds = install(top_path, source=path, reckless=True)\n    eq_(ds.config.get('annex.hardlink', None), 'true')\n    eq_(ds.repo.repo_info()['untrusted repositories'][0]['here'], True)\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_install_recursive_repeat(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n    ok_clean_git(top_src.path)\n\n    # install top level:\n    top_ds = install(path, source=src)\n    ok_(top_ds.is_installed() is True)\n    sub1 = Dataset(opj(path, 'sub 1'))\n    ok_(sub1.is_installed() is False)\n    sub2 = Dataset(opj(path, 'sub 2'))\n    ok_(sub2.is_installed() is False)\n    subsub = Dataset(opj(path, 'sub 1', 'subsub'))\n    ok_(subsub.is_installed() is False)\n\n    # install again, now with data and recursive, but recursion_limit 1:\n    result = get(os.curdir, dataset=path, recursive=True, recursion_limit=1,\n                 result_xfm='datasets')\n    # top-level dataset was not reobtained\n    assert_not_in(top_ds, result)\n    assert_in(sub1, result)\n    assert_in(sub2, result)\n    assert_not_in(subsub, result)\n    ok_(top_ds.repo.file_has_content('top_file.txt') is True)\n    ok_(sub1.repo.file_has_content('sub1file.txt') is True)\n    ok_(sub2.repo.file_has_content('sub2file.txt') is True)\n\n    # install sub1 again, recursively and with data\n    top_ds.install('sub 1', recursive=True, get_data=True)\n    ok_(subsub.is_installed())\n    ok_(subsub.repo.file_has_content('subsubfile.txt'))\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\n@with_tempfile\ndef test_install_skip_list_arguments(src, path, path_outside):\n    ds = install(path, source=src)\n    ok_(ds.is_installed())\n\n    # install a list with valid and invalid items:\n    result = ds.install(\n        path=['subm 1', 'not_existing', path_outside, '2'],\n        get_data=False,\n        on_failure='ignore', result_xfm=None, return_type='list')\n    # good and bad results together\n    ok_(isinstance(result, list))\n    eq_(len(result), 4)\n    # check that we have an 'impossible' status for both invalid args\n    # but all the other tasks have been accomplished\n    for skipped, msg in [(opj(ds.path, 'not_existing'), \"path does not exist\"),\n                         (path_outside, \"path not associated with any dataset\")]:\n        assert_result_count(\n            result, 1, status='impossible', message=msg, path=skipped)\n    for sub in [Dataset(opj(path, 'subm 1')), Dataset(opj(path, '2'))]:\n        assert_result_count(\n            result, 1, status='ok',\n            message=('Installed subdataset in order to get %s', sub.path))\n        ok_(sub.is_installed())\n\n    # return of get is always a list, by default, even if just one thing was gotten\n    # in this case 'subm1' was already obtained above, so this will get this\n    # content of the subdataset\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(path=['subm 1', 'not_existing'])\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.get(path=['subm 1', 'not_existing'])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_skip_failed_recursive(src, path):\n\n    # install top level:\n    ds = install(path, source=src)\n    sub1 = Dataset(opj(path, 'subm 1'))\n    sub2 = Dataset(opj(path, '2'))\n    # sabotage recursive installation of 'subm 1' by polluting the target:\n    with open(opj(path, 'subm 1', 'blocking.txt'), \"w\") as f:\n        f.write(\"sdfdsf\")\n\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        result = ds.get(\n            os.curdir, recursive=True,\n            on_failure='ignore', result_xfm=None)\n        # toplevel dataset was in the house already\n        assert_result_count(\n            result, 0, path=ds.path, type='dataset')\n        # subm 1 should fail to install. [1] since comes after '2' submodule\n        assert_in_results(result, status='error', path=sub1.path)\n        assert_in_results(result, status='ok', path=sub2.path)\n\n        cml.assert_logged(\n            msg=\"target path already exists and not empty\".format(sub1.path),\n            regex=False, level='ERROR')\n    # this is not in effect that this message is not propagated up\n    # assert_in(\n    #     \"destination path '{}' already exists and is not an empty directory\".format(\n    #         sub1.path),\n    #     result[0]['message'][2])\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\ndef test_install_noautoget_data(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n\n    # install top level:\n    # don't filter implicitly installed subdataset to check them for content\n    cdss = install(path, source=src, recursive=True, result_filter=None)\n    # there should only be datasets in the list of installed items,\n    # and none of those should have any data for their annexed files yet\n    for ds in cdss:\n        assert_false(any(ds.repo.file_has_content(ds.repo.get_annexed_files())))\n\n\n@with_tempfile\n@with_tempfile\ndef test_install_source_relpath(src, dest):\n    ds1 = create(src)\n    src_ = basename(src)\n    with chpwd(dirname(src)):\n        ds2 = install(dest, source=src_)\n\n\n@integration  # 41.2043s\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_install_consistent_state(src, dest, dest2, dest3):\n    # if we install a dataset, where sub-dataset \"went ahead\" in that branch,\n    # while super-dataset was not yet updated (e.g. we installed super before)\n    # then it is desired to get that default installed branch to get to the\n    # position where previous location was pointing to.\n    # It is indeed a mere heuristic which might not hold the assumption in some\n    # cases, but it would work for most simple and thus mostly used ones\n    ds1 = create(src)\n    sub1 = ds1.create('sub1')\n\n    def check_consistent_installation(ds):\n        datasets = [ds] + list(\n            map(Dataset, ds.subdatasets(recursive=True, fulfilled=True,\n                                        result_xfm='paths')))\n        assert len(datasets) == 2  # in this test\n        for ds in datasets:\n            # all of them should be in master branch\n            eq_(ds.repo.get_active_branch(), \"master\")\n            # all of them should be clean, so sub should be installed in a \"version\"\n            # as pointed by the super\n            ok_(not ds.repo.dirty)\n\n    dest_ds = install(dest, source=src)\n    # now we progress sub1 by adding sub2\n    subsub2 = sub1.create('sub2')\n\n    # and progress subsub2 forward to stay really thorough\n    put_file_under_git(subsub2.path, 'file.dat', content=\"data\")\n    subsub2.save(\"added a file\")  # above function does not commit\n\n    # just installing a submodule -- apparently different code/logic\n    # but also the same story should hold - we should install the version pointed\n    # by the super, and stay all clean\n    dest_sub1 = dest_ds.install('sub1')\n    check_consistent_installation(dest_ds)\n\n    # So now we have source super-dataset \"dirty\" with sub1 progressed forward\n    # Our install should try to \"retain\" consistency of the installation\n    # whenever possible.\n\n    # install entire hierarchy without specifying dataset\n    # no filter, we want full report\n    dest2_ds = install(dest2, source=src, recursive=True, result_filter=None)\n    check_consistent_installation(dest2_ds[0])  # [1] is the subdataset\n\n    # install entire hierarchy by first installing top level ds\n    # and then specifying sub-dataset\n    dest3_ds = install(dest3, source=src, recursive=False)\n    # and then install both submodules recursively while pointing\n    # to it based on dest3_ds\n    dest3_ds.install('sub1', recursive=True)\n    check_consistent_installation(dest3_ds)\n\n    # TODO: makes a nice use-case for an update operation\n\n\nfrom datalad.tests.utils import skip_ssh\n\n@skip_ssh\n@with_tempfile\n@with_tempfile\ndef test_install_subds_with_space(opath, tpath):\n    ds = create(opath)\n    ds.create('sub ds')\n    # works even now, boring\n    # install(tpath, source=opath, recursive=True)\n    # do via ssh!\n    install(tpath, source=\"localhost:\" + opath, recursive=True)\n    assert Dataset(opj(tpath, 'sub ds')).is_installed()\n\n\n@skip_ssh\n@usecase\n@with_tempfile(mkdir=True)\ndef test_install_subds_from_another_remote(topdir):\n    # https://github.com/datalad/datalad/issues/1905\n    with chpwd(topdir):\n        origin_ = 'origin'\n        clone1_ = 'clone1'\n        clone2_ = 'clone2'\n\n        origin = create(origin_, no_annex=True)\n        clone1 = install(source=origin, path=clone1_)\n        # print(\"Initial clone\")\n        clone1.create_sibling('ssh://localhost%s/%s' % (getpwd(), clone2_), name=clone2_)\n\n        # print(\"Creating clone2\")\n        clone1.publish(to=clone2_)\n        clone2 = Dataset(clone2_)\n        # print(\"Initiating subdataset\")\n        clone2.create('subds1')\n\n        # print(\"Updating\")\n        clone1.update(merge=True, sibling=clone2_)\n        # print(\"Installing within updated dataset -- should be able to install from clone2\")\n        clone1.install('subds1')",
            "header": {
                "file": {
                    "path": "datalad/distribution/tests/test_install.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "32e2cfb2c",
                "new_commit_hash": "95ce3208d",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/distribution/tests/test_install.py"
            },
            "plus_file": {
                "path": "b/datalad/distribution/tests/test_install.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 88,
                            "length": 8
                        },
                        "new_range": {
                            "start": 88,
                            "length": 19
                        },
                        "section": "def test_installationpath_from_url():"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "              'lastbit.git/',",
                                "type": "context"
                            },
                            {
                                "content": "              'http://example.com/lastbit',",
                                "type": "context"
                            },
                            {
                                "content": "              'http://example.com/lastbit.git',",
                                "type": "context"
                            },
                            {
                                "content": "              'http://lastbit:8000'",
                                "type": "added"
                            },
                            {
                                "content": "              ):",
                                "type": "context"
                            },
                            {
                                "content": "        eq_(_get_installationpath_from_url(p), 'lastbit')",
                                "type": "context"
                            },
                            {
                                "content": "    # we need to deal with quoted urls",
                                "type": "added"
                            },
                            {
                                "content": "    for url in (",
                                "type": "added"
                            },
                            {
                                "content": "        # although some docs say that space could've been replaced with +",
                                "type": "added"
                            },
                            {
                                "content": "        'http://localhost:8000/+last%20bit',",
                                "type": "added"
                            },
                            {
                                "content": "        'http://localhost:8000/%2Blast%20bit',",
                                "type": "added"
                            },
                            {
                                "content": "        '///%2Blast%20bit',",
                                "type": "added"
                            },
                            {
                                "content": "        '///d1/%2Blast%20bit',",
                                "type": "added"
                            },
                            {
                                "content": "        '///d1/+last bit',",
                                "type": "added"
                            },
                            {
                                "content": "    ):",
                                "type": "added"
                            },
                            {
                                "content": "        eq_(_get_installationpath_from_url(url), '+last bit')",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "def test_get_git_url_from_source():",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/distribution/tests/test_install.py",
                            "type": "function",
                            "name": "test_installationpath_from_url",
                            "content": "def test_installationpath_from_url():\n    for p in ('lastbit',\n              'lastbit/',\n              '/lastbit',\n              'lastbit.git',\n              'lastbit.git/',\n              'http://example.com/lastbit',\n              'http://example.com/lastbit.git',\n              'http://lastbit:8000'\n              ):\n        eq_(_get_installationpath_from_url(p), 'lastbit')\n    # we need to deal with quoted urls\n    for url in (\n        # although some docs say that space could've been replaced with +\n        'http://localhost:8000/+last%20bit',\n        'http://localhost:8000/%2Blast%20bit',\n        '///%2Blast%20bit',\n        '///d1/%2Blast%20bit',\n        '///d1/+last bit',\n    ):\n        eq_(_get_installationpath_from_url(url), '+last bit')",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 83,
                            "end_lineno": 103,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "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\"\"\"Distribution utility functions\n\n\"\"\"\n\nimport logging\nfrom os.path import exists\nfrom os.path import isdir\nfrom os.path import join as opj\nfrom os.path import islink\nfrom os.path import isabs\nfrom os.path import normpath\nimport posixpath\n\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.support.network import DataLadRI\nfrom datalad.support.network import URL\nfrom datalad.support.network import RI\nfrom datalad.support.network import PathRI\nfrom datalad.utils import knows_annex\n\n\nlgr = logging.getLogger('datalad.distribution.utils')\n\n\ndef _fixup_submodule_dotgit_setup(ds, relativepath):\n    \"\"\"Implementation of our current of .git in a subdataset\n\n    Each subdataset/module has its own .git directory where a standalone\n    repository would have it. No gitdir files, no symlinks.\n    \"\"\"\n    # move .git to superrepo's .git/modules, remove .git, create\n    # .git-file\n    path = opj(ds.path, relativepath)\n    src_dotgit = get_git_dir(path)\n\n    # at this point install always yields the desired result\n    # just make sure\n    assert(src_dotgit == '.git')\n\n\ndef get_git_dir(path):\n    \"\"\"figure out a repo's gitdir\n\n    '.git' might be a  directory, a symlink or a file\n\n    Parameter\n    ---------\n    path: str\n      currently expected to be the repos base dir\n\n    Returns\n    -------\n    str\n      relative path to the repo's git dir; So, default would be \".git\"\n    \"\"\"\n\n    from os.path import isfile\n\n    dot_git = opj(path, \".git\")\n    if not exists(dot_git):\n        raise RuntimeError(\"Missing .git in %s.\" % path)\n    elif islink(dot_git):\n        # readlink cannot be imported on windows, but there should also\n        # be no symlinks\n        from os import readlink\n        git_dir = readlink(dot_git)\n    elif isdir(dot_git):\n        git_dir = \".git\"\n    elif isfile(dot_git):\n        with open(dot_git) as f:\n            git_dir = f.readline()\n            if git_dir.startswith(\"gitdir:\"):\n                git_dir = git_dir[7:]\n            git_dir = git_dir.strip()\n\n    return git_dir\n\n\ndef _get_git_url_from_source(source):\n    \"\"\"Return URL for cloning associated with a source specification\n\n    For now just resolves DataLadRIs\n    \"\"\"\n    # TODO: Probably RF this into RI.as_git_url(), that would be overridden\n    # by subclasses or sth. like that\n    if not isinstance(source, RI):\n        source_ri = RI(source)\n    else:\n        source_ri = source\n    if isinstance(source_ri, DataLadRI):\n        # we have got our DataLadRI as the source, so expand it\n        source = source_ri.as_git_url()\n    else:\n        source = str(source_ri)\n    return source\n\n\ndef _get_tracking_source(ds):\n    \"\"\"Returns name and url of a potential configured source\n    tracking remote\"\"\"\n    vcs = ds.repo\n    # if we have a remote, let's check the location of that remote\n    # for the presence of the desired submodule\n\n    remote_name, tracking_branch = vcs.get_tracking_branch()\n    # TODO: better default `None`? Check where we might rely on '':\n    remote_url = ''\n    if remote_name:\n        remote_url = vcs.get_remote_url(remote_name, push=False)\n\n    return remote_name, remote_url\n\n\ndef _get_flexible_source_candidates(src, base_url=None, alternate_suffix=True):\n    \"\"\"Get candidates to try cloning from.\n\n    Primarily to mitigate the problem that git doesn't append /.git\n    while cloning from non-bare repos over dummy protocol (http*).  Also to\n    simplify creation of urls whenever base url and relative path within it\n    provided\n\n    Parameters\n    ----------\n    src : string or RI\n      Full or relative (then considered within base_url if provided) path\n    base_url : string or RI, optional\n    alternate_suffix : bool\n      Whether to generate URL candidates with and without '/.git' suffixes.\n\n    Returns\n    -------\n    candidates : list of str\n      List of RIs (path, url, ssh targets) to try to install from\n    \"\"\"\n    candidates = []\n\n    ri = RI(src)\n    if isinstance(ri, PathRI) and not isabs(ri.path) and base_url:\n        ri = RI(base_url)\n        if ri.path.endswith('/.git'):\n            base_path = ri.path[:-5]\n            base_suffix = '.git'\n        else:\n            base_path = ri.path\n            base_suffix = ''\n        if isinstance(ri, PathRI):\n            # this is a path, so stay native\n            ri.path = normpath(opj(base_path, src, base_suffix))\n        else:\n            # we are handling a URL, use POSIX path conventions\n            ri.path = posixpath.normpath(\n                posixpath.join(base_path, src, base_suffix))\n\n    src = str(ri)\n\n    candidates.append(src)\n    if alternate_suffix and isinstance(ri, URL):\n        if ri.scheme in {'http', 'https'}:\n            # additionally try to consider .git:\n            if not src.rstrip('/').endswith('/.git'):\n                candidates.append(\n                    '{0}/.git'.format(src.rstrip('/')))\n\n    # TODO:\n    # We need to provide some error msg with InstallFailedError, since now\n    # it just swallows everything.\n    # yoh: not sure if this comment applies here, but could be still applicable\n    # outisde\n\n    return candidates\n\n\ndef _handle_possible_annex_dataset(dataset, reckless, description=None):\n    \"\"\"If dataset \"knows annex\" -- annex init it, set into reckless etc\n\n    Provides additional tune up to a possibly an annex repo, e.g.\n    \"enables\" reckless mode, sets up description\n    \"\"\"\n    # in any case check whether we need to annex-init the installed thing:\n    if not knows_annex(dataset.path):\n        # not for us\n        return\n\n    # init annex when traces of a remote annex can be detected\n    if reckless:\n        lgr.debug(\n            \"Instruct annex to hardlink content in %s from local \"\n            \"sources, if possible (reckless)\", dataset.path)\n        dataset.config.add(\n            'annex.hardlink', 'true', where='local', reload=True)\n    lgr.debug(\"Initializing annex repo at %s\", dataset.path)\n    # XXX this is rather convoluted, init does init, but cannot\n    # set a description without `create=True`\n    repo = AnnexRepo(dataset.path, init=True)\n    # so do manually see #1403\n    if description:\n        repo._init(description=description)\n    if reckless:\n        repo._run_annex_command('untrust', annex_options=['here'])\n    # go through list of special remotes and issue info message that\n    # some additional ones are present and were not auto-enabled\n    remote_names = repo.get_remotes(\n        with_urls_only=False,\n        exclude_special_remotes=False)\n    for k, v in repo.get_special_remotes().items():\n        sr_name = v.get('name', None)\n        if sr_name and sr_name not in remote_names:\n            # if it is not listed among the remotes, it wasn't enabled\n            lgr.info(\n                'access to dataset sibling \"%s\" not auto-enabled, enable with:\\n\\t\\tdatalad siblings -d \"%s\" enable -s %s',\n                sr_name,\n                dataset.path,\n                sr_name)\n\n\ndef _get_installationpath_from_url(url):\n    \"\"\"Returns a relative path derived from the trailing end of a URL\n\n    This can be used to determine an installation path of a Dataset\n    from a URL, analog to what `git clone` does.\n    \"\"\"\n    path = url.rstrip('/')\n    if '/' in path:\n        path = path.split('/')\n        if path[-1] == '.git':\n            path = path[-2]\n        else:\n            path = path[-1]\n    if path.endswith('.git'):\n        path = path[:-4]\n    return path\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\"\"\"Distribution utility functions\n\n\"\"\"\n\nimport logging\nimport re\n\nfrom os.path import exists\nfrom os.path import isdir\nfrom os.path import join as opj\nfrom os.path import islink\nfrom os.path import isabs\nfrom os.path import normpath\nimport posixpath\n\nfrom six.moves.urllib.parse import unquote as urlunquote\n\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.support.network import DataLadRI\nfrom datalad.support.network import URL\nfrom datalad.support.network import RI\nfrom datalad.support.network import PathRI\nfrom datalad.utils import knows_annex\n\n\nlgr = logging.getLogger('datalad.distribution.utils')\n\n\ndef _fixup_submodule_dotgit_setup(ds, relativepath):\n    \"\"\"Implementation of our current of .git in a subdataset\n\n    Each subdataset/module has its own .git directory where a standalone\n    repository would have it. No gitdir files, no symlinks.\n    \"\"\"\n    # move .git to superrepo's .git/modules, remove .git, create\n    # .git-file\n    path = opj(ds.path, relativepath)\n    src_dotgit = get_git_dir(path)\n\n    # at this point install always yields the desired result\n    # just make sure\n    assert(src_dotgit == '.git')\n\n\ndef get_git_dir(path):\n    \"\"\"figure out a repo's gitdir\n\n    '.git' might be a  directory, a symlink or a file\n\n    Parameter\n    ---------\n    path: str\n      currently expected to be the repos base dir\n\n    Returns\n    -------\n    str\n      relative path to the repo's git dir; So, default would be \".git\"\n    \"\"\"\n\n    from os.path import isfile\n\n    dot_git = opj(path, \".git\")\n    if not exists(dot_git):\n        raise RuntimeError(\"Missing .git in %s.\" % path)\n    elif islink(dot_git):\n        # readlink cannot be imported on windows, but there should also\n        # be no symlinks\n        from os import readlink\n        git_dir = readlink(dot_git)\n    elif isdir(dot_git):\n        git_dir = \".git\"\n    elif isfile(dot_git):\n        with open(dot_git) as f:\n            git_dir = f.readline()\n            if git_dir.startswith(\"gitdir:\"):\n                git_dir = git_dir[7:]\n            git_dir = git_dir.strip()\n\n    return git_dir\n\n\ndef _get_git_url_from_source(source):\n    \"\"\"Return URL for cloning associated with a source specification\n\n    For now just resolves DataLadRIs\n    \"\"\"\n    # TODO: Probably RF this into RI.as_git_url(), that would be overridden\n    # by subclasses or sth. like that\n    if not isinstance(source, RI):\n        source_ri = RI(source)\n    else:\n        source_ri = source\n    if isinstance(source_ri, DataLadRI):\n        # we have got our DataLadRI as the source, so expand it\n        source = source_ri.as_git_url()\n    else:\n        source = str(source_ri)\n    return source\n\n\ndef _get_tracking_source(ds):\n    \"\"\"Returns name and url of a potential configured source\n    tracking remote\"\"\"\n    vcs = ds.repo\n    # if we have a remote, let's check the location of that remote\n    # for the presence of the desired submodule\n\n    remote_name, tracking_branch = vcs.get_tracking_branch()\n    # TODO: better default `None`? Check where we might rely on '':\n    remote_url = ''\n    if remote_name:\n        remote_url = vcs.get_remote_url(remote_name, push=False)\n\n    return remote_name, remote_url\n\n\ndef _get_flexible_source_candidates(src, base_url=None, alternate_suffix=True):\n    \"\"\"Get candidates to try cloning from.\n\n    Primarily to mitigate the problem that git doesn't append /.git\n    while cloning from non-bare repos over dummy protocol (http*).  Also to\n    simplify creation of urls whenever base url and relative path within it\n    provided\n\n    Parameters\n    ----------\n    src : string or RI\n      Full or relative (then considered within base_url if provided) path\n    base_url : string or RI, optional\n    alternate_suffix : bool\n      Whether to generate URL candidates with and without '/.git' suffixes.\n\n    Returns\n    -------\n    candidates : list of str\n      List of RIs (path, url, ssh targets) to try to install from\n    \"\"\"\n    candidates = []\n\n    ri = RI(src)\n    if isinstance(ri, PathRI) and not isabs(ri.path) and base_url:\n        ri = RI(base_url)\n        if ri.path.endswith('/.git'):\n            base_path = ri.path[:-5]\n            base_suffix = '.git'\n        else:\n            base_path = ri.path\n            base_suffix = ''\n        if isinstance(ri, PathRI):\n            # this is a path, so stay native\n            ri.path = normpath(opj(base_path, src, base_suffix))\n        else:\n            # we are handling a URL, use POSIX path conventions\n            ri.path = posixpath.normpath(\n                posixpath.join(base_path, src, base_suffix))\n\n    src = str(ri)\n\n    candidates.append(src)\n    if alternate_suffix and isinstance(ri, URL):\n        if ri.scheme in {'http', 'https'}:\n            # additionally try to consider .git:\n            if not src.rstrip('/').endswith('/.git'):\n                candidates.append(\n                    '{0}/.git'.format(src.rstrip('/')))\n\n    # TODO:\n    # We need to provide some error msg with InstallFailedError, since now\n    # it just swallows everything.\n    # yoh: not sure if this comment applies here, but could be still applicable\n    # outisde\n\n    return candidates\n\n\ndef _handle_possible_annex_dataset(dataset, reckless, description=None):\n    \"\"\"If dataset \"knows annex\" -- annex init it, set into reckless etc\n\n    Provides additional tune up to a possibly an annex repo, e.g.\n    \"enables\" reckless mode, sets up description\n    \"\"\"\n    # in any case check whether we need to annex-init the installed thing:\n    if not knows_annex(dataset.path):\n        # not for us\n        return\n\n    # init annex when traces of a remote annex can be detected\n    if reckless:\n        lgr.debug(\n            \"Instruct annex to hardlink content in %s from local \"\n            \"sources, if possible (reckless)\", dataset.path)\n        dataset.config.add(\n            'annex.hardlink', 'true', where='local', reload=True)\n    lgr.debug(\"Initializing annex repo at %s\", dataset.path)\n    # XXX this is rather convoluted, init does init, but cannot\n    # set a description without `create=True`\n    repo = AnnexRepo(dataset.path, init=True)\n    # so do manually see #1403\n    if description:\n        repo._init(description=description)\n    if reckless:\n        repo._run_annex_command('untrust', annex_options=['here'])\n    # go through list of special remotes and issue info message that\n    # some additional ones are present and were not auto-enabled\n    remote_names = repo.get_remotes(\n        with_urls_only=False,\n        exclude_special_remotes=False)\n    for k, v in repo.get_special_remotes().items():\n        sr_name = v.get('name', None)\n        if sr_name and sr_name not in remote_names:\n            # if it is not listed among the remotes, it wasn't enabled\n            lgr.info(\n                'access to dataset sibling \"%s\" not auto-enabled, enable with:\\n\\t\\tdatalad siblings -d \"%s\" enable -s %s',\n                sr_name,\n                dataset.path,\n                sr_name)\n\n\ndef _get_installationpath_from_url(url):\n    \"\"\"Returns a relative path derived from the trailing end of a URL\n\n    This can be used to determine an installation path of a Dataset\n    from a URL, analog to what `git clone` does.\n    \"\"\"\n    ri = RI(url)\n    if isinstance(ri, (URL, DataLadRI)):  # decode only if URL\n        path = urlunquote(ri.path) or ri.hostname\n    else:\n        path = url\n    path = path.rstrip('/')\n    if '/' in path:\n        path = path.split('/')\n        if path[-1] == '.git':\n            path = path[-2]\n        else:\n            path = path[-1]\n    if path.endswith('.git'):\n        path = path[:-4]\n    return path\n",
            "header": {
                "file": {
                    "path": "datalad/distribution/utils.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "a069c2a2c",
                "new_commit_hash": "e813044ad",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/datalad/distribution/utils.py"
            },
            "plus_file": {
                "path": "b/datalad/distribution/utils.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 11,
                            "length": 6
                        },
                        "new_range": {
                            "start": 11,
                            "length": 8
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "\"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "import logging",
                                "type": "context"
                            },
                            {
                                "content": "import re",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "from os.path import exists",
                                "type": "context"
                            },
                            {
                                "content": "from os.path import isdir",
                                "type": "context"
                            },
                            {
                                "content": "from os.path import join as opj",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/distribution/utils.py",
                            "type": "import",
                            "name": "re",
                            "content": "import re",
                            "ast_type_str": "Import",
                            "start_lineno": 14,
                            "end_lineno": 14,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 19,
                            "length": 6
                        },
                        "new_range": {
                            "start": 21,
                            "length": 8
                        },
                        "section": "from os.path import isabs"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from os.path import normpath",
                                "type": "context"
                            },
                            {
                                "content": "import posixpath",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "from six.moves.urllib.parse import unquote as urlunquote",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "from datalad.support.annexrepo import AnnexRepo",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.support.network import DataLadRI",
                                "type": "context"
                            },
                            {
                                "content": "from datalad.support.network import URL",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "datalad/distribution/utils.py",
                            "type": "statement",
                            "name": "",
                            "content": "from six.moves.urllib.parse import unquote as urlunquote",
                            "ast_type_str": "ImportFrom",
                            "start_lineno": 24,
                            "end_lineno": 24,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 227,
                            "length": 7
                        },
                        "new_range": {
                            "start": 231,
                            "length": 12
                        },
                        "section": "def _get_installationpath_from_url(url):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "    This can be used to determine an installation path of a Dataset",
                                "type": "context"
                            },
                            {
                                "content": "    from a URL, analog to what `git clone` does.",
                                "type": "context"
                            },
                            {
                                "content": "    \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "    path = url.rstrip('/')",
                                "type": "deleted"
                            },
                            {
                                "content": "    ri = RI(url)",
                                "type": "added"
                            },
                            {
                                "content": "    if isinstance(ri, (URL, DataLadRI)):  # decode only if URL",
                                "type": "added"
                            },
                            {
                                "content": "        path = urlunquote(ri.path) or ri.hostname",
                                "type": "added"
                            },
                            {
                                "content": "    else:",
                                "type": "added"
                            },
                            {
                                "content": "        path = url",
                                "type": "added"
                            },
                            {
                                "content": "    path = path.rstrip('/')",
                                "type": "added"
                            },
                            {
                                "content": "    if '/' in path:",
                                "type": "context"
                            },
                            {
                                "content": "        path = path.split('/')",
                                "type": "context"
                            },
                            {
                                "content": "        if path[-1] == '.git':",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "datalad/distribution/utils.py",
                            "type": "function",
                            "name": "_get_installationpath_from_url",
                            "content": "def _get_installationpath_from_url(url):\n    \"\"\"Returns a relative path derived from the trailing end of a URL\n\n    This can be used to determine an installation path of a Dataset\n    from a URL, analog to what `git clone` does.\n    \"\"\"\n    path = url.rstrip('/')\n    if '/' in path:\n        path = path.split('/')\n        if path[-1] == '.git':\n            path = path[-2]\n        else:\n            path = path[-1]\n    if path.endswith('.git'):\n        path = path[:-4]\n    return path",
                            "ast_type_str": "FunctionDef",
                            "start_lineno": 224,
                            "end_lineno": 239,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "0dd56479fb13c5ff8010a1d2995e54b633a5f5ba^",
    "new_commit_hash": "0dd56479fb13c5ff8010a1d2995e54b633a5f5ba",
    "commit_message": "BF: urlunquote path while getting it from URL and DataladRI",
    "commit_date": "2018-02-26T13:26:53-05:00",
    "metadata": {}
}
{
    "repo_name": "datalad",
    "new_commit_hash": "0dd56479fb13c5ff8010a1d2995e54b633a5f5ba",
    "test_file_codes": [
        "# 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\"\"\"Test install action\n\n\"\"\"\n\nfrom datalad.tests.utils import known_failure_v6\nfrom datalad.tests.utils import known_failure_direct_mode\n\n\nimport logging\nimport os\n\nfrom os.path import join as opj\nfrom os.path import isdir\nfrom os.path import exists\nfrom os.path import realpath\nfrom os.path import basename\nfrom os.path import dirname\n\nfrom mock import patch\n\nfrom datalad.utils import getpwd\n\nfrom datalad.api import create\nfrom datalad.api import install\nfrom datalad.api import get\nfrom datalad import consts\nfrom datalad.utils import chpwd\nfrom datalad.interface.results import YieldDatasets\nfrom datalad.interface.results import YieldRelativePaths\nfrom datalad.support.exceptions import InsufficientArgumentsError\nfrom datalad.support.exceptions import InstallFailedError\nfrom datalad.support.exceptions import IncompleteResultsError\nfrom datalad.support.gitrepo import GitRepo\nfrom datalad.support.gitrepo import GitCommandError\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.cmd import Runner\nfrom datalad.tests.utils import create_tree\nfrom datalad.tests.utils import with_tempfile\nfrom datalad.tests.utils import assert_in\nfrom datalad.tests.utils import with_tree\nfrom datalad.tests.utils import with_testrepos\nfrom datalad.tests.utils import eq_\nfrom datalad.tests.utils import ok_\nfrom datalad.tests.utils import assert_false\nfrom datalad.tests.utils import ok_file_has_content\nfrom datalad.tests.utils import assert_not_in\nfrom datalad.tests.utils import assert_raises\nfrom datalad.tests.utils import assert_is_instance\nfrom datalad.tests.utils import assert_result_count\nfrom datalad.tests.utils import assert_status\nfrom datalad.tests.utils import assert_in_results\nfrom datalad.tests.utils import assert_not_in_results\nfrom datalad.tests.utils import ok_startswith\nfrom datalad.tests.utils import ok_clean_git\nfrom datalad.tests.utils import serve_path_via_http\nfrom datalad.tests.utils import swallow_logs\nfrom datalad.tests.utils import use_cassette\nfrom datalad.tests.utils import skip_if_no_network\nfrom datalad.tests.utils import put_file_under_git\nfrom datalad.tests.utils import integration\nfrom datalad.tests.utils import slow\nfrom datalad.tests.utils import usecase\nfrom datalad.tests.utils import get_datasets_topdir\nfrom datalad.utils import _path_\nfrom datalad.utils import rmtree\n\nfrom datalad.distribution.dataset import Dataset\nfrom datalad.distribution.utils import _get_installationpath_from_url\nfrom datalad.distribution.utils import _get_git_url_from_source\n\n###############\n# Test helpers:\n###############\n\n\ndef test_installationpath_from_url():\n    for p in ('lastbit',\n              'lastbit/',\n              '/lastbit',\n              'lastbit.git',\n              'lastbit.git/',\n              'http://example.com/lastbit',\n              'http://example.com/lastbit.git',\n              'http://lastbit:8000'\n              ):\n        eq_(_get_installationpath_from_url(p), 'lastbit')\n    # we need to deal with quoted urls\n    for url in (\n        # although some docs say that space could've been replaced with +\n        'http://localhost:8000/+last%20bit',\n        'http://localhost:8000/%2Blast%20bit',\n        '///%2Blast%20bit',\n        '///d1/%2Blast%20bit',\n        '///d1/+last bit',\n    ):\n        eq_(_get_installationpath_from_url(url), '+last bit')\n\n\ndef test_get_git_url_from_source():\n\n    # resolves datalad RIs:\n    eq_(_get_git_url_from_source('///subds'), consts.DATASETS_TOPURL + 'subds')\n    assert_raises(NotImplementedError, _get_git_url_from_source,\n                  '//custom/subds')\n\n    # doesn't harm others:\n    eq_(_get_git_url_from_source('http://example.com'), 'http://example.com')\n    eq_(_get_git_url_from_source('/absolute/path'), '/absolute/path')\n    eq_(_get_git_url_from_source('file://localhost/some'),\n        'file://localhost/some')\n    eq_(_get_git_url_from_source('localhost/another/path'),\n        'localhost/another/path')\n    eq_(_get_git_url_from_source('user@someho.st/mydir'),\n        'user@someho.st/mydir')\n    eq_(_get_git_url_from_source('ssh://somewhe.re/else'),\n        'ssh://somewhe.re/else')\n    eq_(_get_git_url_from_source('git://github.com/datalad/testrepo--basic--r1'),\n        'git://github.com/datalad/testrepo--basic--r1')\n\n\n@with_tree(tree={'file.txt': '123'})\n@serve_path_via_http\n@with_tempfile\ndef _test_guess_dot_git(annex, path, url, tdir):\n    repo = (AnnexRepo if annex else GitRepo)(path, create=True)\n    repo.add('file.txt', commit=True, git=not annex)\n\n    # we need to prepare to be served via http, otherwise it must fail\n    with swallow_logs() as cml:\n        assert_raises(IncompleteResultsError, install, path=tdir, source=url)\n    ok_(not exists(tdir))\n\n    Runner(cwd=path)(['git', 'update-server-info'])\n\n    with swallow_logs() as cml:\n        installed = install(tdir, source=url)\n        assert_not_in(\"Failed to get annex.uuid\", cml.out)\n    eq_(realpath(installed.path), realpath(tdir))\n    ok_(exists(tdir))\n    ok_clean_git(tdir, annex=annex)\n\n\ndef test_guess_dot_git():\n    for annex in False, True:\n        yield _test_guess_dot_git, annex\n\n\n######################\n# Test actual Install:\n######################\n\ndef test_insufficient_args():\n    assert_raises(InsufficientArgumentsError, install)\n    assert_raises(InsufficientArgumentsError, install, description=\"some\")\n    assert_raises(InsufficientArgumentsError, install, None)\n    assert_raises(InsufficientArgumentsError, install, None, description=\"some\")\n\n\n@with_tempfile(mkdir=True)\ndef test_invalid_args(path):\n    assert_raises(IncompleteResultsError, install, 'Zoidberg', source='Zoidberg')\n    # install to an invalid URL\n    assert_raises(ValueError, install, 'ssh://mars:Zoidberg', source='Zoidberg')\n    # install to a remote location\n    assert_raises(ValueError, install, 'ssh://mars/Zoidberg', source='Zoidberg')\n    # make fake dataset\n    ds = create(path)\n    assert_raises(IncompleteResultsError, install, '/higherup.', 'Zoidberg', dataset=ds)\n\n\n# This test caused a mysterious segvault in gh-1350. I reimplementation of\n# the same test functionality in test_clone.py:test_clone_crcns that uses\n# `clone` instead of `install` passes without showing this behavior\n# This test is disabled until some insight into the cause of the issue\n# materializes.\n#@skip_if_no_network\n#@use_cassette('test_install_crcns')\n#@with_tempfile(mkdir=True)\n#@with_tempfile(mkdir=True)\n#def test_install_crcns(tdir, ds_path):\n#    with chpwd(tdir):\n#        with swallow_logs(new_level=logging.INFO) as cml:\n#            install(\"all-nonrecursive\", source='///')\n#            # since we didn't log decorations such as log level atm while\n#            # swallowing so lets check if exit code is returned or not\n#            # I will test both\n#            assert_not_in('ERROR', cml.out)\n#            # below one must not fail alone! ;)\n#            assert_not_in('with exit code', cml.out)\n#\n#        # should not hang in infinite recursion\n#        with chpwd('all-nonrecursive'):\n#            get(\"crcns\")\n#        ok_(exists(_path_(\"all-nonrecursive/crcns/.git/config\")))\n#        # and we could repeat installation and get the same result\n#        ds1 = install(_path_(\"all-nonrecursive/crcns\"))\n#        ok_(ds1.is_installed())\n#        ds2 = Dataset('all-nonrecursive').install('crcns')\n#        eq_(ds1, ds2)\n#        eq_(ds1.path, ds2.path)  # to make sure they are a single dataset\n#\n#    # again, but into existing dataset:\n#    ds = create(ds_path)\n#    crcns = ds.install(\"///crcns\")\n#    ok_(crcns.is_installed())\n#    eq_(crcns.path, opj(ds_path, \"crcns\"))\n#    assert_in(crcns.path, ds.get_subdatasets(absolute=True))\n\n\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tree(tree={'sub': {}})\ndef test_install_datasets_root(tdir):\n    with chpwd(tdir):\n        ds = install(\"///\")\n        ok_(ds.is_installed())\n        eq_(ds.path, opj(tdir, get_datasets_topdir()))\n\n        # do it a second time:\n        result = install(\"///\", result_xfm=None, return_type='list')\n        assert_status('notneeded', result)\n        eq_(YieldDatasets()(result[0]), ds)\n\n        # and a third time into an existing something, that is not a dataset:\n        with open(opj(tdir, 'sub', 'a_file.txt'), 'w') as f:\n            f.write(\"something\")\n\n        with assert_raises(IncompleteResultsError) as cme:\n            install(\"sub\", source='///')\n        assert_in(\"already exists and not empty\", str(cme.exception))\n\n\n@known_failure_v6  #FIXME\n@with_testrepos('.*basic.*', flavors=['local-url', 'network', 'local'])\n@with_tempfile(mkdir=True)\ndef test_install_simple_local(src, path):\n    origin = Dataset(path)\n\n    # now install it somewhere else\n    ds = install(path, source=src, description='mydummy')\n    eq_(ds.path, path)\n    ok_(ds.is_installed())\n    if not isinstance(origin.repo, AnnexRepo):\n        # this means it is a GitRepo\n        ok_(isinstance(origin.repo, GitRepo))\n        # stays plain Git repo\n        ok_(isinstance(ds.repo, GitRepo))\n        ok_(not isinstance(ds.repo, AnnexRepo))\n        ok_(GitRepo.is_valid_repo(ds.path))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt'})\n        ok_clean_git(path, annex=False)\n    else:\n        # must be an annex\n        ok_(isinstance(ds.repo, AnnexRepo))\n        ok_(AnnexRepo.is_valid_repo(ds.path, allow_noninitialized=False))\n        eq_(set(ds.repo.get_indexed_files()),\n            {'test.dat', 'INFO.txt', 'test-annex.dat'})\n        ok_clean_git(path, annex=True)\n        # no content was installed:\n        ok_(not ds.repo.file_has_content('test-annex.dat'))\n        uuid_before = ds.repo.uuid\n        eq_(ds.repo.get_description(), 'mydummy')\n\n    # installing it again, shouldn't matter:\n    res = install(path, source=src, result_xfm=None, return_type='list')\n    assert_status('notneeded', res)\n    ok_(ds.is_installed())\n    if isinstance(origin.repo, AnnexRepo):\n        eq_(uuid_before, ds.repo.uuid)\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local-url', 'network', 'local'])\n@with_tempfile\ndef test_install_dataset_from_just_source(url, path):\n    with chpwd(path, mkdir=True):\n        ds = install(source=url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@known_failure_v6  #FIXME\n@with_testrepos(flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_dataset_from_instance(src, dst):\n    origin = Dataset(src)\n    clone = install(source=origin, path=dst)\n\n    assert_is_instance(clone, Dataset)\n    ok_startswith(clone.path, dst)\n    ok_(clone.is_installed())\n    ok_(GitRepo.is_valid_repo(clone.path))\n    ok_clean_git(clone.path, annex=None)\n    assert_in('INFO.txt', clone.repo.get_indexed_files())\n\n\n@with_testrepos(flavors=['network'])\n@with_tempfile\n@known_failure_v6  #FIXME\ndef test_install_dataset_from_just_source_via_path(url, path):\n    # for remote urls only, the source could be given to `path`\n    # to allows for simplistic cmdline calls\n    # Q (ben): remote urls only? Sure? => TODO\n\n    with chpwd(path, mkdir=True):\n        ds = install(url)\n\n    ok_startswith(ds.path, path)\n    ok_(ds.is_installed())\n    ok_(GitRepo.is_valid_repo(ds.path))\n    ok_clean_git(ds.path, annex=None)\n    assert_in('INFO.txt', ds.repo.get_indexed_files())\n\n\n@with_tree(tree={\n    'ds': {'test.txt': 'some'},\n    })\n@serve_path_via_http\n@with_tempfile(mkdir=True)\ndef test_install_dataladri(src, topurl, path):\n    # make plain git repo\n    ds_path = opj(src, 'ds')\n    gr = GitRepo(ds_path, create=True)\n    gr.add('test.txt')\n    gr.commit('demo')\n    Runner(cwd=gr.path)(['git', 'update-server-info'])\n    # now install it somewhere else\n    with patch('datalad.consts.DATASETS_TOPURL', topurl), \\\n            swallow_logs():\n        ds = install(path, source='///ds')\n    eq_(ds.path, path)\n    ok_clean_git(path, annex=False)\n    ok_file_has_content(opj(path, 'test.txt'), 'some')\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\ndef test_install_recursive(src, path_nr, path_r):\n    # first install non-recursive:\n    ds = install(path_nr, source=src, recursive=False)\n    ok_(ds.is_installed())\n    for sub in ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(not sub.is_installed(),\n            \"Unintentionally installed: %s\" % (sub,))\n    # this also means, subdatasets to be listed as not fulfilled:\n    eq_(set(ds.subdatasets(recursive=True, fulfilled=False, result_xfm='relpaths')),\n        {'subm 1', '2'})\n\n    # now recursively:\n    # don't filter implicit results so we can inspect them\n    ds_list = install(path_r, source=src, recursive=True, result_filter=None)\n    # installed a dataset and two subdatasets\n    eq_(len(ds_list), 3)\n    eq_(sum([isinstance(i, Dataset) for i in ds_list]), 3)\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(ds_list[0].path, path_r)\n    top_ds = ds_list[0]\n    ok_(top_ds.is_installed())\n\n    # the subdatasets are contained in returned list:\n    # (Note: Until we provide proper (singleton) instances for Datasets,\n    # need to check for their paths)\n    assert_in(opj(top_ds.path, 'subm 1'), [i.path for i in ds_list])\n    assert_in(opj(top_ds.path, '2'), [i.path for i in ds_list])\n\n    eq_(len(top_ds.subdatasets(recursive=True)), 2)\n\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(),\n            \"Not installed: %s\" % (subds,))\n        # no content was installed:\n        ok_(not any(subds.repo.file_has_content(\n            subds.repo.get_annexed_files())))\n    # no unfulfilled subdatasets:\n    ok_(top_ds.subdatasets(recursive=True, fulfilled=False) == [])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_recursive_with_data(src, path):\n\n    # now again; with data:\n    res = install(path, source=src, recursive=True, get_data=True,\n                  result_filter=None, result_xfm=None)\n    assert_status('ok', res)\n    # installed a dataset and two subdatasets, and one file with content in\n    # each, plus the report that we got all content in each dataset's root dir\n    eq_(len(res), 9)\n    assert_result_count(res, 3, type='dataset')\n    # we recurse top down during installation, so toplevel should appear at\n    # first position in returned list\n    eq_(res[0]['path'], path)\n    top_ds = YieldDatasets()(res[0])\n    ok_(top_ds.is_installed())\n    if isinstance(top_ds.repo, AnnexRepo):\n        ok_(all(top_ds.repo.file_has_content(top_ds.repo.get_annexed_files())))\n    for subds in top_ds.subdatasets(recursive=True, result_xfm='datasets'):\n        ok_(subds.is_installed(), \"Not installed: %s\" % (subds,))\n        if isinstance(subds.repo, AnnexRepo):\n            ok_(all(subds.repo.file_has_content(subds.repo.get_annexed_files())))\n\n\n# @known_failure_direct_mode  #FIXME:\n# If we use all testrepos, we get a mixed hierarchy. Therefore ok_clean_git\n# fails if we are in direct mode and run into a plain git beneath an annex, due\n# to currently impossible recursion of `AnnexRepo._submodules_dirty_direct_mode`\n\n@slow  # 88.0869s  because of going through multiple test repos, ~8sec each time\n@with_testrepos('.*annex.*', flavors=['local'])\n# 'local-url', 'network'\n# TODO: Somehow annex gets confused while initializing installed ds, whose\n# .git/config show a submodule url \"file:///aaa/bbb%20b/...\"\n# this is delivered by with_testrepos as the url to clone\n@with_tempfile\ndef test_install_into_dataset(source, top_path):\n\n    ds = create(top_path)\n    ok_clean_git(ds.path)\n\n    subds = ds.install(\"sub\", source=source, save=False)\n    if isinstance(subds.repo, AnnexRepo) and subds.repo.is_direct_mode():\n        ok_(exists(opj(subds.path, '.git')))\n    else:\n        ok_(isdir(opj(subds.path, '.git')))\n    ok_(subds.is_installed())\n    assert_in('sub', ds.subdatasets(result_xfm='relpaths'))\n    # sub is clean:\n    ok_clean_git(subds.path, annex=None)\n    # top is too:\n    ok_clean_git(ds.path, annex=None)\n    ds.save('addsub')\n    # now it is:\n    ok_clean_git(ds.path, annex=None)\n\n    # but we could also save while installing and there should be no side-effect\n    # of saving any other changes if we state to not auto-save changes\n    # Create a dummy change\n    create_tree(ds.path, {'dummy.txt': 'buga'})\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n    subds_ = ds.install(\"sub2\", source=source)\n    eq_(subds_.path, opj(ds.path, \"sub2\"))  # for paranoid yoh ;)\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n    # and we should achieve the same behavior if we create a dataset\n    # and then decide to add it\n    create(_path_(top_path, 'sub3'))\n    ok_clean_git(ds.path, untracked=['dummy.txt', 'sub3/'])\n    ds.add('sub3')\n    ok_clean_git(ds.path, untracked=['dummy.txt'])\n\n\n@usecase  # 39.3074s\n@skip_if_no_network\n@use_cassette('test_install_crcns')\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_failed_install_multiple(top_path):\n    ds = create(top_path)\n\n    create(_path_(top_path, 'ds1'))\n    create(_path_(top_path, 'ds3'))\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n\n    # specify install with multiple paths and one non-existing\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(['ds1', 'ds2', '///crcns', '///nonexisting', 'ds3'],\n                   on_failure='continue')\n\n    # install doesn't add existing submodules -- add does that\n    ok_clean_git(ds.path, annex=None, untracked=['ds1/', 'ds3/'])\n    ds.add(['ds1', 'ds3'])\n    ok_clean_git(ds.path, annex=None)\n    # those which succeeded should be saved now\n    eq_(ds.subdatasets(result_xfm='relpaths'), ['crcns', 'ds1', 'ds3'])\n    # and those which didn't -- listed\n    eq_(set(r.get('source_url', r['path']) for r in cme.exception.failed),\n        {'///nonexisting', _path_(top_path, 'ds2')})\n\n\n@with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n@with_tempfile(mkdir=True)\ndef test_install_known_subdataset(src, path):\n\n    # get the superdataset:\n    ds = install(path, source=src)\n    # subdataset not installed:\n    subds = Dataset(opj(path, 'subm 1'))\n    assert_false(subds.is_installed())\n    assert_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n    # install it:\n    ds.install('subm 1')\n    ok_(subds.is_installed())\n    ok_(AnnexRepo.is_valid_repo(subds.path, allow_noninitialized=False))\n    # Verify that it is the correct submodule installed and not\n    # new repository initiated\n    eq_(set(subds.repo.get_indexed_files()),\n        {'test.dat', 'INFO.txt', 'test-annex.dat'})\n    assert_not_in('subm 1', ds.subdatasets(fulfilled=False, result_xfm='relpaths'))\n    assert_in('subm 1', ds.subdatasets(fulfilled=True, result_xfm='relpaths'))\n\n    # now, get the data by reinstalling with -g:\n    ok_(subds.repo.file_has_content('test-annex.dat') is False)\n    with chpwd(ds.path):\n        result = get(path='subm 1', dataset=os.curdir)\n        assert_in_results(result, path=opj(subds.path, 'test-annex.dat'))\n        ok_(subds.repo.file_has_content('test-annex.dat') is True)\n        ok_(subds.is_installed())\n\n\n@slow  # 46.3650s\n@with_tempfile(mkdir=True)\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_implicit_install(src, dst):\n\n    origin_top = create(src)\n    origin_sub = origin_top.create(\"sub\")\n    origin_subsub = origin_sub.create(\"subsub\")\n    with open(opj(origin_top.path, \"file1.txt\"), \"w\") as f:\n        f.write(\"content1\")\n    origin_top.add(\"file1.txt\")\n    with open(opj(origin_sub.path, \"file2.txt\"), \"w\") as f:\n        f.write(\"content2\")\n    origin_sub.add(\"file2.txt\")\n    with open(opj(origin_subsub.path, \"file3.txt\"), \"w\") as f:\n        f.write(\"content3\")\n    origin_subsub.add(\"file3.txt\")\n    origin_top.save(recursive=True)\n\n    # first, install toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # fail on obscure non-existing one\n    assert_raises(IncompleteResultsError, ds.install, source='obscure')\n\n    # install 3rd level and therefore implicitly the 2nd:\n    result = ds.install(path=opj(\"sub\", \"subsub\"))\n    ok_(sub.is_installed())\n    ok_(subsub.is_installed())\n    # but by default implicit results are not reported\n    eq_(result, subsub)\n\n    # fail on obscure non-existing one in subds\n    assert_raises(IncompleteResultsError, ds.install, source=opj('sub', 'obscure'))\n\n    # clean up, the nasty way\n    rmtree(dst, chmod_files=True)\n    ok_(not exists(dst))\n\n    # again first toplevel:\n    ds = install(dst, source=src)\n    ok_(ds.is_installed())\n    sub = Dataset(opj(ds.path, \"sub\"))\n    ok_(not sub.is_installed())\n    subsub = Dataset(opj(sub.path, \"subsub\"))\n    ok_(not subsub.is_installed())\n\n    # now implicit but without an explicit dataset to install into\n    # (deriving from CWD):\n    with chpwd(dst):\n        # don't ask for the file content to make return value comparison\n        # simpler\n        result = get(path=opj(\"sub\", \"subsub\"), get_data=False, result_xfm='datasets')\n        ok_(sub.is_installed())\n        ok_(subsub.is_installed())\n        eq_(result, [sub, subsub])\n\n\n@with_tempfile(mkdir=True)\ndef test_failed_install(dspath):\n    ds = create(dspath)\n    assert_raises(IncompleteResultsError,\n                  ds.install,\n                  \"sub\",\n                  source=\"http://nonexistingreallyanything.datalad.org/bla\")\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_list(path, top_path):\n\n    # we want to be able to install several things, if these are known\n    # (no 'source' allowed). Therefore first toplevel:\n    ds = install(top_path, source=path, recursive=False)\n    assert_not_in('annex.hardlink', ds.config)\n    ok_(ds.is_installed())\n    sub1 = Dataset(opj(top_path, 'subm 1'))\n    sub2 = Dataset(opj(top_path, '2'))\n    ok_(not sub1.is_installed())\n    ok_(not sub2.is_installed())\n\n    # fails, when `source` is passed:\n    assert_raises(ValueError, ds.install,\n                  path=['subm 1', '2'],\n                  source='something')\n\n    # now should work:\n    result = ds.install(path=['subm 1', '2'], result_xfm='paths')\n    ok_(sub1.is_installed())\n    ok_(sub2.is_installed())\n    eq_(set(result), {sub1.path, sub2.path})\n    # and if we request it again via get, result should be empty\n    get_result = ds.get(path=['subm 1', '2'], get_data=False)\n    assert_status('notneeded', get_result)\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_reckless(path, top_path):\n    ds = install(top_path, source=path, reckless=True)\n    eq_(ds.config.get('annex.hardlink', None), 'true')\n    eq_(ds.repo.repo_info()['untrusted repositories'][0]['here'], True)\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\n@known_failure_direct_mode  #FIXME\ndef test_install_recursive_repeat(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n    ok_clean_git(top_src.path)\n\n    # install top level:\n    top_ds = install(path, source=src)\n    ok_(top_ds.is_installed() is True)\n    sub1 = Dataset(opj(path, 'sub 1'))\n    ok_(sub1.is_installed() is False)\n    sub2 = Dataset(opj(path, 'sub 2'))\n    ok_(sub2.is_installed() is False)\n    subsub = Dataset(opj(path, 'sub 1', 'subsub'))\n    ok_(subsub.is_installed() is False)\n\n    # install again, now with data and recursive, but recursion_limit 1:\n    result = get(os.curdir, dataset=path, recursive=True, recursion_limit=1,\n                 result_xfm='datasets')\n    # top-level dataset was not reobtained\n    assert_not_in(top_ds, result)\n    assert_in(sub1, result)\n    assert_in(sub2, result)\n    assert_not_in(subsub, result)\n    ok_(top_ds.repo.file_has_content('top_file.txt') is True)\n    ok_(sub1.repo.file_has_content('sub1file.txt') is True)\n    ok_(sub2.repo.file_has_content('sub2file.txt') is True)\n\n    # install sub1 again, recursively and with data\n    top_ds.install('sub 1', recursive=True, get_data=True)\n    ok_(subsub.is_installed())\n    ok_(subsub.repo.file_has_content('subsubfile.txt'))\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\n@with_tempfile\ndef test_install_skip_list_arguments(src, path, path_outside):\n    ds = install(path, source=src)\n    ok_(ds.is_installed())\n\n    # install a list with valid and invalid items:\n    result = ds.install(\n        path=['subm 1', 'not_existing', path_outside, '2'],\n        get_data=False,\n        on_failure='ignore', result_xfm=None, return_type='list')\n    # good and bad results together\n    ok_(isinstance(result, list))\n    eq_(len(result), 4)\n    # check that we have an 'impossible' status for both invalid args\n    # but all the other tasks have been accomplished\n    for skipped, msg in [(opj(ds.path, 'not_existing'), \"path does not exist\"),\n                         (path_outside, \"path not associated with any dataset\")]:\n        assert_result_count(\n            result, 1, status='impossible', message=msg, path=skipped)\n    for sub in [Dataset(opj(path, 'subm 1')), Dataset(opj(path, '2'))]:\n        assert_result_count(\n            result, 1, status='ok',\n            message=('Installed subdataset in order to get %s', sub.path))\n        ok_(sub.is_installed())\n\n    # return of get is always a list, by default, even if just one thing was gotten\n    # in this case 'subm1' was already obtained above, so this will get this\n    # content of the subdataset\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.install(path=['subm 1', 'not_existing'])\n    with assert_raises(IncompleteResultsError) as cme:\n        ds.get(path=['subm 1', 'not_existing'])\n\n\n@with_testrepos('submodule_annex', flavors=['local'])\n@with_tempfile(mkdir=True)\ndef test_install_skip_failed_recursive(src, path):\n\n    # install top level:\n    ds = install(path, source=src)\n    sub1 = Dataset(opj(path, 'subm 1'))\n    sub2 = Dataset(opj(path, '2'))\n    # sabotage recursive installation of 'subm 1' by polluting the target:\n    with open(opj(path, 'subm 1', 'blocking.txt'), \"w\") as f:\n        f.write(\"sdfdsf\")\n\n    with swallow_logs(new_level=logging.WARNING) as cml:\n        result = ds.get(\n            os.curdir, recursive=True,\n            on_failure='ignore', result_xfm=None)\n        # toplevel dataset was in the house already\n        assert_result_count(\n            result, 0, path=ds.path, type='dataset')\n        # subm 1 should fail to install. [1] since comes after '2' submodule\n        assert_in_results(result, status='error', path=sub1.path)\n        assert_in_results(result, status='ok', path=sub2.path)\n\n        cml.assert_logged(\n            msg=\"target path already exists and not empty\".format(sub1.path),\n            regex=False, level='ERROR')\n    # this is not in effect that this message is not propagated up\n    # assert_in(\n    #     \"destination path '{}' already exists and is not an empty directory\".format(\n    #         sub1.path),\n    #     result[0]['message'][2])\n\n\n@with_tree(tree={'top_file.txt': 'some',\n                 'sub 1': {'sub1file.txt': 'something else',\n                           'subsub': {'subsubfile.txt': 'completely different',\n                                      }\n                           },\n                 'sub 2': {'sub2file.txt': 'meaningless',\n                           }\n                 })\n@with_tempfile(mkdir=True)\ndef test_install_noautoget_data(src, path):\n    subsub_src = Dataset(opj(src, 'sub 1', 'subsub')).create(force=True)\n    sub1_src = Dataset(opj(src, 'sub 1')).create(force=True)\n    sub2_src = Dataset(opj(src, 'sub 2')).create(force=True)\n    top_src = Dataset(src).create(force=True)\n    top_src.add('.', recursive=True)\n\n    # install top level:\n    # don't filter implicitly installed subdataset to check them for content\n    cdss = install(path, source=src, recursive=True, result_filter=None)\n    # there should only be datasets in the list of installed items,\n    # and none of those should have any data for their annexed files yet\n    for ds in cdss:\n        assert_false(any(ds.repo.file_has_content(ds.repo.get_annexed_files())))\n\n\n@with_tempfile\n@with_tempfile\ndef test_install_source_relpath(src, dest):\n    ds1 = create(src)\n    src_ = basename(src)\n    with chpwd(dirname(src)):\n        ds2 = install(dest, source=src_)\n\n\n@integration  # 41.2043s\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@with_tempfile\n@known_failure_direct_mode  #FIXME\ndef test_install_consistent_state(src, dest, dest2, dest3):\n    # if we install a dataset, where sub-dataset \"went ahead\" in that branch,\n    # while super-dataset was not yet updated (e.g. we installed super before)\n    # then it is desired to get that default installed branch to get to the\n    # position where previous location was pointing to.\n    # It is indeed a mere heuristic which might not hold the assumption in some\n    # cases, but it would work for most simple and thus mostly used ones\n    ds1 = create(src)\n    sub1 = ds1.create('sub1')\n\n    def check_consistent_installation(ds):\n        datasets = [ds] + list(\n            map(Dataset, ds.subdatasets(recursive=True, fulfilled=True,\n                                        result_xfm='paths')))\n        assert len(datasets) == 2  # in this test\n        for ds in datasets:\n            # all of them should be in master branch\n            eq_(ds.repo.get_active_branch(), \"master\")\n            # all of them should be clean, so sub should be installed in a \"version\"\n            # as pointed by the super\n            ok_(not ds.repo.dirty)\n\n    dest_ds = install(dest, source=src)\n    # now we progress sub1 by adding sub2\n    subsub2 = sub1.create('sub2')\n\n    # and progress subsub2 forward to stay really thorough\n    put_file_under_git(subsub2.path, 'file.dat', content=\"data\")\n    subsub2.save(\"added a file\")  # above function does not commit\n\n    # just installing a submodule -- apparently different code/logic\n    # but also the same story should hold - we should install the version pointed\n    # by the super, and stay all clean\n    dest_sub1 = dest_ds.install('sub1')\n    check_consistent_installation(dest_ds)\n\n    # So now we have source super-dataset \"dirty\" with sub1 progressed forward\n    # Our install should try to \"retain\" consistency of the installation\n    # whenever possible.\n\n    # install entire hierarchy without specifying dataset\n    # no filter, we want full report\n    dest2_ds = install(dest2, source=src, recursive=True, result_filter=None)\n    check_consistent_installation(dest2_ds[0])  # [1] is the subdataset\n\n    # install entire hierarchy by first installing top level ds\n    # and then specifying sub-dataset\n    dest3_ds = install(dest3, source=src, recursive=False)\n    # and then install both submodules recursively while pointing\n    # to it based on dest3_ds\n    dest3_ds.install('sub1', recursive=True)\n    check_consistent_installation(dest3_ds)\n\n    # TODO: makes a nice use-case for an update operation\n\n\nfrom datalad.tests.utils import skip_ssh\n\n@skip_ssh\n@with_tempfile\n@with_tempfile\ndef test_install_subds_with_space(opath, tpath):\n    ds = create(opath)\n    ds.create('sub ds')\n    # works even now, boring\n    # install(tpath, source=opath, recursive=True)\n    # do via ssh!\n    install(tpath, source=\"localhost:\" + opath, recursive=True)\n    assert Dataset(opj(tpath, 'sub ds')).is_installed()\n\n\n@skip_ssh\n@usecase\n@with_tempfile(mkdir=True)\ndef test_install_subds_from_another_remote(topdir):\n    # https://github.com/datalad/datalad/issues/1905\n    with chpwd(topdir):\n        origin_ = 'origin'\n        clone1_ = 'clone1'\n        clone2_ = 'clone2'\n\n        origin = create(origin_, no_annex=True)\n        clone1 = install(source=origin, path=clone1_)\n        # print(\"Initial clone\")\n        clone1.create_sibling('ssh://localhost%s/%s' % (getpwd(), clone2_), name=clone2_)\n\n        # print(\"Creating clone2\")\n        clone1.publish(to=clone2_)\n        clone2 = Dataset(clone2_)\n        # print(\"Initiating subdataset\")\n        clone2.create('subds1')\n\n        # print(\"Updating\")\n        clone1.update(merge=True, sibling=clone2_)\n        # print(\"Installing within updated dataset -- should be able to install from clone2\")\n        clone1.install('subds1')",
        "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...\n❌ Verification failed\nPython 3.9 installation failed, trying Python 3.7...\nVerifying installation...\nDatalad version: 0.9.1.dev297\n✅ Installation successful!\nSuccessfully installed Datalad using Python 3.7\n",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 25 packages in 58ms\nInstalled 25 packages in 6.48s\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\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpDJt4AR/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpDJt4AR/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpDJt4AR/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpDJt4AR/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmpDJt4AR/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nerror: The build backend returned an error\n  Caused by: Call to `setuptools.build_meta:__legacy__.build_editable` failed (exit status: 1)\n\n[stderr]\nTraceback (most recent call last):\n  File \"<string>\", line 14, in <module>\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmplzihHF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 483, in get_requires_for_build_editable\n    return self.get_requires_for_build_wheel(config_settings)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmplzihHF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 334, in get_requires_for_build_wheel\n    return self._get_build_requires(config_settings, requirements=[])\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmplzihHF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 304, in _get_build_requires\n    self.run_setup()\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmplzihHF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 522, in run_setup\n    super().run_setup(setup_script=setup_script)\n  File \"/home/gcpuser/.cache/uv/builds-v0/.tmplzihHF/lib/python3.9/site-packages/setuptools/build_meta.py\", line 320, in run_setup\n    exec(code, locals())\n  File \"<string>\", line 48, in <module>\nAttributeError: module 'platform' has no attribute 'dist'\n\nhint: This usually indicates a problem with the package or the build environment.\nTraceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/datalad/__init__.py\", line 17, in <module>\n    from datalad.cmd import GitRunner\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/datalad/cmd.py\", line 35, in <module>\n    from .utils import on_windows, get_tempfile_kwargs, assure_unicode\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/datalad/utils.py\", line 24, in <module>\n    import wrapt\nModuleNotFoundError: No module named 'wrapt'\nUsing CPython 3.7.9\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 26 packages in 193ms\nInstalled 26 packages in 3.46s\n + bids==0.0\n + coverage==7.2.7\n + docopt==0.6.2\n + exceptiongroup==1.2.2\n + fasteners==0.19\n + grabbit==0.2.6\n + importlib-metadata==6.7.0\n + iniconfig==2.0.0\n + nibabel==4.0.2\n + num2words==0.5.14\n + numpy==1.21.6\n + packaging==24.0\n + pandas==1.3.5\n + patsy==1.0.1\n + pluggy==1.2.0\n + pybids==0.6.5\n + pytest==7.4.4\n + pytest-cov==4.1.0\n + python-dateutil==2.9.0.post0\n + pytz==2024.2\n + scipy==1.7.3\n + setuptools==68.0.0\n + six==1.17.0\n + tomli==2.0.1\n + typing-extensions==4.7.1\n + zipp==3.15.0\nResolved 79 packages in 1.38s\nPrepared 1 package in 1.28s\nInstalled 73 packages in 63ms\n + appdirs==1.4.4\n + attrs==24.2.0\n + automat==22.10.0\n + beautifulsoup4==4.12.3\n + boto==2.49.0\n + cachetools==5.5.0\n + certifi==2024.12.14\n + cffi==1.15.1\n + charset-normalizer==3.4.1\n + citeproc-py==0.6.0\n + constantly==15.1.0\n + cryptography==44.0.0\n + cssselect==1.2.0\n + datalad==0.9.1.dev1 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba)\n + deprecated==1.2.15\n + duecredit==0.9.3\n + filelock==3.12.2\n + frozendict==2.4.6\n + gitdb==4.0.11\n + gitpython==3.1.43\n + httpretty==1.1.4\n + humanize==4.6.0\n + hyperlink==21.0.0\n + idna==3.10\n + importlib-resources==5.12.0\n + incremental==22.10.0\n + iso8601==2.1.0\n + itemadapter==0.8.0\n + itemloaders==1.1.0\n + jaraco-classes==3.2.3\n + jeepney==0.8.0\n + jmespath==1.0.1\n + jsmin==3.0.1\n + keyring==24.1.1\n + keyrings-alt==4.2.0\n + lxml==5.3.0\n + mock==5.1.0\n + more-itertools==9.1.0\n + msgpack-python==0.5.6\n + multidict==6.0.5\n + nose==1.3.7\n + parsel==1.8.1\n + patool==1.12\n + protego==0.3.0\n + pyasn1==0.5.1\n + pyasn1-modules==0.3.0\n + pycparser==2.21\n + pydispatcher==2.0.7\n + pygithub==2.3.0\n + pyjwt==2.8.0\n + pyld==2.0.4\n + pynacl==1.5.0\n + pyopenssl==24.3.0\n + pyyaml==6.0.1\n + queuelib==1.6.2\n + requests==2.31.0\n + requests-file==2.1.0\n + requests-ftp==0.3.1\n + scrapy==2.9.0\n + secretstorage==3.3.3\n + service-identity==21.1.0\n + simplejson==3.19.3\n + smmap==5.0.1\n + soupsieve==2.4.1\n + tldextract==4.0.0\n + tqdm==4.67.1\n + twisted==23.8.0\n + urllib3==2.0.7\n + vcrpy==4.3.0\n + w3lib==2.1.2\n + wrapt==1.16.0\n + yarl==1.9.4\n + zope-interface==6.4.post2\nResolved 101 packages in 197ms\nInstalled 19 packages in 99ms\n + alabaster==0.7.13\n + babel==2.14.0\n + docutils==0.19\n + imagesize==1.4.1\n + jinja2==3.1.5\n + markupsafe==2.1.5\n + nose-timer==1.0.1\n + pygments==2.17.2\n + pypandoc==1.14\n + snowballstemmer==2.2.0\n + sphinx==5.3.0\n + sphinx-rtd-theme==2.0.0\n + sphinxcontrib-applehelp==1.0.2\n + sphinxcontrib-devhelp==1.0.2\n + sphinxcontrib-htmlhelp==2.0.0\n + sphinxcontrib-jquery==4.1\n + sphinxcontrib-jsmath==1.0.1\n + sphinxcontrib-qthelp==1.0.3\n + sphinxcontrib-serializinghtml==1.1.5\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba\nplugins: cov-4.1.0\ncollected 28 items\n\nr2e_tests/test_1.py ..x.FEEEEEEEEEEEEEEEEEEEEEEE                         [100%]\n\n==================================== ERRORS ====================================\n_________________ ERROR at setup of test_install_datasets_root _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 217\n  @skip_if_no_network\n  @use_cassette('test_install_crcns')\n  @with_tree(tree={'sub': {}})\n  def test_install_datasets_root(tdir):\nE       fixture 'tdir' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:217\n_________________ ERROR at setup of test_install_simple_local __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 240\n  @known_failure_v6  #FIXME\n  @with_testrepos('.*basic.*', flavors=['local-url', 'network', 'local'])\n  @with_tempfile(mkdir=True)\n  def test_install_simple_local(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:240\n___________ ERROR at setup of test_install_dataset_from_just_source ____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 280\n  @known_failure_v6  #FIXME\n  @with_testrepos(flavors=['local-url', 'network', 'local'])\n  @with_tempfile\n  def test_install_dataset_from_just_source(url, path):\nE       fixture 'url' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:280\n_____________ ERROR at setup of test_install_dataset_from_instance _____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 294\n  @known_failure_v6  #FIXME\n  @with_testrepos(flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_dataset_from_instance(src, dst):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:294\n_______ ERROR at setup of test_install_dataset_from_just_source_via_path _______\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 309\n  @with_testrepos(flavors=['network'])\n  @with_tempfile\n  @known_failure_v6  #FIXME\n  def test_install_dataset_from_just_source_via_path(url, path):\nE       fixture 'url' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:309\n___________________ ERROR at setup of test_install_dataladri ___________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 327\n  @with_tree(tree={\n      'ds': {'test.txt': 'some'},\n      })\n  @serve_path_via_http\n  @with_tempfile(mkdir=True)\n  def test_install_dataladri(src, topurl, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:327\n___________________ ERROR at setup of test_install_recursive ___________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 348\n  @with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n  @with_tempfile(mkdir=True)\n  @with_tempfile(mkdir=True)\n  def test_install_recursive(src, path_nr, path_r):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:348\n______________ ERROR at setup of test_install_recursive_with_data ______________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 392\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_recursive_with_data(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:392\n_________________ ERROR at setup of test_install_into_dataset __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 422\n  @slow  # 88.0869s  because of going through multiple test repos, ~8sec each time\n  @with_testrepos('.*annex.*', flavors=['local'])\n  # 'local-url', 'network'\n  # TODO: Somehow annex gets confused while initializing installed ds, whose\n  # .git/config show a submodule url \"file:///aaa/bbb%20b/...\"\n  # this is delivered by with_testrepos as the url to clone\n  @with_tempfile\n  def test_install_into_dataset(source, top_path):\nE       fixture 'source' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:422\n________________ ERROR at setup of test_failed_install_multiple ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 466\n  @usecase  # 39.3074s\n  @skip_if_no_network\n  @use_cassette('test_install_crcns')\n  @with_tempfile\n  @known_failure_direct_mode  #FIXME\n  def test_failed_install_multiple(top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:466\n_______________ ERROR at setup of test_install_known_subdataset ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 494\n  @with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n  @with_tempfile(mkdir=True)\n  def test_install_known_subdataset(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:494\n___________________ ERROR at setup of test_implicit_install ____________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 525\n  @slow  # 46.3650s\n  @with_tempfile(mkdir=True)\n  @with_tempfile(mkdir=True)\n  @known_failure_direct_mode  #FIXME\n  def test_implicit_install(src, dst):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:525\n____________________ ERROR at setup of test_failed_install _____________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 590\n  @with_tempfile(mkdir=True)\n  def test_failed_install(dspath):\nE       fixture 'dspath' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:590\n_____________________ ERROR at setup of test_install_list ______________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 599\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_list(path, top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:599\n_______________________ ERROR at setup of test_reckless ________________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 628\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_reckless(path, top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:628\n_______________ ERROR at setup of test_install_recursive_repeat ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 636\n  @with_tree(tree={'top_file.txt': 'some',\n                   'sub 1': {'sub1file.txt': 'something else',\n                             'subsub': {'subsubfile.txt': 'completely different',\n                                        }\n                             },\n                   'sub 2': {'sub2file.txt': 'meaningless',\n                             }\n                   })\n  @with_tempfile(mkdir=True)\n  @known_failure_direct_mode  #FIXME\n  def test_install_recursive_repeat(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:636\n______________ ERROR at setup of test_install_skip_list_arguments ______________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 682\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  @with_tempfile\n  def test_install_skip_list_arguments(src, path, path_outside):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:682\n_____________ ERROR at setup of test_install_skip_failed_recursive _____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 718\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_skip_failed_recursive(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:718\n________________ ERROR at setup of test_install_noautoget_data _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 751\n  @with_tree(tree={'top_file.txt': 'some',\n                   'sub 1': {'sub1file.txt': 'something else',\n                             'subsub': {'subsubfile.txt': 'completely different',\n                                        }\n                             },\n                   'sub 2': {'sub2file.txt': 'meaningless',\n                             }\n                   })\n  @with_tempfile(mkdir=True)\n  def test_install_noautoget_data(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:751\n________________ ERROR at setup of test_install_source_relpath _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 776\n  @with_tempfile\n  @with_tempfile\n  def test_install_source_relpath(src, dest):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:776\n_______________ ERROR at setup of test_install_consistent_state ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 785\n  @integration  # 41.2043s\n  @with_tempfile\n  @with_tempfile\n  @with_tempfile\n  @with_tempfile\n  @known_failure_direct_mode  #FIXME\n  def test_install_consistent_state(src, dest, dest2, dest3):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:785\n_______________ ERROR at setup of test_install_subds_with_space ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 849\n  @skip_ssh\n  @with_tempfile\n  @with_tempfile\n  def test_install_subds_with_space(opath, tpath):\nE       fixture 'opath' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:849\n___________ ERROR at setup of test_install_subds_from_another_remote ___________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 862\n  @skip_ssh\n  @usecase\n  @with_tempfile(mkdir=True)\n  def test_install_subds_from_another_remote(topdir):\nE       fixture 'topdir' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:862\n=================================== FAILURES ===================================\n______________________________ test_invalid_args _______________________________\n\narg = (), kw = {'path': '/tmp/tmp-page2annex5dtgdatf'}\nfilename = '/tmp/datalad_temp_test_invalid_argsbj73hwix'\n\n    @wraps(t)\n    def newfunc(*arg, **kw):\n        with make_tempfile(wrapped=t, **tkwargs) as filename:\n>           return t(*(arg + (filename,)), **kw)\nE           TypeError: test_invalid_args() got multiple values for argument 'path'\n\ndatalad/tests/utils.py:627: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_installationpath_from_url\nPASSED r2e_tests/test_1.py::test_get_git_url_from_source\nPASSED r2e_tests/test_1.py::test_insufficient_args\nXFAIL r2e_tests/test_1.py::test_guess_dot_git - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_guess_dot_git will be ignored\nERROR r2e_tests/test_1.py::test_install_datasets_root\nERROR r2e_tests/test_1.py::test_install_simple_local\nERROR r2e_tests/test_1.py::test_install_dataset_from_just_source\nERROR r2e_tests/test_1.py::test_install_dataset_from_instance\nERROR r2e_tests/test_1.py::test_install_dataset_from_just_source_via_path\nERROR r2e_tests/test_1.py::test_install_dataladri\nERROR r2e_tests/test_1.py::test_install_recursive\nERROR r2e_tests/test_1.py::test_install_recursive_with_data\nERROR r2e_tests/test_1.py::test_install_into_dataset\nERROR r2e_tests/test_1.py::test_failed_install_multiple\nERROR r2e_tests/test_1.py::test_install_known_subdataset\nERROR r2e_tests/test_1.py::test_implicit_install\nERROR r2e_tests/test_1.py::test_failed_install\nERROR r2e_tests/test_1.py::test_install_list\nERROR r2e_tests/test_1.py::test_reckless\nERROR r2e_tests/test_1.py::test_install_recursive_repeat\nERROR r2e_tests/test_1.py::test_install_skip_list_arguments\nERROR r2e_tests/test_1.py::test_install_skip_failed_recursive\nERROR r2e_tests/test_1.py::test_install_noautoget_data\nERROR r2e_tests/test_1.py::test_install_source_relpath\nERROR r2e_tests/test_1.py::test_install_consistent_state\nERROR r2e_tests/test_1.py::test_install_subds_with_space\nERROR r2e_tests/test_1.py::test_install_subds_from_another_remote\nFAILED r2e_tests/test_1.py::test_invalid_args - TypeError: test_invalid_args(...\n============== 1 failed, 3 passed, 1 xfailed, 23 errors in 1.12s ===============\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts ==============================\nplatform linux -- Python 3.7.9, pytest-7.4.4, pluggy-1.2.0\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba\nplugins: cov-4.1.0\ncollected 28 items\n\nr2e_tests/test_1.py F.x.FEEEEEEEEEEEEEEEEEEEEEEE                         [100%]\n\n==================================== ERRORS ====================================\n_________________ ERROR at setup of test_install_datasets_root _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 217\n  @skip_if_no_network\n  @use_cassette('test_install_crcns')\n  @with_tree(tree={'sub': {}})\n  def test_install_datasets_root(tdir):\nE       fixture 'tdir' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:217\n_________________ ERROR at setup of test_install_simple_local __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 240\n  @known_failure_v6  #FIXME\n  @with_testrepos('.*basic.*', flavors=['local-url', 'network', 'local'])\n  @with_tempfile(mkdir=True)\n  def test_install_simple_local(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:240\n___________ ERROR at setup of test_install_dataset_from_just_source ____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 280\n  @known_failure_v6  #FIXME\n  @with_testrepos(flavors=['local-url', 'network', 'local'])\n  @with_tempfile\n  def test_install_dataset_from_just_source(url, path):\nE       fixture 'url' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:280\n_____________ ERROR at setup of test_install_dataset_from_instance _____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 294\n  @known_failure_v6  #FIXME\n  @with_testrepos(flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_dataset_from_instance(src, dst):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:294\n_______ ERROR at setup of test_install_dataset_from_just_source_via_path _______\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 309\n  @with_testrepos(flavors=['network'])\n  @with_tempfile\n  @known_failure_v6  #FIXME\n  def test_install_dataset_from_just_source_via_path(url, path):\nE       fixture 'url' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:309\n___________________ ERROR at setup of test_install_dataladri ___________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 327\n  @with_tree(tree={\n      'ds': {'test.txt': 'some'},\n      })\n  @serve_path_via_http\n  @with_tempfile(mkdir=True)\n  def test_install_dataladri(src, topurl, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:327\n___________________ ERROR at setup of test_install_recursive ___________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 348\n  @with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n  @with_tempfile(mkdir=True)\n  @with_tempfile(mkdir=True)\n  def test_install_recursive(src, path_nr, path_r):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:348\n______________ ERROR at setup of test_install_recursive_with_data ______________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 392\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_recursive_with_data(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:392\n_________________ ERROR at setup of test_install_into_dataset __________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 422\n  @slow  # 88.0869s  because of going through multiple test repos, ~8sec each time\n  @with_testrepos('.*annex.*', flavors=['local'])\n  # 'local-url', 'network'\n  # TODO: Somehow annex gets confused while initializing installed ds, whose\n  # .git/config show a submodule url \"file:///aaa/bbb%20b/...\"\n  # this is delivered by with_testrepos as the url to clone\n  @with_tempfile\n  def test_install_into_dataset(source, top_path):\nE       fixture 'source' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:422\n________________ ERROR at setup of test_failed_install_multiple ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 466\n  @usecase  # 39.3074s\n  @skip_if_no_network\n  @use_cassette('test_install_crcns')\n  @with_tempfile\n  @known_failure_direct_mode  #FIXME\n  def test_failed_install_multiple(top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:466\n_______________ ERROR at setup of test_install_known_subdataset ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 494\n  @with_testrepos('submodule_annex', flavors=['local', 'local-url', 'network'])\n  @with_tempfile(mkdir=True)\n  def test_install_known_subdataset(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:494\n___________________ ERROR at setup of test_implicit_install ____________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 525\n  @slow  # 46.3650s\n  @with_tempfile(mkdir=True)\n  @with_tempfile(mkdir=True)\n  @known_failure_direct_mode  #FIXME\n  def test_implicit_install(src, dst):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:525\n____________________ ERROR at setup of test_failed_install _____________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 590\n  @with_tempfile(mkdir=True)\n  def test_failed_install(dspath):\nE       fixture 'dspath' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:590\n_____________________ ERROR at setup of test_install_list ______________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 599\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_list(path, top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:599\n_______________________ ERROR at setup of test_reckless ________________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 628\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_reckless(path, top_path):\nE       fixture 'top_path' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:628\n_______________ ERROR at setup of test_install_recursive_repeat ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 636\n  @with_tree(tree={'top_file.txt': 'some',\n                   'sub 1': {'sub1file.txt': 'something else',\n                             'subsub': {'subsubfile.txt': 'completely different',\n                                        }\n                             },\n                   'sub 2': {'sub2file.txt': 'meaningless',\n                             }\n                   })\n  @with_tempfile(mkdir=True)\n  @known_failure_direct_mode  #FIXME\n  def test_install_recursive_repeat(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:636\n______________ ERROR at setup of test_install_skip_list_arguments ______________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 682\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  @with_tempfile\n  def test_install_skip_list_arguments(src, path, path_outside):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:682\n_____________ ERROR at setup of test_install_skip_failed_recursive _____________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 718\n  @with_testrepos('submodule_annex', flavors=['local'])\n  @with_tempfile(mkdir=True)\n  def test_install_skip_failed_recursive(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:718\n________________ ERROR at setup of test_install_noautoget_data _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 751\n  @with_tree(tree={'top_file.txt': 'some',\n                   'sub 1': {'sub1file.txt': 'something else',\n                             'subsub': {'subsubfile.txt': 'completely different',\n                                        }\n                             },\n                   'sub 2': {'sub2file.txt': 'meaningless',\n                             }\n                   })\n  @with_tempfile(mkdir=True)\n  def test_install_noautoget_data(src, path):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:751\n________________ ERROR at setup of test_install_source_relpath _________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 776\n  @with_tempfile\n  @with_tempfile\n  def test_install_source_relpath(src, dest):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:776\n_______________ ERROR at setup of test_install_consistent_state ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 785\n  @integration  # 41.2043s\n  @with_tempfile\n  @with_tempfile\n  @with_tempfile\n  @with_tempfile\n  @known_failure_direct_mode  #FIXME\n  def test_install_consistent_state(src, dest, dest2, dest3):\nE       fixture 'src' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:785\n_______________ ERROR at setup of test_install_subds_with_space ________________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 849\n  @skip_ssh\n  @with_tempfile\n  @with_tempfile\n  def test_install_subds_with_space(opath, tpath):\nE       fixture 'opath' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:849\n___________ ERROR at setup of test_install_subds_from_another_remote ___________\nfile /home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py, line 862\n  @skip_ssh\n  @usecase\n  @with_tempfile(mkdir=True)\n  def test_install_subds_from_another_remote(topdir):\nE       fixture 'topdir' not found\n>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, cov, doctest_namespace, monkeypatch, no_cover, path, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, setup_git_config, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory\n>       use 'pytest --fixtures [testpath]' for help on them.\n\n/home/gcpuser/buckets/local_repoeval_bucket/repos/datalad_0dd56479fb13c5ff8010a1d2995e54b633a5f5ba/r2e_tests/test_1.py:862\n=================================== FAILURES ===================================\n________________________ test_installationpath_from_url ________________________\n\n    def test_installationpath_from_url():\n        for p in ('lastbit',\n                  'lastbit/',\n                  '/lastbit',\n                  'lastbit.git',\n                  'lastbit.git/',\n                  'http://example.com/lastbit',\n                  'http://example.com/lastbit.git',\n                  'http://lastbit:8000'\n                  ):\n>           eq_(_get_installationpath_from_url(p), 'lastbit')\n\nr2e_tests/test_1.py:93: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \n\na = 'lastbit:8000', b = 'lastbit', msg = None\n\n    def eq_(a, b, msg=None):\n        \"\"\"Shorthand for 'assert a == b, \"%r != %r\" % (a, b)\n        \"\"\"\n        if not a == b:\n>           raise AssertionError(msg or \"%r != %r\" % (a, b))\nE           AssertionError: 'lastbit:8000' != 'lastbit'\n\n.venv/lib/python3.7/site-packages/nose/tools/trivial.py:29: AssertionError\n______________________________ test_invalid_args _______________________________\n\narg = (), kw = {'path': '/tmp/tmp-page2annex5bgp5159'}\nfilename = '/tmp/datalad_temp_test_invalid_args3eoxkp2j'\n\n    @wraps(t)\n    def newfunc(*arg, **kw):\n        with make_tempfile(wrapped=t, **tkwargs) as filename:\n>           return t(*(arg + (filename,)), **kw)\nE           TypeError: test_invalid_args() got multiple values for argument 'path'\n\ndatalad/tests/utils.py:627: TypeError\n==================================== PASSES ====================================\n=========================== short test summary info ============================\nPASSED r2e_tests/test_1.py::test_get_git_url_from_source\nPASSED r2e_tests/test_1.py::test_insufficient_args\nXFAIL r2e_tests/test_1.py::test_guess_dot_git - reason: [NOTRUN] yield tests were removed in pytest 4.0 - test_guess_dot_git will be ignored\nERROR r2e_tests/test_1.py::test_install_datasets_root\nERROR r2e_tests/test_1.py::test_install_simple_local\nERROR r2e_tests/test_1.py::test_install_dataset_from_just_source\nERROR r2e_tests/test_1.py::test_install_dataset_from_instance\nERROR r2e_tests/test_1.py::test_install_dataset_from_just_source_via_path\nERROR r2e_tests/test_1.py::test_install_dataladri\nERROR r2e_tests/test_1.py::test_install_recursive\nERROR r2e_tests/test_1.py::test_install_recursive_with_data\nERROR r2e_tests/test_1.py::test_install_into_dataset\nERROR r2e_tests/test_1.py::test_failed_install_multiple\nERROR r2e_tests/test_1.py::test_install_known_subdataset\nERROR r2e_tests/test_1.py::test_implicit_install\nERROR r2e_tests/test_1.py::test_failed_install\nERROR r2e_tests/test_1.py::test_install_list\nERROR r2e_tests/test_1.py::test_reckless\nERROR r2e_tests/test_1.py::test_install_recursive_repeat\nERROR r2e_tests/test_1.py::test_install_skip_list_arguments\nERROR r2e_tests/test_1.py::test_install_skip_failed_recursive\nERROR r2e_tests/test_1.py::test_install_noautoget_data\nERROR r2e_tests/test_1.py::test_install_source_relpath\nERROR r2e_tests/test_1.py::test_install_consistent_state\nERROR r2e_tests/test_1.py::test_install_subds_with_space\nERROR r2e_tests/test_1.py::test_install_subds_from_another_remote\nFAILED r2e_tests/test_1.py::test_installationpath_from_url - AssertionError: ...\nFAILED r2e_tests/test_1.py::test_invalid_args - TypeError: test_invalid_args(...\n============== 2 failed, 2 passed, 1 xfailed, 23 errors in 0.69s ===============\n",
    "old_commit_res_stderr": ""
}
datalad/distribution/tests/test_install.py datalad/distribution/utils.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]

**Title:** Incorrect Handling of Encoded Paths and Ports in Installation URL

**Description:**

When providing a URL that includes percent-encoded characters or specifies a port, the installation path is not correctly extracted. This leads to unexpected and incorrect paths being returned.

**Example Code:**

```python
url = 'http://localhost:8000/%2Blast%20bit'
path = _get_installationpath_from_url(url)
print(path)  # Output: 'lastbit:8000'
```

**Expected Behavior:**

The installation path should properly decode the percent-encoded characters and exclude the port number, resulting in `'+last bit'`.

**Actual Behavior:**

The returned path includes the port number and does not decode the percent-encoded characters, resulting in `'lastbit:8000'`.

[/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/distribution/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.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Distribution utility functions

"""

import logging
from os.path import exists
from os.path import isdir
from os.path import join as opj
from os.path import islink
from os.path import isabs
from os.path import normpath
import posixpath

from datalad.support.annexrepo import AnnexRepo
from datalad.support.network import DataLadRI
from datalad.support.network import URL
from datalad.support.network import RI
from datalad.support.network import PathRI
from datalad.utils import knows_annex


lgr = logging.getLogger('datalad.distribution.utils')


def _fixup_submodule_dotgit_setup(ds, relativepath):
    """Implementation of our current of .git in a subdataset

    Each subdataset/module has its own .git directory where a standalone
    repository would have it. No gitdir files, no symlinks.
    """
    # move .git to superrepo's .git/modules, remove .git, create
    # .git-file
    path = opj(ds.path, relativepath)
    src_dotgit = get_git_dir(path)

    # at this point install always yields the desired result
    # just make sure
    assert(src_dotgit == '.git')


def get_git_dir(path):
    """figure out a repo's gitdir

    '.git' might be a  directory, a symlink or a file

    Parameter
    ---------
    path: str
      currently expected to be the repos base dir

    Returns
    -------
    str
      relative path to the repo's git dir; So, default would be ".git"
    """

    from os.path import isfile

    dot_git = opj(path, ".git")
    if not exists(dot_git):
        raise RuntimeError("Missing .git in %s." % path)
    elif islink(dot_git):
        # readlink cannot be imported on windows, but there should also
        # be no symlinks
        from os import readlink
        git_dir = readlink(dot_git)
    elif isdir(dot_git):
        git_dir = ".git"
    elif isfile(dot_git):
        with open(dot_git) as f:
            git_dir = f.readline()
            if git_dir.startswith("gitdir:"):
                git_dir = git_dir[7:]
            git_dir = git_dir.strip()

    return git_dir


def _get_git_url_from_source(source):
    """Return URL for cloning associated with a source specification

    For now just resolves DataLadRIs
    """
    # TODO: Probably RF this into RI.as_git_url(), that would be overridden
    # by subclasses or sth. like that
    if not isinstance(source, RI):
        source_ri = RI(source)
    else:
        source_ri = source
    if isinstance(source_ri, DataLadRI):
        # we have got our DataLadRI as the source, so expand it
        source = source_ri.as_git_url()
    else:
        source = str(source_ri)
    return source


def _get_tracking_source(ds):
    """Returns name and url of a potential configured source
    tracking remote"""
    vcs = ds.repo
    # if we have a remote, let's check the location of that remote
    # for the presence of the desired submodule

    remote_name, tracking_branch = vcs.get_tracking_branch()
    # TODO: better default `None`? Check where we might rely on '':
    remote_url = ''
    if remote_name:
        remote_url = vcs.get_remote_url(remote_name, push=False)

    return remote_name, remote_url


def _get_flexible_source_candidates(src, base_url=None, alternate_suffix=True):
    """Get candidates to try cloning from.

    Primarily to mitigate the problem that git doesn't append /.git
    while cloning from non-bare repos over dummy protocol (http*).  Also to
    simplify creation of urls whenever base url and relative path within it
    provided

    Parameters
    ----------
    src : string or RI
      Full or relative (then considered within base_url if provided) path
    base_url : string or RI, optional
    alternate_suffix : bool
      Whether to generate URL candidates with and without '/.git' suffixes.

    Returns
    -------
    candidates : list of str
      List of RIs (path, url, ssh targets) to try to install from
    """
    candidates = []

    ri = RI(src)
    if isinstance(ri, PathRI) and not isabs(ri.path) and base_url:
        ri = RI(base_url)
        if ri.path.endswith('/.git'):
            base_path = ri.path[:-5]
            base_suffix = '.git'
        else:
            base_path = ri.path
            base_suffix = ''
        if isinstance(ri, PathRI):
            # this is a path, so stay native
            ri.path = normpath(opj(base_path, src, base_suffix))
        else:
            # we are handling a URL, use POSIX path conventions
            ri.path = posixpath.normpath(
                posixpath.join(base_path, src, base_suffix))

    src = str(ri)

    candidates.append(src)
    if alternate_suffix and isinstance(ri, URL):
        if ri.scheme in {'http', 'https'}:
            # additionally try to consider .git:
            if not src.rstrip('/').endswith('/.git'):
                candidates.append(
                    '{0}/.git'.format(src.rstrip('/')))

    # TODO:
    # We need to provide some error msg with InstallFailedError, since now
    # it just swallows everything.
    # yoh: not sure if this comment applies here, but could be still applicable
    # outisde

    return candidates


def _handle_possible_annex_dataset(dataset, reckless, description=None):
    """If dataset "knows annex" -- annex init it, set into reckless etc

    Provides additional tune up to a possibly an annex repo, e.g.
    "enables" reckless mode, sets up description
    """
    # in any case check whether we need to annex-init the installed thing:
    if not knows_annex(dataset.path):
        # not for us
        return

    # init annex when traces of a remote annex can be detected
    if reckless:
        lgr.debug(
            "Instruct annex to hardlink content in %s from local "
            "sources, if possible (reckless)", dataset.path)
        dataset.config.add(
            'annex.hardlink', 'true', where='local', reload=True)
    lgr.debug("Initializing annex repo at %s", dataset.path)
    # XXX this is rather convoluted, init does init, but cannot
    # set a description without `create=True`
    repo = AnnexRepo(dataset.path, init=True)
    # so do manually see #1403
    if description:
        repo._init(description=description)
    if reckless:
        repo._run_annex_command('untrust', annex_options=['here'])
    # go through list of special remotes and issue info message that
    # some additional ones are present and were not auto-enabled
    remote_names = repo.get_remotes(
        with_urls_only=False,
        exclude_special_remotes=False)
    for k, v in repo.get_special_remotes().items():
        sr_name = v.get('name', None)
        if sr_name and sr_name not in remote_names:
            # if it is not listed among the remotes, it wasn't enabled
            lgr.info(
                'access to dataset sibling "%s" not auto-enabled, enable with:\n\t\tdatalad siblings -d "%s" enable -s %s',
                sr_name,
                dataset.path,
                sr_name)


def _get_installationpath_from_url(url):
    """Returns a relative path derived from the trailing end of a URL

    This can be used to determine an installation path of a Dataset
    from a URL, analog to what `git clone` does.
    """
    path = url.rstrip('/')
    if '/' in path:
        path = path.split('/')
        if path[-1] == '.git':
            path = path[-2]
        else:
            path = path[-1]
    if path.endswith('.git'):
        path = path[:-4]
    return path

```
--- 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:** Incorrect Handling of Encoded Paths and Ports in Installation URL

**Description:**

When providing a URL that includes percent-encoded characters or specifies a port, the installation path is not correctly extracted. This leads to unexpected and incorrect paths being returned.

**Example Code:**

```python
url = 'http://localhost:8000/%2Blast%20bit'
path = _get_installationpath_from_url(url)
print(path)  # Output: 'lastbit:8000'
```

**Expected Behavior:**

The installation path should properly decode the percent-encoded characters and exclude the port number, resulting in `'+last bit'`.

**Actual Behavior:**

The returned path includes the port number and does not decode the percent-encoded characters, resulting in `'lastbit:8000'`.

[/ISSUE]
{
    "test_installationpath_from_url": "PASSED",
    "test_get_git_url_from_source": "PASSED",
    "test_insufficient_args": "PASSED",
    "test_install_datasets_root": "ERROR",
    "test_install_simple_local": "ERROR",
    "test_install_dataset_from_just_source": "ERROR",
    "test_install_dataset_from_instance": "ERROR",
    "test_install_dataset_from_just_source_via_path": "ERROR",
    "test_install_dataladri": "ERROR",
    "test_install_recursive": "ERROR",
    "test_install_recursive_with_data": "ERROR",
    "test_install_into_dataset": "ERROR",
    "test_failed_install_multiple": "ERROR",
    "test_install_known_subdataset": "ERROR",
    "test_implicit_install": "ERROR",
    "test_failed_install": "ERROR",
    "test_install_list": "ERROR",
    "test_reckless": "ERROR",
    "test_install_recursive_repeat": "ERROR",
    "test_install_skip_list_arguments": "ERROR",
    "test_install_skip_failed_recursive": "ERROR",
    "test_install_noautoget_data": "ERROR",
    "test_install_source_relpath": "ERROR",
    "test_install_consistent_state": "ERROR",
    "test_install_subds_with_space": "ERROR",
    "test_install_subds_from_another_remote": "ERROR",
    "test_invalid_args": "FAILED"
}
diff --git a/datalad/distribution/utils.py b/datalad/distribution/utils.py
index a069c2a2c..e813044ad 100644
--- a/datalad/distribution/utils.py
+++ b/datalad/distribution/utils.py
@@ -11,6 +11,8 @@
 """
 
 import logging
+import re
+
 from os.path import exists
 from os.path import isdir
 from os.path import join as opj
@@ -19,6 +21,8 @@ from os.path import isabs
 from os.path import normpath
 import posixpath
 
+from six.moves.urllib.parse import unquote as urlunquote
+
 from datalad.support.annexrepo import AnnexRepo
 from datalad.support.network import DataLadRI
 from datalad.support.network import URL
@@ -227,7 +231,12 @@ def _get_installationpath_from_url(url):
     This can be used to determine an installation path of a Dataset
     from a URL, analog to what `git clone` does.
     """
-    path = url.rstrip('/')
+    ri = RI(url)
+    if isinstance(ri, (URL, DataLadRI)):  # decode only if URL
+        path = urlunquote(ri.path) or ri.hostname
+    else:
+        path = url
+    path = path.rstrip('/')
     if '/' in path:
         path = path.split('/')
         if path[-1] == '.git':
 

{"datalad/distribution/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\"\"\"Distribution utility functions\n\n\"\"\"\n\nimport logging\nfrom os.path import exists\nfrom os.path import isdir\nfrom os.path import join as opj\nfrom os.path import islink\nfrom os.path import isabs\nfrom os.path import normpath\nimport posixpath\n\nfrom datalad.support.annexrepo import AnnexRepo\nfrom datalad.support.network import DataLadRI\nfrom datalad.support.network import URL\nfrom datalad.support.network import RI\nfrom datalad.support.network import PathRI\nfrom datalad.utils import knows_annex\n\n\nlgr = logging.getLogger('datalad.distribution.utils')\n\n\ndef _fixup_submodule_dotgit_setup(ds, relativepath):\n    \"\"\"Implementation of our current of .git in a subdataset\n\n    Each subdataset/module has its own .git directory where a standalone\n    repository would have it. No gitdir files, no symlinks.\n    \"\"\"\n    # move .git to superrepo's .git/modules, remove .git, create\n    # .git-file\n    path = opj(ds.path, relativepath)\n    src_dotgit = get_git_dir(path)\n\n    # at this point install always yields the desired result\n    # just make sure\n    assert(src_dotgit == '.git')\n\n\ndef get_git_dir(path):\n    \"\"\"figure out a repo's gitdir\n\n    '.git' might be a  directory, a symlink or a file\n\n    Parameter\n    ---------\n    path: str\n      currently expected to be the repos base dir\n\n    Returns\n    -------\n    str\n      relative path to the repo's git dir; So, default would be \".git\"\n    \"\"\"\n\n    from os.path import isfile\n\n    dot_git = opj(path, \".git\")\n    if not exists(dot_git):\n        raise RuntimeError(\"Missing .git in %s.\" % path)\n    elif islink(dot_git):\n        # readlink cannot be imported on windows, but there should also\n        # be no symlinks\n        from os import readlink\n        git_dir = readlink(dot_git)\n    elif isdir(dot_git):\n        git_dir = \".git\"\n    elif isfile(dot_git):\n        with open(dot_git) as f:\n            git_dir = f.readline()\n            if git_dir.startswith(\"gitdir:\"):\n                git_dir = git_dir[7:]\n            git_dir = git_dir.strip()\n\n    return git_dir\n\n\ndef _get_git_url_from_source(source):\n    \"\"\"Return URL for cloning associated with a source specification\n\n    For now just resolves DataLadRIs\n    \"\"\"\n    # TODO: Probably RF this into RI.as_git_url(), that would be overridden\n    # by subclasses or sth. like that\n    if not isinstance(source, RI):\n        source_ri = RI(source)\n    else:\n        source_ri = source\n    if isinstance(source_ri, DataLadRI):\n        # we have got our DataLadRI as the source, so expand it\n        source = source_ri.as_git_url()\n    else:\n        source = str(source_ri)\n    return source\n\n\ndef _get_tracking_source(ds):\n    \"\"\"Returns name and url of a potential configured source\n    tracking remote\"\"\"\n    vcs = ds.repo\n    # if we have a remote, let's check the location of that remote\n    # for the presence of the desired submodule\n\n    remote_name, tracking_branch = vcs.get_tracking_branch()\n    # TODO: better default `None`? Check where we might rely on '':\n    remote_url = ''\n    if remote_name:\n        remote_url = vcs.get_remote_url(remote_name, push=False)\n\n    return remote_name, remote_url\n\n\ndef _get_flexible_source_candidates(src, base_url=None, alternate_suffix=True):\n    \"\"\"Get candidates to try cloning from.\n\n    Primarily to mitigate the problem that git doesn't append /.git\n    while cloning from non-bare repos over dummy protocol (http*).  Also to\n    simplify creation of urls whenever base url and relative path within it\n    provided\n\n    Parameters\n    ----------\n    src : string or RI\n      Full or relative (then considered within base_url if provided) path\n    base_url : string or RI, optional\n    alternate_suffix : bool\n      Whether to generate URL candidates with and without '/.git' suffixes.\n\n    Returns\n    -------\n    candidates : list of str\n      List of RIs (path, url, ssh targets) to try to install from\n    \"\"\"\n    candidates = []\n\n    ri = RI(src)\n    if isinstance(ri, PathRI) and not isabs(ri.path) and base_url:\n        ri = RI(base_url)\n        if ri.path.endswith('/.git'):\n            base_path = ri.path[:-5]\n            base_suffix = '.git'\n        else:\n            base_path = ri.path\n            base_suffix = ''\n        if isinstance(ri, PathRI):\n            # this is a path, so stay native\n            ri.path = normpath(opj(base_path, src, base_suffix))\n        else:\n            # we are handling a URL, use POSIX path conventions\n            ri.path = posixpath.normpath(\n                posixpath.join(base_path, src, base_suffix))\n\n    src = str(ri)\n\n    candidates.append(src)\n    if alternate_suffix and isinstance(ri, URL):\n        if ri.scheme in {'http', 'https'}:\n            # additionally try to consider .git:\n            if not src.rstrip('/').endswith('/.git'):\n                candidates.append(\n                    '{0}/.git'.format(src.rstrip('/')))\n\n    # TODO:\n    # We need to provide some error msg with InstallFailedError, since now\n    # it just swallows everything.\n    # yoh: not sure if this comment applies here, but could be still applicable\n    # outisde\n\n    return candidates\n\n\ndef _handle_possible_annex_dataset(dataset, reckless, description=None):\n    \"\"\"If dataset \"knows annex\" -- annex init it, set into reckless etc\n\n    Provides additional tune up to a possibly an annex repo, e.g.\n    \"enables\" reckless mode, sets up description\n    \"\"\"\n    # in any case check whether we need to annex-init the installed thing:\n    if not knows_annex(dataset.path):\n        # not for us\n        return\n\n    # init annex when traces of a remote annex can be detected\n    if reckless:\n        lgr.debug(\n            \"Instruct annex to hardlink content in %s from local \"\n            \"sources, if possible (reckless)\", dataset.path)\n        dataset.config.add(\n            'annex.hardlink', 'true', where='local', reload=True)\n    lgr.debug(\"Initializing annex repo at %s\", dataset.path)\n    # XXX this is rather convoluted, init does init, but cannot\n    # set a description without `create=True`\n    repo = AnnexRepo(dataset.path, init=True)\n    # so do manually see #1403\n    if description:\n        repo._init(description=description)\n    if reckless:\n        repo._run_annex_command('untrust', annex_options=['here'])\n    # go through list of special remotes and issue info message that\n    # some additional ones are present and were not auto-enabled\n    remote_names = repo.get_remotes(\n        with_urls_only=False,\n        exclude_special_remotes=False)\n    for k, v in repo.get_special_remotes().items():\n        sr_name = v.get('name', None)\n        if sr_name and sr_name not in remote_names:\n            # if it is not listed among the remotes, it wasn't enabled\n            lgr.info(\n                'access to dataset sibling \"%s\" not auto-enabled, enable with:\\n\\t\\tdatalad siblings -d \"%s\" enable -s %s',\n                sr_name,\n                dataset.path,\n                sr_name)\n\n\ndef _get_installationpath_from_url(url):\n    \"\"\"Returns a relative path derived from the trailing end of a URL\n\n    This can be used to determine an installation path of a Dataset\n    from a URL, analog to what `git clone` does.\n    \"\"\"\n    path = url.rstrip('/')\n    if '/' in path:\n        path = path.split('/')\n        if path[-1] == '.git':\n            path = path[-2]\n        else:\n            path = path[-1]\n    if path.endswith('.git'):\n        path = path[:-4]\n    return path\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:** Incorrect Handling of Encoded Paths and Ports in Installation URL

**Description:**

When providing a URL that includes percent-encoded characters or specifies a port, the installation path is not correctly extracted. This leads to unexpected and incorrect paths being returned.

**Example Code:**

```python
url = 'http://localhost:8000/%2Blast%20bit'
path = _get_installationpath_from_url(url)
print(path)  # Output: 'lastbit:8000'
```

**Expected Behavior:**

The installation path should properly decode the percent-encoded characters and exclude the port number, resulting in `'+last bit'`.

**Actual Behavior:**

The returned path includes the port number and does not decode the percent-encoded characters, resulting in `'lastbit:8000'`.

[/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/distribution/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.
#
# ## ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
"""Distribution utility functions

"""

import logging
from os.path import exists
from os.path import isdir
from os.path import join as opj
from os.path import islink
from os.path import isabs
from os.path import normpath
import posixpath

from datalad.support.annexrepo import AnnexRepo
from datalad.support.network import DataLadRI
from datalad.support.network import URL
from datalad.support.network import RI
from datalad.support.network import PathRI
from datalad.utils import knows_annex


lgr = logging.getLogger('datalad.distribution.utils')


def _fixup_submodule_dotgit_setup(ds, relativepath):
    """Implementation of our current of .git in a subdataset

    Each subdataset/module has its own .git directory where a standalone
    repository would have it. No gitdir files, no symlinks.
    """
    # move .git to superrepo's .git/modules, remove .git, create
    # .git-file
    path = opj(ds.path, relativepath)
    src_dotgit = get_git_dir(path)

    # at this point install always yields the desired result
    # just make sure
    assert(src_dotgit == '.git')


def get_git_dir(path):
    """figure out a repo's gitdir

    '.git' might be a  directory, a symlink or a file

    Parameter
    ---------
    path: str
      currently expected to be the repos base dir

    Returns
    -------
    str
      relative path to the repo's git dir; So, default would be ".git"
    """

    from os.path import isfile

    dot_git = opj(path, ".git")
    if not exists(dot_git):
        raise RuntimeError("Missing .git in %s." % path)
    elif islink(dot_git):
        # readlink cannot be imported on windows, but there should also
        # be no symlinks
        from os import readlink
        git_dir = readlink(dot_git)
    elif isdir(dot_git):
        git_dir = ".git"
    elif isfile(dot_git):
        with open(dot_git) as f:
            git_dir = f.readline()
            if git_dir.startswith("gitdir:"):
                git_dir = git_dir[7:]
            git_dir = git_dir.strip()

    return git_dir


def _get_git_url_from_source(source):
    """Return URL for cloning associated with a source specification

    For now just resolves DataLadRIs
    """
    # TODO: Probably RF this into RI.as_git_url(), that would be overridden
    # by subclasses or sth. like that
    if not isinstance(source, RI):
        source_ri = RI(source)
    else:
        source_ri = source
    if isinstance(source_ri, DataLadRI):
        # we have got our DataLadRI as the source, so expand it
        source = source_ri.as_git_url()
    else:
        source = str(source_ri)
    return source


def _get_tracking_source(ds):
    """Returns name and url of a potential configured source
    tracking remote"""
    vcs = ds.repo
    # if we have a remote, let's check the location of that remote
    # for the presence of the desired submodule

    remote_name, tracking_branch = vcs.get_tracking_branch()
    # TODO: better default `None`? Check where we might rely on '':
    remote_url = ''
    if remote_name:
        remote_url = vcs.get_remote_url(remote_name, push=False)

    return remote_name, remote_url


def _get_flexible_source_candidates(src, base_url=None, alternate_suffix=True):
    """Get candidates to try cloning from.

    Primarily to mitigate the problem that git doesn't append /.git
    while cloning from non-bare repos over dummy protocol (http*).  Also to
    simplify creation of urls whenever base url and relative path within it
    provided

    Parameters
    ----------
    src : string or RI
      Full or relative (then considered within base_url if provided) path
    base_url : string or RI, optional
    alternate_suffix : bool
      Whether to generate URL candidates with and without '/.git' suffixes.

    Returns
    -------
    candidates : list of str
      List of RIs (path, url, ssh targets) to try to install from
    """
    candidates = []

    ri = RI(src)
    if isinstance(ri, PathRI) and not isabs(ri.path) and base_url:
        ri = RI(base_url)
        if ri.path.endswith('/.git'):
            base_path = ri.path[:-5]
            base_suffix = '.git'
        else:
            base_path = ri.path
            base_suffix = ''
        if isinstance(ri, PathRI):
            # this is a path, so stay native
            ri.path = normpath(opj(base_path, src, base_suffix))
        else:
            # we are handling a URL, use POSIX path conventions
            ri.path = posixpath.normpath(
                posixpath.join(base_path, src, base_suffix))

    src = str(ri)

    candidates.append(src)
    if alternate_suffix and isinstance(ri, URL):
        if ri.scheme in {'http', 'https'}:
            # additionally try to consider .git:
            if not src.rstrip('/').endswith('/.git'):
                candidates.append(
                    '{0}/.git'.format(src.rstrip('/')))

    # TODO:
    # We need to provide some error msg with InstallFailedError, since now
    # it just swallows everything.
    # yoh: not sure if this comment applies here, but could be still applicable
    # outisde

    return candidates


def _handle_possible_annex_dataset(dataset, reckless, description=None):
    """If dataset "knows annex" -- annex init it, set into reckless etc

    Provides additional tune up to a possibly an annex repo, e.g.
    "enables" reckless mode, sets up description
    """
    # in any case check whether we need to annex-init the installed thing:
    if not knows_annex(dataset.path):
        # not for us
        return

    # init annex when traces of a remote annex can be detected
    if reckless:
        lgr.debug(
            "Instruct annex to hardlink content in %s from local "
            "sources, if possible (reckless)", dataset.path)
        dataset.config.add(
            'annex.hardlink', 'true', where='local', reload=True)
    lgr.debug("Initializing annex repo at %s", dataset.path)
    # XXX this is rather convoluted, init does init, but cannot
    # set a description without `create=True`
    repo = AnnexRepo(dataset.path, init=True)
    # so do manually see #1403
    if description:
        repo._init(description=description)
    if reckless:
        repo._run_annex_command('untrust', annex_options=['here'])
    # go through list of special remotes and issue info message that
    # some additional ones are present and were not auto-enabled
    remote_names = repo.get_remotes(
        with_urls_only=False,
        exclude_special_remotes=False)
    for k, v in repo.get_special_remotes().items():
        sr_name = v.get('name', None)
        if sr_name and sr_name not in remote_names:
            # if it is not listed among the remotes, it wasn't enabled
            lgr.info(
                'access to dataset sibling "%s" not auto-enabled, enable with:\n\t\tdatalad siblings -d "%s" enable -s %s',
                sr_name,
                dataset.path,
                sr_name)


def _get_installationpath_from_url(url):
    """Returns a relative path derived from the trailing end of a URL

    This can be used to determine an installation path of a Dataset
    from a URL, analog to what `git clone` does.
    """
    path = url.rstrip('/')
    if '/' in path:
        path = path.split('/')
        if path[-1] == '.git':
            path = path[-2]
        else:
            path = path[-1]
    if path.endswith('.git'):
        path = path[:-4]
    return path

```
--- 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