Exemplo n.º 1
0
def test_cant_overwrite_file_with_symlink():
    if ub.WIN32:
        # Can't distinguish this case on windows
        pytest.skip()

    dpath = ub.ensure_app_cache_dir('ubelt',
                                    'test_cant_overwrite_file_with_symlink')
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)

    happy_fpath = join(dpath, 'happy_fpath.txt')
    happy_flink = join(dpath, 'happy_flink.txt')

    for verbose in [2, 1, 0]:
        print('=======')
        print('verbose = {!r}'.format(verbose))
        ub.delete(dpath, verbose=verbose)
        ub.ensuredir(dpath, verbose=verbose)
        ub.touch(happy_fpath, verbose=verbose)
        ub.touch(happy_flink)  # create a file where a link should be

        util_links._dirstats(dpath)
        with pytest.raises(FileExistsError):  # file exists error
            ub.symlink(happy_fpath,
                       happy_flink,
                       overwrite=False,
                       verbose=verbose)

        with pytest.raises(FileExistsError):  # file exists error
            ub.symlink(happy_fpath,
                       happy_flink,
                       overwrite=True,
                       verbose=verbose)
Exemplo n.º 2
0
def test_broken_link():
    """
    CommandLine:
        python -m ubelt.tests.test_links test_broken_link
    """
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_broken_link')

    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)
    util_links._dirstats(dpath)

    broken_fpath = join(dpath, 'broken_fpath.txt')
    broken_flink = join(dpath, 'broken_flink.txt')

    ub.touch(broken_fpath, verbose=2)
    util_links._dirstats(dpath)
    ub.symlink(broken_fpath, broken_flink, verbose=2)

    util_links._dirstats(dpath)
    ub.delete(broken_fpath, verbose=2)

    util_links._dirstats(dpath)

    # make sure I am sane that this is the correct check.
    can_symlink = util_links._can_symlink()
    print('can_symlink = {!r}'.format(can_symlink))
    if can_symlink:
        # normal behavior
        assert islink(broken_flink)
        assert not exists(broken_flink)
    else:
        # on windows hard links are essentially the same file.
        # there is no trace that it was actually a link.
        assert exists(broken_flink)
Exemplo n.º 3
0
    def check_path_condition(path, positive, want, msg):
        if not want:
            positive = not positive
            msg = 'not ' + msg

        if not positive:
            util_links._dirstats(dpath)
            print('About to raise error: {}'.format(msg))
            print('path = {!r}'.format(path))
            print('exists(path) = {!r}'.format(exists(path)))
            print('islink(path) = {!r}'.format(islink(path)))
            print('isdir(path) = {!r}'.format(isdir(path)))
            print('isfile(path) = {!r}'.format(isfile(path)))
            raise AssertionError('path={} {}'.format(path, msg))
Exemplo n.º 4
0
def test_overwrite_symlink():
    """
    CommandLine:
        python ~/code/ubelt/tests/test_links.py test_overwrite_symlink
    """

    # TODO: test that we handle broken links
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_overwrite_symlink')
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)

    happy_fpath = join(dpath, 'happy_fpath.txt')
    other_fpath = join(dpath, 'other_fpath.txt')
    happy_flink = join(dpath, 'happy_flink.txt')

    for verbose in [2, 1, 0]:
        print('@==========@')
        print('verbose = {!r}'.format(verbose))

        print('[test] Setup')
        ub.delete(dpath, verbose=verbose)
        ub.ensuredir(dpath, verbose=verbose)
        ub.touch(happy_fpath, verbose=verbose)
        ub.touch(other_fpath, verbose=verbose)

        print('[test] Dirstats dpath')
        util_links._dirstats(dpath)

        print('[test] Create initial link (to happy)')
        ub.symlink(happy_fpath, happy_flink, verbose=verbose)

        print('[test] Dirstats dpath')
        util_links._dirstats(dpath)

        # Creating a duplicate link
        print('[test] Create a duplicate link (to happy)')
        ub.symlink(happy_fpath, happy_flink, verbose=verbose)

        print('[test] Dirstats dpath')
        util_links._dirstats(dpath)

        print('[test] Create an unauthorized overwrite link (to other)')
        with pytest.raises(Exception) as exc_info:  # file exists error
            ub.symlink(other_fpath, happy_flink, verbose=verbose)
        print(' * exc_info = {!r}'.format(exc_info))

        print('[test] Create an authorized overwrite link (to other)')
        ub.symlink(other_fpath, happy_flink, verbose=verbose, overwrite=True)

        print('[test] Dirstats dpath')
        ub.delete(other_fpath, verbose=verbose)

        print('[test] Create an unauthorized overwrite link (back to happy)')
        with pytest.raises(Exception) as exc_info:  # file exists error
            ub.symlink(happy_fpath, happy_flink, verbose=verbose)
        print(' * exc_info = {!r}'.format(exc_info))

        print('[test] Create an authorized overwrite link (back to happy)')
        ub.symlink(happy_fpath, happy_flink, verbose=verbose, overwrite=True)
Exemplo n.º 5
0
def test_overwrite_symlink():
    """
    CommandLine:
        python -m ubelt.tests.test_links test_overwrite_symlink
    """

    # TODO: test that we handle broken links
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_overwrite_symlink')
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)

    happy_fpath = join(dpath, 'happy_fpath.txt')
    other_fpath = join(dpath, 'other_fpath.txt')
    happy_flink = join(dpath, 'happy_flink.txt')

    for verbose in [2, 1, 0]:
        print('=======')
        print('verbose = {!r}'.format(verbose))
        ub.delete(dpath, verbose=verbose)
        ub.ensuredir(dpath, verbose=verbose)
        ub.touch(happy_fpath, verbose=verbose)
        ub.touch(other_fpath, verbose=verbose)

        util_links._dirstats(dpath)
        ub.symlink(happy_fpath, happy_flink, verbose=verbose)

        # Creating a duplicate link
        # import six
        # import sys
        # if not six.PY2 and sys.platform.startswith('win32'):
        util_links._dirstats(dpath)
        ub.symlink(happy_fpath, happy_flink, verbose=verbose)

        util_links._dirstats(dpath)
        with pytest.raises(Exception):  # file exists error
            ub.symlink(other_fpath, happy_flink, verbose=verbose)

        ub.symlink(other_fpath, happy_flink, verbose=verbose, overwrite=True)

        ub.delete(other_fpath, verbose=verbose)
        with pytest.raises(Exception):  # file exists error
            ub.symlink(happy_fpath, happy_flink, verbose=verbose)
        ub.symlink(happy_fpath, happy_flink, verbose=verbose, overwrite=True)
Exemplo n.º 6
0
def _win32_can_symlink(verbose=0, force=0, testing=0):
    """
    Args:
        verbose (int, default=0): flag
        force (int, default=0): flag
        testing (int, default=0): flag

    Example:
        >>> # xdoctest: +REQUIRES(WIN32)
        >>> import ubelt as ub
        >>> _win32_can_symlink(verbose=1, force=1, testing=1)
    """
    global __win32_can_symlink__
    if verbose:
        print('__win32_can_symlink__ = {!r}'.format(__win32_can_symlink__))
    if __win32_can_symlink__ is not None and not force:
        return __win32_can_symlink__

    from ubelt import util_platform
    tempdir = util_platform.ensure_app_cache_dir('ubelt', '_win32_can_symlink')

    util_io.delete(tempdir)
    util_path.ensuredir(tempdir)

    dpath = join(tempdir, 'dpath')
    fpath = join(tempdir, 'fpath.txt')

    dlink = join(tempdir, 'dlink')
    flink = join(tempdir, 'flink.txt')

    util_path.ensuredir(dpath)
    util_io.touch(fpath)

    # Add broken variants of the links for testing purposes
    # Its ugly, but so is all this windows code.
    if testing:
        broken_dpath = join(tempdir, 'broken_dpath')
        broken_fpath = join(tempdir, 'broken_fpath.txt')
        # Create files that we will delete after we link to them
        util_path.ensuredir(broken_dpath)
        util_io.touch(broken_fpath)

    try:
        _win32_symlink(dpath, dlink)
        if testing:
            _win32_symlink(broken_dpath, join(tempdir, 'broken_dlink'))
        can_symlink_directories = os.path.islink(dlink)
    except OSError:
        can_symlink_directories = False
    if verbose:
        print('can_symlink_directories = {!r}'.format(can_symlink_directories))

    try:
        _win32_symlink(fpath, flink)
        if testing:
            _win32_symlink(broken_fpath, join(tempdir, 'broken_flink'))
        can_symlink_files = os.path.islink(flink)
        # os.path.islink(flink)
    except OSError:
        can_symlink_files = False
    if verbose:
        print('can_symlink_files = {!r}'.format(can_symlink_files))

    if int(can_symlink_directories) + int(can_symlink_files) == 1:
        raise AssertionError(
            'can do one but not both. Unexpected {} {}'.format(
                can_symlink_directories, can_symlink_files))

    try:
        # test that we can create junctions, even if symlinks are disabled
        djunc = _win32_junction(dpath, join(tempdir, 'djunc'))
        fjunc = _win32_junction(fpath, join(tempdir, 'fjunc.txt'))
        if testing:
            _win32_junction(broken_dpath, join(tempdir, 'broken_djunc'))
            _win32_junction(broken_fpath, join(tempdir, 'broken_fjunc.txt'))
        if not _win32_is_junction(djunc):
            raise AssertionError('expected junction')
        if not _win32_is_hardlinked(fpath, fjunc):
            raise AssertionError('expected hardlink')
    except Exception:
        warnings.warn('We cannot create junctions either!')
        raise

    if testing:
        # break the links
        util_io.delete(broken_dpath)
        util_io.delete(broken_fpath)

        if verbose:
            from ubelt import util_links
            util_links._dirstats(tempdir)

    try:
        # Cleanup the test directory
        util_io.delete(tempdir)
    except Exception:
        print('ERROR IN DELETE')
        from ubelt import util_links
        util_links._dirstats(tempdir)
        raise

    can_symlink = can_symlink_directories and can_symlink_files
    __win32_can_symlink__ = can_symlink
    if not can_symlink:
        warnings.warn('Cannot make real symlink. Falling back to junction')

    if verbose:
        print('can_symlink = {!r}'.format(can_symlink))
        print('__win32_can_symlink__ = {!r}'.format(__win32_can_symlink__))
    return can_symlink
Exemplo n.º 7
0
def test_rel_file_link():
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_rel_file_link')
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)

    real_fpath = join(ub.ensuredir((dpath, 'dir1')), 'real')
    link_fpath = join(ub.ensuredir((dpath, 'dir2')), 'link')
    ub.touch(real_fpath)

    orig = os.getcwd()
    try:
        os.chdir(dpath)
        real_path = relpath(real_fpath, dpath)
        link_path = relpath(link_fpath, dpath)
        link = ub.symlink(real_path, link_path)
        import sys
        if sys.platform.startswith('win32') and isfile(link):
            # Note: if windows hard links the file there is no way we can
            # tell that it was a symlink. Just verify it exists.
            from ubelt import _win32_links
            assert _win32_links._win32_is_hardlinked(real_fpath, link_fpath)
        else:
            pointed = ub.util_links._readlink(link)
            resolved = ub.truepath(join(dirname(link), pointed), real=True)
            assert ub.truepath(real_fpath, real=True) == resolved
    except Exception:
        util_links._dirstats(dpath)
        util_links._dirstats(join(dpath, 'dir1'))
        util_links._dirstats(join(dpath, 'dir2'))
        print('TEST FAILED: test_rel_link')
        print('real_fpath = {!r}'.format(real_fpath))
        print('link_fpath = {!r}'.format(link_fpath))
        print('real_path = {!r}'.format(real_path))
        print('link_path = {!r}'.format(link_path))
        try:
            if 'link' in vars():
                print('link = {!r}'.format(link))
            if 'pointed' in vars():
                print('pointed = {!r}'.format(pointed))
            if 'resolved' in vars():
                print('resolved = {!r}'.format(resolved))
        except Exception:
            print('...rest of the names are not available')
        raise
    finally:
        util_links._dirstats(dpath)
        util_links._dirstats(join(dpath, 'dir1'))
        util_links._dirstats(join(dpath, 'dir2'))
        os.chdir(orig)
Exemplo n.º 8
0
def test_rel_dir_link():
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_rel_dir_link')
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)

    real_dpath = join(ub.ensuredir((dpath, 'dir1')), 'real')
    link_dpath = join(ub.ensuredir((dpath, 'dir2')), 'link')
    ub.ensuredir(real_dpath)

    orig = os.getcwd()
    try:
        os.chdir(dpath)
        real_path = relpath(real_dpath, dpath)
        link_path = relpath(link_dpath, dpath)
        link = ub.symlink(real_path, link_path)
        # Note: on windows this is hacked.
        pointed = ub.util_links._readlink(link)
        resolved = ub.truepath(join(dirname(link), pointed), real=True)
        assert ub.truepath(real_dpath, real=True) == resolved
    except Exception:
        util_links._dirstats(dpath)
        util_links._dirstats(join(dpath, 'dir1'))
        util_links._dirstats(join(dpath, 'dir2'))
        print('TEST FAILED: test_rel_link')
        print('real_dpath = {!r}'.format(real_dpath))
        print('link_dpath = {!r}'.format(link_dpath))
        print('real_path = {!r}'.format(real_path))
        print('link_path = {!r}'.format(link_path))
        try:
            if 'link' in vars():
                print('link = {!r}'.format(link))
            if 'pointed' in vars():
                print('pointed = {!r}'.format(pointed))
            if 'resolved' in vars():
                print('resolved = {!r}'.format(resolved))
        except Exception:
            print('...rest of the names are not available')
        raise
    finally:
        util_links._dirstats(dpath)
        util_links._dirstats(join(dpath, 'dir1'))
        util_links._dirstats(join(dpath, 'dir2'))
        os.chdir(orig)
Exemplo n.º 9
0
def test_delete_symlinks():
    """
    CommandLine:
        python -m ubelt.tests.test_links test_delete_symlinks
    """
    # TODO: test that we handle broken links
    dpath = ub.ensure_app_cache_dir('ubelt', 'test_delete_links')

    happy_dpath = join(dpath, 'happy_dpath')
    happy_dlink = join(dpath, 'happy_dlink')
    happy_fpath = join(dpath, 'happy_fpath.txt')
    happy_flink = join(dpath, 'happy_flink.txt')
    broken_dpath = join(dpath, 'broken_dpath')
    broken_dlink = join(dpath, 'broken_dlink')
    broken_fpath = join(dpath, 'broken_fpath.txt')
    broken_flink = join(dpath, 'broken_flink.txt')

    def check_path_condition(path, positive, want, msg):
        if not want:
            positive = not positive
            msg = 'not ' + msg

        if not positive:
            util_links._dirstats(dpath)
            print('About to raise error: {}'.format(msg))
            print('path = {!r}'.format(path))
            print('exists(path) = {!r}'.format(exists(path)))
            print('islink(path) = {!r}'.format(islink(path)))
            print('isdir(path) = {!r}'.format(isdir(path)))
            print('isfile(path) = {!r}'.format(isfile(path)))
            raise AssertionError('path={} {}'.format(path, msg))

    def assert_sometrace(path, want=True):
        # Either exists or is a broken link
        positive = exists(path) or islink(path)
        check_path_condition(path, positive, want, 'has trace')

    def assert_broken_link(path, want=True):
        if util_links._can_symlink():
            print('path={} should{} be a broken link'.format(
                path, ' ' if want else ' not'))
            positive = not exists(path) and islink(path)
            check_path_condition(path, positive, want, 'broken link')
        else:
            # TODO: we can test this
            # positive = util_links._win32_is_junction(path)
            print('path={} should{} be a broken link (junction)'.format(
                path, ' ' if want else ' not'))
            print('cannot check this yet')
            # We wont be able to differentiate links and nonlinks for junctions
            # positive = exists(path)
            # check_path_condition(path, positive, want, 'broken link')

    util_links._dirstats(dpath)
    ub.delete(dpath, verbose=2)
    ub.ensuredir(dpath, verbose=2)
    util_links._dirstats(dpath)

    ub.ensuredir(happy_dpath, verbose=2)
    ub.ensuredir(broken_dpath, verbose=2)
    ub.touch(happy_fpath, verbose=2)
    ub.touch(broken_fpath, verbose=2)
    util_links._dirstats(dpath)

    ub.symlink(broken_fpath, broken_flink, verbose=2)
    ub.symlink(broken_dpath, broken_dlink, verbose=2)
    ub.symlink(happy_fpath, happy_flink, verbose=2)
    ub.symlink(happy_dpath, happy_dlink, verbose=2)
    util_links._dirstats(dpath)

    # Deleting the files should not delete the symlinks (windows)
    ub.delete(broken_fpath, verbose=2)
    util_links._dirstats(dpath)

    ub.delete(broken_dpath, verbose=2)
    util_links._dirstats(dpath)

    assert_broken_link(broken_flink, 1)
    assert_broken_link(broken_dlink, 1)
    assert_sometrace(broken_fpath, 0)
    assert_sometrace(broken_dpath, 0)

    assert_broken_link(happy_flink, 0)
    assert_broken_link(happy_dlink, 0)
    assert_sometrace(happy_fpath, 1)
    assert_sometrace(happy_dpath, 1)

    # broken symlinks no longer exist after they are deleted
    ub.delete(broken_dlink, verbose=2)
    util_links._dirstats(dpath)
    assert_sometrace(broken_dlink, 0)

    ub.delete(broken_flink, verbose=2)
    util_links._dirstats(dpath)
    assert_sometrace(broken_flink, 0)

    # real symlinks no longer exist after they are deleted
    # but the original data is fine
    ub.delete(happy_dlink, verbose=2)
    util_links._dirstats(dpath)
    assert_sometrace(happy_dlink, 0)
    assert_sometrace(happy_dpath, 1)

    ub.delete(happy_flink, verbose=2)
    util_links._dirstats(dpath)
    assert_sometrace(happy_flink, 0)
    assert_sometrace(happy_fpath, 1)