Ejemplo n.º 1
0
Archivo: fsops.py Proyecto: Byron/bcore
class CreateFSItemOperation(FSOperationBase):

    """Create a directory or file with the given access permissions and ownership. In
    case of a file, you may specify an initial content.
    For this operation to succeed, the destination path must not exist yet!"""
    __slots__ = ("_path", "_content", "_mode", "_uid", "_gid")

    name = "CreateFSItem"

    def __init__(self, transaction, path, initial_file_content=None, mode=None, uid=None, gid=None):
        """Initialize the operation with a path to create. If initial_file_content is set, 
        to a string, it will be written in binary mode to a file. If it is unset, 
        a directory will be created. Non-existing parent-directories will be created.
        After creation, the mode will be set if not None, and uid and gid will be set as well to the given
        numerical ID if of of them is not None"""
        super(CreateFSItemOperation, self).__init__(transaction)
        self._assert_posix()
        self._path = Path(path)
        self._content = initial_file_content
        self._mode = mode
        self._uid = uid
        self._gid = gid

    def apply(self):
        if self._content and self._path.isdir() or not self._content and self._path.isfile():
            raise AssertionError(
                "Cannot create item of type directory or file as the an equally named item of different type exists")
        # END sanity check

        if self._dry_run():
            return

        if self._path.exists():
            return
        # end ignore existing items of the same type

        # we don't do it the most efficient way, as we could specify certain things in
        # at creation. For now, we don't do it though as it shouldn't matter
        if self._content:
            self.log.info("creating file  %s", self._path)
            self._path.write_bytes(self._content)
        else:
            self.log.info("creating directory %s", self._path)
            self._path.makedirs()
        # END initial creation
        self._operation_performed = True

        if self._mode is not None:
            self._path.chmod(self._mode)
        # END handle mode

        self.set_user_group(self._path, self._gid, self._uid)

    def rollback(self):
        try:
            if not self._operation_performed or not self._path.exists():
                return

            if self._content:
                self.log.info("Removing file %s", self._path)
                self._path.remove()
            else:
                self.log.info("Removing single directory %s", self._path)
                self._path.rmdir()
            # END handle removal, safely as we don't recursively delete anything
        finally:
            self._reset_state()