-
These stub packages which will be used to simulate what a revdep failure looks like.
The respective directory structure.stub-b/ ├── opam ├── dune-project └── src/ ├── dune └── b.ml stub-a/ ├── opam ├── dune-project └── src/ ├── dune └── a.ml
-
Then use a template where
A <- B
(A needs B). So we need to make 2 opam files.2.1 Contents of a file :
stub-b/opam
opam-version: "2.0" name: "stub-b" version: "0.1.0" synopsis: "Example dependency package" description: "Simple demonstration package for OPAM dependencies" maintainer: "[email protected]" authors: ["You"] license: "MIT" build: [ ["dune" "build" "-p" name] ] depends: [ "dune" {>= "2.0"} "ocaml" {>= "4.08.0"} ]
2.2 Contents of file :
stub-a/opam
opam-version: "2.0" name: "stub-a" version: "0.1.0" synopsis: "Package depending on stub-b" description: "Demonstrates dependency on another OPAM package" maintainer: "[email protected]" authors: ["You"] license: "MIT" build: [ ["dune" "build" "-p" name] ] depends: [ "dune" {>= "2.0"} "ocaml" {>= "4.08.0"} "stub-b" # stub-a <- stub-b ]
-
Then define
dune-project
at the root of the OPAM packages.3.1 Contents of
stub-b/dune-project
(lang dune 3.0) (name stub-b) (version 0.1.0) (implicit_transitive_deps false) ; Crucial for dependency resolution (package (name stub-b) (version 0.1.0))
3.2 Contents of
stub-a/dune-project
(lang dune 3.0) (name stub-a) (version 0.1.0) (implicit_transitive_deps false) ; Crucial for dependency resolution (package (name stub-a) (version 0.1.0))
-
And also define local dune file
stub-a/src/dune
andstub-b/src/dune
stub-a/src/dune
(library (public_name stub-a) (name a) (libraries stub-b)) ; Declares dependency
and
stub-b/src/dune
(library (public_name stub-b) (name b))
-
We also don't need to define
a.ml
andb.ml
. I am defining it to make this a readable example. Calling B from A.(* stub-b/src/b.ml *) let greet () = "Hello from Package B!"
and
(* stub-a/src/a.ml *) let run () = "Package A says: " ^ B.greet ()
-
Like the
opam-repository
maintained by folks onopam
we are going to make a custom local index which containsstub-a
andstub-b
my-opam-repo/ ├── packages/ │ ├── stub-b.0.1.0/ │ │ └── opam │ └── stub-a.0.1.0/ │ └── opam └── repo
-
repo
file is used to let the opam-cli recognize this as an opam-repository and when asked to install packagesstub-b
andstub-a
go through the directoryopam-version
key-value pair is enough for our goal.echo 'opam-version: "2.0"' > my-opam-repo/repo
-
Unlike other package registries OPAM repos doesn't store/get a tarball. THere is a specific section for URLs identifying their
src
and theirchecksum
to locate the package source. While adding packages to opam repository ocaml folks often follow the convention of<package-name>.<version>
. Forstub-a
that would look likestub-a.0.1.0
and similarly forstub-b
-stub-b.0.1.0
. These directories only contain a single opam file. Quite similar to the opam file where the package is defined.# stub-a opam-version: "2.0" name: "stub-a" version: "0.1.0" synopsis: "Package depending on stub-b" description: "Demonstrates dependency on another OPAM package" maintainer: "[email protected]" authors: ["You"] license: "MIT" build: [ ["dune" "build" "-p" name] ] depends: [ "dune" {>= "2.0"} "ocaml" {>= "4.08.0"} "stub-b" ] # stub-b opam-version: "2.0" name: "stub-b" version: "0.1.0" synopsis: "Dependency package" build: [ ["dune" "build" "-p" name] ] depends: [ "dune" {>= "2.0"} "ocaml" {>= "4.08.0"} ]
-
Pinning packages (give an example of what pinning does briefly and also pin it)
-
Update the
stub-b/src/b.ml
file to show breaking changes. -
Bump up the package version from
0.1.0
to0.2.0
-
Re-pin and display the error which would look like initially
The following actions will be performed:
=== install 1 package
∗ stub-a 0.1.0 (pinned)
Proceed with ∗ 1 installation? [y/n] y
<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>
[ERROR] The compilation of stub-a.0.1.0 failed at "dune build -p stub-a".
#=== ERROR while compiling stub-a.0.1.0 =======================================#
# context 2.3.0 | linux/x86_64 | ocaml-base-compiler.5.1.1 | pinned(file:///home/sk/my-opam-pkgs/stub-a)
# path ~/.opam/revdep-test/.opam-switch/build/stub-a.0.1.0
# command ~/.opam/opam-init/hooks/sandbox.sh build dune build -p stub-a
# exit-code 1
# env-file ~/.opam/log/stub-a-198184-81ec23.env
# output-file ~/.opam/log/stub-a-198184-81ec23.out
### output ###
# (cd _build/default && /home/sk/.opam/revdep-test/bin/ocamlc.opt -w -40 -g -bin-annot -I src/.a.objs/byte -I /home/sk/.opam/revdep-test/lib/stub-b -no-alias-deps -o src/.a.objs/byte/a.cmo -c -impl src/a.ml)
# File "src/a.ml", line 2, characters 31-33:
# 2 | "Package A says: " ^ B.greet ()
# ^^
# Error: This expression has type unit but an expression was expected of type
# string
And after fixing the API to accomodate stub-b
show the error for conflict