예제 #1
0
    def snapshot(
        self,
        version: Optional[dict],
        tale: dict,
        new_version: dict,
        user=None,
        force=False,
    ) -> None:
        """Creates a new version from the current state and an old version. The implementation
        here differs a bit from
        https://docs.google.com/document/d/1b2xZtIYvgVXz7EVeV-C18So_a7QLGg59dPQMxvBcA5o since
        the document assumes traditional use of Girder objects to simulate a filesystem, whereas
        the current reality is that we are moving more towards Girder being a thin layer on top
        of an actual FS (i.e. virtual_resources). In particular, the data folder remains in the
        domain of the DMS, meaning that actual files are only downloaded on demand. The current
        implementation of the virtual objects does not seem to have a straightforward way of
        embedding pure girder folders inside a virtual tree. The solution currently adopted to
        address this issue involves storing the dataset in the version folder itself, which, for
        efficiency reasons remains a Girder folder (but also a virtual_resources root).

        It may be relevant to note that this implementation uses option (b) in the above document
        with respect to the meaning of "copy" in step 4.1.2.1. To be more precise, when a file is
        changed in the current workspace, the new version will hard link to the file in question
        instead of doing an actual copy. This allows for O(1) equality comparisons between files,
        but requires that modifications to files in the workspace always create a new file (which
        is the case if files are only modified through the WebDAV FS mounted in a tale container).
        """
        new_version_path = Path(new_version["fsPath"])
        manifest = Manifest(tale,
                            user,
                            versionId=new_version["_id"],
                            expand_folders=False)
        with open((new_version_path / "manifest.json").as_posix(), "w") as fp:
            fp.write(manifest.dump_manifest())

        with open((new_version_path / "environment.json").as_posix(),
                  "w") as fp:
            fp.write(manifest.dump_environment())

        oldWorkspace = (None if version is None else Path(version["fsPath"]) /
                        "workspace")
        workspace = Folder().load(tale["workspaceId"], force=True)
        crtWorkspace = Path(workspace["fsPath"])
        newWorkspace = new_version_path / "workspace"
        newWorkspace.mkdir()
        self.snapshotRecursive(oldWorkspace, crtWorkspace, newWorkspace)
예제 #2
0
    def _is_same(self, tale, version, user):
        workspace = Folder().load(tale["workspaceId"], force=True)
        tale_workspace_path = Path(workspace["fsPath"])

        version_path = None if version is None else Path(version["fsPath"])
        version_workspace_path = None if version_path is None else version_path / "workspace"

        manifest_obj = Manifest(tale, user)
        manifest = json.loads(manifest_obj.dump_manifest())
        environment = json.loads(manifest_obj.dump_environment())
        tale_restored_from_wrk = Tale().restoreTale(manifest, environment)
        tale_restored_from_ver = \
            self._restoreTaleFromVersion(version, annotate=False) if version else None

        if self._sameTaleMetadata(tale_restored_from_ver, tale_restored_from_wrk) and \
                self._sameTree(version_workspace_path, tale_workspace_path):
            raise RestException('Not modified',
                                code=303,
                                extra=str(version["_id"]))