Skip to content

Commit 72d774e

Browse files
committed
[Cmdliner] Add alias option
options that expand to others. Uses it for `--release` and `-p`. Fixes ocaml#4682 , the options are really used
1 parent 123572b commit 72d774e

File tree

11 files changed

+75
-40
lines changed

11 files changed

+75
-40
lines changed

bin/common.ml

+11-29
Original file line numberDiff line numberDiff line change
@@ -410,22 +410,12 @@ module Options_implied_by_dash_p = struct
410410
; promote_install_files
411411
}
412412

413-
let release_options =
414-
{ root = Some "."
415-
; only_packages = No_restriction
416-
; ignore_promoted_rules = true
417-
; config_from_config_file = Dune_config.Partial.empty
418-
; profile = Some Profile.Release
419-
; default_target =
420-
Arg.Dep.alias_rec ~dir:Path.Local.root Dune_engine.Alias.Name.install
421-
; always_show_command_line = true
422-
; promote_install_files = true
423-
}
424-
425413
let dash_dash_release =
426-
let+ (_ : bool) =
427414
Arg.(
428-
value & flag
415+
value & alias ["--root";".";"--ignore-promoted-rules";"--no-config";
416+
"--profile";"release";"--always-show-command-line";
417+
"--promote-install-files";
418+
"--default-target";"@install"]
429419
& info [ "release" ] ~docs ~docv:"PACKAGES"
430420
~doc:
431421
"Put $(b,dune) into a reproducible $(i,release) mode. This is in \
@@ -435,11 +425,10 @@ module Options_implied_by_dash_p = struct
435425
use this option for release builds. For instance, you must use \
436426
this option in your $(i,<package>.opam) files. Except if you \
437427
already use $(b,-p), as $(b,-p) implies this option.")
438-
in
439-
release_options
440428

441429
let options =
442-
let+ t = one_of options dash_dash_release
430+
let+ t = options
431+
and+ _ = dash_dash_release
443432
and+ only_packages =
444433
let+ names =
445434
Arg.(
@@ -463,11 +452,10 @@ module Options_implied_by_dash_p = struct
463452
{ t with only_packages }
464453

465454
let dash_p =
466-
let+ pkgs, args =
467455
Term.with_used_args
468456
Arg.(
469457
value
470-
& opt (some packages) None
458+
& alias_opt (fun s -> ["--release";"--only-packages";s] )
471459
& info
472460
[ "p"; "for-release-of-packages" ]
473461
~docs ~docv:"PACKAGES"
@@ -477,23 +465,17 @@ module Options_implied_by_dash_p = struct
477465
order to build only what's necessary when your project \
478466
contains multiple packages as well as getting reproducible \
479467
builds.")
480-
in
481-
{ release_options with
482-
only_packages =
483-
(match pkgs with
484-
| None -> No_restriction
485-
| Some names -> Restrict { names; command_line_option = List.hd args })
486-
}
487468

488469
let term =
489-
let+ t = one_of options dash_p
470+
let+ t = options
471+
and+ _ = dash_p
490472
and+ profile =
491473
let doc =
492474
"Build profile. $(b,dev) if unspecified or $(b,release) if -p is set."
493475
in
494476
Arg.(
495-
value
496-
& opt (some profile) None
477+
last
478+
& opt_all (some profile) [None]
497479
& info [ "profile" ] ~docs
498480
~env:(Arg.env_var ~doc "DUNE_PROFILE")
499481
~doc:

test/blackbox-tests/test-cases/cmdline/profile.t/run.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
; profile = User_defined "bar"
1111

1212
$ DUNE_PROFILE="bar" dune build -p foo --verbose 2>&1 | grep "; profile"
13-
; profile = User_defined "bar"
13+
; profile = Release

test/blackbox-tests/test-cases/github3530.t/run.t

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ When an empty string is passed to `-p`, we get a nice error message.
22

33
$ echo '(lang dune 2.0)' > dune-project
44
$ dune build -p ''
5-
dune build: option `-p': Invalid package name: ""
5+
dune build: option `--only-packages': Invalid package name: ""
66
Usage: dune build [OPTION]... [TARGET]...
77
Try `dune build --help' or `dune --help' for more information.
88
[1]
99

1010
This can happen in a list as well:
1111

1212
$ dune build -p 'a,b,'
13-
dune build: option `-p': Invalid package name: ""
13+
dune build: option `--only-packages': Invalid package name: ""
1414
Usage: dune build [OPTION]... [TARGET]...
1515
Try `dune build --help' or `dune --help' for more information.
1616
[1]

test/blackbox-tests/test-cases/misc.t/run.t

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ Test that incompatible options are properly reported
1212
[1]
1313

1414
$ dune build -p toto --root .
15-
dune build: Cannot use --root and -p simultaneously
15+
dune build: option `--root' cannot be repeated
1616
Usage: dune build [OPTION]... [TARGET]...
1717
Try `dune build --help' or `dune --help' for more information.
1818
[1]
1919

2020
$ dune build --for-release-of-packages toto --root .
21-
dune build: Cannot use --root and --for-release-of-packages simultaneously
21+
dune build: option `--root' cannot be repeated
2222
Usage: dune build [OPTION]... [TARGET]...
2323
Try `dune build --help' or `dune --help' for more information.
2424
[1]
@@ -30,13 +30,13 @@ Test that incompatible options are properly reported
3030
[1]
3131

3232
$ dune build -p toto --release
33-
dune build: Cannot use --release and -p simultaneously
33+
dune build: option `--root' cannot be repeated
3434
Usage: dune build [OPTION]... [TARGET]...
3535
Try `dune build --help' or `dune --help' for more information.
3636
[1]
3737

3838
$ dune build --release --root .
39-
dune build: Cannot use --root and --release simultaneously
39+
dune build: option `--root' cannot be repeated
4040
Usage: dune build [OPTION]... [TARGET]...
4141
Try `dune build --help' or `dune --help' for more information.
4242
[1]

test/blackbox-tests/test-cases/vendor/dash-p-and-vendored-packages.t/run.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ Asking to keep "bar" makes no sense since it is vendored:
4949

5050
$ dune exec -p foo,bar ./foo.exe
5151
Error: Package bar is vendored and so will never be masked. It is redundant
52-
to pass it to -p.
52+
to pass it to --only-packages.
5353
[1]

vendor/cmdliner/src/cmdliner.mli

+10
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,16 @@ module Arg : sig
657657
{b Note.} Environment variable lookup is unsupported for
658658
for these arguments. *)
659659

660+
661+
val alias : string list -> info -> bool t
662+
(** [alias l i] is a [flag i] except the arguments [l] are also parsed as
663+
if they appeared in place of the option. *)
664+
665+
val alias_opt : (string -> string list) -> info -> bool t
666+
(** [alias l i] is a [flag i] except the arguments [l arg] are also parsed as
667+
if they appeared in place of the option. [arg] is the possible argument
668+
given on the command line *)
669+
660670
val opt : ?vopt:'a -> 'a conv -> 'a -> info -> 'a t
661671
(** [opt vopt c v i] is an ['a] argument defined by the value of
662672
an optional argument that may appear {e at most} once on the command

vendor/cmdliner/src/cmdliner_arg.ml

+33
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,31 @@ let list_to_args f l =
8484
let add acc v = Cmdliner_info.Args.add (f v) acc in
8585
List.fold_left add Cmdliner_info.Args.empty l
8686

87+
let alias_opt aliases a =
88+
let a = Cmdliner_info.arg_make_opt ~absent:Err ~kind:Opt a in
89+
let aliases = (fun o -> assert (Option.is_some o); aliases (Option.get o)) in
90+
let a = Cmdliner_info.arg_aliases ~aliases a in
91+
if Cmdliner_info.arg_is_pos a then invalid_arg err_not_opt else
92+
let convert ei cl = match Cmdliner_cline.opt_arg cl a with
93+
| [] -> try_env ei a Cmdliner_base.env_bool_parse ~absent:false
94+
| [_, _, None] -> Ok true
95+
| [_, f, Some v] -> Ok true
96+
| (_, f, _) :: (_ ,g, _) :: _ -> err (Cmdliner_msg.err_opt_repeated f g)
97+
in
98+
arg_to_args a, convert
99+
100+
let alias aliases a =
101+
let aliases = (fun o -> assert (Option.is_none o); aliases) in
102+
let a = Cmdliner_info.arg_aliases ~aliases a in
103+
if Cmdliner_info.arg_is_pos a then invalid_arg err_not_opt else
104+
let convert ei cl = match Cmdliner_cline.opt_arg cl a with
105+
| [] -> try_env ei a Cmdliner_base.env_bool_parse ~absent:false
106+
| [_, _, None] -> Ok true
107+
| [_, f, Some v] -> err (Cmdliner_msg.err_flag_value f v)
108+
| (_, f, _) :: (_ ,g, _) :: _ -> err (Cmdliner_msg.err_opt_repeated f g)
109+
in
110+
arg_to_args a, convert
111+
87112
let flag a =
88113
if Cmdliner_info.arg_is_pos a then invalid_arg err_not_opt else
89114
let convert ei cl = match Cmdliner_cline.opt_arg cl a with
@@ -290,6 +315,14 @@ let last (args, convert) =
290315
in
291316
args, convert
292317

318+
let last_or_none (args, convert) =
319+
let convert ei cl = match convert ei cl with
320+
| Ok [] -> Ok None
321+
| Ok l -> Ok (Some (List.hd (List.rev l)))
322+
| Error _ as e -> e
323+
in
324+
args, convert
325+
293326
(* Predefined arguments *)
294327

295328
let man_fmts =

vendor/cmdliner/src/cmdliner_arg.mli

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ val flag : info -> bool t
4141
val flag_all : info -> bool list t
4242
val vflag : 'a -> ('a * info) list -> 'a t
4343
val vflag_all : 'a list -> ('a * info) list -> 'a list t
44+
val alias : string list -> info -> bool t
45+
val alias_opt : (string -> string list) -> info -> bool t
4446
val opt : ?vopt:'a -> 'a converter -> 'a -> info -> 'a t
4547
val opt_all : ?vopt:'a -> 'a converter -> 'a list -> info -> 'a list t
4648

vendor/cmdliner/src/cmdliner_cline.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ let parse_opt_args ~peek_opts optidx cl args =
111111
| v :: rest -> if is_opt v then None, args else Some v, rest
112112
in
113113
let arg = O ((k, name, value) :: opt_arg cl a) in
114-
loop errs (k + 1) (Amap.add a arg cl) pargs args
114+
loop errs (k + 1) (Amap.add a arg cl) pargs
115+
((Cmdliner_info.arg_alias a value)@args)
115116
| `Not_found when peek_opts -> loop errs (k + 1) cl pargs args
116117
| `Not_found ->
117118
let hints = hint_matching_opt optidx s in

vendor/cmdliner/src/cmdliner_info.ml

+7-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ type arg = (* information about a command line argument. *)
6464
pos : pos_kind; (* positional arg kind. *)
6565
opt_kind : opt_kind; (* optional arg kind. *)
6666
opt_names : string list; (* names (for opt args). *)
67-
opt_all : bool; } (* repeatable (for opt args). *)
67+
opt_all : bool; (* repeatable (for opt args). *)
68+
opt_alias: string option -> string list;
69+
}
6870

6971
let dumb_pos = pos ~rev:false ~start:(-1) ~len:None
7072

@@ -79,7 +81,8 @@ let arg ?docs ?(docv = "") ?(doc = "") ?env names =
7981
| _ -> Cmdliner_manpage.s_options
8082
in
8183
{ id = new_id (); absent = Val (lazy ""); env; doc; docv; docs;
82-
pos = dumb_pos; opt_kind = Flag; opt_names; opt_all = false; }
84+
pos = dumb_pos; opt_kind = Flag; opt_names; opt_all = false;
85+
opt_alias = fun _ -> [] }
8386

8487
let arg_id a = a.id
8588
let arg_absent a = a.absent
@@ -99,6 +102,7 @@ let arg_opt_name_sample a =
99102
| n :: ns -> if (String.length n) > 2 then n else find ns
100103
in
101104
find a.opt_names
105+
let arg_alias a = a.opt_alias
102106

103107
let arg_make_req a = { a with absent = Err }
104108
let arg_make_all_opts a = { a with opt_all = true }
@@ -108,6 +112,7 @@ let arg_make_opt_all ~absent ~kind:opt_kind a =
108112

109113
let arg_make_pos ~pos a = { a with pos }
110114
let arg_make_pos_abs ~absent ~pos a = { a with absent; pos }
115+
let arg_aliases ~aliases a = { a with opt_alias = aliases }
111116

112117
let arg_is_opt a = a.opt_names <> []
113118
let arg_is_pos a = a.opt_names = []

vendor/cmdliner/src/cmdliner_info.mli

+2
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ val arg_opt_names : arg -> string list (* has dashes *)
5656
val arg_opt_name_sample : arg -> string (* warning must be an opt arg *)
5757
val arg_opt_kind : arg -> opt_kind
5858
val arg_pos : arg -> pos_kind
59+
val arg_alias : arg -> string option -> string list
5960

6061
val arg_make_req : arg -> arg
6162
val arg_make_all_opts : arg -> arg
6263
val arg_make_opt : absent:arg_absence -> kind:opt_kind -> arg -> arg
6364
val arg_make_opt_all : absent:arg_absence -> kind:opt_kind -> arg -> arg
6465
val arg_make_pos : pos:pos_kind -> arg -> arg
6566
val arg_make_pos_abs : absent:arg_absence -> pos:pos_kind -> arg -> arg
67+
val arg_aliases : aliases:(string option -> string list) -> arg -> arg
6668

6769
val arg_is_opt : arg -> bool
6870
val arg_is_pos : arg -> bool

0 commit comments

Comments
 (0)