Compare commits

..

No commits in common. "develop" and "1.7.0" have entirely different histories.

7 changed files with 70 additions and 97 deletions

View file

@ -35,7 +35,6 @@ body:
label: Version label: Version
description: What version are you running? Look to AYON Tray description: What version are you running? Look to AYON Tray
options: options:
- 1.7.0
- 1.6.13 - 1.6.13
- 1.6.12 - 1.6.12
- 1.6.11 - 1.6.11

View file

@ -160,14 +160,9 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin):
dst_path: str, dst_path: str,
) -> bool: ) -> bool:
self.log.debug("Outputting thumbnail with OIIO: {}".format(dst_path)) self.log.debug("Outputting thumbnail with OIIO: {}".format(dst_path))
try: resolution_args = self._get_resolution_args(
resolution_args = self._get_resolution_args( "oiiotool", src_path
"oiiotool", src_path )
)
except Exception:
self.log.warning("Failed to get resolution args for OIIO.")
return False
oiio_cmd = get_oiio_tool_args("oiiotool", "-a", src_path) oiio_cmd = get_oiio_tool_args("oiiotool", "-a", src_path)
if resolution_args: if resolution_args:
# resize must be before -o # resize must be before -o
@ -193,13 +188,9 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin):
src_path: str, src_path: str,
dst_path: str, dst_path: str,
) -> bool: ) -> bool:
try: resolution_args = self._get_resolution_args(
resolution_args = self._get_resolution_args( "ffmpeg", src_path
"ffmpeg", src_path )
)
except Exception:
self.log.warning("Failed to get resolution args for ffmpeg.")
return False
max_int = str(2147483647) max_int = str(2147483647)
ffmpeg_cmd = get_ffmpeg_tool_args( ffmpeg_cmd = get_ffmpeg_tool_args(

View file

@ -1,8 +1,11 @@
import os import os
import sys
import copy import copy
import errno
import itertools import itertools
import shutil import shutil
from concurrent.futures import ThreadPoolExecutor
from speedcopy import copyfile
import clique import clique
import pyblish.api import pyblish.api
@ -13,15 +16,11 @@ from ayon_api.operations import (
) )
from ayon_api.utils import create_entity_id from ayon_api.utils import create_entity_id
from ayon_core.lib import source_hash from ayon_core.lib import create_hard_link, source_hash
from ayon_core.lib.file_transaction import ( from ayon_core.lib.file_transaction import wait_for_future_errors
FileTransaction,
DuplicateDestinationError,
)
from ayon_core.pipeline.publish import ( from ayon_core.pipeline.publish import (
get_publish_template_name, get_publish_template_name,
OptionalPyblishPluginMixin, OptionalPyblishPluginMixin,
KnownPublishError,
) )
@ -422,40 +421,19 @@ class IntegrateHeroVersion(
(repre_entity, dst_paths) (repre_entity, dst_paths)
) )
file_transactions = FileTransaction( self.path_checks = []
log=self.log,
# Enforce unique transfers
allow_queue_replacements=False
)
mode = FileTransaction.MODE_COPY
if self.use_hardlinks:
mode = FileTransaction.MODE_LINK
try: # Copy(hardlink) paths of source and destination files
for src_path, dst_path in itertools.chain( # TODO should we *only* create hardlinks?
src_to_dst_file_paths, # TODO should we keep files for deletion until this is successful?
other_file_paths_mapping with ThreadPoolExecutor(max_workers=8) as executor:
): futures = [
file_transactions.add(src_path, dst_path, mode=mode) executor.submit(self.copy_file, src_path, dst_path)
for src_path, dst_path in itertools.chain(
self.log.debug("Integrating source files to destination ...") src_to_dst_file_paths, other_file_paths_mapping
file_transactions.process() )
]
except DuplicateDestinationError as exc: wait_for_future_errors(executor, futures)
# Raise DuplicateDestinationError as KnownPublishError
# and rollback the transactions
file_transactions.rollback()
raise KnownPublishError(exc).with_traceback(sys.exc_info()[2])
except Exception as exc:
# Rollback the transactions
file_transactions.rollback()
self.log.critical("Error when copying files", exc_info=True)
raise exc
# Finalizing can't rollback safely so no use for moving it to
# the try, except.
file_transactions.finalize()
# Update prepared representation etity data with files # Update prepared representation etity data with files
# and integrate it to server. # and integrate it to server.
@ -644,6 +622,48 @@ class IntegrateHeroVersion(
).format(path)) ).format(path))
return path return path
def copy_file(self, src_path, dst_path):
# TODO check drives if are the same to check if cas hardlink
dirname = os.path.dirname(dst_path)
try:
os.makedirs(dirname)
self.log.debug("Folder(s) created: \"{}\"".format(dirname))
except OSError as exc:
if exc.errno != errno.EEXIST:
self.log.error("An unexpected error occurred.", exc_info=True)
raise
self.log.debug("Folder already exists: \"{}\"".format(dirname))
if self.use_hardlinks:
# First try hardlink and copy if paths are cross drive
self.log.debug("Hardlinking file \"{}\" to \"{}\"".format(
src_path, dst_path
))
try:
create_hard_link(src_path, dst_path)
# Return when successful
return
except OSError as exc:
# re-raise exception if different than
# EXDEV - cross drive path
# EINVAL - wrong format, must be NTFS
self.log.debug(
"Hardlink failed with errno:'{}'".format(exc.errno))
if exc.errno not in [errno.EXDEV, errno.EINVAL]:
raise
self.log.debug(
"Hardlinking failed, falling back to regular copy...")
self.log.debug("Copying file \"{}\" to \"{}\"".format(
src_path, dst_path
))
copyfile(src_path, dst_path)
def version_from_representations(self, project_name, repres): def version_from_representations(self, project_name, repres):
for repre in repres: for repre in repres:
version = ayon_api.get_version_by_id( version = ayon_api.get_version_by_id(

View file

@ -1045,23 +1045,10 @@ class ProjectPushItemProcess:
copied_tags = self._get_transferable_tags(src_version_entity) copied_tags = self._get_transferable_tags(src_version_entity)
copied_status = self._get_transferable_status(src_version_entity) copied_status = self._get_transferable_status(src_version_entity)
description_parts = []
dst_attr_description = dst_attrib.get("description")
if dst_attr_description:
description_parts.append(dst_attr_description)
description = self._create_src_version_description(
self._item.src_project_name,
src_version_entity
)
if description:
description_parts.append(description)
dst_attrib["description"] = "\n\n".join(description_parts)
version_entity = new_version_entity( version_entity = new_version_entity(
dst_version, dst_version,
product_id, product_id,
author=src_version_entity["author"],
status=copied_status, status=copied_status,
tags=copied_tags, tags=copied_tags,
task_id=self._task_info.get("id"), task_id=self._task_info.get("id"),
@ -1383,30 +1370,6 @@ class ProjectPushItemProcess:
return copied_status["name"] return copied_status["name"]
return None return None
def _create_src_version_description(
self,
src_project_name: str,
src_version_entity: dict[str, Any]
) -> str:
"""Creates description text about source version."""
src_version_id = src_version_entity["id"]
src_author = src_version_entity["author"]
query = "&".join([
f"project={src_project_name}",
"type=version",
f"id={src_version_id}"
])
version_url = (
f"{ayon_api.get_base_url()}"
f"/projects/{src_project_name}/products?{query}"
)
description = (
f"Version copied from from {version_url} "
f"created by '{src_author}', "
)
return description
class IntegrateModel: class IntegrateModel:
def __init__(self, controller): def __init__(self, controller):

View file

@ -1,3 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Package declaring AYON addon 'core' version.""" """Package declaring AYON addon 'core' version."""
__version__ = "1.7.0+dev" __version__ = "1.7.0"

View file

@ -1,6 +1,6 @@
name = "core" name = "core"
title = "Core" title = "Core"
version = "1.7.0+dev" version = "1.7.0"
client_dir = "ayon_core" client_dir = "ayon_core"

View file

@ -5,7 +5,7 @@
[tool.poetry] [tool.poetry]
name = "ayon-core" name = "ayon-core"
version = "1.7.0+dev" version = "1.7.0"
description = "" description = ""
authors = ["Ynput Team <team@ynput.io>"] authors = ["Ynput Team <team@ynput.io>"]
readme = "README.md" readme = "README.md"