User:Nathan M. Swan/DPM Proposal
This is a proposal for dpm
, a D package manager. I don't want to start working on any code until I get feedback from the community.
It has these conflicting principles:
- ease of use. If the package manager is complicated, you might as well use
git
andmake
alone. - almost backwards compatibility. Platforms are only as good as the software that uses them; therefore, it should be really easy to
dpm
-ize packages. - Turing-complete customization. D projects are full of automatic C binders, documentation generators, and other useful stuff that the package manager shouldn't get in the way of.
Contents
Scenarios
These are the main scenarios:
- A package user installing/managing packages they import/run
- A package creator creating/configuring packages they wrote
- A build script doing things with the source/binary/headers/docs/whatever.
Installing packages
Overview
You enter the command:
$ dpm install <package-name> [<package-version>] [from <cpr-name>]
And you can now either run the executable or import/link the library in other projects.
Details
The repository can be a "genuine" or "pseudo" package. A genuine package has been created with dpm
, which means that it simply follows the instructions of the dpm configuration file.
Pseudo-packages are D code repositories that have yet to use dpm. Because of this, it will open a shell in the top directory of the installed repository, telling the user they will have to install it manually, encouraging them to checkout the READMEs and INSTALLs it finds.
Genuine packages have a file dpmconfig.d
at the top directory, which contains the code run to install the package. Technically, it can do what it wants, though it most likely will import dpm;
, a separate D file compiled alongside it. That file will contain a series of useful functions for making it easy to program the config file, including ways to call common build methods like make
or rdmd
.
Creating packages
Overview
If this is an old project you're migrating over, you enter the command:
$ dpm create template <build type>
If this is a new project:
$ dpm create init <make | raw>
Detail
Migrating to dpm
should be easy. Therefore, users with existing build options shouldn't have to redo it, just have dpmconfig.d
call existing build code.
There will be a dpm
command called create template
, which automatically generates these configuration file templates:
Template Build Script make -> make(); make-install -> make("install"); make-make-install -> make(); make("install"); rdmd-build -> rdmd("build.d"); exec "code" -> // executes "code" empty -> // does nothing
The create init
command can happen two ways: make
will generate a Makefile
, which has the advantage of not requiring dpm
; or a raw
file, which builds right from the config file script (with all the lovely dpm.d
APIs).
The dpm.d
API would contain various process-calling convenience functions, directory-scanning functions, and so on. One important function is:
void depend(string repo, string version_="");
Which makes dpm
install that package if it isn't there already.
It has a variant for non-D projects, which does a default system install (e.g. apt-get
), e.g. gtk as a dependency for gtkD:
void dependSys(string repo);
To ensure the right versioning requirements, this command generates dependency requests for every package dpm has installed:
$ dpm freeze > commands.d
These can be edited down and pasted into the config file.
Examples
Example bare-bones config file:
import dpm;
void dpm_main() {
make();
}
System Interface
TODO
Central Package Repositories
Overview
A package is simply a reference in a git
repository. It can either refer to the tip of a branch, or a tag. They are referred to using this notation:
<git repository url> [branch=<branch> | tag=<tag>]
The repository-url and branch/tag are respectively the package-name and package-version of the install command.
But directly specifying URLs can be inconvenient, so there can exist a CPR, a Central Package Repository. A CPR is simply a configured URL to which requests for a repository are sent. A system can be configured to have multiple CPRs.
CPR Management
Users can add/remove CPRs using the cpr add
and cpr rm
commands, respectively:
dpm cpr add <name> <url> dpm cpr rm <name>
They are added like a LIFO stack, so when multiple CPRs give a successful resolution, the CPR most recently added is chosen.
The order can be changed with the dpm cpr store
, which gives the filename for a CPR store:
[vim | emacs] `dpm cpr store`
It is of the following format:
<item1-name> <item1-url> <item2-name> <item2-url> ...
With the top items taking precedence.
Package Resolution Protocol
A request for package resolution is an HTTP POST request to the given URL, with the following application/json
body:
{"prp-version":"0.1", "name": "<name>", "version": "<version>"}
The response will have a status of 200 and a body of either
{"prp-version":"0.1", "git-url": "<repo url>", ["branch": "<branch>" | "tag": "<tag>"]}
or
{"prp-version":"0.1", "notfound-message": "<error message>"}
Sample packages
These are all popular D libraries (as far as I can tell), which I will use to test dpm
's ease-of-use and flexibility:
https://github.com/rejectedsoftware/vibe.d https://github.com/gtkd-developers/GtkD https://github.com/aldacron/Derelict3 https://github.com/jacob-carlborg/orange https://github.com/eldar/candydoc https://github.com/CyberShadow/DustMite https://github.com/SiegeLord/Tango-D2 https://github.com/D-Programming-Deimos/openssl