Detect the package name as topkg-jbuilder does
This commit is contained in:
parent
09b8e04f1c
commit
add2a063c0
10
bin/main.ml
10
bin/main.ml
|
@ -650,14 +650,16 @@ let subst =
|
||||||
; `Blocks help_secs
|
; `Blocks help_secs
|
||||||
]
|
]
|
||||||
in
|
in
|
||||||
let go common package =
|
let go common name =
|
||||||
set_common common;
|
set_common common;
|
||||||
Future.Scheduler.go (Watermarks.subst ~package)
|
Future.Scheduler.go (Watermarks.subst ?name ())
|
||||||
in
|
in
|
||||||
( Term.(const go
|
( Term.(const go
|
||||||
$ common
|
$ common
|
||||||
$ Arg.(required
|
$ Arg.(value
|
||||||
& pos 0 (some string) None (Arg.info [] ~docv:"PACKAGE"))
|
& opt (some string) None
|
||||||
|
& info ["n"; "name"] ~docv:"NAME"
|
||||||
|
~doc:"Use this package name instead of detecting it.")
|
||||||
)
|
)
|
||||||
, Term.info "subst" ~doc ~man)
|
, Term.info "subst" ~doc ~man)
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ let bootstrap () =
|
||||||
let main () =
|
let main () =
|
||||||
let anon s = raise (Arg.Bad (Printf.sprintf "don't know what to do with %s\n" s)) in
|
let anon s = raise (Arg.Bad (Printf.sprintf "don't know what to do with %s\n" s)) in
|
||||||
let subst () =
|
let subst () =
|
||||||
Future.Scheduler.go (Watermarks.subst ~package:"jbuilder");
|
Future.Scheduler.go (Watermarks.subst () ~name:"jbuilder");
|
||||||
exit 0
|
exit 0
|
||||||
in
|
in
|
||||||
Arg.parse
|
Arg.parse
|
||||||
|
|
|
@ -20,38 +20,47 @@ let is_a_source_file fn =
|
||||||
| ".woff" -> false
|
| ".woff" -> false
|
||||||
| _ -> true
|
| _ -> true
|
||||||
|
|
||||||
let make_watermark_map ~package ~opam_file ~git_describe ~git_commit =
|
let make_watermark_map ~name ~version ~commit =
|
||||||
|
let opam_file = OpamParser.file (name ^ ".opam") in
|
||||||
let version_num =
|
let version_num =
|
||||||
if String.is_prefix git_describe ~prefix:"v" then
|
if String.is_prefix version ~prefix:"v" then
|
||||||
String.sub git_describe ~pos:1 ~len:(String.length git_describe - 1)
|
String.sub version ~pos:1 ~len:(String.length version - 1)
|
||||||
else
|
else
|
||||||
git_describe
|
version
|
||||||
in
|
in
|
||||||
let opam_var name sep =
|
let opam_var name sep =
|
||||||
match
|
match
|
||||||
List.find_map opam_file.OpamParserTypes.file_contents
|
List.find_map opam_file.file_contents
|
||||||
~f:(function
|
~f:(function
|
||||||
| Variable (_, var, value) when name = var ->
|
| Variable (_, var, value) when name = var ->
|
||||||
Some value
|
Some value
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
with
|
with
|
||||||
| None -> sprintf "<variable %S not found in opam file>" name
|
| None -> Error (sprintf "variable %S not found in opam file" name)
|
||||||
| Some value ->
|
| Some value ->
|
||||||
let err = sprintf "<invalid value for variable %S in opam file>" name in
|
let err = Error (sprintf "invalid value for variable %S in opam file" name) in
|
||||||
match value with
|
match value with
|
||||||
| String (_, s) -> s
|
| String (_, s) -> Ok s
|
||||||
| List (_, l) ->
|
| List (_, l) -> begin
|
||||||
List.map l ~f:(function
|
match
|
||||||
| OpamParserTypes.String (_, s) -> s
|
List.fold_left l ~init:(Ok []) ~f:(fun acc v ->
|
||||||
| _ -> err)
|
match acc with
|
||||||
|> String.concat ~sep
|
| Error _ -> acc
|
||||||
|
| Ok l ->
|
||||||
|
match v with
|
||||||
|
| OpamParserTypes.String (_, s) -> Ok (s :: l)
|
||||||
|
| _ -> err)
|
||||||
|
with
|
||||||
|
| Error _ as e -> e
|
||||||
|
| Ok l -> Ok (String.concat ~sep (List.rev l))
|
||||||
|
end
|
||||||
| _ -> err
|
| _ -> err
|
||||||
in
|
in
|
||||||
String_map.of_alist_exn
|
String_map.of_alist_exn
|
||||||
[ "NAME" , package
|
[ "NAME" , Ok name
|
||||||
; "VERSION" , git_describe
|
; "VERSION" , Ok version
|
||||||
; "VERSION_NUM" , version_num
|
; "VERSION_NUM" , Ok version_num
|
||||||
; "VCS_COMMIT_ID" , git_commit
|
; "VCS_COMMIT_ID" , Ok commit
|
||||||
; "PKG_MAINTAINER" , opam_var "maintainer" ", "
|
; "PKG_MAINTAINER" , opam_var "maintainer" ", "
|
||||||
; "PKG_AUTHORS" , opam_var "authors" ", "
|
; "PKG_AUTHORS" , opam_var "authors" ", "
|
||||||
; "PKG_HOMEPAGE" , opam_var "homepage" " "
|
; "PKG_HOMEPAGE" , opam_var "homepage" " "
|
||||||
|
@ -61,9 +70,28 @@ let make_watermark_map ~package ~opam_file ~git_describe ~git_commit =
|
||||||
; "PKG_REPO" , opam_var "dev-repo" " "
|
; "PKG_REPO" , opam_var "dev-repo" " "
|
||||||
]
|
]
|
||||||
|
|
||||||
let subst_string s ~map =
|
let subst_string s ~fname ~map =
|
||||||
let len = String.length s in
|
let len = String.length s in
|
||||||
let longest_var = List.longest (String_map.keys map) in
|
let longest_var = List.longest (String_map.keys map) in
|
||||||
|
let loc_of_offset ~ofs ~len =
|
||||||
|
let rec loop lnum bol i =
|
||||||
|
if i = ofs then
|
||||||
|
let pos =
|
||||||
|
{ Lexing.
|
||||||
|
pos_fname = fname
|
||||||
|
; pos_cnum = i
|
||||||
|
; pos_lnum = lnum
|
||||||
|
; pos_bol = bol
|
||||||
|
}
|
||||||
|
in
|
||||||
|
{ Loc.start = pos; stop = { pos with pos_cnum = pos.pos_cnum + len } }
|
||||||
|
else
|
||||||
|
match s.[i] with
|
||||||
|
| '\n' -> loop (lnum + 1) (i + 1) (i + 1)
|
||||||
|
| _ -> loop lnum bol (i + 1)
|
||||||
|
in
|
||||||
|
loop 1 0 0
|
||||||
|
in
|
||||||
let rec loop i acc =
|
let rec loop i acc =
|
||||||
if i = len then
|
if i = len then
|
||||||
acc
|
acc
|
||||||
|
@ -105,9 +133,12 @@ let subst_string s ~map =
|
||||||
let var = String.sub s ~pos:(start + 2) ~len:(i - start - 3) in
|
let var = String.sub s ~pos:(start + 2) ~len:(i - start - 3) in
|
||||||
match String_map.find var map with
|
match String_map.find var map with
|
||||||
| None -> in_var ~start:(i - 1) (i + 1) acc
|
| None -> in_var ~start:(i - 1) (i + 1) acc
|
||||||
| Some repl ->
|
| Some (Ok repl) ->
|
||||||
let acc = (start, i + 1, repl) :: acc in
|
let acc = (start, i + 1, repl) :: acc in
|
||||||
loop (i + 1) acc
|
loop (i + 1) acc
|
||||||
|
| Some (Error msg) ->
|
||||||
|
let loc = loc_of_offset ~ofs:start ~len:(i + 1 - start) in
|
||||||
|
Loc.fail loc "%s" msg
|
||||||
end
|
end
|
||||||
| _ -> loop (i + 1) acc
|
| _ -> loop (i + 1) acc
|
||||||
in
|
in
|
||||||
|
@ -131,17 +162,49 @@ let subst_string s ~map =
|
||||||
let subst_file fn ~map =
|
let subst_file fn ~map =
|
||||||
let s = read_file fn in
|
let s = read_file fn in
|
||||||
let s =
|
let s =
|
||||||
if String.is_suffix fn ~suffix:".opam" then
|
if Filename.dirname fn = "." && String.is_suffix fn ~suffix:".opam" then
|
||||||
"version: \"%%" ^ "VERSION_NUM" ^ "%%\"\n" ^ s
|
"version: \"%%" ^ "VERSION_NUM" ^ "%%\"\n" ^ s
|
||||||
else
|
else
|
||||||
s
|
s
|
||||||
in
|
in
|
||||||
match subst_string s ~map with
|
match subst_string s ~map ~fname:fn with
|
||||||
| None -> ()
|
| None -> ()
|
||||||
| Some s -> write_file fn s
|
| Some s -> write_file fn s
|
||||||
|
|
||||||
let subst_git ~package =
|
let get_name ~files ?name () =
|
||||||
let opam_file = OpamParser.file (package ^ ".opam") in
|
let package_names =
|
||||||
|
List.filter_map files ~f:(fun fn ->
|
||||||
|
if Filename.dirname fn = "." then
|
||||||
|
match Filename.split_extension fn with
|
||||||
|
| s, ".opam" -> Some s
|
||||||
|
| _ -> None
|
||||||
|
else
|
||||||
|
None)
|
||||||
|
in
|
||||||
|
if package_names = [] then die "@{<error>Error@}: no <package>.opam files found.";
|
||||||
|
match name with
|
||||||
|
| Some name ->
|
||||||
|
if List.mem name ~set:package_names then
|
||||||
|
die "@{<error>Error@}: file %s.opam doesn't exist." name;
|
||||||
|
name
|
||||||
|
| None ->
|
||||||
|
let shortest =
|
||||||
|
match package_names with
|
||||||
|
| [] -> assert false
|
||||||
|
| first :: rest ->
|
||||||
|
List.fold_left rest ~init:first ~f:(fun acc s ->
|
||||||
|
if String.length s < String.length acc then
|
||||||
|
s
|
||||||
|
else
|
||||||
|
acc)
|
||||||
|
in
|
||||||
|
if List.for_all package_names ~f:(String.is_prefix ~prefix:shortest) then
|
||||||
|
shortest
|
||||||
|
else
|
||||||
|
die "@{<error>Error@}: cannot determine name automatically.\n\
|
||||||
|
You must pass a [--name] command line argument."
|
||||||
|
|
||||||
|
let subst_git ?name () =
|
||||||
let rev = "HEAD" in
|
let rev = "HEAD" in
|
||||||
let git =
|
let git =
|
||||||
match Bin.which "git" with
|
match Bin.which "git" with
|
||||||
|
@ -153,17 +216,18 @@ let subst_git ~package =
|
||||||
(Future.run_capture Strict git ["describe"; "--always"; "--dirty"])
|
(Future.run_capture Strict git ["describe"; "--always"; "--dirty"])
|
||||||
(Future.run_capture Strict git ["rev-parse"; rev]))
|
(Future.run_capture Strict git ["rev-parse"; rev]))
|
||||||
(Future.run_capture_lines Strict git ["ls-tree"; "-r"; "--name-only"; rev])
|
(Future.run_capture_lines Strict git ["ls-tree"; "-r"; "--name-only"; rev])
|
||||||
>>= fun ((git_describe, git_commit), files) ->
|
>>= fun ((version, commit), files) ->
|
||||||
let git_describe = String.trim git_describe in
|
let version = String.trim version in
|
||||||
let git_commit = String.trim git_commit in
|
let commit = String.trim commit in
|
||||||
let watermarks = make_watermark_map ~package ~opam_file ~git_describe ~git_commit in
|
let name = get_name ~files ?name () in
|
||||||
|
let watermarks = make_watermark_map ~name ~version ~commit in
|
||||||
List.iter files ~f:(fun fn ->
|
List.iter files ~f:(fun fn ->
|
||||||
if is_a_source_file fn then
|
if is_a_source_file fn then
|
||||||
subst_file fn ~map:watermarks);
|
subst_file fn ~map:watermarks);
|
||||||
Future.return ()
|
Future.return ()
|
||||||
|
|
||||||
let subst ~package =
|
let subst ?name () =
|
||||||
if Sys.file_exists ".git" then
|
if Sys.file_exists ".git" then
|
||||||
subst_git ~package
|
subst_git ?name ()
|
||||||
else
|
else
|
||||||
Future.return ()
|
Future.return ()
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
This is only used when a package is pinned. *)
|
This is only used when a package is pinned. *)
|
||||||
|
|
||||||
val subst : package:string -> unit Future.t
|
val subst : ?name:string -> unit -> unit Future.t
|
||||||
|
|
Loading…
Reference in New Issue