vxSDK/vxsdk/core/pkg/find.py

127 lines
3.8 KiB
Python

"""
Package find backend abstraction
"""
from core.logger import log
from core.pkg.backend import PKG_CORE_BACKEND_REMOTE, PKG_CORE_BACKEND_LOCAL
__all__ = [
'pkg_find'
]
#---
# Internals
#---
def _pkg_find_merge_result(pkg_list_remote, pkg_list_local):
""" Merge two custom package information list
@arg
> pkg_list_remote (list,dict) - package list
> pkg_list_local (list,dict) - package list
@return
> The first list modified
"""
for pkg_local in pkg_list_local:
pkg_found = False
for pkg_remote in pkg_list_remote:
if pkg_remote['name'] != pkg_local['name']:
continue
pkg_found = True
for pkg_ver_local in pkg_local['versions']:
version_found = False
for pkg_ver_remote in pkg_remote['versions']:
if pkg_ver_remote.name != pkg_ver_local.name:
continue
pkg_ver_remote.addSource('local')
version_found = True
break
if not version_found:
pkg_remote['versions'].append(pkg_ver_local)
if not pkg_found:
pkg_list_remote.append(pkg_local)
return pkg_list_remote
def _pkg_find_select_best(pkg_remote, pkg_local):
""" Select the best version
@arg
> pkg_remote (dict) - pacakge information
> pkg_local (dict) - pacakge information
@return
> a list with the best pacakge information version
"""
if not 'version' in pkg_remote or not 'version' in pkg_local:
log.warn("[log] misformed package search result, silently ignored")
return []
if pkg_remote['version'].compare(pkg_local['version'].name) > 0:
pkg_remote['version'] = pkg_local['version']
return [pkg_remote]
#---
# Public
#---
def pkg_find(name, version=None, local=False, remote=True):
r""" Find the most appropriate package information
This function will request to the remote backend the list of all version of
the pacakge, which is basically all tags and branches. Then, we will check
all of these until a version match with the `version` query.
Note that the version query can contains special operation as described in
<core/pkg/version>
@args
> name (str) - exact valid package name
> version (str) - version query string
> local (bool) - enable local search
> remote (bool) - enable remote search
@return
> a list of all matched package dictionnary :
[
{
'name' : <package name>,
'path' : <paclage path or URL>
'versions' : [
<list of all available (or matched) version (VxVersion)>
...
]
]
> None if error
"""
if not local and not remote:
return []
# perform explicit request for each backend
pkg_list_local = []
pkg_list_remote = []
if remote:
pkg_list_remote = PKG_CORE_BACKEND_REMOTE.package_find(name, version)
if local:
pkg_list_local = PKG_CORE_BACKEND_LOCAL.package_find(name, version)
# verify useless checking and merging operation
if not pkg_list_remote:
return pkg_list_local
if not pkg_list_local:
return pkg_list_remote
# if a version is provided, each backend will return only one dictionary
# with the best match in local and remote one. We will select the best
# between these two.
if version:
return _pkg_find_select_best(
pkg_list_remote[0],
pkg_list_local[0],
)
# if no version information as been specified each `pkg_list_remote` and
# `pkg_list_local` will contains a list of all matched package information.
# So, we need to merge these two list.
return _pkg_find_merge_result(pkg_list_remote, pkg_list_local)