Changeset View
Standalone View
swh/loader/package/opam/loader.py
- This file was added.
# Copyright (C) 2021 The Software Heritage developers | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
vlorentz: copyright header | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# See the AUTHORS file at the top-level directory of this distribution | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# License: GNU General Public License version 3, or any later version | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# See top-level LICENSE file for more information | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import io | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import os | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from subprocess import PIPE, Popen, call | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from typing import Iterator, List, Optional, Tuple | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import attr | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from swh.loader.package.loader import BasePackageInfo, PackageLoader | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from swh.model.model import Person, Revision, RevisionType, Sha1Git | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from swh.storage.interface import StorageInterface | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@attr.s | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class OpamPackageInfo(BasePackageInfo): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
author = attr.ib(type=Person) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
committer = attr.ib(type=Person) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
version = attr.ib(type=str) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class OpamLoader(PackageLoader[OpamPackageInfo]): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
visit_type = "opam" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline ActionsAs you did for the opam lister, can you please add a small explanation summary as a Thanks in advance. [1] https://forge.softwareheritage.org/source/swh-lister/browse/master/swh/lister/opam/lister.py$0-26 ardumont: As you did for the opam lister, can you please add a small explanation summary as a
first… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
storage: StorageInterface, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_root: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_instance: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_url: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_package: str, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_content_size: Optional[int] = None, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
super().__init__(storage=storage, url=url, max_content_size=max_content_size) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_root = opam_root | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_instance = opam_instance | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_url = opam_url | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_package = opam_package | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.env = os.environ.copy() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.env["OPAMROOT"] = opam_root | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if not os.path.isdir(opam_root): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if os.path.isfile(opam_root): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError("invalid opam root") | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
call( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"opam", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"init", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--reinit", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--bare", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--no-setup", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_instance, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline ActionsOut of curiosity, do we really need to use the environment variable? (not asking to change) ardumont: Out of curiosity, do we really need to use the environment variable?
Can't we just use the `… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Done Inline Actionsboth are fine, the --root way will probably make the code easier to understand but I used the environment variable in the lister too... I'll change it here, don't you mind updating the lister ? aleo: both are fine, the `--root` way will probably make the code easier to understand but I used the… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline Actionssure thing, fine for me. ardumont: sure thing, fine for me. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
opam_url, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
env=self.env, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
elif not os.path.isfile(os.path.join(opam_root, "config")): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError("invalid opam root") | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_versions(self) -> List[str]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
proc = Popen( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"opam", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"show", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--color", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"never", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--normalise", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-f", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"all-versions", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_package, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
env=self.env, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout=PIPE, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if proc.stdout is not None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in io.TextIOWrapper(proc.stdout): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# we only care about the first line | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# and there should be only one line anyway | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return line.split() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"can't get versions for package {self.opam_package} \ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(at url {self.url}) from `opam show`" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_default_version(self) -> str: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
proc = Popen( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"opam", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"show", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--color", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"never", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--normalise", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-f", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"version", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.opam_package, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline Actions
what do you think of the following? That should decrease the repetition a bit. ardumont: what do you think of the following?
That should decrease the repetition a bit. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
env=self.env, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout=PIPE, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if proc.stdout is not None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in io.TextIOWrapper(proc.stdout): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# we only care about the first element of the first line | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# and there should be only one element and one line anyway | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
v = line.split() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if len(v) == 1: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return v[0] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"can't get default version for package {self.opam_package} \ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(at url {self.url}) from `opam show`" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_enclosed_single_line_field(self, field, version) -> Optional[str]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
proc = Popen( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"opam", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"show", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--color", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"never", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"--normalise", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-f", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
field, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"{self.opam_package}.{version}", | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline Actions
which then becomes according to the previous suggestion. ardumont: which then becomes according to the previous suggestion. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
env=self.env, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stdout=PIPE, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if proc.stdout is not None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in io.TextIOWrapper(proc.stdout): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# we only care about the first line | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# and there should be only one line anyway | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# we also need to remove the enclosing " and the trailing \n | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return line[1:-2] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return None | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_package_info(self, version: str) -> Iterator[Tuple[str, OpamPackageInfo]]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
branch_name = f"{self.opam_package}.{version}" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url = self.get_enclosed_single_line_field("url.src:", version) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if url is None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise ValueError( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f"can't get field url.src: for version {version} of package {self.opam_package} \ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(at url {self.url}) from `opam show`" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
authors_field = self.get_enclosed_single_line_field("authors:", version) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline Actions
finally ;) ardumont: finally ;) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fullname = b"" if authors_field is None else str.encode(authors_field) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
author = Person(fullname=fullname, name=None, email=None) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
maintainer_field = self.get_enclosed_single_line_field("maintainer:", version) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fullname = b"" if maintainer_field is None else str.encode(maintainer_field) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
committer = Person(fullname=fullname, name=None, email=None) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline ActionsSo this could potentiality contain multiple names per Person, right? vlorentz: So this could potentiality contain multiple names per `Person`, right? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Done Inline ActionsIndeed. Is there another class that I should use then ? aleo: Indeed. Is there another class that I should use then ? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline ActionsUnfortunately, the data-model doesn't allow this yet. In the meantime, I wonder if we should use a hack like Github's to embed them in the message... https://docs.github.com/en/github/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors This probably needs to be discussed with the whole team vlorentz: Unfortunately, the data-model doesn't allow this yet.
In the meantime, I wonder if we should… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yield branch_name, OpamPackageInfo( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url=url, filename=None, author=author, committer=committer, version=version | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def build_revision( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
self, p_info: OpamPackageInfo, uncompressed_path: str, directory: Sha1Git | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) -> Optional[Revision]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Revision( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type=RevisionType.TAR, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
author=p_info.author, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline Actionsif there are no release notes, could you write the version number as message? vlorentz: if there are no release notes, could you write the version number as message? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Done Inline ActionsDone ! aleo: Done ! | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
committer=p_info.committer, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
message=str.encode(p_info.version), | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Not Done Inline ActionsOh :( I see there is a publication date on Opam's web interface, is there no way we could fetch that? vlorentz: Oh :(
I see there is a publication date on Opam's web interface, is there no way we could… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Done Inline ActionsI don't see an easy way to do that. It's not really part of the opam repository. I guess you can get it if the opam repository is a git repository by checking the git history but I'm not sure we want to do that neither if it always makes sense. Especially it won't be possible in the case of a local opam repository (used for tests) or for the Coq opam repository which is there: https://coq.inria.fr/opam/released/ The two opam developpers are on vacation, I'll ask them if there's an easy way to do it but I don't expect so. aleo: I don't see an easy way to do that. It's not really part of the opam repository. I guess you… | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
date=None, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
committer_date=None, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parents=(), | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
directory=directory, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
synthetic=True, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) |
copyright header