|
|
@ -0,0 +1,238 @@ |
|
|
|
\section{Cet article s'autodétruira dans cent ans} |
|
|
|
|
|
|
|
Le logiciel libre est une bonne chose. Plus personne de sérieux n'en doute, pas même Microsoft ! En 2001, le successeur de Bill Gates, \href{https://web.archive.org/web/20011108013601/http://www.suntimes.com/output/tech/cst-fin-micro01.html}{Steve Ballmer, déclarait} : \begin{quote} |
|
|
|
Linux is not in the public domain. Linux is a cancer that attaches |
|
|
|
itself in an intellectual property sense to everything it touches. |
|
|
|
That's the way that the license works. |
|
|
|
\end{quote} |
|
|
|
Quinze ans plus tard, le 16 novembre 2016, \href{https://web.archive.org/web/20161117013721/https://www.linuxfoundation.org/announcements/microsoft-fortifies-commitment-to-open-source-becomes-linux-foundation-platinum}{Microsoft devenait sponsor de la fondation Linux}. |
|
|
|
|
|
|
|
Seulement, libre ne veut pas dire éternel, surtout sur Internet. Le lecteur attentif en aura déjà eu la preuve : les deux liens précédents n'existent plus. S'ils sont encore disponibles, c'est au moyen de la \href{https://web.archive.org}{Wayback Machine}, un site web fourni par l'\href{https://fr.wikipedia.org/wiki/Internet_Archive}{Internet Archive} et qui permet l'accès à des sauvegardes d'instantanés de pages webs effectuées à plusieurs dates. Dans cent ans, il est probable que cet article n'existera plus et ne soit plus accessible que sous forme de sauvegarde. |
|
|
|
% |
|
|
|
Malheureusement, archiver l'intégralité du web est une tâche ardue et il arrive qu'on ne puisse pas retrouver un contenu disparu par ce moyen. |
|
|
|
|
|
|
|
Lorsque les logiciels libres disparaissent d'Internet, cela peut avoir de lourdes conséquences. Un exemple bien connu est celui d'un paquet d'une dizaine de lignes de code appelé \href{https://www.reddit.com/r/programming/comments/4bjss2/an_11_line_npm_package_called_leftpad_with_only}{leftpad retiré de npm par son auteur}, cassant au passage des milliers d'autres paquets dont \href{https://reactjs.org}{React}. Mais cela arrive de bien d'autres manières: |
|
|
|
|
|
|
|
\begin{itemize} |
|
|
|
\item une personne supprime du code écrit il y a des années de GitHub parce qu'elle en a honte ; |
|
|
|
\item un chercheur part à la retraite et son site web institutionnel n'est pas maintenu ; |
|
|
|
\item une forge hébergeant de nombreux logiciels ferme (e.g. Bitbucket abandonnant le support des dépôts Mercurial, Inria fermant \href{https://gforge.inria.fr/}{sa forge}, rachat et fermeture de Gitorious en l'espace de trois semaines, fermeture de GoogleCode) ; |
|
|
|
\item une entreprise fait faillite et son instance GitLab n'est plus accessible. |
|
|
|
\end{itemize} |
|
|
|
Quelles conséquences à cela ? Vous ne pouvez plus jouer à \href{https://github.com/emersion/mlgrope}{ce petit jeu vidéo} écrit par un étudiant de master qui vous amusait tant : passe encore. Les résultats d'un article de recherche ne sont plus reproductibles : c'est embêtant. Des milliers de bibliothèques logicielles ne sont plus disponibles : caramba ! Une autre entreprise ne peut plus maintenir son logiciel phare car elle dépendait de nombreux logiciels sur cette instance GitLab : elle fait faillite ! |
|
|
|
|
|
|
|
Soyez rassurés, nul besoin de vivre avec l'angoisse que ceci vous arrive, il existe une solution : Software Heritage ! Dans la suite de l'article, nous vous présenterons Software Heritage et le travail effectué par OCamlPro en lien avec opam, OCaml et Software Heritage. Ce travail ayant été rendu possible grâce à \href{https://www.softwareheritage.org/2021/04/20/connecting-ocaml}{une bourse de l'Alfred P. Sloan Foundation}. |
|
|
|
|
|
|
|
\section{Software Heritage} |
|
|
|
|
|
|
|
Software Heritage~\cite{DiCosmo17} est une initiative à but non lucratif, dont la mission est, selon leurs propres termes, la suivante : |
|
|
|
|
|
|
|
\begin{quote} |
|
|
|
We are building the universal software archive. We collect and preserve software in source code form, because software embodies our technical and scientific knowledge and humanity cannot afford the risk of losing it. Software is a precious part of our cultural heritage. We curate and make accessible all the software we collect, because only by sharing it we can guarantee its preservation in the very long term. |
|
|
|
\end{quote} |
|
|
|
|
|
|
|
À l'origine du projet, il y a \href{https://www.inria.fr}{Inria}, un établissement de recherche public français dont vous avez peut-être déjà entendu parler, pour avoir notamment été le lieu où a été développé un petit langage de programmation du nom d'\href{https://ocaml.org}{OCaml}. Le projet Software Heritage est dirigé par \href{https://en.wikipedia.org/wiki/Roberto_Di_Cosmo}{Roberto \bsc{Di Cosmo}} et \href{https://en.wikipedia.org/wiki/Stefano_Zacchiroli}{Stefano \bsc{Zacchiroli}}, deux personnes réputées pour leur implication dans le monde du logiciel libre, d'OCaml ou encore du projet \href{https://www.debian.org}{Debian}. |
|
|
|
|
|
|
|
Aujourd'hui, Software Heritage supporte, entre autres, l'archivage de \href{https://bitbucket.org}{Bitbucket}, \href{https://git.zx2c4.com/cgit/about}{cgit}, \href{https://cran.r-project.org/}{CRAN}, \href{https://www.debian.org}{Debian}, \href{https://gitea.io}{Gitea}, \href{https://github.com}{GitHub}, \href{https://about.gitlab.com}{GitLab}, \href{https://guix.gnu.org}{Guix}, \href{https://www.gnu.org/}{GNU}, \href{https://heptapod.net}{Heptapod}, \href{https://launchpad.net}{Launchpad}, \href{https://nixos.org}{NixOS}, \href{https://www.npmjs.com}{npm}, \href{https://pypi.org}{PyPI} et \href{https://sourceforge.net}{SourceForge}. |
|
|
|
% |
|
|
|
Au moment de l'écriture de cet article, sont archivés environ: |
|
|
|
|
|
|
|
\begin{itemize} |
|
|
|
\item 11 milliards de fichiers sources, |
|
|
|
\item 9 milliards de dossiers, |
|
|
|
\item 2 milliards de commits, |
|
|
|
\item 165 millions de projets, |
|
|
|
\item 19 millions de versions publiées de logiciels\footnote{C'est en réalité plus mais pour des raisons techniques beaucoup de versions ne sont actuellement considérées que comme des \emph{commits}.}. |
|
|
|
\end{itemize} |
|
|
|
|
|
|
|
Archiver tant de logiciels demande des ressources importantes. Software Heritage a donc de nombreux sponsors lui permettant de mener à bien sa mission et garantissant sa pérénnité. On peut notamment citer Huawei, Microsoft, Intel, le CNRS, la Société Générale, le MESRI, Open Invention Network, Sorbonne Université, Université de Paris, Adacore, CAST Software, DINSIC, GitHub, Google, Università di Pisa, VMware, Dans, FOSSID, University of Bologna, Nokia Bell Labs et UQAM. |
|
|
|
|
|
|
|
\section{Support d'opam dans Software Heritage} |
|
|
|
|
|
|
|
Une partie du logiciel libre archivé par Software Heritage est écrit dans le langage OCaml. À l'instar de nombreux langages, OCaml dispose d'un gestionnaire de paquets, \href{https://opam.ocaml.org}{Opam}, qui permet d'installer facilement des bibliothèques et des exécutables à partir de leurs sources. Opam étant très largement utilisé dans la communauté OCaml, il constitue de fait un point d'entrée idéal pour récupérer des sources OCaml. Dans cette section est présenté un travail qui automatise l'archivage des paquets opam par Software Heritage. |
|
|
|
|
|
|
|
Depuis quelques jours, tout le \href{https://github.com/ocaml/opam-repository}{dépôt opam officiel} est archivé ! Vous pouvez vous-même vérifier que votre \href{https://archive.softwareheritage.org/browse/search/?q=fury-puyo\&with_visit=true\&with_content=true\&visit_type=opam}{paquet opam favori} est bien archivé. Il est prévu d'archiver également des dépôts alternatifs. Ils peuvent être signalés sur \href{https://discuss.ocaml.org/t/alternative-opam-repositories}{discuss.ocaml.org}. |
|
|
|
|
|
|
|
Pour ajouter le support d'une nouvelle \emph{software origin} à Software Heritage, il est nécessaire d'écrire deux choses : un \emph{lister} et un \emph{loader}. C'est ce que nous avons fait pour opam. |
|
|
|
% |
|
|
|
Software Heritage étant écrit en Python, le \emph{lister} doit prendre la forme d'un module Python contenant une classe, \texttt{OpamLister} dans notre cas. Pour se conformer à l'architecture du projet, la classe doit fournir deux méthodes: \texttt{get\_pages} et \texttt{get\_origins\_from\_page}. |
|
|
|
|
|
|
|
Dans le cas d'opam, le nombre de paquets étant relativement faible et puisqu'on possède en local toutes les informations du dépôt nécessaires, il n'y a pas de problème lié à un éventuel \emph{rate limiting}. Chaque page ne contient donc qu'un paquet --- on aurait aussi bien pu mettre tous les paquets dans une seule page. La méthode \texttt{get\_pages} a été écrite en faisant simplement appel au binaire opam. Un \emph{opam root} sans \emph{switch} a été initialisé par la classe. Il ne reste qu'à récupérer la sortie d'\texttt{opam list --all}, chaque ligne correspondant à une nouvelle page. |
|
|
|
|
|
|
|
La fonction \texttt{get\_origins\_from\_page} doit ensuite convertir les noms de paquets en une instance de \texttt{ListedOrigins}, laquelle ne contient que le \texttt{visit\_type} (\texttt{opam} dans notre cas) et une URL représentant l'origine. Puisqu'opam supporte tout un tas d'URL différentes (\texttt{git}, \texttt{https}, \texttt{file}\ldots{}), on a fait le choix d'une URL virtuelle prenant la forme |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{python} |
|
|
|
url = f"opam+{self.url}/packages/{page}" |
|
|
|
\end{minted} |
|
|
|
% |
|
|
|
où \texttt{self.url} est l'adresse du dépôt opam que l'on archive et où \texttt{page} est le nom du paquet à archiver. |
|
|
|
% |
|
|
|
Le code complet est disponible sur le dépôt \href{https://archive.softwareheritage.org/browse/origin/content/?origin_url=https://forge.softwareheritage.org/source/swh-lister.git&path=swh/lister/opam/lister.py}{swh-lister}. |
|
|
|
|
|
|
|
C'est pour le \emph{loader} que les choses se compliquent. Pour chaque URL fournie par le \emph{lister}, on doit récupérer l'ensemble des versions disponibles et pour chacune d'elle, fournir l'URL d'une archive à sauvegarder, laquelle sera insérée dans le \href{https://en.wikipedia.org/wiki/Merkle_tree}{graphe orienté acyclique de Merkle}~\cite{PietriSpinellisZacchiroli19} servant à stocker tous les objets archivés par Software Heritage. |
|
|
|
|
|
|
|
Seulement, on ne veut pas recréer un \emph{opam root} pour chacune de ces URLs. On a donc modifié un peu le \emph{lister} afin qu'il passe le chemin de l'\emph{opam root} au \emph{loader}. Si le \emph{loader} tourne sur le même worker que le \emph{lister}, il réutilisera l'\emph{opam root}, sinon, il le recréera et les autres \emph{loaders} pourront réutiliser cet \emph{opam root}. |
|
|
|
|
|
|
|
On doit fournir les quatre méthodes suivantes : \texttt{get\_default\_version}, \texttt{get\_package\_info}, \texttt{build\_revision}, \texttt{get\_versions}. Initialement, elles étaient toutes implémentées en utilisant un simple appel à \texttt{opam list} pour récupérer toutes les versions et à \texttt{opam show} pour récupérer les champs qui nous intéressent (\texttt{url.src}, \texttt{authors}\ldots{}). |
|
|
|
|
|
|
|
Malheureusement, \texttt{opam show} ne supportant pas encore l'option \texttt{--repos}, un conflit aurait été possible si deux paquets avec le même nom étaient présents dans deux dépôts différents. On utilise donc un petit \emph{hack} permettant de faire sans. On calcule le chemin du fichier qui nous intéresse |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{python} |
|
|
|
f"{self.opam_root}/repo/{self.opam_instance}/packages/{self.opam_package}" |
|
|
|
\end{minted} |
|
|
|
% |
|
|
|
et on passe ce fichier à \texttt{opam show} en utilisant l'option \texttt{--file}. |
|
|
|
% |
|
|
|
Le code complet est disponible dans le dépôt \href{https://archive.softwareheritage.org/browse/origin/content/?origin_url=https://forge.softwareheritage.org/source/swh-loader-core.git&path=swh/loader/package/opam/loader.py×tamp=2021-10-01T13:46:03Z}{swh-loader-core}. |
|
|
|
|
|
|
|
Au moment de tester le déploiement, beaucoup d'erreurs ont été rencontrées. La plupart venaient de Software Heritage, par exemple le format \texttt{.tbz} n'était pas supporté. Mais beaucoup venaient du fait que des archives de paquets opam n'existaient plus, menant à une erreur 404. La plupart étaient en fait toujours disponibles dans le cache d'opam, certaines avaient été déplacées, etc. Quoi qu'il en soit, environ \href{https://github.com/ocaml/opam-repository/pulls?page=1\&q=is\%3Apr+author\%3Azapashcanon+url.src}{80 pull requests} ont été ouvertes sur le dépôt opam pour corriger des URLs. |
|
|
|
|
|
|
|
\section{La bibliothèque \emph{swhid}} |
|
|
|
|
|
|
|
Pour permettre aux développeurs OCaml d'accéder à Software Heritage dans leurs projets, nous avons écrit une bibliothèque OCaml \href{https://github.com/OCamlPro/swhid}{\emph{swhid}} permettant de travailler avec les \href{https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html}{\emph{persistent identifiers}} de Software Heritage. Un \emph{persistent identifier} est un identifiant vers un objet archivé dans Software Heritage. En voilà un exemple: |
|
|
|
|
|
|
|
\begin{verbatim} |
|
|
|
swh:1:dir:4431f2b743ef6dffc837e710bdd7e2169f0c5fc9 |
|
|
|
\end{verbatim} |
|
|
|
|
|
|
|
Les lettres \texttt{swh} indiquent tout simplement qu'il s'agit d'un \emph{persistent identifier} de Software Heritage. Le \texttt{1} est le numéro de version du schéma des \emph{persistent identifiers} utilisé. Le mot-clé \texttt{dir} indique le type d'objet représenté par l'identifiant et la chaîne finale de 40 caractères est un \emph{hash} de l'objet. |
|
|
|
% |
|
|
|
Il arrive que l'identifiant contienne des informations supplémentaires, appelées \emph{qualifiers}, qui ne sont pas essentielles, par exemple: |
|
|
|
|
|
|
|
|
|
|
|
\begin{verbatim} |
|
|
|
swh:1:dir:4431f2b743ef6dffc837e710bdd7e2169f0c5fc9 |
|
|
|
;origin=deb://Debian/packages/freedink |
|
|
|
;visit=swh:1:snp:f6df60118578aa9ee91672dc3958908a2bf61fdb |
|
|
|
;anchor=swh:1:rev:db21f0afdb54c16b265754ca599869fda0ca4bfc |
|
|
|
\end{verbatim} |
|
|
|
% |
|
|
|
Elles ne nous intéressent pas dans ce cadre, une explication détaillée est disponible sur la documentation des \href{https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html\#qualifiers}{qualifiers}. |
|
|
|
|
|
|
|
Software Heritage peut archiver cinq types d'objets différents. Voici leur description tirée (et traduite) de la documentation de Software Heritage : |
|
|
|
|
|
|
|
\begin{itemize} |
|
|
|
\item \texttt{cnt} pour \texttt{content} (aussi appelés \texttt{blobs}): le contenu brut d'un fichier source sous forme d'une séquence d'octets, sans nom de fichier ou autre métadonnée. Le contenu des fichiers est souvent récurrent, par exemple d'une version d'un logiciel à la suivante, ou dans différents répertoires d'un même projet ou même dans des projets complètement disjoints. |
|
|
|
\item \texttt{dir} pour \texttt{directory} : une liste d'entrées nommées d'un même répertoire, chacune pointant vers d'autres artéfacts qui sont généralement des objets \texttt{cnt} ou bien des sous-répertoires. Ces entrées sont souvent associées à des métadonnées comprenant un nom et des bits de permission. |
|
|
|
\item \texttt{rev} pour \texttt{revision} (aussi appelés \texttt{commits}): le développement logiciel au sein d'un projet spécifique est essentiellement une série de copies à partir du répertoire racine, indexées dans le temps, et qui contient la totalité du code source du projet. Le logiciel évolue quand un développeur modifie le contenu d'un ou plusieurs fichiers dans ce répertoire et enregistre ses modifications. Chaque copie enregistrée de la racine s'appelle une révision. Elle pointe vers un répertoire complètement déterminé et est équipée d'un lot arbitraire de métadonnées. Certaines sont ajoutée manuellement par le développeur (les messages de commit), d'autres sont générées par l'outil de gestion de versions (date de modification, commits précédents, etc.). |
|
|
|
\item \texttt{rel} pour \texttt{release} (aussi appelés \texttt{tags}): toutes les révisions ne sont pas égales entres elles, et certaines sont choisies par les développeurs comme étant des jalons aussi appelées publications. Chaque release pointe vers le commit le plus récent dans l'historique du projet qui correspond à la-dite sortie et peut comporter des métadonnées arbitraires : nom de release et version, message d'annonce de sortie, des signatures cryptographiques, etc. |
|
|
|
\item \texttt{snp} pour \texttt{snapshot} : quelle que soit l'origine d'un logiciel, celle-ci offrira de multiples pointeurs vers les version courantes du développement d'un projet. Dans le cas des systèmes de gestion de version, cela se manifeste au travers de branches (master, development, branches dites "de fonctionnalités" font évoluer un logiciel dans une direction précise); pour les gestionnaires de paquets aussi ce fait est visible, notamment dans l'existence de \emph{versions (suites)} qui témoignent de la maturité individuelle des paquets qu'ils distribuent (Debian Stable, Debian Testing, \ldots). Le snapshot de l'origine d'un logiciel donné enregistre toutes les entrées qui s'y trouvent et ce vers quoi ces entrées pointaient à un moment donné. Par exemple, un objet snapshot peut tout aussi bien suivre le commit vers lequel la branche master pointait à un moment donné, que la sortie la plus récente d'un paquet donné dans la version stable d'une distribution. |
|
|
|
\end{itemize} |
|
|
|
|
|
|
|
Deux autres types d'objets spéciaux sont disponibles mais ils ne nous intéressent pas ici: \texttt{origins} et \texttt{visits}. Une explication détaillée est donnée dans la documentation des \href{https://docs.softwareheritage.org/devel/swh-model/data-model.html\#software-artifacts}{software artifacts}. |
|
|
|
|
|
|
|
\subsection{Parser, valider et afficher des SWHIDs} |
|
|
|
|
|
|
|
Notre bibliothèque est capable de parser, de valider et d'afficher des |
|
|
|
\emph{persistent identifiers} : |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{OCaml} |
|
|
|
let id = "swh:1:cnt:80131a360f0ae3d4d643f9e222591db8d4aa744c" |
|
|
|
|
|
|
|
let () = |
|
|
|
match Swhid.Parse.from_string id with |
|
|
|
| Error e -> Format.eprintf "error: %s@." e |
|
|
|
| Ok id -> Format.printf "the id is: %a@." Swhid.Pp.identifier id |
|
|
|
\end{minted} |
|
|
|
% |
|
|
|
S'il y en a, les \texttt{qualifiers} sont parsés mais pas validés. |
|
|
|
|
|
|
|
\subsection{Calculer des SWHIDs} |
|
|
|
|
|
|
|
Notre bibliothèque est capable de calculer des SWHIDs pour les cinq |
|
|
|
types d'objets présentés précédemment : |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{OCaml} |
|
|
|
(* some file for which we'd like to compute a SWHID *) |
|
|
|
let content = |
|
|
|
{|(executable |
|
|
|
(name hello) |
|
|
|
(modules hello)) |
|
|
|
|} |
|
|
|
|
|
|
|
let swhid = Swhid.Compute.content_identifier content |
|
|
|
|
|
|
|
let () = |
|
|
|
match swhid with |
|
|
|
| None -> Format.eprintf "invalid ID :S@." |
|
|
|
| Some swhid -> Format.printf "ID is: `%a`.@." Swhid.Pp.identifier swhid |
|
|
|
\end{minted} |
|
|
|
À l'exécution on obtient: |
|
|
|
\begin{minted}[bgcolor=lightBackground]{md} |
|
|
|
ID is: `swh:1:cnt:f5a5bc805b67f7510d2e2eb07500f47ced8af8ca`. |
|
|
|
\end{minted} |
|
|
|
On peut maintenant communiquer cet identifiant en sachant que le jour où notre fichier sera archivé, il aura cet identifiant. Les autres types d'objet sont plus compliqués à calculer. On laisse le lecteur curieux se référer à la documentation du module \href{https://ocamlpro.github.io/swhid/api/swhid/Swhid/Compute/index.html}{Swhid.Compute}. |
|
|
|
|
|
|
|
\subsection{Télécharger des SWHIDs} |
|
|
|
|
|
|
|
Pour télécharger un objet à partir de son identifiant, une \href{https://archive.softwareheritage.org/api/}{Web API} est disponible sur Software Heritage. Il n'est généralement pas possible de récupérer directement un objet en utilisant cette API. Il faut effectuer une requête afin d'obtenir une URL où, après un petit temps de préparation, on pourra récupérer l'objet voulu. C'est assez simple pour \texttt{cnt} ou \texttt{dir} par exemple, mais plus compliqué pour \texttt{release}, une \emph{release} pouvant pointer vers différents types d'objets. Il faut faire une première requête pour obtenir l'objet vers lequel elle pointe et recommencer récursivement. De même, un \texttt{snapshot} étant un ensemble d'objets, on obtiendra un ensemble d'URLs où télécharger ces objets. |
|
|
|
% |
|
|
|
Notre bibliothèque contient un module \texttt{Download} contenant une fonction pour chaque type d'objet: |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{OCaml} |
|
|
|
(* an identifier we want to download (a file from FreeDink) *) |
|
|
|
let id = "swh:1:cnt:80131a360f0ae3d4d643f9e222591db8d4aa744c" |
|
|
|
|
|
|
|
let url = |
|
|
|
(* we parse the string to get a Swhid.Lang.identifier *) |
|
|
|
match Swhid.Parse.from_string id with |
|
|
|
| Error _e as e -> e |
|
|
|
| Ok id -> ( |
|
|
|
(* we ask SWH for an URL from which the object can be downloaded *) |
|
|
|
Swhid.Download.content id |
|
|
|
|
|
|
|
let () = |
|
|
|
match url with |
|
|
|
| Error e -> |
|
|
|
(* we didn't get an URL *) |
|
|
|
Format.eprintf |
|
|
|
"Can't get a download URL: %s@." e; |
|
|
|
exit 1 |
|
|
|
| Ok url -> |
|
|
|
(* we got a valid URL ! :D *) |
|
|
|
Format.printf "The file can be downloaded at url `%s`.@." url |
|
|
|
\end{minted} |
|
|
|
Et l'on obtient bien: |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=lightBackground]{md} |
|
|
|
The file can be downloaded at url `https://archive.softwareheritage.org/api/1/content/sha1_git:80131a360f0ae3d4d643f9e222591db8d4aa744c/raw/`. |
|
|
|
\end{minted} |
|
|
|
|
|
|
|
Une fonction \texttt{any} est aussi fournie, qui permet de récupérer une liste d'URLs pour un identifiant quelconque. La liste ne contiendra qu'un élément dans tous les cas, sauf pour \texttt{snapshot} où elle pourra en contenir plusieurs. |
|
|
|
% |
|
|
|
Plus d'informations sont disponibles dans la documentation du module \href{https://ocamlpro.github.io/swhid/api/swhid/Swhid/Download/index.html}{Swhid.Download}. |
|
|
|
|
|
|
|
\section{Ajout du support dans opam} |
|
|
|
|
|
|
|
La dernière partie de ce travail, qui est toujours en cours, consiste à permettre à opam d'aller automatiquement chercher des archives dans Software Heritage dans le cas où l'archive d'un paquet aurait disparu et ne serait pas non plus disponible dans le cache d'opam. |
|
|
|
% |
|
|
|
Pour cela, les étapes à effectuer sont les suivantes : |
|
|
|
|
|
|
|
\begin{itemize} |
|
|
|
\item support dans opam d'un champ \texttt{swhid} optionnel pour les fichiers \texttt{.opam} ; |
|
|
|
\item téléchargement depuis Software Heritage de l'archive correspondant à l'identifiant contenu dans ce champ en cas de nécessité ; |
|
|
|
\item modification du dépôt opam officiel pour ajouter les SWHIDs de toutes les versions de chaque paquet. |
|
|
|
\end{itemize} |
|
|
|
|
|
|
|
Plusieurs solutions ont été envisagées pour le support du champ \emph{swhid} dans les fichiers \emph{.opam}. \href{https://github.com/ocaml/opam/pull/4852}{L'approche initiale} consistait à ajouter un nouveau type de \emph{checksum}, mais cela impactait trop de parties du code. \href{https://github.com/ocaml/opam/pull/4859}{Une solution plus simple} a ensuite été envisagée : ajouter un champ \emph{swhid} au sein du champ \emph{url}. Elle fonctionnait correctement mais posait un problème (présent aussi dans la solution initiale) : cela n'est pas rétro-compatible et aurait empêché la mise à jour du dépôt opam officiel avec les SWHIDs avant que la majorité des clients aient été mis à jour. La solution retenue consiste à ajouter plutôt une fausse adresse au champ \emph{mirrors} : |
|
|
|
|
|
|
|
\begin{minted}[bgcolor=darkBackground]{json} |
|
|
|
url { |
|
|
|
src: "..." |
|
|
|
mirrors: [ ... "https://swhid.opam.ocaml.org/swh:1:rev:15e2f26f2ae0f0197ce95b997b4fe024c3491f9e" ] |
|
|
|
} |
|
|
|
\end{minted} |
|
|
|
|
|
|
|
Les anciens clients échoueraient au moment de télécharger l'objet mais ils pourraient au moins utiliser le fichier opam. Les nouveaux clients pourraient quant à eux récupérer le SWHID et récupérer l'archive. De plus, il est prévu de supporter dès maintenant une adresse de la forme \texttt{swh:1:\ldots} afin de pouvoir remplacer les fausses adresses dans le futur. Ainsi, on utilisera directement le SWHID qui est une URL valide et dont le schéma est déjà enregistré à l'IANA. |
|
|
|
|
|
|
|
On ne devrait avoir besoin que de supporter des objets de type \emph{rel}, cependant du fait d'un \href{https://forge.softwareheritage.org/T1258}{bogue} connu de Software Heritage, certaines \emph{releases} ne sont considérées que comme des objets de type \emph{rev}. Le support des deux types d'objet est donc prévu. |
|
|
|
|
|
|
|
Les parties de téléchargement et de mise à jour du dépôt opam sont relativement faciles. Le téléchargement étant déjà implémenté dans la bibliothèque \emph{swhid}, il ne restera plus qu'à l'adapter à opam. Le patch du dépôt opam sera généré : on télécharge l'ensemble des archives, on calcule leur identifiant et on modifie le fichier opam à l'endroit idoine. |
|
|
|
|
|
|
|
|
|
|
|
\section{Conclusion} |
|
|
|
|
|
|
|
Les logiciels libres sont des objets de valeur. Nous avons expliqué comment Software Heritage les préserve et fait en sorte que tous les logiciels publiés sur opam soient eux aussi correctement archivés. Enfin, nous avons développé des outils OCaml permettant de travailler avec Software Heritage au moyen d'une bibliothèque et en ajoutant à opam le moyen de récupérer sur Software Heritage des logiciels disparus. Grâce à ce travail, c'est déjà plus de 3500 paquets qui ont été archivés et les auteurs de paquets opam ont maintenant la garantie que leur travail restera accessible à jamais via opam et Software Heritage. De même, les développeurs de logiciels OCaml savent désormais que les paquets dont ils dépendent ne risquent plus de disparaître. |
|
|
|
|
|
|
|
\paragraph{Remerciements.} |
|
|
|
Merci à Nicolas \bsc{Dandrimont}, Antoine R. \bsc{Dumont}, Antoine \bsc{Lambert} et Valentin \bsc{Lorentz} pour leur aide sur Software Heritage ; ainsi qu'à Roberto \bsc{Di Cosmo} et Jean-Christophe \bsc{Filliâtre} pour leur relecture. |