Ejemplo n.º 1
0
    def execute(self, source_path, target_path, read_only=False, **kwargs):
        """
        Main hook entry point

        :param source_path: String
                            Source file path to copy

        :param target_path: String
                            Target file path to copy to

        """

        # create the folder if it doesn't exist
        dirname = os.path.dirname(target_path)
        if not os.path.isdir(dirname):
            old_umask = os.umask(0)
            # os.makedirs(dirname, 0777)
            # USE JSTOOLS INSTEAD
            dd_jstools_utils.makedir_with_jstools(dirname)
            os.umask(old_umask)

        current_permission = os.stat(source_path).st_mode
        if read_only:
            # make file read_only
            ro_mask = 0777 ^ (stat.S_IWRITE | stat.S_IWGRP | stat.S_IWOTH)
            permission = current_permission & ro_mask
        else:
            # make file writeable by user+group
            rw_mask = stat.S_IWRITE | stat.S_IWGRP
            permission = current_permission | rw_mask

        copy_file(source_path, target_path, permission)
Ejemplo n.º 2
0
    def _copy_outsource_to_work(self, settings, item):

        work_template = item.properties.get("work_template")
        if not work_template:
            self.logger.debug("No work template set on the item. "
                              "Skipping copy file to publish location.")
            return

        # by default, the path that was collected for publishing
        outsource_files = [item.properties.path]
        # ---- copy the outsource files to the work location

        if not item.properties.fields:
            self.logger.debug("No item fields supplied from collector."
                              "Required to resolve template paths.")
            return

        for outsource_file in outsource_files:

            # if not work_template.validate(outsource_file):
            #     self.logger.warning(
            #         "Work file '%s' did not match work template '%s'. "
            #         "Publishing in place." % (outsource_file, work_template)
            #     )
            #     return

            # work_fields = work_template.get_fields(outsource_file)

            # missing_keys = work_template.missing_keys(work_fields)

            # if missing_keys:
            #     self.logger.warning(
            #         "Work file '%s' missing keys required for the publish "
            #         "template: %s" % (outsource_file, missing_keys)
            #     )
            #     return

            work_file = work_template.apply_fields(item.properties.fields)
            self.logger.debug(">>>>> work_file: %s" % str(work_file))
            self.logger.debug(">>>>> outsource_file: %s" % str(outsource_file))

            # copy the file
            try:
                work_folder = os.path.dirname(work_file)
                ensure_folder_exists(work_folder)
                copy_file(outsource_file, work_file)
            except Exception:
                raise Exception(
                    "Failed to copy outsource file from '%s' to '%s'.\n%s" %
                    (outsource_file, work_file, traceback.format_exc()))

            self.logger.debug("Copied work file '%s' to work file '%s'." %
                              (outsource_file, work_file))
Ejemplo n.º 3
0
    def _copy_work_to_publish(self, settings, item):
        """
        This method handles exporting a layer and copying it to a designated
        publish location.
        This method requires a "publish_template" be set on the supplied item.
        The method will not attempt to copy files if any of the above
        requirements are not met. If the requirements are met, the file will
        ensure the publish path folder exists and then copy the file to that
        location.
        """

        krita_app = Krita.instance()

        node = item.properties["node"]
        session_path = item.properties["session_path"]
        active_doc = item.properties.get("session_document")

        export_path = self.get_export_path(settings, item)
        export_path_folder = os.path.dirname(export_path)
        ensure_folder_exists(export_path_folder)

        # this is so the publisher picks the right location for this layer
        item.properties.path = export_path

        # export the layer
        with _batch_mode(True):
            self._export_layer(node, export_path, active_doc)

        publish_path = self.get_publish_path(settings, item)

        # if the publish path is different that were the layer was exported
        # copy the file over
        if not os.path.normpath(publish_path) == os.path.normpath(export_path):
            publish_folder = os.path.dirname(publish_path)
            ensure_folder_exists(publish_folder)

            # copy the file to the publish location
            try:
                copy_file(export_path, publish_path)
                self.logger.debug(
                    "Copied exported files '%s' to publish folder '%s'." %
                    (export_path, publish_path))
            except Exception:
                raise TankError(
                    "Failed to copy exported file from '%s' to '%s'.\n%s" %
                    (export_path, publish_path, traceback.format_exc()))
        else:
            self.logger.debug("Skipping copy file to publish location.")

        # this is so the publisher picks the right location for this layer
        item.properties.path = publish_path
        item.set_thumbnail_from_path(publish_path)
Ejemplo n.º 4
0
    def _copy_files(self, dest_path, item):
        """
        This method handles copying an item's path(s) to a designated location.

        If the item has "sequence_paths" set, it will attempt to copy all paths
        assuming they meet the required criteria.
        """

        publisher = self.parent

        # ---- get a list of files to be copied
        if item.properties["is_sequence"]:
            work_files = item.properties.get("sequence_paths", [])
        else:
            work_files = [item.properties["path"]]

        # ---- copy the work files to the publish location
        processed_files = []
        for work_file in work_files:

            if item.properties["is_sequence"]:
                frame_num = publisher.util.get_frame_number(work_file)
                dest_file = publisher.util.get_path_for_frame(dest_path, frame_num)
            else:
                dest_file = dest_path

            # If the file paths are the same, skip...
            if work_file == dest_file:
                continue

            # copy the file
            try:
                dest_folder = os.path.dirname(dest_file)
                ensure_folder_exists(dest_folder)
                copy_file(work_file, dest_file,
                          permissions=stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
            except Exception as e:
                raise Exception(
                    "Failed to copy work file from '%s' to '%s'.\n%s" %
                    (work_file, dest_file, traceback.format_exc())
                )

            self.logger.debug(
                "Copied work file '%s' to '%s'." % (work_file, dest_file)
            )
            processed_files.append(dest_file)

        return processed_files
Ejemplo n.º 5
0
    def copy_files(self,
                   src_files,
                   dest_path,
                   seal_files=False,
                   is_sequence=False):
        """
        This method handles copying an item's path(s) to a designated location.

        If the item has "sequence_paths" set, it will attempt to copy all paths
        assuming they meet the required criteria.
        """

        publisher = self.parent

        logger = publisher.logger

        # ---- copy the src files to the dest location
        processed_files = []
        for src_file in src_files:

            if is_sequence:
                frame_num = self.get_frame_number(src_file)
                dest_file = self.get_path_for_frame(dest_path, frame_num)
            else:
                dest_file = dest_path

            # If the file paths are the same, lock permissions
            if src_file == dest_file:
                filesystem.freeze_permissions(dest_file)
                continue

            # copy the file
            try:
                dest_folder = os.path.dirname(dest_file)
                filesystem.ensure_folder_exists(dest_folder)
                filesystem.copy_file(src_file,
                                     dest_file,
                                     permissions=stat.S_IRUSR | stat.S_IRGRP
                                     | stat.S_IROTH,
                                     seal=seal_files)
            except Exception as e:
                raise Exception("Failed to copy file from '%s' to '%s'.\n%s" %
                                (src_file, dest_file, traceback.format_exc()))

            logger.debug("Copied file '%s' to '%s'." % (src_file, dest_file))
            processed_files.append(dest_file)

        return processed_files
Ejemplo n.º 6
0
    def _copy_work_to_publish(self, settings, item):
        """
        This method handles copying work file path(s) to a designated publish
        location.

        This method requires a "work_template" and a "publish_template" be set
        on the supplied item.

        The method will handle copying the "path" property to the corresponding
        publish location assuming the path corresponds to the "work_template"
        and the fields extracted from the "work_template" are sufficient to
        satisfy the "publish_template".

        The method will not attempt to copy files if any of the above
        requirements are not met. If the requirements are met, the file will
        ensure the publish path folder exists and then copy the file to that
        location.

        If the item has "sequence_paths" set, it will attempt to copy all paths
        assuming they meet the required criteria with respect to the templates.

        """

        #### IMPORTANT ####
        # Due to a quirk in the system, this function hooked here,
        # but executes from a call in the app_store
        #### /IMPORTANT ####

        # ---- ensure templates are available
        work_template = item.properties.get("work_template")
        if not work_template:
            self.logger.debug("No work template set on the item. "
                              "Skipping copy file to publish location.")
            return

        publish_template = item.properties.get("publish_template")
        if not publish_template:
            self.logger.debug("No publish template set on the item. "
                              "Skipping copying file to publish location.")
            return

        # ---- get nuke script to copy and its copy destination
        work_file = item.properties.get("path")
        publish_file = item.properties.get("copy_destination")

        # check for missing keys to make 100% sure the file can be copied
        work_fields = item.properties.get("work_fields")
        missing_keys = publish_template.missing_keys(work_fields)

        if missing_keys:
            self.logger.warning(
                "Work file '%s' missing keys required for the publish "
                "template: %s" % (work_file, missing_keys))
            return

        # final sanity check to prevent overwriting backup files
        # if a file already exists, create a duplicate.
        if not os.path.exists(publish_file):
            self.logger.debug("Creating Backup of Nuke Script")
            pass
        else:
            self.logger.warning(
                "A backup by this name already exists. Creating a copy...")

            copy_number = 1
            while os.path.exists(publish_file) == True:

                prev_copy_version = "_copy%s.nk" % str(copy_number -
                                                       1).zfill(3)
                copy_version = "_copy%s.nk" % str(copy_number).zfill(3)

                if re.search(r"v\d\d\d\.nk", publish_file[-7:]):
                    publish_file = publish_file.replace(".nk", copy_version)
                    copy_number += 1
                elif re.search(r"_copy\d\d\d\.nk", publish_file[-11:]):
                    publish_file = publish_file.replace(
                        prev_copy_version, copy_version)
                    copy_number += 1
                else:
                    pass

        # copy the file
        try:
            publish_folder = os.path.dirname(publish_file)
            ensure_folder_exists(publish_folder)
            copy_file(work_file, publish_file)
        except Exception:
            raise Exception("Failed to copy work file from '%s' to '%s'.\n%s" %
                            (work_file, publish_file, traceback.format_exc()))

        self.logger.debug("Copied work file '%s' to publish file '%s'." %
                          (work_file, publish_file))
    def _copy_work_to_publish(self, settings, item):
        """
        This method handles copying work file path(s) to a designated publish
        location.

        This method requires a "work_template" and a "publish_template" be set
        on the supplied item.

        The method will handle copying the "path" property to the corresponding
        publish location assuming the path corresponds to the "work_template"
        and the fields extracted from the "work_template" are sufficient to
        satisfy the "publish_template".

        The method will not attempt to copy files if any of the above
        requirements are not met. If the requirements are met, the file will
        ensure the publish path folder exists and then copy the file to that
        location.

        If the item has "sequence_paths" set, it will attempt to copy all paths
        assuming they meet the required criteria with respect to the templates.

        """

        # ---- ensure templates are available
        work_template = item.properties.get("work_template")
        if not work_template:
            self.logger.debug(
                "No work template set on the item. "
                "Skipping copy file to publish location."
            )
            return

        publish_template = self.get_publish_template(settings, item)
        if not publish_template:
            self.logger.debug(
                "No publish template set on the item. "
                "Skipping copying file to publish location."
            )
            return

        # ---- get a list of files to be copied

        # by default, the path that was collected for publishing
        work_files = [item.properties.path]

        # if this is a sequence, get the attached files
        if "sequence_paths" in item.properties:
            work_files = item.properties.get("sequence_paths", [])
            if not work_files:
                self.logger.warning(
                    "Sequence publish without a list of files. Publishing "
                    "the sequence path in place: %s" % (item.properties.path,)
                )
                return

        # ---- copy the work files to the publish location

        for work_file in work_files:

            if not work_template.validate(work_file):
                self.logger.warning(
                    "Work file '%s' did not match work template '%s'. "
                    "Publishing in place." % (work_file, work_template)
                )
                return

            work_fields = work_template.get_fields(work_file)

            missing_keys = publish_template.missing_keys(work_fields)

            if missing_keys:
                self.logger.warning(
                    "Work file '%s' missing keys required for the publish "
                    "template: %s" % (work_file, missing_keys)
                )
                return

            publish_file = publish_template.apply_fields(work_fields)

            # copy the file
            try:
                publish_folder = os.path.dirname(publish_file)
                ensure_folder_exists(publish_folder)
                copy_file(work_file, publish_file)
            except Exception, e:
                raise Exception(
                    "Failed to copy work file from '%s' to '%s'.\n%s" %
                    (work_file, publish_file, traceback.format_exc())
                )

            self.logger.debug(
                "Copied work file '%s' to publish file '%s'." %
                (work_file, publish_file)
            )
    def publish(self, settings, item):
        """
        Executes the publish logic for the given item and settings.

        :param settings: Dictionary of Settings. The keys are strings, matching
            the keys returned in the settings property. The values are `Setting`
            instances.
        :param item: Item to process
        """

        publisher = self.parent
        path = item.properties.get("path")

        publish_info = self._get_publish_path(settings, item)
        publish_name = publish_info[0]
        publish_path = publish_info[1]

        publish_folder = os.path.dirname(publish_path)
        ensure_folder_exists(publish_folder)

        if 'Texture Folder' in self.get_publish_type(settings, item)[0]:
            try:
                udims = publisher.util.get_frame_sequences(path)
                if udims:
                    for (inFile, seq) in udims:
                        match = re.search(r'%(\d+)d', inFile)
                        if match:
                            glob_path = inFile.split(match.group(0))
                        else:
                            glob_path = os.path.splitext(inFile)

                        glob_path_m = glob_path[0][:-1] if "_" or "." in glob_path[0][-1] else glob_path[0]

                        match_texturename = re.search(r'([^_|.]+)$', glob_path_m)
                        
                        if match_texturename:
                            for in_frame in glob.glob(inFile.replace(match.group(0), '*')):
                                mt = in_frame.replace(glob_path[0], "")
                                out_frame = os.path.splitext(publish_path)[0]
                                out_frame = "%s_%s.%s" % (out_frame, match_texturename.group(0), mt)

                                if not os.path.exists(out_frame):
                                    copy_file(in_frame, out_frame)
                                
                publish_path = os.path.dirname(publish_path)
            except Exception:
                raise Exception(
                    "Failed to copy sequence from '%s' to '%s'.\n%s" %
                    (path, publish_folder, traceback.format_exc())
                )                
        else:
            try:
                match = re.search(r'%(\d+)d', path)
                if match:
                    for in_frame in glob.glob(path.replace(match.group(0), '*')):
                        out_frame = publish_path % int(in_frame.replace(path.split(match.group(0))[0], '').split(".")[0])
                        if not os.path.exists(out_frame):
                            copy_file(in_frame, out_frame)
                else:
                    copy_file(path, publish_path)

            except Exception:
                raise Exception(
                    "Failed to copy sequence from '%s' to '%s'.\n%s" %
                    (path, publish_folder, traceback.format_exc())
                )
        
        self.logger.debug(
            "@@@ R8S Custom @@@ This files needs copying "
            "from '%s' to '%s' before publish." % (path, publish_path))
        
        item.properties['path'] = publish_path
        
        # ---- determine the information required to publish

        # We allow the information to be pre-populated by the collector or a
        # base class plugin. They may have more information than is available
        # here such as custom type or template settings.

        publish_path = self.get_publish_path(settings, item)
        publish_type = self.get_publish_type(settings, item)[0]
        publish_version = self.get_publish_version(settings, item)
        publish_dependencies = self.get_publish_dependencies(settings, item)
        publish_user = self.get_publish_user(settings, item)

        # if the parent item has a publish path, include it in the list of
        # dependencies
        if "sg_publish_path" in item.parent.properties:
            publish_dependencies.append(item.parent.properties.sg_publish_path)

        # handle copying of work to publish if templates are in play
        self._copy_work_to_publish(settings, item)

        # arguments for publish registration
        self.logger.info("Registering publish...")
        publish_data = {
            "tk": publisher.sgtk,
            "context": item.context,
            "comment": item.description,
            "path": publish_path,
            "name": publish_name,
            "created_by": publish_user,
            "version_number": publish_version,
            "thumbnail_path": item.get_thumbnail_as_path(),
            "published_file_type": publish_type,
            "dependency_paths": publish_dependencies
        }

        # log the publish data for debugging
        self.logger.debug(
            "Populated Publish data...",
            extra={
                "action_show_more_info": {
                    "label": "Publish Data",
                    "tooltip": "Show the complete Publish data dictionary",
                    "text": "<pre>%s</pre>" % (pprint.pformat(publish_data),)
                }
            }
        )

        # create the publish and stash it in the item properties for other
        # plugins to use.
        item.properties.sg_publish_data = sgtk.util.register_publish(
            **publish_data)
        self.logger.info("Publish registered!")
        self.logger.debug(
            "Shotgun Publish data...",
            extra={
                "action_show_more_info": {
                    "label": "Shotgun Publish Data",
                    "tooltip": "Show the complete Shotgun Publish Entity dictionary",
                    "text": "<pre>%s</pre>" % (pprint.pformat(item.properties.sg_publish_data),)
                }
            }
        )