Improve jbuilder exec (#286)

* Improve jbuilder exec

When the path passed contianed to exec contains a '/', it will be interpreted
relative to the path of a build context (default context when absent)

* Update man page of jbuilder exec

* Add String.drop_prefix

* Make jbuilder exec understand relative/absolute paths

jbuilder exec will now interpret absolute paths as relative to the specified
build context. While relative paths will now be intepreted relative to the cwd
appended to the specified build context.

* Fix jbuilder exec /absolute/path

When the path provided to jbuilder exec is absolute, we should ignore the build
context for looking up the binary.

* Fix exec when ran outside of root

Previously, a call like $ jbuilder exec ./xxx --root=p would raise
an exception. Now ./xxx will be intepreterd relative to --root.

* Fix relative paths when jbuilder is ran outside of --root

* Simplify documentation for jbuilder exec
This commit is contained in:
Rudi Grinberg 2017-11-07 21:41:09 +08:00 committed by GitHub
parent 8718fdac88
commit 9c8ecc9fbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 5 deletions

View File

@ -816,21 +816,45 @@ let exec =
in
let man =
[ `S "DESCRIPTION"
; `P {|$(b,jbuilder exec -- COMMAND) should behave in the same way as if you do:|}
; `P {|$(b,jbuilder exec -- COMMAND) should behave in the same way as if you
do:|}
; `Pre " \\$ jbuilder install\n\
\ \\$ COMMAND"
; `P {|In particular if you run $(b,jbuilder exec ocaml), you will have access
to the libraries defined in the workspace using your usual directives
($(b,#require) for instance)|}
; `P {|In particular if you run $(b,jbuilder exec ocaml), you will have
access to the libraries defined in the workspace using your usual
directives ($(b,#require) for instance)|}
; `P {|When a leading / is present in the command (absolute path), then the
path is interpreted as an absolute path|}
; `P {|When a / is present at any other position (relative path), then the
path is interpreted as relative to the build context + current
working directory (or the value of $(b,--root) when ran outside of
the project root)|}
; `Blocks help_secs
]
in
let go common context prog args =
let runcwd = Sys.getcwd () in
set_common common ~targets:[];
let log = Log.create () in
let setup = Future.Scheduler.go ~log (Main.setup ~log common) in
let context = Main.find_context_exn setup ~name:context in
let path = Config.local_install_bin_dir ~context:context.name :: context.path in
let (prog, path) =
match String.index prog '/' with
| None ->
(prog, Config.local_install_bin_dir ~context:context.name :: context.path)
| Some i ->
let p = Path.of_string prog in
let path =
if i = 0 then (
Path.parent p
) else (
match String.drop_prefix runcwd ~prefix:common.root with
| None ->
Path.append context.build_dir (Path.parent p)
| Some s ->
Path.append (Path.relative context.build_dir s) (Path.parent p)
) in
(Path.basename p, [path]) in
match Bin.which ~path prog with
| None ->
Format.eprintf "@{<Error>Error@}: Program %S not found!@." prog;

View File

@ -209,6 +209,15 @@ module String = struct
len >= suffix_len &&
sub s ~pos:(len - suffix_len) ~len:suffix_len = suffix
let drop_prefix s ~prefix =
if is_prefix s ~prefix then
if length s = length prefix then
Some ""
else
Some (sub s ~pos:(length prefix) ~len:(length s - length prefix - 1))
else
None
include struct
[@@@warning "-3"]
let capitalize_ascii = String.capitalize