Source code for lsst.verify.metadata.lsstsw
#
# LSST Data Management System
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
#
# See COPYRIGHT file at the top of the source tree.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the LSST License Statement and
# the GNU General Public License along with this program. If not,
# see <https://www.lsstcorp.org/LegalNotices/>.
#
"""APIs for building software provenance from lsstsw."""
from __future__ import print_function
__all__ = ['LsstswRepos']
from past.builtins import basestring
import os
import yaml
try:
# GitPython is an optional dependency, not part of the LSST Stack.
import git
except ImportError:
git = None
[docs]class LsstswRepos(object):
"""lsstsw package version information based on repos.yaml and
checked out Git repositories.
Parameters
----------
dirname : `str`
Path of an ``lsstsw`` directory.
"""
def __init__(self, dirname):
self._dirname = dirname
self._repos = self._load_repos_yaml()
def __contains__(self, package_name):
"""Test if a package is present in `lsstsw`'s repos.yaml dataset.
"""
return package_name in self._repos
def __len__(self):
return len(self._repos)
@property
def manifest_path(self):
"""Path of the manifest.txt file."""
return os.path.join(self._dirname, 'build', 'manifest.txt')
[docs] def get_package_repo_path(self, package_name):
"""Path to a EUPS package repository in lsstsw/build.
Parameters
----------
package_name : `str`
Name of the EUPS package.
Returns
-------
path : `str`
Directory path of the package's Git repository in lsstsw/build.
"""
return os.path.join(self._dirname, 'build', package_name)
[docs] def get_package_branch(self, package_name):
"""Get the name of the checked-out branch of an EUPS package cloned in
lsstsw/build.
Parameters
----------
package_name : `str`
Name of the EUPS package.
Returns
-------
branch : `str`
Name of the checked-out Git branch. If GitPython is not
installed, `None` is always returned instead.
"""
if git is not None:
repo = git.Repo(self.get_package_repo_path(package_name))
return repo.active_branch.name
else:
return None
[docs] def get_package_commit_sha(self, package_name):
"""Get the hex SHA of the checked-out commit of an EUPS package
cloned to lsstsw/build.
Parameters
----------
package_name : `str`
Name of the EUPS package.
Returns
-------
commit : `str`
Hex SHA of the checkout-out Git commit. If GitPython is not
installed, `None` is always returned instead.
"""
if git is not None:
repo = git.Repo(self.get_package_repo_path(package_name))
return repo.active_branch.commit.hexsha
else:
return None
[docs] def get_package_repo_url(self, package_name):
"""URL of the package's Git repository.
This data is obtained from lsstsw/etc/repos.yaml.
Parameters
----------
package_name : `str`
Name of the EUPS package.
Returns
-------
repo_url : `str`
Git origin URL of the package's Git repository.
"""
s = self._repos[package_name]
if isinstance(s, basestring):
return s
else:
# For packages that have sub-documents, rather than the value
# as the URL. See repos.yaml for format documentation.
return s['url']
def _load_repos_yaml(self):
"""Load lsstsw's repos.yaml."""
yaml_path = os.path.join(self._dirname, 'etc', 'repos.yaml')
with open(yaml_path) as f:
repos = yaml.safe_load(f)
return repos