Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for OPAM files in opam/ folder #466

Merged
merged 3 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### Added

- Adopt the OCaml Code of Conduct (#473, @rikusilvola)
- Added support for projects that have their OPAM files in the `opam/`
subdirectory. (#466, @Leonidas-from-XIV)

### Changed

Expand Down
5 changes: 5 additions & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ with [Dune](https://github.com/ocaml/dune) and hosted on
[GitHub](https://github.com).")
(depends
(ocaml (>= 4.08.0))
;; two dependencies on dune to work around
;; https://github.com/ocaml/dune/issues/3431
dune
;; the tests require dune 3.8
(dune (and (>= 3.8) :with-test))
(curly (>= 0.3.0))
(fmt (>= 0.8.7))
(fpath (>= 0.7.3))
Expand Down
3 changes: 2 additions & 1 deletion dune-release.opam
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ license: "ISC"
homepage: "https://github.com/tarides/dune-release"
bug-reports: "https://github.com/tarides/dune-release/issues"
depends: [
"dune" {>= "2.7"}
"ocaml" {>= "4.08.0"}
"dune" {>= "2.7"}
"dune" {>= "3.8" & with-test}
"curly" {>= "0.3.0"}
"fmt" {>= "0.8.7"}
"fpath" {>= "0.7.3"}
Expand Down
53 changes: 41 additions & 12 deletions lib/pkg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ let readme p =
let opam p =
match p.opam with
| Some f -> Ok f
| None -> name p >>| fun name -> Fpath.v (name ^ ".opam")
| None ->
name p >>= fun name ->
let filename = name |> Fpath.v |> Fpath.add_ext ".opam" in
let opam_subdir = Fpath.v "opam" in
let in_opam_subdir = Fpath.append opam_subdir filename in
OS.File.exists in_opam_subdir
|> Result.map (function true -> in_opam_subdir | false -> filename)

let opam_descr p =
let descr_file_for_opam opam =
Expand Down Expand Up @@ -263,16 +269,26 @@ let dune_project_name dir =

let infer_pkg_names dir = function
| [] ->
Bos.OS.Dir.contents ~dotfiles:false ~rel:false dir >>= fun files ->
let files = List.fast_sort Fpath.compare files |> List.rev in
let opam_files =
List.filter
(fun p -> String.is_suffix ~affix:".opam" Fpath.(to_string p))
files
let remove_extension =
List.map (fun p -> Fpath.(basename @@ rem_ext p))
in
let collect dir =
Bos.OS.Dir.contents ~dotfiles:false ~rel:false dir >>= fun files ->
let files = List.fast_sort Fpath.compare files |> List.rev in
let opam_files =
List.filter
(fun p -> String.is_suffix ~affix:".opam" Fpath.(to_string p))
files
in
Ok (remove_extension opam_files)
in
if opam_files = [] then
Rresult.R.error_msg "no <package>.opam files found."
else Ok (List.map (fun p -> Fpath.(basename @@ rem_ext p)) opam_files)
Result.bind (collect dir) (function
| [] ->
let opam_subdir = Fpath.(dir / "opam") in
Result.bind (collect opam_subdir) (function
| [] -> Rresult.R.error_msg "no <package>.opam files found."
| opam_files -> Ok opam_files)
| opam_files -> Ok opam_files)
| x -> Ok x

let infer_from_opam_files dir =
Expand Down Expand Up @@ -403,11 +419,24 @@ let prepare_opam_for_distrib ~version ~content =
let without_version = List.filter is_not_version_field content in
Fmt.str "version: \"%a\"" Version.pp version :: without_version

let opam_file_contents name =
let filename = name |> Fpath.v |> Fpath.add_ext ".opam" in
let location =
OS.File.exists filename >>= function
Leonidas-from-XIV marked this conversation as resolved.
Show resolved Hide resolved
| true -> Ok filename
| false -> (
let filename = Fpath.append (Fpath.v "opam") filename in
OS.File.exists filename >>= function
| true -> Ok filename
| false -> Rresult.R.error_msgf "Can't open %a" Fpath.pp filename)
in
location >>= fun filename ->
OS.File.read_lines filename >>| fun content -> (filename, content)

let distrib_version_opam_files ~dry_run ~version =
infer_pkg_names Fpath.(v ".") [] >>= fun names ->
Stdext.Result.List.iter names ~f:(fun name ->
let file = Fpath.(v name + "opam") in
OS.File.read_lines file >>= fun content ->
opam_file_contents name >>= fun (file, content) ->
let content = prepare_opam_for_distrib ~version ~content in
Sos.write_file ~dry_run file (String.concat ~sep:"\n" content))

Expand Down
8 changes: 8 additions & 0 deletions tests/bin/opam-file-locations/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(env
(_
(binaries
(../helpers/make_dune_release_deterministic.exe as
make_dune_release_deterministic))))

(cram
(deps %{bin:dune-release} %{bin:make_dune_release_deterministic}))
102 changes: 102 additions & 0 deletions tests/bin/opam-file-locations/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
Set up a project with an `.opam` file in the toplevel folder:

$ cat > CHANGES.md << EOF
> ## 0.1.0
>
> - Initial release
>
> EOF
$ cat > dune-project << EOF
> (lang dune 3.8)
> (name myproject)
> EOF
$ cat > myproject.opam << EOF
> opam-version: "2.0"
> EOF
$ git init 2> /dev/null . > /dev/null
$ touch README LICENSE
$ cat > .gitignore << EOF
> _build
> .bin
> /dune
> run.t
> EOF
$ git add CHANGES.md README LICENSE *.opam dune-project .gitignore
$ git commit -m 'Initial commit' > /dev/null

Tagging should work

$ dune-release tag -y
[-] Extracting tag from first entry in CHANGES.md
[-] Using tag "0.1.0"
[+] Tagged HEAD with version 0.1.0

`dune-release distrib` should work.

$ dune-release distrib --skip-lint | make_dune_release_deterministic
[-] Building source archive
[+] Wrote archive _build/myproject-0.1.0.tbz

[-] Building package in _build/myproject-0.1.0
[ OK ] package(s) build

[-] Running package tests in _build/myproject-0.1.0
[ OK ] package(s) pass the tests

[+] Distribution for myproject 0.1.0
[+] Commit <deterministic>
[+] Archive _build/myproject-0.1.0.tbz

Now let's move the `.opam` file to the `opam/` subfolder. OPAM supports `.opam`
files in the `opam/` subfolder, but for dune to pick it up we need to tell it
to look in that folder.
Leonidas-from-XIV marked this conversation as resolved.
Show resolved Hide resolved

Importantly, dune requires the packages in the `opam/` folder to be declared in
`dune-project` as `package`.

$ cat > CHANGES.md << EOF
> ## 0.2.0
>
> - Use dune to generate opam file in opam subfolder
>
> EOF
$ cat >> dune-project << EOF
> (package
> (name myproject)
> (allow_empty))
> (generate_opam_files true)
> (opam_file_location inside_opam_directory)
> EOF
$ git rm myproject.opam
rm 'myproject.opam'
$ dune build opam/myproject.opam
$ git add opam/myproject.opam CHANGES.md dune-project
$ git commit -m 'Opam file in subfolder' > /dev/null

Now we should still be able to tag:

$ dune-release tag -y
[-] Extracting tag from first entry in CHANGES.md
[-] Using tag "0.2.0"
[+] Tagged HEAD with version 0.2.0

And as well have a release tarball

$ dune-release distrib --skip-lint | make_dune_release_deterministic
[-] Building source archive
[+] Wrote archive _build/myproject-0.2.0.tbz

[-] Building package in _build/myproject-0.2.0
[ OK ] package(s) build

[-] Running package tests in _build/myproject-0.2.0
[ OK ] package(s) pass the tests

[+] Distribution for myproject 0.2.0
[+] Commit <deterministic>
[+] Archive _build/myproject-0.2.0.tbz

Which contains the `.opam` file in the right location:

$ tar tf _build/myproject-0.2.0.tbz | grep \\.opam
myproject-0.2.0/opam/myproject.opam