mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
♻️ changes in bootstrapping for multiple versions
This commit is contained in:
parent
0e126a2d82
commit
9205d4bde1
1 changed files with 158 additions and 38 deletions
|
|
@ -380,7 +380,8 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
|
||||
@classmethod
|
||||
def get_local_versions(
|
||||
cls, production: bool = None, staging: bool = None
|
||||
cls, production: bool = None,
|
||||
staging: bool = None, compatible_with: OpenPypeVersion = None
|
||||
) -> List:
|
||||
"""Get all versions available on this machine.
|
||||
|
||||
|
|
@ -390,6 +391,8 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
Args:
|
||||
production (bool): Return production versions.
|
||||
staging (bool): Return staging versions.
|
||||
compatible_with (OpenPypeVersion): Return only those compatible
|
||||
with specified version.
|
||||
"""
|
||||
# Return all local versions if arguments are set to None
|
||||
if production is None and staging is None:
|
||||
|
|
@ -406,10 +409,19 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
if not production and not staging:
|
||||
return []
|
||||
|
||||
# DEPRECATED: backwards compatible way to look for versions in root
|
||||
dir_to_search = Path(user_data_dir("openpype", "pypeclub"))
|
||||
versions = OpenPypeVersion.get_versions_from_directory(
|
||||
dir_to_search
|
||||
dir_to_search, compatible_with=compatible_with
|
||||
)
|
||||
if compatible_with:
|
||||
dir_to_search = Path(
|
||||
user_data_dir("openpype", "pypeclub")) / f"{compatible_with.major}.{compatible_with.minor}" # noqa
|
||||
versions += OpenPypeVersion.get_versions_from_directory(
|
||||
dir_to_search, compatible_with=compatible_with
|
||||
)
|
||||
|
||||
|
||||
filtered_versions = []
|
||||
for version in versions:
|
||||
if version.is_staging():
|
||||
|
|
@ -421,7 +433,8 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
|
||||
@classmethod
|
||||
def get_remote_versions(
|
||||
cls, production: bool = None, staging: bool = None
|
||||
cls, production: bool = None,
|
||||
staging: bool = None, compatible_with: OpenPypeVersion = None
|
||||
) -> List:
|
||||
"""Get all versions available in OpenPype Path.
|
||||
|
||||
|
|
@ -431,6 +444,8 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
Args:
|
||||
production (bool): Return production versions.
|
||||
staging (bool): Return staging versions.
|
||||
compatible_with (OpenPypeVersion): Return only those compatible
|
||||
with specified version.
|
||||
"""
|
||||
# Return all local versions if arguments are set to None
|
||||
if production is None and staging is None:
|
||||
|
|
@ -464,7 +479,14 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
if not dir_to_search:
|
||||
return []
|
||||
|
||||
versions = cls.get_versions_from_directory(dir_to_search)
|
||||
# DEPRECATED: look for version in root directory
|
||||
versions = cls.get_versions_from_directory(
|
||||
dir_to_search, compatible_with=compatible_with)
|
||||
if compatible_with:
|
||||
dir_to_search = dir_to_search / f"{compatible_with.major}.{compatible_with.minor}" # noqa
|
||||
versions += cls.get_versions_from_directory(
|
||||
dir_to_search, compatible_with=compatible_with)
|
||||
|
||||
filtered_versions = []
|
||||
for version in versions:
|
||||
if version.is_staging():
|
||||
|
|
@ -475,11 +497,15 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
return list(sorted(set(filtered_versions)))
|
||||
|
||||
@staticmethod
|
||||
def get_versions_from_directory(openpype_dir: Path) -> List:
|
||||
def get_versions_from_directory(
|
||||
openpype_dir: Path,
|
||||
compatible_with: OpenPypeVersion = None) -> List:
|
||||
"""Get all detected OpenPype versions in directory.
|
||||
|
||||
Args:
|
||||
openpype_dir (Path): Directory to scan.
|
||||
compatible_with (OpenPypeVersion): Return only versions compatible
|
||||
with build version specified as OpenPypeVersion.
|
||||
|
||||
Returns:
|
||||
list of OpenPypeVersion
|
||||
|
|
@ -514,6 +540,10 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
)[0]:
|
||||
continue
|
||||
|
||||
if compatible_with and not detected_version.is_compatible(
|
||||
compatible_with):
|
||||
continue
|
||||
|
||||
detected_version.path = item
|
||||
_openpype_versions.append(detected_version)
|
||||
|
||||
|
|
@ -545,8 +575,9 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
def get_latest_version(
|
||||
staging: bool = False,
|
||||
local: bool = None,
|
||||
remote: bool = None
|
||||
) -> OpenPypeVersion:
|
||||
remote: bool = None,
|
||||
compatible_with: OpenPypeVersion = None
|
||||
) -> Union[OpenPypeVersion, None]:
|
||||
"""Get latest available version.
|
||||
|
||||
The version does not contain information about path and source.
|
||||
|
|
@ -564,6 +595,9 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
staging (bool, optional): List staging versions if True.
|
||||
local (bool, optional): List local versions if True.
|
||||
remote (bool, optional): List remote versions if True.
|
||||
compatible_with (OpenPypeVersion, optional) Return only version
|
||||
compatible with compatible_with.
|
||||
|
||||
"""
|
||||
if local is None and remote is None:
|
||||
local = True
|
||||
|
|
@ -594,7 +628,12 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
return None
|
||||
|
||||
all_versions.sort()
|
||||
return all_versions[-1]
|
||||
latest_version: OpenPypeVersion
|
||||
latest_version = all_versions[-1]
|
||||
if compatible_with and not latest_version.is_compatible(
|
||||
compatible_with):
|
||||
return None
|
||||
return latest_version
|
||||
|
||||
@classmethod
|
||||
def get_expected_studio_version(cls, staging=False, global_settings=None):
|
||||
|
|
@ -617,6 +656,21 @@ class OpenPypeVersion(semver.VersionInfo):
|
|||
return None
|
||||
return OpenPypeVersion(version=result)
|
||||
|
||||
def is_compatible(self, version: OpenPypeVersion):
|
||||
"""Test build compatibility.
|
||||
|
||||
This will simply compare major and minor versions (ignoring patch
|
||||
and the rest).
|
||||
|
||||
Args:
|
||||
version (OpenPypeVersion): Version to check compatibility with.
|
||||
|
||||
Returns:
|
||||
bool: if the version is compatible
|
||||
|
||||
"""
|
||||
return self.major == version.major and self.minor == version.minor
|
||||
|
||||
|
||||
class BootstrapRepos:
|
||||
"""Class for bootstrapping local OpenPype installation.
|
||||
|
|
@ -737,8 +791,9 @@ class BootstrapRepos:
|
|||
return
|
||||
|
||||
# create destination directory
|
||||
if not self.data_dir.exists():
|
||||
self.data_dir.mkdir(parents=True)
|
||||
destination = self.data_dir / f"{installed_version.major}.{installed_version.minor}" # noqa
|
||||
if not destination.exists():
|
||||
destination.mkdir(parents=True)
|
||||
|
||||
# create zip inside temporary directory.
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
|
|
@ -766,7 +821,9 @@ class BootstrapRepos:
|
|||
Path to moved zip on success.
|
||||
|
||||
"""
|
||||
destination = self.data_dir / zip_file.name
|
||||
version = OpenPypeVersion.version_in_str(zip_file.name)
|
||||
destination_dir = self.data_dir / f"{version.major}.{version.minor}"
|
||||
destination = destination_dir / zip_file.name
|
||||
|
||||
if destination.exists():
|
||||
self._print(
|
||||
|
|
@ -778,7 +835,7 @@ class BootstrapRepos:
|
|||
self._print(str(e), LOG_ERROR, exc_info=True)
|
||||
return None
|
||||
try:
|
||||
shutil.move(zip_file.as_posix(), self.data_dir.as_posix())
|
||||
shutil.move(zip_file.as_posix(), destination_dir.as_posix())
|
||||
except shutil.Error as e:
|
||||
self._print(str(e), LOG_ERROR, exc_info=True)
|
||||
return None
|
||||
|
|
@ -991,6 +1048,16 @@ class BootstrapRepos:
|
|||
|
||||
@staticmethod
|
||||
def _validate_dir(path: Path) -> tuple:
|
||||
"""Validate checksums in a given path.
|
||||
|
||||
Args:
|
||||
path (Path): path to folder to validate.
|
||||
|
||||
Returns:
|
||||
tuple(bool, str): returns status and reason as a bool
|
||||
and str in a tuple.
|
||||
|
||||
"""
|
||||
checksums_file = Path(path / "checksums")
|
||||
if not checksums_file.exists():
|
||||
# FIXME: This should be set to False sometimes in the future
|
||||
|
|
@ -1072,7 +1139,20 @@ class BootstrapRepos:
|
|||
sys.path.insert(0, directory.as_posix())
|
||||
|
||||
@staticmethod
|
||||
def find_openpype_version(version, staging):
|
||||
def find_openpype_version(
|
||||
version: Union[str, OpenPypeVersion],
|
||||
staging: bool,
|
||||
compatible_with: OpenPypeVersion = None
|
||||
) -> Union[OpenPypeVersion, None]:
|
||||
"""Find location of specified OpenPype version.
|
||||
|
||||
Args:
|
||||
version (Union[str, OpenPypeVersion): Version to find.
|
||||
staging (bool): Filter staging versions.
|
||||
compatible_with (OpenPypeVersion, optional): Find only
|
||||
versions compatible with specified one.
|
||||
|
||||
"""
|
||||
if isinstance(version, str):
|
||||
version = OpenPypeVersion(version=version)
|
||||
|
||||
|
|
@ -1081,7 +1161,8 @@ class BootstrapRepos:
|
|||
return installed_version
|
||||
|
||||
local_versions = OpenPypeVersion.get_local_versions(
|
||||
staging=staging, production=not staging
|
||||
staging=staging, production=not staging,
|
||||
compatible_with=compatible_with
|
||||
)
|
||||
zip_version = None
|
||||
for local_version in local_versions:
|
||||
|
|
@ -1095,7 +1176,8 @@ class BootstrapRepos:
|
|||
return zip_version
|
||||
|
||||
remote_versions = OpenPypeVersion.get_remote_versions(
|
||||
staging=staging, production=not staging
|
||||
staging=staging, production=not staging,
|
||||
compatible_with=compatible_with
|
||||
)
|
||||
for remote_version in remote_versions:
|
||||
if remote_version == version:
|
||||
|
|
@ -1103,13 +1185,14 @@ class BootstrapRepos:
|
|||
return None
|
||||
|
||||
@staticmethod
|
||||
def find_latest_openpype_version(staging):
|
||||
def find_latest_openpype_version(
|
||||
staging, compatible_with: OpenPypeVersion = None):
|
||||
installed_version = OpenPypeVersion.get_installed_version()
|
||||
local_versions = OpenPypeVersion.get_local_versions(
|
||||
staging=staging
|
||||
staging=staging, compatible_with=compatible_with
|
||||
)
|
||||
remote_versions = OpenPypeVersion.get_remote_versions(
|
||||
staging=staging
|
||||
staging=staging, compatible_with=compatible_with
|
||||
)
|
||||
all_versions = local_versions + remote_versions
|
||||
if not staging:
|
||||
|
|
@ -1134,7 +1217,9 @@ class BootstrapRepos:
|
|||
self,
|
||||
openpype_path: Union[Path, str] = None,
|
||||
staging: bool = False,
|
||||
include_zips: bool = False) -> Union[List[OpenPypeVersion], None]:
|
||||
include_zips: bool = False,
|
||||
compatible_with: OpenPypeVersion = None
|
||||
) -> Union[List[OpenPypeVersion], None]:
|
||||
"""Get ordered dict of detected OpenPype version.
|
||||
|
||||
Resolution order for OpenPype is following:
|
||||
|
|
@ -1150,6 +1235,8 @@ class BootstrapRepos:
|
|||
otherwise.
|
||||
include_zips (bool, optional): If set True it will try to find
|
||||
OpenPype in zip files in given directory.
|
||||
compatible_with (OpenPypeVersion, optional): Find only those
|
||||
versions compatible with the one specified.
|
||||
|
||||
Returns:
|
||||
dict of Path: Dictionary of detected OpenPype version.
|
||||
|
|
@ -1168,30 +1255,56 @@ class BootstrapRepos:
|
|||
("Finding OpenPype in non-filesystem locations is"
|
||||
" not implemented yet."))
|
||||
|
||||
dir_to_search = self.data_dir
|
||||
user_versions = self.get_openpype_versions(self.data_dir, staging)
|
||||
# if we have openpype_path specified, search only there.
|
||||
version_dir = ""
|
||||
if compatible_with:
|
||||
version_dir = f"{compatible_with.major}.{compatible_with.minor}"
|
||||
|
||||
# if checks bellow for OPENPYPE_PATH and registry fails, use data_dir
|
||||
# DEPRECATED: lookup in root of this folder is deprecated in favour
|
||||
# of major.minor sub-folders.
|
||||
dirs_to_search = [
|
||||
self.data_dir
|
||||
]
|
||||
if compatible_with:
|
||||
dirs_to_search.append(self.data_dir / version_dir)
|
||||
|
||||
if openpype_path:
|
||||
dir_to_search = openpype_path
|
||||
dirs_to_search = [openpype_path]
|
||||
|
||||
if compatible_with:
|
||||
dirs_to_search.append(openpype_path / version_dir)
|
||||
else:
|
||||
if os.getenv("OPENPYPE_PATH"):
|
||||
if Path(os.getenv("OPENPYPE_PATH")).exists():
|
||||
dir_to_search = Path(os.getenv("OPENPYPE_PATH"))
|
||||
# first try OPENPYPE_PATH and if that is not available,
|
||||
# try registry.
|
||||
if os.getenv("OPENPYPE_PATH") \
|
||||
and Path(os.getenv("OPENPYPE_PATH")).exists():
|
||||
dirs_to_search = [Path(os.getenv("OPENPYPE_PATH"))]
|
||||
|
||||
if compatible_with:
|
||||
dirs_to_search.append(
|
||||
Path(os.getenv("OPENPYPE_PATH")) / version_dir)
|
||||
else:
|
||||
try:
|
||||
registry_dir = Path(
|
||||
str(self.registry.get_item("openPypePath")))
|
||||
if registry_dir.exists():
|
||||
dir_to_search = registry_dir
|
||||
dirs_to_search = [registry_dir]
|
||||
if compatible_with:
|
||||
dirs_to_search.append(registry_dir / version_dir)
|
||||
|
||||
except ValueError:
|
||||
# nothing found in registry, we'll use data dir
|
||||
pass
|
||||
|
||||
openpype_versions = self.get_openpype_versions(dir_to_search, staging)
|
||||
openpype_versions += user_versions
|
||||
openpype_versions = []
|
||||
for dir_to_search in dirs_to_search:
|
||||
try:
|
||||
openpype_versions += self.get_openpype_versions(
|
||||
dir_to_search, staging, compatible_with=compatible_with)
|
||||
except ValueError:
|
||||
# location is invalid, skip it
|
||||
pass
|
||||
|
||||
# remove zip file version if needed.
|
||||
if not include_zips:
|
||||
openpype_versions = [
|
||||
v for v in openpype_versions if v.path.suffix != ".zip"
|
||||
|
|
@ -1304,9 +1417,8 @@ class BootstrapRepos:
|
|||
raise ValueError(
|
||||
f"version {version} is not associated with any file")
|
||||
|
||||
destination = self.data_dir / version.path.stem
|
||||
if destination.exists():
|
||||
assert destination.is_dir()
|
||||
destination = self.data_dir / f"{version.major}.{version.minor}" / version.path.stem # noqa
|
||||
if destination.exists() and destination.is_dir():
|
||||
try:
|
||||
shutil.rmtree(destination)
|
||||
except OSError as e:
|
||||
|
|
@ -1375,7 +1487,7 @@ class BootstrapRepos:
|
|||
else:
|
||||
dir_name = openpype_version.path.stem
|
||||
|
||||
destination = self.data_dir / dir_name
|
||||
destination = self.data_dir / f"{openpype_version.major}.{openpype_version.minor}" / dir_name # noqa
|
||||
|
||||
# test if destination directory already exist, if so lets delete it.
|
||||
if destination.exists() and force:
|
||||
|
|
@ -1553,14 +1665,18 @@ class BootstrapRepos:
|
|||
return False
|
||||
return True
|
||||
|
||||
def get_openpype_versions(self,
|
||||
openpype_dir: Path,
|
||||
staging: bool = False) -> list:
|
||||
def get_openpype_versions(
|
||||
self,
|
||||
openpype_dir: Path,
|
||||
staging: bool = False,
|
||||
compatible_with: OpenPypeVersion = None) -> list:
|
||||
"""Get all detected OpenPype versions in directory.
|
||||
|
||||
Args:
|
||||
openpype_dir (Path): Directory to scan.
|
||||
staging (bool, optional): Find staging versions if True.
|
||||
compatible_with (OpenPypeVersion, optional): Get only versions
|
||||
compatible with the one specified.
|
||||
|
||||
Returns:
|
||||
list of OpenPypeVersion
|
||||
|
|
@ -1570,7 +1686,7 @@ class BootstrapRepos:
|
|||
|
||||
"""
|
||||
if not openpype_dir.exists() and not openpype_dir.is_dir():
|
||||
raise ValueError("specified directory is invalid")
|
||||
raise ValueError(f"specified directory {openpype_dir} is invalid")
|
||||
|
||||
_openpype_versions = []
|
||||
# iterate over directory in first level and find all that might
|
||||
|
|
@ -1595,6 +1711,10 @@ class BootstrapRepos:
|
|||
):
|
||||
continue
|
||||
|
||||
if compatible_with and \
|
||||
not detected_version.is_compatible(compatible_with):
|
||||
continue
|
||||
|
||||
detected_version.path = item
|
||||
if staging and detected_version.is_staging():
|
||||
_openpype_versions.append(detected_version)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue