コード例 #1
0
async def test_access_not_loaded_entry(running_backend,
                                       alice_entry_transactions):
    entry_transactions = alice_entry_transactions

    entry_id = entry_transactions.get_workspace_entry().id
    manifest = await entry_transactions.local_storage.get_manifest(entry_id)
    async with entry_transactions.local_storage.lock_entry_id(entry_id):
        await entry_transactions.local_storage.clear_manifest(entry_id)

    with pytest.raises(FSRemoteManifestNotFound):
        await entry_transactions.entry_info(FsPath("/"))

    async with entry_transactions.local_storage.lock_entry_id(entry_id):
        await entry_transactions.local_storage.set_manifest(entry_id, manifest)
    entry_info = await entry_transactions.entry_info(FsPath("/"))
    assert entry_info == {
        "type": "folder",
        "id": entry_id,
        "created": datetime(2000, 1, 1),
        "updated": datetime(2000, 1, 1),
        "base_version": 0,
        "is_placeholder": True,
        "need_sync": True,
        "children": [],
        "confinement_point": None,
    }
コード例 #2
0
async def test_file_create_delete(alice_entry_transactions,
                                  alice_sync_transactions):
    entry_transactions = alice_entry_transactions
    sync_transactions = alice_sync_transactions

    # Create and delete a foo file
    foo_id, fd = await entry_transactions.file_create(FsPath("/foo"),
                                                      open=False)
    assert fd is None
    assert await entry_transactions.file_delete(FsPath("/foo")) == foo_id

    # The file is not synced
    manifest = await entry_transactions.local_storage.get_manifest(foo_id)
    assert manifest.need_sync

    # Create and sync a bar file
    bar_id, fd = await entry_transactions.file_create(FsPath("/bar"),
                                                      open=False)
    remote = await sync_transactions.synchronization_step(bar_id)
    assert await sync_transactions.synchronization_step(bar_id, remote) is None

    # Remove the bar file, the manifest is synced
    assert await entry_transactions.file_delete(FsPath("/bar")) == bar_id
    manifest = await entry_transactions.local_storage.get_manifest(bar_id)
    assert not manifest.need_sync
コード例 #3
0
async def test_mountpoint_iterdir_with_many_files(n, base_path,
                                                  base_mountpoint,
                                                  alice_user_fs, event_bus):
    wid = await alice_user_fs.workspace_create(EntryName("w"))
    workspace = alice_user_fs.get_workspace(wid)
    await workspace.mkdir(base_path, parents=True, exist_ok=True)
    names = [f"some_file_{i:03d}.txt" for i in range(n)]
    path_list = [FsPath(f"{base_path}/{name}") for name in names]

    for path in path_list:
        await workspace.touch(path)

    # Now we can start fuse
    async with mountpoint_manager_factory(
            alice_user_fs, event_bus, base_mountpoint) as mountpoint_manager:

        await mountpoint_manager.mount_workspace(wid)

        test_path = mountpoint_manager.get_path_in_mountpoint(
            wid, FsPath(base_path))

        # Work around trio issue #1308 (https://github.com/python-trio/trio/issues/1308)
        items = await trio.to_thread.run_sync(
            lambda: [path.name for path in Path(test_path).iterdir()])
        assert items == names

        for path in path_list:
            item_path = mountpoint_manager.get_path_in_mountpoint(wid, path)
            assert await trio.Path(item_path).exists()
コード例 #4
0
async def test_file_create(alice_entry_transactions, alice_file_transactions):
    entry_transactions = alice_entry_transactions
    file_transactions = alice_file_transactions

    with freeze_time("2000-01-02"):
        access_id, fd = await entry_transactions.file_create(FsPath("/foo.txt")
                                                             )
        await file_transactions.fd_close(fd)

    assert fd == 1
    root_stat = await entry_transactions.entry_info(FsPath("/"))
    assert root_stat == {
        "type": "folder",
        "id": entry_transactions.workspace_id,
        "base_version": 0,
        "is_placeholder": True,
        "need_sync": True,
        "created": datetime(2000, 1, 1),
        "updated": datetime(2000, 1, 2),
        "children": [EntryName("foo.txt")],
        "confinement_point": None,
    }

    foo_stat = await entry_transactions.entry_info(FsPath("/foo.txt"))
    assert foo_stat == {
        "type": "file",
        "id": access_id,
        "base_version": 0,
        "is_placeholder": True,
        "need_sync": True,
        "created": datetime(2000, 1, 2),
        "updated": datetime(2000, 1, 2),
        "size": 0,
        "confinement_point": None,
    }
コード例 #5
0
async def test_root_entry_info(alice_workspace_t2, alice_workspace_t4):
    stat2 = await alice_workspace_t2.transactions.entry_info(FsPath("/"))
    assert stat2 == {
        "type": "folder",
        "id": alice_workspace_t4.transactions.workspace_id,
        "base_version": 1,
        "is_placeholder": False,
        "need_sync": False,
        "created": datetime(1999, 12, 31),
        "updated": datetime(1999, 12, 31),
        "children": [EntryName("foo")],
        "confinement_point": None,
    }

    stat4 = await alice_workspace_t4.transactions.entry_info(FsPath("/"))
    assert stat4 == {
        "type": "folder",
        "id": alice_workspace_t4.transactions.workspace_id,
        "base_version": 2,
        "is_placeholder": False,
        "need_sync": False,
        "created": datetime(1999, 12, 31),
        "updated": datetime(2000, 1, 4),
        "children": [EntryName("files"), EntryName("foo")],
        "confinement_point": None,
    }
コード例 #6
0
async def test_get_path_in_mountpoint(base_mountpoint, alice_user_fs,
                                      event_bus):
    # Populate a bit the fs first...
    wid = await alice_user_fs.workspace_create(EntryName("mounted_wksp"))
    wid2 = await alice_user_fs.workspace_create(EntryName("not_mounted_wksp"))
    workspace1 = alice_user_fs.get_workspace(wid)
    workspace2 = alice_user_fs.get_workspace(wid2)
    await workspace1.touch("/bar.txt")
    await workspace2.touch("/foo.txt")

    # Now we can start fuse
    async with mountpoint_manager_factory(
        alice_user_fs, event_bus, base_mountpoint) as mountpoint_manager:
        await mountpoint_manager.mount_workspace(wid)

        bar_path = mountpoint_manager.get_path_in_mountpoint(
            wid, FsPath("/bar.txt"))

        assert isinstance(bar_path, PurePath)
        # Windows uses drives, not base_mountpoint
        if sys.platform != "win32":
            expected = base_mountpoint / "mounted_wksp" / "bar.txt"
            assert str(bar_path) == str(expected.absolute())
        assert await trio.Path(bar_path).exists()

        with pytest.raises(MountpointNotMounted):
            mountpoint_manager.get_path_in_mountpoint(wid2, FsPath("/foo.txt"))
コード例 #7
0
async def test_mountpoint_access_unicode(base_mountpoint, alice_user_fs,
                                         event_bus):
    weird_name = "ÉŸ奇怪😀🔫🐍"

    wid = await alice_user_fs.workspace_create(EntryName(weird_name))
    workspace = alice_user_fs.get_workspace(wid)
    await workspace.touch(f"/{weird_name}")

    # Now we can start fuse
    async with mountpoint_manager_factory(
        alice_user_fs, event_bus, base_mountpoint) as mountpoint_manager:

        await mountpoint_manager.mount_workspace(wid)

        root_path = mountpoint_manager.get_path_in_mountpoint(
            wid, FsPath(f"/"))

        # Work around trio issue #1308 (https://github.com/python-trio/trio/issues/1308)
        items = await trio.to_thread.run_sync(
            lambda: [path.name for path in Path(root_path).iterdir()])
        assert items == [weird_name]

        item_path = mountpoint_manager.get_path_in_mountpoint(
            wid, FsPath(f"/{weird_name}"))
        assert await trio.Path(item_path).exists()
コード例 #8
0
async def test_version_non_existing_directory(alice_workspace, alice):
    version_lister = alice_workspace.get_version_lister()
    versions, version_list_is_complete = await version_lister.list(
        FsPath("/moved"))
    assert version_list_is_complete is True
    assert len(versions) == 2

    assert versions[0][1:] == (
        5,
        _day(9),
        _day(10),
        alice.device_id,
        _day(8),
        True,
        None,
        FsPath("/files"),
        None,
    )
    assert versions[1][1:] == (
        6,
        _day(10),
        _day(11),
        alice.device_id,
        _day(10),
        True,
        None,
        None,
        FsPath("/files"),
    )
コード例 #9
0
async def test_path_info_remote_loader_exceptions(monkeypatch, alice_workspace,
                                                  alice):
    manifest, _ = await alice_workspace.transactions._get_manifest_from_path(
        FsPath("/foo/bar"))
    async with alice_workspace.local_storage.lock_entry_id(manifest.id):
        await alice_workspace.local_storage.clear_manifest(manifest.id)

    vanilla_file_manifest_deserialize = BaseRemoteManifest._deserialize

    def mocked_file_manifest_deserialize(*args, **kwargs):
        return vanilla_file_manifest_deserialize(
            *args, **kwargs).evolve(**manifest_modifiers)

    monkeypatch.setattr(BaseRemoteManifest, "_deserialize",
                        mocked_file_manifest_deserialize)

    manifest_modifiers = {"id": EntryID.new()}
    with pytest.raises(FSError) as exc:
        await alice_workspace.path_info(FsPath("/foo/bar"))
    assert f"Invalid entry ID: expected `{manifest.id}`, got `{manifest_modifiers['id']}`" in str(
        exc.value)

    manifest_modifiers = {"version": 4}
    with pytest.raises(FSError) as exc:
        await alice_workspace.path_info(FsPath("/foo/bar"))
    assert "Invalid version: expected `1`, got `4`" in str(exc.value)

    manifest_modifiers = {"author": DeviceID("mallory@pc1")}
    with pytest.raises(FSError) as exc:
        await alice_workspace.path_info(FsPath("/foo/bar"))
    assert "Invalid author: expected `alice@dev1`, got `mallory@pc1`" in str(
        exc.value)
コード例 #10
0
ファイル: test_rsync.py プロジェクト: Scille/parsec-cloud
async def test_upsert_file(alice_workspace):

    _update_file_mock = AsyncMock(spec=mock.Mock())
    _create_path_mock = AsyncMock(spec=mock.Mock())

    path = FsPath("/test")
    workspace_path = FsPath("/path_in_workspace")
    entry_id = EntryID.new()

    with mock.patch("parsec.core.cli.rsync._create_path", _create_path_mock):
        with mock.patch("parsec.core.cli.rsync._update_file",
                        _update_file_mock):
            await rsync._upsert_file(entry_id, alice_workspace, path,
                                     workspace_path)
            _update_file_mock.assert_called_once_with(alice_workspace,
                                                      entry_id, path,
                                                      workspace_path)
            _create_path_mock.assert_not_called()

    _update_file_mock.reset_mock()
    entry_id = None

    with mock.patch("parsec.core.cli.rsync._create_path", _create_path_mock):
        with mock.patch("parsec.core.cli.rsync._update_file",
                        _update_file_mock):
            await rsync._upsert_file(None, alice_workspace, path,
                                     workspace_path)
            _update_file_mock.assert_not_called()
            _create_path_mock.assert_called_once_with(alice_workspace, False,
                                                      path, workspace_path)
コード例 #11
0
async def test_mountpoint_remote_error_event(aqtbot, running_backend, logged_gui, snackbar_catcher):
    c_w = logged_gui.test_get_central_widget()

    async with aqtbot.wait_signal(c_w.new_notification):
        c_w.event_bus.send(
            CoreEvent.MOUNTPOINT_REMOTE_ERROR,
            exc=FSWorkspaceNoReadAccess("Cannot get workspace roles: no read access"),
            path=FsPath("/bar"),
            mountpoint=Path("/foo"),
            operation="open",
            workspace_id=EntryID.new(),
            timestamp=None,
        )

    assert "Read access to " in snackbar_catcher.snackbars[0][1]
    snackbar_catcher.reset()

    async with aqtbot.wait_signal(c_w.new_notification):
        c_w.event_bus.send(
            CoreEvent.MOUNTPOINT_UNHANDLED_ERROR,
            exc=RuntimeError("D'Oh !"),
            path=FsPath("/bar"),
            mountpoint=Path("/foo"),
            operation="unlink",
            workspace_id=EntryID.new(),
        )

    assert "Error with the mountpoint " in snackbar_catcher.snackbars[0][1]
    snackbar_catcher.reset()
コード例 #12
0
async def test_listdir(alice_workspace):
    lst = await alice_workspace.listdir("/")
    assert lst == [FsPath("/foo")]
    lst = await alice_workspace.listdir("/foo")
    assert lst == [FsPath("/foo/bar"), FsPath("/foo/baz")]

    with pytest.raises(NotADirectoryError):
        await alice_workspace.listdir("/foo/bar")
    with pytest.raises(FileNotFoundError):
        await alice_workspace.listdir("/baz")
コード例 #13
0
async def test_iterdir(alice_workspace):
    lst = [child async for child in alice_workspace.iterdir("/")]
    assert lst == [FsPath("/foo")]
    lst = [child async for child in alice_workspace.iterdir("/foo")]
    assert lst == [FsPath("/foo/bar"), FsPath("/foo/baz")]

    with pytest.raises(NotADirectoryError):
        async for child in alice_workspace.iterdir("/foo/bar"):
            assert False, child
    with pytest.raises(FileNotFoundError):
        async for child in alice_workspace.iterdir("/baz"):
            assert False, child
コード例 #14
0
async def test_get_minimal_remote_manifest(alice, alice_sync_transactions):
    sync_transactions = alice_sync_transactions

    # Prepare
    w_id = sync_transactions.workspace_id
    a_id, fd = await sync_transactions.file_create(FsPath("/a"))
    await sync_transactions.fd_write(fd, b"abc", 0)
    await sync_transactions.fd_close(fd)
    b_id = await sync_transactions.folder_create(FsPath("/b"))
    c_id = await sync_transactions.folder_create(FsPath("/b/c"))

    # Workspace manifest
    minimal = await sync_transactions.get_minimal_remote_manifest(w_id)
    local = await sync_transactions.local_storage.get_manifest(w_id)
    expected = local.to_remote(author=alice.device_id,
                               timestamp=minimal.timestamp).evolve(
                                   children={}, updated=local.created)
    assert minimal == expected

    await sync_transactions.synchronization_step(w_id, minimal)
    assert await sync_transactions.get_minimal_remote_manifest(w_id) is None

    # File manifest
    minimal = await sync_transactions.get_minimal_remote_manifest(a_id)
    local = await sync_transactions.local_storage.get_manifest(a_id)
    expected = local.evolve(blocks=(), updated=local.created,
                            size=0).to_remote(author=alice.device_id,
                                              timestamp=minimal.timestamp)
    assert minimal == expected
    await sync_transactions.file_reshape(a_id)
    await sync_transactions.synchronization_step(a_id, minimal)
    assert await sync_transactions.get_minimal_remote_manifest(a_id) is None

    # Folder manifest
    minimal = await sync_transactions.get_minimal_remote_manifest(b_id)
    local = await sync_transactions.local_storage.get_manifest(b_id)
    expected = local.to_remote(author=alice.device_id,
                               timestamp=minimal.timestamp).evolve(
                                   children={}, updated=local.created)
    assert minimal == expected
    await sync_transactions.synchronization_step(b_id, minimal)
    assert await sync_transactions.get_minimal_remote_manifest(b_id) is None

    # Empty folder manifest
    minimal = await sync_transactions.get_minimal_remote_manifest(c_id)
    local = await sync_transactions.local_storage.get_manifest(c_id)
    expected = local.to_remote(author=alice.device_id,
                               timestamp=minimal.timestamp)
    assert minimal == expected
    await sync_transactions.synchronization_step(c_id, minimal)
    assert await sync_transactions.get_minimal_remote_manifest(c_id) is None
コード例 #15
0
async def test_access_not_loaded_entry(alice_workspace_t4):
    entry_id = alice_workspace_t4.transactions.get_workspace_entry().id
    alice_workspace_t4.transactions.local_storage._cache.clear()
    with pytest.raises(FSLocalMissError):
        await alice_workspace_t4.transactions.local_storage.get_manifest(
            entry_id)
    await alice_workspace_t4.transactions.entry_info(FsPath("/"))
コード例 #16
0
async def test_versions_not_enough_download_permited(alice_workspace, alice):
    version_lister = alice_workspace.get_version_lister()
    version_lister = alice_workspace.get_version_lister()
    versions, version_list_is_complete = await version_lister.list(
        FsPath("/files/renamed"),
        skip_minimal_sync=False,
        max_manifest_queries=1)
    assert version_list_is_complete is False
    versions, version_list_is_complete = await version_lister.list(
        FsPath("/files/renamed"), skip_minimal_sync=False)
    assert version_list_is_complete is True
    versions, version_list_is_complete = await version_lister.list(
        FsPath("/files/renamed"),
        skip_minimal_sync=False,
        max_manifest_queries=1)
    assert version_list_is_complete is True
コード例 #17
0
ファイル: test_rsync.py プロジェクト: Scille/parsec-cloud
async def test_clear_path(alice_workspace):
    is_dir_mock = AsyncMock(spec=mock.Mock, side_effect=lambda x: True)
    alice_workspace.is_dir = is_dir_mock

    rmtree_mock = AsyncMock(spec=mock.Mock)
    alice_workspace.rmtree = rmtree_mock

    unlink_mock = AsyncMock(spec=mock.Mock)
    alice_workspace.unlink = unlink_mock

    sync_mock = AsyncMock(spec=mock.Mock)
    alice_workspace.sync = sync_mock

    path = FsPath("/path_in_workspace/test")

    await rsync._clear_path(alice_workspace, path)
    is_dir_mock.assert_called_once_with(path)
    rmtree_mock.assert_called_once_with(path)
    unlink_mock.assert_not_called()
    sync_mock.assert_called_once_with()

    alice_workspace.is_dir.side_effect = lambda x: False
    is_dir_mock.reset_mock()
    rmtree_mock.reset_mock()
    sync_mock.reset_mock()

    await rsync._clear_path(alice_workspace, path)
    is_dir_mock.assert_called_once_with(path)
    rmtree_mock.assert_not_called()
    unlink_mock.assert_called_once_with(path)
    sync_mock.assert_called_once_with()
コード例 #18
0
async def _root_manifest_parent(
    path_destination: FsPath, workspace_fs: WorkspaceFS,
    workspace_manifest: WorkspaceManifest
) -> Tuple[Union[WorkspaceManifest, FolderManifest], FsPath]:

    root_manifest = workspace_manifest
    parent = FsPath("/")
    if path_destination:
        for p in path_destination.parts:
            parent = FsPath(parent / p)
            entry_id = root_manifest.children.get(p)
            root_manifest = await _get_or_create_directory(
                entry_id, workspace_fs, parent, parent)
            assert isinstance(root_manifest, FolderManifest)

    return root_manifest, parent
コード例 #19
0
ファイル: test_path.py プロジェクト: Scille/parsec-cloud
def test_stringify(path, sanitized_path):
    # Don't test '//' because according to POSIX path resolution:
    # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11
    # "A pathname that begins with two successive slashes may be
    # interpreted in an implementation-defined manner, although more
    # than two leading slashes shall be treated as a single slash".
    obj = FsPath(path)
    assert str(obj) == sanitized_path
コード例 #20
0
async def test_operations_on_file(alice_workspace_t4, alice_workspace_t5):
    _, fd4 = await alice_workspace_t4.transactions.file_open(
        FsPath("/files/content"), write_mode=False
    )
    assert isinstance(fd4, int)
    transactions_t4 = alice_workspace_t4.transactions
    _, fd5 = await alice_workspace_t5.transactions.file_open(
        FsPath("/files/content"), write_mode=False
    )
    assert isinstance(fd5, int)
    transactions_t5 = alice_workspace_t5.transactions

    data = await transactions_t4.fd_read(fd4, 1, 0)
    assert data == b"a"
    data = await transactions_t4.fd_read(fd4, 3, 1)
    assert data == b"bcd"
    data = await transactions_t4.fd_read(fd4, 100, 4)
    assert data == b"e"

    data = await transactions_t4.fd_read(fd4, 4, 0)
    assert data == b"abcd"
    data = await transactions_t4.fd_read(fd4, -1, 0)
    assert data == b"abcde"

    with pytest.raises(FSError):  # if removed from local_storage, no write right error?..
        await alice_workspace_t4.transactions.fd_write(fd4, b"hello ", 0)

    data = await transactions_t5.fd_read(fd5, 100, 0)
    assert data == b"fghij"
    data = await transactions_t5.fd_read(fd5, 1, 1)
    assert data == b"g"

    data = await transactions_t4.fd_read(fd4, 1, 2)
    assert data == b"c"

    await transactions_t5.fd_close(fd5)
    with pytest.raises(FSInvalidFileDescriptor):
        data = await transactions_t5.fd_read(fd5, 1, 0)
    data = await transactions_t4.fd_read(fd4, 1, 3)
    assert data == b"d"

    _, fd5 = await alice_workspace_t5.transactions.file_open(
        FsPath("/files/content"), write_mode=False
    )
    data = await transactions_t5.fd_read(fd5, 3, 0)
    assert data == b"fgh"
コード例 #21
0
async def test_flush_file(alice_workspace_t4):
    _, fd4 = await alice_workspace_t4.transactions.file_open(
        FsPath("/files/content"), write_mode=False
    )
    assert isinstance(fd4, int)
    transactions_t4 = alice_workspace_t4.transactions

    await transactions_t4.fd_flush(fd4)
コード例 #22
0
ファイル: test_rsync.py プロジェクト: Scille/parsec-cloud
async def test_sync_directory(alice_workspace):

    _get_or_create_directory_mock = AsyncMock(
        spec=mock.Mock(), side_effect=lambda *x: "folder_manifest_mock")
    _sync_directory_content_mock = AsyncMock(spec=mock.Mock())
    _clear_directory_mock = AsyncMock(spec=mock.Mock())

    entry_id = EntryID.new()
    path = FsPath("/test")
    workspace_path = FsPath("/path_in_workspace")

    with mock.patch("parsec.core.cli.rsync._get_or_create_directory",
                    _get_or_create_directory_mock):
        with mock.patch("parsec.core.cli.rsync._sync_directory_content",
                        _sync_directory_content_mock):
            with mock.patch("parsec.core.cli.rsync._clear_directory",
                            _clear_directory_mock):
                await rsync._sync_directory(entry_id, alice_workspace, path,
                                            workspace_path)
                _get_or_create_directory_mock.assert_called_once_with(
                    entry_id, alice_workspace, path, workspace_path)
                _sync_directory_content_mock.assert_called_once_with(
                    workspace_path, path, alice_workspace,
                    "folder_manifest_mock")
                _clear_directory_mock.assert_called_once_with(
                    workspace_path, path, alice_workspace,
                    "folder_manifest_mock")

    _get_or_create_directory_mock.reset_mock()
    _sync_directory_content_mock.reset_mock()
    _clear_directory_mock.reset_mock()

    with mock.patch("parsec.core.cli.rsync._get_or_create_directory",
                    _get_or_create_directory_mock):
        with mock.patch("parsec.core.cli.rsync._sync_directory_content",
                        _sync_directory_content_mock):
            with mock.patch("parsec.core.cli.rsync._clear_directory",
                            _clear_directory_mock):
                await rsync._sync_directory(None, alice_workspace, path,
                                            workspace_path)
                _get_or_create_directory_mock.assert_called_once_with(
                    None, alice_workspace, path, workspace_path)
                _sync_directory_content_mock.assert_called_once_with(
                    workspace_path, path, alice_workspace,
                    "folder_manifest_mock")
                _clear_directory_mock.assert_not_called()
コード例 #23
0
    def open_workspace_file(self, workspace_fs, file_name):
        file_name = FsPath("/", file_name) if file_name else FsPath("/")

        try:
            path = self.core.mountpoint_manager.get_path_in_mountpoint(
                workspace_fs.workspace_id,
                file_name,
                workspace_fs.timestamp
                if isinstance(workspace_fs, WorkspaceFSTimestamped) else None,
            )
            self.jobs_ctx.submit_job(self.file_open_success,
                                     self.file_open_error,
                                     desktop.open_files_job, [path])
        except MountpointNotMounted:
            # The mountpoint has been umounted in our back, nothing left to do
            show_error(
                self,
                _("TEXT_FILE_OPEN_ERROR_file").format(file=str(file_name)))
コード例 #24
0
async def test_versions_non_existing_file_remove_minimal_synced(
        alice_workspace, alice, skip_minimal_sync):
    version_lister = alice_workspace.get_version_lister()
    versions, version_list_is_complete = await version_lister.list(
        FsPath("/moved/renamed"), skip_minimal_sync=skip_minimal_sync)
    assert version_list_is_complete is True
    assert len(versions) == 1

    assert versions[0][1:] == (
        2,
        _day(9),
        _day(11),
        alice.device_id,
        _day(8),
        False,
        6,
        FsPath("/files/renamed"),
        FsPath("/files/renamed"),
    )
コード例 #25
0
async def _do_rename(workspace_fs, paths):
    new_names = {}
    for (old_path, new_path, entry_id) in paths:
        try:
            await workspace_fs.rename(old_path, new_path)
            new_names[entry_id] = FsPath(new_path).name
        except FileExistsError as exc:
            raise JobResultError("already-exists",
                                 multi=len(paths) > 1) from exc
        except OSError as exc:
            raise JobResultError("not-empty", multi=len(paths) > 1) from exc
コード例 #26
0
def _parse_destination(
        core: LoggedCore,
        destination: str) -> Tuple[WorkspaceEntry, Optional[FsPath]]:
    try:
        workspace_name, path = destination.split(":")
    except ValueError:
        workspace_name = destination
        path = None
    if path:
        try:
            path = FsPath(path)
        except ValueError:
            path = FsPath(f"/{path}")

    for workspace in core.user_fs.get_user_manifest().workspaces:
        if workspace.name == workspace_name:
            break
    else:
        raise SystemExit(f"Unknown workspace ({destination})")
    return workspace, path
コード例 #27
0
 def rename(self, path: FsPath, destination: str):
     destination = FsPath(destination)
     if not path.parent.is_root() and re.match(r".*\.sb-\w*-\w*", str(path.parent.name)):
         # This shouldn't happen with the defer_permission option in the FUSE function,
         # but if there ever is a permission error while saving with Apple softwares,
         # this is a fallback to avoid any unintended behavior related to this format
         # of temporary files. See https://github.com/Scille/parsec-cloud/pull/2211
         self.fs_access.workspace_move(path, destination)
     else:
         self.fs_access.entry_rename(path, destination, overwrite=True)
     return 0
コード例 #28
0
async def test_unlink(alice_workspace):
    await alice_workspace.unlink("/foo/bar")
    lst = await alice_workspace.listdir("/foo")
    assert lst == [FsPath("/foo/baz")]

    with pytest.raises(FileNotFoundError):
        await alice_workspace.unlink("/foo/bar")
    with pytest.raises(IsADirectoryError):
        await alice_workspace.unlink("/foo")
    # TODO: should this be a `IsADirectoryError`?
    with pytest.raises(PermissionError):
        await alice_workspace.unlink("/")
コード例 #29
0
async def _clear_directory(
    workspace_directory_path: FsPath,
    local_path: AnyPath,
    workspace_fs: WorkspaceFS,
    folder_manifest: FolderManifest,
) -> None:
    local_children_keys = [p.name for p in await local_path.iterdir()]
    for name in folder_manifest.children.keys():
        if name not in local_children_keys:
            absolute_path = FsPath(workspace_directory_path / name)
            print("delete %s" % absolute_path)
            await _clear_path(workspace_fs, absolute_path)
コード例 #30
0
ファイル: test_rsync.py プロジェクト: Scille/parsec-cloud
async def test_root_manifest_parent(alice_workspace):
    workspace_manifest = mock.Mock(spec=WorkspaceManifest)

    _get_or_create_directory_mock = AsyncMock(spec=mock.Mock)
    with mock.patch("parsec.core.cli.rsync._get_or_create_directory",
                    _get_or_create_directory_mock):

        root_manifest, parent = await rsync._root_manifest_parent(
            None, alice_workspace, workspace_manifest)
        _get_or_create_directory_mock.assert_not_called()
        assert root_manifest is workspace_manifest
        assert parent == FsPath("/")

    workspace_manifest.children = {"test": "id1"}
    workspace_test_save_manifest = mock.Mock(spec=FolderManifest)
    workspace_test_save_manifest.children = {}
    workspace_test_manifest = mock.Mock(spec=FolderManifest)
    _get_or_create_directory_mock.side_effect = [
        workspace_test_manifest,
        workspace_test_save_manifest,
    ]

    with mock.patch("parsec.core.cli.rsync._get_or_create_directory",
                    _get_or_create_directory_mock):
        root_manifest, parent = await rsync._root_manifest_parent(
            FsPath("/path_in_workspace"), alice_workspace, workspace_manifest)
        assert root_manifest == workspace_test_manifest
        assert parent == FsPath("/path_in_workspace")

    _get_or_create_directory_mock.side_effect = [
        workspace_test_manifest,
        workspace_test_save_manifest,
    ]
    with mock.patch("parsec.core.cli.rsync._get_or_create_directory",
                    _get_or_create_directory_mock):
        root_manifest, parent = await rsync._root_manifest_parent(
            FsPath("/path_in_workspace/save"), alice_workspace,
            workspace_manifest)
        assert root_manifest == workspace_test_save_manifest
        assert parent == FsPath("/path_in_workspace/save")