Skip to content

Commit

Permalink
arg: escape windows paths in manpage
Browse files Browse the repository at this point in the history
* OpamArg.dir_sep, an escaped windows separator
* OpamArg.escape_path, a function to escape windows paths
  • Loading branch information
rjbou committed Apr 16, 2020
1 parent fb910c7 commit 9f154ef
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 59 deletions.
60 changes: 35 additions & 25 deletions src/client/opamAdminCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ let admin_command_doc =

let admin_command_man = [
`S "DESCRIPTION";
`P "This command can perform various actions on repositories in the opam \
format. It is expected to be run from the root of a repository, i.e. a \
directory containing a 'repo' file and a subdirectory 'packages/' \
holding package definition within subdirectories. A 'compilers/' \
subdirectory (opam repository format version < 2) will also be used by \
the $(b,upgrade-format) subcommand."
`P (Printf.sprintf
"This command can perform various actions on repositories in the opam \
format. It is expected to be run from the root of a repository, i.e. a \
directory containing a 'repo' file and a subdirectory 'packages%s' \
holding package definition within subdirectories. A 'compilers%s' \
subdirectory (opam repository format version < 2) will also be used by \
the $(b,upgrade-format) subcommand."
OpamArg.dir_sep OpamArg.dir_sep)
]

let index_command_doc =
Expand Down Expand Up @@ -189,8 +191,10 @@ let cache_command =
let link_arg =
Arg.(value & opt (some OpamArg.dirname) None &
info ["link"] ~docv:"DIR" ~doc:
"Create reverse symbolic links to the archives within $(i,DIR), in \
the form $(b,DIR/PKG.VERSION/FILENAME).")
(Printf.sprintf
"Create reverse symbolic links to the archives within $(i,DIR), in \
the form $(b,DIR%sPKG.VERSION%sFILENAME)."
OpamArg.dir_sep OpamArg.dir_sep))
in
let jobs_arg =
Arg.(value & opt OpamArg.positive_integer 8 &
Expand Down Expand Up @@ -264,7 +268,7 @@ let add_hashes_command =
"This command scans through package definitions, and add hashes as \
requested (fetching the archives if required). A cache is generated \
in %s for subsequent runs."
(OpamFilename.Dir.to_string cache_dir));
(OpamArg.escape_path (OpamFilename.Dir.to_string cache_dir)));
]
in
let hash_kinds = [`MD5; `SHA256; `SHA512] in
Expand Down Expand Up @@ -456,18 +460,21 @@ let upgrade_command =
let doc = upgrade_command_doc in
let man = [
`S "DESCRIPTION";
`P "This command reads repositories from earlier opam versions, and \
converts them to repositories suitable for the current opam version. \
Packages might be created or renamed, and any compilers defined in the \
old format ('compilers/' directory) will be turned into packages, \
using a pre-defined hierarchy that assumes OCaml compilers."
`P (Printf.sprintf
"This command reads repositories from earlier opam versions, and \
converts them to repositories suitable for the current opam version. \
Packages might be created or renamed, and any compilers defined in the \
old format ('compilers%s' directory) will be turned into packages, \
using a pre-defined hierarchy that assumes OCaml compilers."
OpamArg.dir_sep)
]
in
let clear_cache_arg =
let doc =
"Instead of running the upgrade, clear the cache of archive hashes (held \
in ~/.cache), that is used to avoid re-downloading files to obtain \
their hashes at every run."
Printf.sprintf
"Instead of running the upgrade, clear the cache of archive hashes (held \
in ~%s.cache), that is used to avoid re-downloading files to obtain \
their hashes at every run." OpamArg.dir_sep
in
Arg.(value & flag & info ["clear-cache"] ~doc)
in
Expand Down Expand Up @@ -680,14 +687,17 @@ let pattern_list_arg =
Arg.string

let env_arg =
Arg.(value & opt (list string) [] & info ["environment"] ~doc:
"Use the given opam environment, in the form of a list \
comma-separated 'var=value' bindings, when resolving variables. \
This is used e.g. when computing available packages: if undefined, \
availability of packages is not taken into account. Note that, \
unless overridden, variables like 'root' or 'opam-version' may be \
taken from the current opam installation. What is defined in \
$(i,~/.opam/config) is always ignored.")
Arg.(value & opt (list string) [] & info ["environment"] ~doc:(
Printf.sprintf
"Use the given opam environment, in the form of a list of \
comma-separated 'var=value' bindings, when resolving variables. This \
is used e.g. when computing available packages: if undefined, \
availability of packages will be assumed as soon as it can not be \
resolved purely from globally defined variables. Note that, unless \
overridden, variables like 'root' or 'opam-version' may be taken \
from the current opam installation. What is defined in \
$(i,~%s.opam%sconfig) is always ignored."
OpamArg.dir_sep OpamArg.dir_sep))

let state_selection_arg =
let docs = OpamArg.package_selection_section in
Expand Down
35 changes: 26 additions & 9 deletions src/client/opamArg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,18 @@ let help_sections = [
]

(* Converters *)

(* Windows directory separator need to be escaped for manpage *)
let dir_sep, escape_path =
match Filename.dir_sep with
| "\\" ->
let esc = "\\\\" in
esc,
fun p ->
OpamStd.List.concat_map esc (fun x -> x)
(OpamStd.String.split_delim p '\\')
| ds -> ds, fun x -> x

let pr_str = Format.pp_print_string

let repository_name =
Expand Down Expand Up @@ -423,7 +435,7 @@ let existing_filename_or_dash =

let dirname =
let parse str = `Ok (OpamFilename.Dir.of_string str) in
let print ppf dir = pr_str ppf (OpamFilename.prettify_dir dir) in
let print ppf dir = pr_str ppf (escape_path (OpamFilename.prettify_dir dir)) in
parse, print

let existing_filename_dirname_or_dash =
Expand Down Expand Up @@ -829,8 +841,11 @@ let shell_opt =

let dot_profile_flag =
mk_opt ["dot-profile"]
"FILENAME" "Name of the configuration file to update instead of \
$(i,~/.profile) or $(i,~/.zshrc) based on shell detection."
"FILENAME"
(Printf.sprintf
"Name of the configuration file to update instead of \
$(i,~%s.profile) or $(i,~%s.zshrc) based on shell detection."
dir_sep dir_sep)
(Arg.some filename) None

let repo_kind_flag =
Expand Down Expand Up @@ -869,16 +884,18 @@ let atom_list =

let atom_or_local_list =
arg_list "PACKAGES"
"List of package names, with an optional version or constraint, e.g `pkg', \
`pkg.1.0' or `pkg>=0.5' ; or files or directory names containing package \
description, with explicit directory (e.g. `./foo.opam' or `.')"
(Printf.sprintf
"List of package names, with an optional version or constraint, e.g `pkg', \
`pkg.1.0' or `pkg>=0.5' ; or files or directory names containing package \
description, with explicit directory (e.g. `.%sfoo.opam' or `.')" dir_sep)
atom_or_local

let atom_or_dir_list =
arg_list "PACKAGES"
"List of package names, with an optional version or constraint, e.g `pkg', \
`pkg.1.0' or `pkg>=0.5' ; or directory names containing package \
description, with explicit directory (e.g. `./srcdir' or `.')"
(Printf.sprintf
"List of package names, with an optional version or constraint, e.g `pkg', \
`pkg.1.0' or `pkg>=0.5' ; or directory names containing package \
description, with explicit directory (e.g. `.%ssrcdir' or `.')" dir_sep)
atom_or_dir

let nonempty_atom_list =
Expand Down
7 changes: 7 additions & 0 deletions src/client/opamArg.mli
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ val mk_opt_all:
string list -> string -> string ->
'a Arg.converter -> 'a list Term.t

(* Escaped Windows directory separator. To use instead of [Filename.dir_sep] for
manpage strings *)
val dir_sep: string

(* Escape Windows path *)
val escape_path: string -> string

(** {2 Flags} *)

(** --short *)
Expand Down
62 changes: 37 additions & 25 deletions src/client/opamCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ let switch_to_updated_self debug opamroot =
let global_options =
let no_self_upgrade =
mk_flag ~section:global_option_section ["no-self-upgrade"]
"Opam will replace itself with a newer binary found \
at $(b,OPAMROOT/opam) if present. This disables this behaviour." in
(Printf.sprintf
"Opam will replace itself with a newer binary found \
at $(b,OPAMROOT%sopam) if present. This disables this behaviour."
OpamArg.dir_sep) in
let self_upgrade no_self_upgrade options =
let self_upgrade_status =
if OpamStd.Config.env_string "NOSELFUPGRADE" =
Expand Down Expand Up @@ -169,25 +171,31 @@ let init =
let man = [
`S "DESCRIPTION";
`P "Initialise the opam state, or update opam init options";
`P "The $(b,init) command initialises a local \"opam root\" (by default, \
$(i,~/.opam/)) that holds opam's data and packages. This is a \
necessary step for normal operation of opam. The initial software \
repositories are fetched, and an initial 'switch' can also be \
installed, according to the configuration and options. These can be \
afterwards configured using $(b,opam switch) and $(b,opam \
repository).";
`P "The initial repository and defaults can be set through a \
configuration file found at $(i,~/.opamrc) or $(i,/etc/opamrc).";
`P (Printf.sprintf
"The $(b,init) command initialises a local \"opam root\" (by default, \
$(i,~%s.opam%s)) that holds opam's data and packages. This is a \
necessary step for normal operation of opam. The initial software \
repositories are fetched, and an initial 'switch' can also be \
installed, according to the configuration and options. These can be \
afterwards configured using $(b,opam switch) and $(b,opam \
repository)."
OpamArg.dir_sep OpamArg.dir_sep);
`P (Printf.sprintf
"The initial repository and defaults can be set through a \
configuration file found at $(i,~%s.opamrc) or $(i,/etc/opamrc)."
OpamArg.dir_sep);
`P "Additionally, this command allows one to customise some aspects of opam's \
shell integration, when run initially (avoiding the interactive \
dialog), but also at any later time.";
`S "ARGUMENTS";
`S "OPTIONS";
`S "CONFIGURATION FILE";
`P "Any field from the built-in initial configuration can be overridden \
through $(i,~/.opamrc), $(i,/etc/opamrc), or a file supplied with \
$(i,--config). The default configuration for this version of opam \
can be obtained using $(b,--show-default-opamrc).";
`P (Printf.sprintf
"Any field from the built-in initial configuration can be overridden \
through $(i,~%s.opamrc), $(i,/etc/opamrc), or a file supplied with \
$(i,--config). The default configuration for this version of opam \
can be obtained using $(b,--show-default-opamrc)."
OpamArg.dir_sep);
`S OpamArg.build_option_section;
] in
let compiler =
Expand Down Expand Up @@ -265,8 +273,9 @@ let init =
in
let no_config_file =
mk_flag ["no-opamrc"]
"Don't read `/etc/opamrc' or `~/.opamrc': use the default settings and \
the files specified through $(b,--config) only"
(Printf.sprintf
"Don't read `/etc/opamrc' or `~%s.opamrc': use the default settings and \
the files specified through $(b,--config) only" OpamArg.dir_sep)
in
let reinit =
mk_flag ["reinit"]
Expand Down Expand Up @@ -1941,16 +1950,17 @@ let switch =
switch set) to set the currently active switch. Without argument, \
lists installed switches, with one switch argument, defaults to \
$(b,set).";
`P ("Switch handles $(i,SWITCH) can be either a plain name, for switches \
that will be held inside $(i,~/.opam), or a directory name, which in \
that case is the directory where the switch prefix will be installed, as "
^ OpamSwitch.external_dirname ^
". Opam will automatically select a switch by that name found in the \
`P (Printf.sprintf
"Switch handles $(i,SWITCH) can be either a plain name, for switches \
that will be held inside $(i,~%s.opam), or a directory name, which in \
that case is the directory where the switch prefix will be installed, as \
%s. Opam will automatically select a switch by that name found in the \
current directory or its parents, unless $(i,OPAMSWITCH) is set or \
$(b,--switch) is specified. When creating a directory switch, if \
package definitions are found locally, the user is automatically \
prompted to install them after the switch is created unless \
$(b,--no-install) is specified.");
$(b,--no-install) is specified."
OpamArg.dir_sep OpamSwitch.external_dirname);
`P "$(b,opam switch set) sets the default switch globally, but it is also \
possible to select a switch in a given shell session, using the \
environment. For that, use $(i,eval \\$(opam env \
Expand Down Expand Up @@ -2887,8 +2897,10 @@ let clean =
in
let download_cache =
mk_flag ["c"; "download-cache"]
"Clear the cache of downloaded files (\\$OPAMROOT/download-cache), as \
well as the obsolete \\$OPAMROOT/archives, if that exists."
(Printf.sprintf
"Clear the cache of downloaded files (\\$OPAMROOT%sdownload-cache), as \
well as the obsolete \\$OPAMROOT%sarchives, if that exists."
OpamArg.dir_sep OpamArg.dir_sep)
in
let repos =
mk_flag ["unused-repositories"]
Expand Down

0 comments on commit 9f154ef

Please sign in to comment.