Coverage for python/lsst/verify/metadata/lsstsw.py: 40%
43 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-27 03:08 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-27 03:08 -0700
1# This file is part of verify.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21"""APIs for building software provenance from lsstsw."""
23__all__ = ['LsstswRepos']
25import os
27import yaml
28try:
29 # GitPython is an optional dependency, not part of the LSST Stack.
30 import git
31except ImportError:
32 git = None
35class LsstswRepos(object):
36 """lsstsw package version information based on repos.yaml and
37 checked out Git repositories.
39 Parameters
40 ----------
41 dirname : `str`
42 Path of an ``lsstsw`` directory.
43 """
44 def __init__(self, dirname):
45 self._dirname = dirname
46 self._repos = self._load_repos_yaml()
48 def __contains__(self, package_name):
49 """Test if a package is present in `lsstsw`'s repos.yaml dataset.
50 """
51 return package_name in self._repos
53 def __len__(self):
54 return len(self._repos)
56 @property
57 def manifest_path(self):
58 """Path of the manifest.txt file."""
59 return os.path.join(self._dirname, 'build', 'manifest.txt')
61 def get_package_repo_path(self, package_name):
62 """Path to a EUPS package repository in lsstsw/build.
64 Parameters
65 ----------
66 package_name : `str`
67 Name of the EUPS package.
69 Returns
70 -------
71 path : `str`
72 Directory path of the package's Git repository in lsstsw/build.
73 """
74 return os.path.join(self._dirname, 'build', package_name)
76 def get_package_branch(self, package_name):
77 """Get the name of the checked-out branch of an EUPS package cloned in
78 lsstsw/build.
80 Parameters
81 ----------
82 package_name : `str`
83 Name of the EUPS package.
85 Returns
86 -------
87 branch : `str`
88 Name of the checked-out Git branch. If GitPython is not
89 installed, `None` is always returned instead.
90 """
91 path = self.get_package_repo_path(package_name)
92 if git is not None and os.path.exists(path):
93 repo = git.Repo(path)
94 return repo.active_branch.name
95 else:
96 return None
98 def get_package_commit_sha(self, package_name):
99 """Get the hex SHA of the checked-out commit of an EUPS package
100 cloned to lsstsw/build.
102 Parameters
103 ----------
104 package_name : `str`
105 Name of the EUPS package.
107 Returns
108 -------
109 commit : `str`
110 Hex SHA of the checkout-out Git commit. If GitPython is not
111 installed, `None` is always returned instead.
112 """
113 path = self.get_package_repo_path(package_name)
114 if git is not None and os.path.exists(path):
115 repo = git.Repo(path)
116 return repo.active_branch.commit.hexsha
117 else:
118 return None
120 def get_package_repo_url(self, package_name):
121 """URL of the package's Git repository.
123 This data is obtained from lsstsw/etc/repos.yaml.
125 Parameters
126 ----------
127 package_name : `str`
128 Name of the EUPS package.
130 Returns
131 -------
132 repo_url : `str`
133 Git origin URL of the package's Git repository.
134 """
135 s = self._repos[package_name]
136 if isinstance(s, str):
137 return s
138 else:
139 # For packages that have sub-documents, rather than the value
140 # as the URL. See repos.yaml for format documentation.
141 return s['url']
143 def _load_repos_yaml(self):
144 """Load lsstsw's repos.yaml."""
145 yaml_path = os.path.join(self._dirname, 'etc', 'repos.yaml')
146 with open(yaml_path) as f:
147 repos = yaml.safe_load(f)
148 return repos