diff --git a/doc/changes/11274.md b/doc/changes/11274.md new file mode 100644 index 00000000000..d81850f7d17 --- /dev/null +++ b/doc/changes/11274.md @@ -0,0 +1 @@ +- Support for opam `(maintenance_intent ...)` in dune-project (#11274, @art-w) diff --git a/doc/howto/opam-file-generation.rst b/doc/howto/opam-file-generation.rst index 9fbe584cf7e..319a66ab957 100644 --- a/doc/howto/opam-file-generation.rst +++ b/doc/howto/opam-file-generation.rst @@ -81,6 +81,7 @@ For example, if your opam file looks like: "conduit-async" { >= "1.0.3" } "async" { >= "v0.10.0" } ] + x-maintenance-intent: [ "(latest)" ] You can express this as:: @@ -88,6 +89,7 @@ You can express this as:: (license ISC) (authors "Anil Madhavapeddy" "Rudi Grinberg") (maintainers "team@mirage.org") + (maintenance_intent "(latest)") (package (name cohttp-async) diff --git a/doc/reference/dune-project/generate_opam_files.rst b/doc/reference/dune-project/generate_opam_files.rst index cf0c8e128c3..7a4885ac7e3 100644 --- a/doc/reference/dune-project/generate_opam_files.rst +++ b/doc/reference/dune-project/generate_opam_files.rst @@ -63,6 +63,19 @@ defined in the project: "Jane Doe " "John Doe ") +.. _maintenance_intent: +.. describe:: (maintenance_intent ) + + .. versionadded:: 3.18 + + Specify the `opam maintenance intent `__. + + Example: + + .. code:: dune + + (maintenance_intent "(latest)") + .. describe:: (source ...) .. versionadded:: 1.7 diff --git a/doc/reference/dune-project/package.rst b/doc/reference/dune-project/package.rst index f90580ff31a..a09095a861f 100644 --- a/doc/reference/dune-project/package.rst +++ b/doc/reference/dune-project/package.rst @@ -60,6 +60,13 @@ package The same as (and takes precedences over) the corresponding global field. + .. describe:: (maintenance_intent ...) + + .. versionadded:: 3.18 + + The same as (and takes precedences over) the corresponding global field. + See :doc:`the global field for details `. + .. describe:: (source ...) .. versionadded:: 2.0 diff --git a/src/dune_config_file/dune_config_file.ml b/src/dune_config_file/dune_config_file.ml index 6d4e8958b73..e5a349d0273 100644 --- a/src/dune_config_file/dune_config_file.ml +++ b/src/dune_config_file/dune_config_file.ml @@ -20,6 +20,7 @@ module Dune_config = struct type t = { authors : string list option ; maintainers : string list option + ; maintenance_intent : string list option ; license : string list option } @@ -27,14 +28,19 @@ module Dune_config = struct fields (let+ authors = field_o "authors" (repeat string) and+ maintainers = field_o "maintainers" (repeat string) + and+ maintenance_intent = field_o "maintenance_intent" (repeat string) and+ license = field_o "license" (repeat string) in - { authors; maintainers; license }) + { authors; maintainers; maintenance_intent; license }) ;; let to_dyn t = let f = Dyn.(option (list string)) in Dyn.record - [ "authors", f t.authors; "maintainers", f t.maintainers; "license", f t.license ] + [ "authors", f t.authors + ; "maintainers", f t.maintainers + ; "maintenance_intent", f t.maintenance_intent + ; "license", f t.license + ] ;; end @@ -359,6 +365,7 @@ module Dune_config = struct ; project_defaults = { authors = Some [ "Author Name " ] ; maintainers = Some [ "Maintainer Name " ] + ; maintenance_intent = None ; license = Some [ "LICENSE" ] } ; experimental = [] diff --git a/src/dune_config_file/dune_config_file.mli b/src/dune_config_file/dune_config_file.mli index e18d38cbda8..743ada5e59f 100644 --- a/src/dune_config_file/dune_config_file.mli +++ b/src/dune_config_file/dune_config_file.mli @@ -8,6 +8,7 @@ module Dune_config : sig type t = { authors : string list option ; maintainers : string list option + ; maintenance_intent : string list option ; license : string list option } diff --git a/src/dune_lang/package_info.ml b/src/dune_lang/package_info.ml index cfcce1b6eb8..730fbd664c7 100644 --- a/src/dune_lang/package_info.ml +++ b/src/dune_lang/package_info.ml @@ -9,6 +9,7 @@ type t = ; bug_reports : string option ; documentation : string option ; maintainers : string list option + ; maintenance_intent : string list option } let source t = t.source @@ -29,6 +30,7 @@ let bug_reports t = let documentation t = t.documentation let maintainers t = t.maintainers +let maintenance_intent t = t.maintenance_intent let empty = { source = None @@ -38,6 +40,7 @@ let empty = ; bug_reports = None ; documentation = None ; maintainers = None + ; maintenance_intent = None } ;; @@ -54,10 +57,20 @@ let example ~authors ~maintainers ~license = (* homepage and bug_reports are inferred from the source *) ; homepage = None ; bug_reports = None + ; maintenance_intent = None } ;; -let to_dyn { source; license; authors; homepage; bug_reports; documentation; maintainers } +let to_dyn + { source + ; license + ; authors + ; homepage + ; bug_reports + ; documentation + ; maintainers + ; maintenance_intent + } = let open Dyn in record @@ -67,18 +80,28 @@ let to_dyn { source; license; authors; homepage; bug_reports; documentation; mai ; "documentation", (option string) documentation ; "bug_reports", (option string) bug_reports ; "maintainers", option (list string) maintainers + ; "maintenance_intent", option (list string) maintenance_intent ; "authors", option (list string) authors ] ;; let encode_fields - { source; authors; license; homepage; documentation; bug_reports; maintainers } + { source + ; authors + ; license + ; homepage + ; documentation + ; bug_reports + ; maintainers + ; maintenance_intent + } = let open Encoder in record_fields [ field_o "source" Source_kind.encode source ; field_l "authors" string (Option.value ~default:[] authors) ; field_l "maintainers" string (Option.value ~default:[] maintainers) + ; field_l "maintenance_intent" string (Option.value ~default:[] maintenance_intent) ; field_l "license" string (Option.value ~default:[] license) ; field_o "homepage" string homepage ; field_o "documentation" string documentation @@ -109,8 +132,18 @@ let decode ?since () = field_o "bug_reports" (Syntax.since Stanza.syntax (v (1, 10)) >>> string) and+ maintainers = field_o "maintainers" (Syntax.since Stanza.syntax (v (1, 10)) >>> repeat string) + and+ maintenance_intent = + field_o "maintenance_intent" (Syntax.since Stanza.syntax (v (3, 18)) >>> repeat string) in - { source; authors; license; homepage; documentation; bug_reports; maintainers } + { source + ; authors + ; license + ; homepage + ; documentation + ; bug_reports + ; maintainers + ; maintenance_intent + } ;; let superpose t1 t2 = @@ -126,9 +159,27 @@ let superpose t1 t2 = ; documentation = f t1.documentation t2.documentation ; bug_reports = f t1.bug_reports t2.bug_reports ; maintainers = f t1.maintainers t2.maintainers + ; maintenance_intent = f t1.maintenance_intent t2.maintenance_intent } ;; -let create ~maintainers ~authors ~homepage ~bug_reports ~documentation ~license ~source = - { maintainers; authors; homepage; bug_reports; documentation; license; source } +let create + ~maintainers + ~maintenance_intent + ~authors + ~homepage + ~bug_reports + ~documentation + ~license + ~source + = + { maintainers + ; authors + ; homepage + ; bug_reports + ; documentation + ; license + ; source + ; maintenance_intent + } ;; diff --git a/src/dune_lang/package_info.mli b/src/dune_lang/package_info.mli index 7a5dd3e1dba..bc951e6557f 100644 --- a/src/dune_lang/package_info.mli +++ b/src/dune_lang/package_info.mli @@ -7,6 +7,7 @@ val homepage : t -> string option val bug_reports : t -> string option val documentation : t -> string option val maintainers : t -> string list option +val maintenance_intent : t -> string list option (** example package info (used for project initialization ) *) val example @@ -28,6 +29,7 @@ val superpose : t -> t -> t val create : maintainers:string list option + -> maintenance_intent:string list option -> authors:string list option -> homepage:string option -> bug_reports:string option diff --git a/src/dune_pkg/opam_file.ml b/src/dune_pkg/opam_file.ml index c28ec969749..e19948ae0a5 100644 --- a/src/dune_pkg/opam_file.ml +++ b/src/dune_pkg/opam_file.ml @@ -260,6 +260,7 @@ let load_opam_file_with_contents ~contents:opam_file_string file name = let info = Dune_lang.Package_info.create ~maintainers:(get_many "maintainer") + ~maintenance_intent:(get_many "x-maintenance-intent") ~authors:(get_many "authors") ~homepage:(get_one "homepage") ~bug_reports:(get_one "bug-reports") diff --git a/src/dune_rules/opam_create.ml b/src/dune_rules/opam_create.ml index 2dcf1f96b05..4da9091ee49 100644 --- a/src/dune_rules/opam_create.ml +++ b/src/dune_rules/opam_create.ml @@ -196,6 +196,15 @@ let insert_odoc_dep depends = loop [] depends ;; +let maintenance_intent dune_version info = + if dune_version < (3, 18) + then None + else ( + match Package_info.maintenance_intent info with + | None -> Some [ "(latest)" ] + | x -> x) +;; + let opam_fields project (package : Package.t) = let dune_version = Dune_project.dune_version project in let package_name = Package.name package in @@ -228,6 +237,7 @@ let opam_fields project (package : Package.t) = in let list_fields = [ "maintainer", Package_info.maintainers info + ; "x-maintenance-intent", maintenance_intent dune_version info ; "authors", Package_info.authors info ; ( "license" , match Package_info.license info with diff --git a/test/blackbox-tests/test-cases/config-project-defaults.t b/test/blackbox-tests/test-cases/config-project-defaults.t index 7186ee51147..c8ed372d0fb 100644 --- a/test/blackbox-tests/test-cases/config-project-defaults.t +++ b/test/blackbox-tests/test-cases/config-project-defaults.t @@ -4,10 +4,11 @@ generated 'dune-project' file. $ touch dune-config $ cat >dune-config < (lang dune 3.17) + > (lang dune 3.18) > (project_defaults > (authors AuthorTest) > (maintainers MaintainerTest) + > (maintenance_intent "(latest)") > (license MIT)) > EOF @@ -33,11 +34,12 @@ Change the version of the config file to one which does not support the $ sed -i -e '1s|.*|(lang dune 3.16)|' dune-config $ dune init proj test_proj1 --config-file=dune-config - File "$TESTCASE_ROOT/dune-config", lines 2-5, characters 0-85: + File "$TESTCASE_ROOT/dune-config", lines 2-6, characters 0-118: 2 | (project_defaults 3 | (authors AuthorTest) 4 | (maintainers MaintainerTest) - 5 | (license MIT)) + 5 | (maintenance_intent "(latest)") + 6 | (license MIT)) Error: 'project_defaults' is only available since version 3.17 of the dune language. Please update your dune config file to have (lang dune 3.17). [1] @@ -47,7 +49,7 @@ Change the version of the config file to one which does not support the Check to ensure that the default values are used when optional stanzas are removed/not used. - $ sed -i -e '3,5c\ + $ sed -i -e '3,6c\ > )' dune-config $ dune init proj test_proj1 --config-file=dune-config Entering directory 'test_proj1' diff --git a/test/blackbox-tests/test-cases/dune-init.t/run.t b/test/blackbox-tests/test-cases/dune-init.t/run.t index 3fe686d4b53..0b05931b954 100644 --- a/test/blackbox-tests/test-cases/dune-init.t/run.t +++ b/test/blackbox-tests/test-cases/dune-init.t/run.t @@ -403,6 +403,7 @@ And the opam file will be generated as expected ] ] dev-repo: "git+https://github.com/username/reponame.git" + x-maintenance-intent: ["(latest)"] We can build and run the resulting executable: @@ -513,6 +514,7 @@ And the opam file will be generated as expected ] ] dev-repo: "git+https://github.com/username/reponame.git" + x-maintenance-intent: ["(latest)"] And we we can run the tests: diff --git a/test/blackbox-tests/test-cases/dune-project-meta/override.t b/test/blackbox-tests/test-cases/dune-project-meta/override.t index 61d0f549bcf..d1edc81b293 100644 --- a/test/blackbox-tests/test-cases/dune-project-meta/override.t +++ b/test/blackbox-tests/test-cases/dune-project-meta/override.t @@ -1,13 +1,14 @@ Package information fields can be overridden per-package: $ cat >dune-project < (lang dune 2.5) + > (lang dune 3.18) > (name foo) > (version 1.0.0) > (source (github mirage/ocaml-cohttp)) > (license ISC) > (authors "Anil Madhavapeddy" "Rudi Grinberg") > (homepage https://my.home.page) + > (maintenance_intent "(none)") > ; > (generate_opam_files true) > ; @@ -16,7 +17,9 @@ Package information fields can be overridden per-package: > (version 1.0.1) > (source (github mirage/foo)) > (license MIT) - > (authors "Foo" "Bar")) + > (authors "Foo" "Bar") + > (maintenance_intent "0.9" "1.0.1") + > (allow_empty)) > EOF $ dune build @install @@ -30,10 +33,11 @@ Package information fields can be overridden per-package: homepage: "https://my.home.page" bug-reports: "https://github.com/mirage/foo/issues" depends: [ - "dune" {>= "2.5"} + "dune" {>= "3.18"} + "odoc" {with-doc} ] build: [ - ["dune" "subst"] {pinned} + ["dune" "subst"] {dev} [ "dune" "build" @@ -47,3 +51,4 @@ Package information fields can be overridden per-package: ] ] dev-repo: "git+https://github.com/mirage/foo.git" + x-maintenance-intent: ["0.9" "1.0.1"] diff --git a/test/expect-tests/dune_config_file/dune_config_test.ml b/test/expect-tests/dune_config_file/dune_config_test.ml index 6f2224340bc..e2635090d6c 100644 --- a/test/expect-tests/dune_config_file/dune_config_test.ml +++ b/test/expect-tests/dune_config_file/dune_config_test.ml @@ -30,11 +30,12 @@ let%expect_test "cache-check-probability 0.1" = ; project_defaults = { authors = Some [ "Author Name " ] ; maintainers = Some [ "Maintainer Name " ] + ; maintenance_intent = None ; license = Some [ "LICENSE" ] } ; experimental = [] } - |}] + |}] ;; let%expect_test "cache-storage-mode copy" = @@ -53,11 +54,12 @@ let%expect_test "cache-storage-mode copy" = ; project_defaults = { authors = Some [ "Author Name " ] ; maintainers = Some [ "Maintainer Name " ] + ; maintenance_intent = None ; license = Some [ "LICENSE" ] } ; experimental = [] } - |}] + |}] ;; let%expect_test "cache-storage-mode hardlink" = @@ -76,9 +78,10 @@ let%expect_test "cache-storage-mode hardlink" = ; project_defaults = { authors = Some [ "Author Name " ] ; maintainers = Some [ "Maintainer Name " ] + ; maintenance_intent = None ; license = Some [ "LICENSE" ] } ; experimental = [] } - |}] + |}] ;;