#+TITLE: CLPI Specification v0.4 #+AUTHOR: Eric Timmons #+EMAIL: clpm-devel@common-lisp.net This document provides the specification of version 0.4 of the Common Lisp Project Index. Much of this specification is inspired by [[https://github.com/rubygems/compact_index][RubyGems' compact_index]], with modifications to make it more Lispy and account for prevalent Common Lisp practices. An index consists of a series of objects that contain information about the projects and systems defined in the index. Two common examples of indices would be an index located on a file system (where each object is a seperate file on the file system) and an index accessed over HTTP (where each object is accessed via a separate URL). Each object must contain s-expressions that can be =READ= by a Common Lisp implementation. All symbols in the s-expressions must be keywords. Any plist may contain keys beyond those defined by this specification. However, as there is no central registry of extensions to the spec, all such keywords *must* be prefixed with an identifier followed by a =/=. There may also be additional objects in the index beyond those defined by this specification. Any new objects not part of the spec *must* be prefixed with by =ext/ID/= where ID is a reasonably unique identifer. For example, the =ql-clpi= project stores version aliases for projects in the =projects/PROJECT-NAME/ext/ql/version-aliases= object. New keys for any plist or new objects may be added to this version of the specification so long as the changes are backwards compatible. As many users of an index may desire to work offline and/or not need access to the entire index, it is designed to be somewhat efficient when syncing across a network. In this case the canonical version of the complete index is called the primary and the local (potentially incomplete) version of the index is called the secondary. * Index metadata The following objects are defined at the top level of the index to contain information about the entire index. + =clpi-version= :: Required. A string naming the version of the CLPI specification used by this index. Must be ="0.4"= for this version of the spec. + =project-index-object-version= :: An integer or NIL/missing whose purpose is further described in [[*Project index]]. + =system-index-object-version= :: An integer or NIL/missing whose purpose is further described in [[*System index]]. * Project index The object =project-index= or =project-index-PROJECT-INDEX-OBJECT-VERSION= must exist, where =PROJECT-INDEX-OBJECT-VERSION= is defined in the [[*Index metadata]]. If the project index object version is NIL/not provided, only the former must exist, otherwise the latter must exist. Each form in this object is a list where the first element is a project name (string). The rest is a list of strings naming versions of releases of this project. It is allowed for a project to be named with no releases. It is allowed for a project to appear multiple times in this object. If it does, all the releases should be combined after reading. If =PROJECT-INDEX-OBJECT-VERSION= is non-NIL, this file must only be appended to. * System index The object =system-index= or =system-index-SYSTEM-INDEX-OBJECT-VERSION= must exist, where =SYSTEM-INDEX-OBJECT-VERSION= is defined in the [[*Index metadata]]. If the system index object version is NIL/not provided, only the former must exist, otherwise the latter must exist. Each form in this object is a list where the first element is a system name (string). The rest is a list of lists describing releases of this system. Each element is a list with one or two member. The first member is a [[*Project release description]]. The second element is the ASD version of the system (if one is defined). If the second element is missing, it is assumed the ASD version of the system is =NIL=. It is allowed for a system to be named with no releases. It is allowed for a system to appear multiple times in this object. If it does, all the releases should be combined after reading. If =SYSTEM-INDEX-OBJECT-VERSION= is non-NIL, this file must only be appended to. * Project metadata Metadata about projects is stored under the prefix =projects/PROJECT-NAME/=. The following objects are defined for each project. + =repo= :: The project's VCS repository, as described in [[*Repository Description]]. + =authors= :: A list of person descriptions, as described in [[*Person Description]]. + =maintainers= :: A list of person descriptions, as described in [[*Person Description]]. + =homepage= :: A string containing the URL of the project's homepage. + =releases-object-version= :: An integer or NIL/missing whose purpose is further described in [[*Project releases]]. + =version-scheme= :: A keyword describing how this project versions its releases. =:date= implies a date based version that is comparable with =#'string<=. =:semantic= implies version numbers that are compatible with [[https://semver.org/][Semver v2]]. * Project releases For every project in the index, the object =project/PROJECT-NAME/releases= or =projects/PROJECT-NAME/releases-RELEASES-OBJECT-VERSION= must exist, where =PROJECT-NAME= is the project name and =RELEASES-OBJECT-VERSION= is defined in the project metadata. If the release object version is NIL/not provided, only the former must exist, otherwise the latter must exist. This object contains information about each release of the project. Every sexp must be of the form: =(version . release-plist)=, where =version= is a string containing the release's version and =release-plist= is a plist with the following keys: + =:url= :: Required. A string containing the URL of an archive for this release. This archive must contain a single top level folder. + =:archive-type= :: A keyword describing the type of archive. Defined keywords are: =:tar.gz= and =:zip=. Defaults to =:tar.gz= if not specified. + =:size= :: The size of the release archive in bytes. + =:md5= :: The md5sum of the release archive. + =:systems= :: An alist mapping paths to system files within the release (relative to the archive's top level folder) to lists of [[*System description]]. ** System description A system description is an alist mapping a string system name to a plist with information about that system. The defined keys in the plist are: + =:version= :: A string containing the version of the system. If non-NIL, must be a dotted sequence of numbers (this requirement comes from ASDF, unfortunately). + =:description= :: A string containing a description of the system. + =:license= :: The license of the system. Can be an arbitrary sexp. + =:dependencies= :: A list of dependencies for this system. For a description of the allowed forms of dependencies, see [[*System dependency]]. * System metadata Metadata about systems is stored under the prefix =projects/SYSTEM-NAME/= where =SYSTEM-NAME= is the primary system name. The following objects are defined for each primary system. + =primary-project= :: A string naming the current home project of this system and all its child systems. * System dependency A system dependency can take one of four forms: 1. A string naming a system. 2. A list with =:require= as the first element and a string naming a module as the second element. 3. A list of the form =(:version SYSTEM-NAME VERSION-SPECIFIER)=, where =SYSTEM-NAME= is a string naming a system and =VERSION-SPECIFIER= is an ASDF version string (dot separated numbers only). This states the minimum version of the system that is needed. 4. A list of the form =(:feature FEATURE-EXPRESSION SYSTEM-DEPENDENCY)= where =FEATURE-EXPRESSION= denotes either a (keyword!) feature, negation, disjunction, or conjunction of feature expressions (see the ASDF manual) and =SYSTEM-DEPENDENCY= is a dependency as defined by this section. * Person Description This is used to describe a person (or other entity). It is either a string containing the name of the entity or a list of two elements. The first element must be a string naming the entity and the second must be a string containing an email address. * Project release description A project release description is a list of two elements. The first element is a string naming a project. The second element is a string naming the version of a release of that project. * Respository Description This is used to describe a source control repository. It must be a list of the form =(REPO-TYPE . REPO-ARGS)= where =REPO-TYPE= is a keyword and =REPO-ARGS= is a plist. This following repo types are defined: ** Gitlab Repository Describes a git repository hosted on a Gitlab server. The =REPO-TYPE= must be =:gitlab=. The following args are defined: + =:host= :: A string containing the hostname of the gitlab server. Defaults to ="gitlab.com"= if not provided. + =:path= :: Required. A string containing the path to the repository. Must not end in =.git=. ** Github Repository Describes a git repository hosted on a Github server. The =REPO-TYPE= must be =:github=. The following args are defined: + =:host= :: A string containing the hostname of the gitlab server. Defaults to ="github.com"= if not provided. + =:path= :: Required. A string containing the path to the repository. Must not end in =.git=.