[linter] Make checkCopyright indep of Utils, and fix build

Summary:
This diff ports checkCopyright to Core, builds it separately from other
executables, and fixes the build command in the linter.

Reviewed By: jvillard

Differential Revision: D4148217

fbshipit-source-id: 8aefc98
master
Josh Berdine 8 years ago committed by Facebook Github Bot
parent eb197a1cd4
commit dcf67c455f

@ -186,8 +186,12 @@ inferScriptMode_test: toplevel
$(call silent_on_success,\
INFER_REPL_BINARY=ocaml $(SCRIPT_DIR)/infer_repl $(INFER_DIR)/tests/repl/infer_batch_script.ml)
.PHONY: checkCopyright
checkCopyright:
$(MAKE) -C $(SRC_DIR) checkCopyright
.PHONY: run-test
run-test: test_build ocaml_unit_test buck_test inferTraceBugs_test inferScriptMode_test
run-test: test_build ocaml_unit_test buck_test inferTraceBugs_test inferScriptMode_test checkCopyright
$(MAKE) -C $(SRC_DIR) mod_dep.dot
.PHONY: test

@ -1,7 +1,7 @@
S src/**
B _build/infer/**
PKG atdgen
PKG core
PKG core_extended
PKG extlib
PKG javalib
PKG ounit

@ -151,8 +151,7 @@ INFER_BASE_TARGETS = \
$(INFER_MAIN).native \
$(INFERANALYZE_MAIN).native \
$(INFERPRINT_MAIN).native \
$(INFERUNIT_MAIN).native \
$(CHECKCOPYRIGHT_MAIN).native
$(INFERUNIT_MAIN).native
INFER_ALL_TARGETS = $(INFER_BASE_TARGETS) \
$(INFERJAVA_MAIN).native \
@ -182,7 +181,6 @@ infer: init $(STACKTREE_ATDGEN_STUBS) $(INFERPRINT_ATDGEN_STUBS)
$(COPY) $(INFER_BUILD_DIR)/$(INFER_MAIN).native $(INFER_BIN)
$(COPY) $(INFER_BUILD_DIR)/$(INFERANALYZE_MAIN).native $(INFERANALYZE_BIN)
$(COPY) $(INFER_BUILD_DIR)/$(INFERPRINT_MAIN).native $(INFERPRINT_BIN)
$(COPY) $(INFER_BUILD_DIR)/$(CHECKCOPYRIGHT_MAIN).native $(CHECKCOPYRIGHT_BIN)
$(COPY) $(INFER_BUILD_DIR)/$(INFERUNIT_MAIN).native $(INFERUNIT_BIN)
ifeq ($(BUILD_JAVA_ANALYZERS),yes)
$(COPY) $(INFER_BUILD_DIR)/$(INFERJAVA_MAIN).native $(INFERJAVA_BIN)
@ -282,6 +280,13 @@ toplevel: init $(STACKTREE_ATDGEN_STUBS) $(INFERPRINT_ATDGEN_STUBS) $(CLANG_ATDG
| grep -v $(roots_grep_regex) > toplevel.mlpack
$(OCAMLBUILD_ALL) -I stubs/ml -build-dir $(INFER_BUILD_DIR) toplevel.cmo
.PHONY: checkCopyright
checkCopyright: $(CHECKCOPYRIGHT_BIN)
$(CHECKCOPYRIGHT_BIN): sanitize $(BUILD_DIR) $(CHECKCOPYRIGHT_MAIN).ml
rebuild -quiet -r -j $(NCPU) -build-dir $(INFER_BUILD_DIR) -pkgs core_extended,str -tag thread -use-ocamlfind $(CHECKCOPYRIGHT_MAIN).native
$(COPY) $(INFER_BUILD_DIR)/$(CHECKCOPYRIGHT_MAIN).native $(CHECKCOPYRIGHT_BIN)
define gen_atdgen_rules
# generate files using atdgen
# parameters:

@ -7,9 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! Utils
open! Core_extended.Std
module L = Logging
module F = Format
let copyright_modified_exit_code = 1
@ -50,7 +49,7 @@ let prefix_of_comment_style = function
let update_files = ref false
let line_contains_copyright line =
string_contains "opyright " line
String.is_substring ~substring:"opyright " line
let rec find_copyright_line lines n = match lines with
| [] -> None
@ -60,18 +59,18 @@ let rec find_copyright_line lines n = match lines with
let find_comment_start_and_style lines_arr n =
(* are we in a line comment? *)
let cur_line_comment = try
Some (IList.find (function
| Line (s) when string_is_prefix s lines_arr.(n) -> true
| _ -> false) comment_styles)
with Not_found -> None in
let cur_line_comment =
List.find comment_styles ~f:(function
| Line (s) when String.is_prefix ~prefix:s lines_arr.(n) -> true
| _ -> false
) in
let is_start line = match cur_line_comment with
| Some (Line (s)) -> if string_is_prefix s line then None else Some (Line (s))
| _ -> try
Some (IList.find (function
| Block(s, _, _) -> string_contains s line
| _ -> false) comment_styles)
with Not_found -> None in
| Some (Line (s)) -> if String.is_prefix ~prefix:s line then None else Some (Line (s))
| _ ->
List.find comment_styles ~f:(function
| Block(s, _, _) -> String.is_substring ~substring:s line
| _ -> false
) in
let i = ref (n - 1) in
(* hacky fake line comment to avoid an option type *)
let found = ref (-1, Line(">>>>>>>>>>>")) in
@ -84,8 +83,8 @@ let find_comment_start_and_style lines_arr n =
let find_comment_end lines_arr n com_style =
let is_end line = match com_style with
| Line s -> not (string_is_prefix s line)
| Block (_, _, s) -> string_contains s line in
| Line s -> not (String.is_prefix ~prefix:s line)
| Block (_, _, s) -> String.is_substring ~substring:s line in
let i = ref (n + 1) in
let len = Array.length lines_arr in
let found = ref (len - 1) in
@ -111,7 +110,7 @@ let looks_like_copyright_message cstart cend lines_arr =
let contains_monoidics cstart cend lines_arr =
let found = ref false in
for i = cstart to cend do
if string_contains "Monoidics" lines_arr.(i) then found := true
if String.is_substring ~substring:"Monoidics" lines_arr.(i) then found := true
done;
!found
@ -129,7 +128,7 @@ let get_fb_year cstart cend lines_arr =
with Not_found -> () in
for i = cstart to cend do
let line = lines_arr.(i) in
if string_contains "Facebook" line then
if String.is_substring ~substring:"Facebook" line then
do_line line
done;
!found
@ -163,8 +162,8 @@ let copyright_has_changed mono fb_year com_style prefix cstart cend lines_arr =
done;
!r in
let new_copyright =
let pp fmt () = pp_copyright mono fb_year com_style fmt prefix in
pp_to_string pp () in
let pp fmt = pp_copyright mono fb_year com_style fmt prefix in
Format.asprintf "%t" pp in
old_copyright <> new_copyright
let update_file fname mono fb_year com_style prefix cstart cend lines_arr =
@ -201,68 +200,71 @@ let com_style_of_lang = [
]
let file_should_have_copyright fname =
IList.mem_assoc Filename.check_suffix fname com_style_of_lang
List.Assoc.mem com_style_of_lang ~equal:Filename.check_suffix fname
let get_filename_extension fname =
try
let len_without_ext = String.length (Filename.chop_extension fname) in
String.sub fname len_without_ext (String.length fname - len_without_ext)
String.slice fname len_without_ext (String.length fname - len_without_ext)
with Not_found -> ""
let output_diff fname lines_arr cstart n cend len mono fb_year com_style prefix =
let range = cend - cstart in
let lang = lang_of_com_style com_style in
L.stderr "%s (start:%d n:%d end:%d len:%d range:%d lang:%s mono:%b year:%d)@."
F.eprintf "%s (start:%d n:%d end:%d len:%d range:%d lang:%s mono:%b year:%d)@."
fname cstart n cend len range lang mono fb_year;
for i = cstart to cend do
L.stdout "%s@." lines_arr.(i)
F.printf "%s@." lines_arr.(i)
done;
L.stdout "-----@.";
L.stdout "@[<v>%a@]" (pp_copyright mono fb_year com_style) prefix;
F.printf "-----@.";
F.printf "@[<v>%a@]" (pp_copyright mono fb_year com_style) prefix;
if !update_files then
update_file fname mono fb_year com_style prefix cstart cend lines_arr
let check_copyright fname = match read_file fname with
| None -> ()
| Some lines ->
match find_copyright_line lines 0 with
| None ->
if file_should_have_copyright fname then
begin
let year = 1900 + (Unix.localtime (Unix.time ())).Unix.tm_year in
let ext = get_filename_extension fname in
let com_style = IList.assoc string_equal ext com_style_of_lang in
let prefix = prefix_of_comment_style com_style in
let start = default_start_line_of_com_style com_style in
output_diff fname (Array.of_list []) start (-1) (-1) 0 false year com_style prefix;
exit copyright_modified_exit_code
end
| Some n ->
let lines_arr = Array.of_list lines in
let line = lines_arr.(n) in
let len = String.length line in
let (cstart, com_style) = find_comment_start_and_style lines_arr n in
let cend = find_comment_end lines_arr n com_style in
if looks_like_copyright_message cstart cend lines_arr then
begin
let mono = contains_monoidics cstart cend lines_arr in
match get_fb_year cstart cend lines_arr with
| None ->
L.stderr "Can't find fb year: %s@." fname;
exit copyright_malformed_exit_code
| Some fb_year ->
let prefix = prefix_of_comment_style com_style in
if copyright_has_changed mono fb_year com_style prefix cstart cend lines_arr then
begin
output_diff fname lines_arr cstart n cend len mono fb_year com_style prefix;
exit copyright_modified_exit_code
end
end
else
begin
L.stderr "Copyright not recognized: %s@." fname;
let check_copyright fname =
let lines =
let readline =
let linebuf = Linebuf.create fname in
fun () -> Linebuf.try_read linebuf in
Lazy_list.to_list (Lazy_list.uniter ~f:readline) in
match find_copyright_line lines 0 with
| None ->
if file_should_have_copyright fname then
begin
let year = 1900 + (Unix.localtime (Unix.time ())).Unix.tm_year in
let ext = get_filename_extension fname in
let com_style = List.Assoc.find_exn com_style_of_lang ~equal:String.equal ext in
let prefix = prefix_of_comment_style com_style in
let start = default_start_line_of_com_style com_style in
output_diff fname (Array.of_list []) start (-1) (-1) 0 false year com_style prefix;
exit copyright_modified_exit_code
end
| Some n ->
let lines_arr = Array.of_list lines in
let line = lines_arr.(n) in
let len = String.length line in
let (cstart, com_style) = find_comment_start_and_style lines_arr n in
let cend = find_comment_end lines_arr n com_style in
if looks_like_copyright_message cstart cend lines_arr then
begin
let mono = contains_monoidics cstart cend lines_arr in
match get_fb_year cstart cend lines_arr with
| None ->
F.eprintf "Can't find fb year: %s@." fname;
exit copyright_malformed_exit_code
end
| Some fb_year ->
let prefix = prefix_of_comment_style com_style in
if copyright_has_changed mono fb_year com_style prefix cstart cend lines_arr then
begin
output_diff fname lines_arr cstart n cend len mono fb_year com_style prefix;
exit copyright_modified_exit_code
end
end
else
begin
F.eprintf "Copyright not recognized: %s@." fname;
exit copyright_malformed_exit_code
end
let speclist = [
@ -279,5 +281,5 @@ let () =
let add_file_to_check fname =
to_check := fname :: !to_check in
Arg.parse (Arg.align speclist) add_file_to_check usage_msg;
IList.iter check_copyright (IList.rev !to_check);
List.iter ~f:check_copyright (List.rev !to_check);
exit 0

@ -27,7 +27,7 @@ remove: [
ocaml-version: [ >= "4.02.1" ]
depends: [
"atdgen" {>="1.6.0"}
"core" {>="113.33.03"}
"core_extended" {>="113.33.03"}
"conf-autoconf"
"extlib-compat" {>="1.5.4"}
"javalib" {>="2.3.2"}

@ -12,7 +12,7 @@
"name": "infer",
"dependencies": {
"@opam-alpha/ocamlfind": "*",
"@opam-alpha/core": "113.33.3",
"@opam-alpha/core_extended": "113.33.3",
"@opam-alpha/ocaml": "4.2.3",
"@opam-alpha/sawja": "^ 1.5.2",
"@opam-alpha/atdgen": "^ 1.10.0",

@ -90,13 +90,19 @@
dependencies:
conf-which-actual "git://github.com/npm-opam/conf-which.git#1.0.0"
"@opam-alpha/core_extended@113.33.3":
version "113.33.3"
resolved core_extended-113.33.3.tgz#119bb3614537bc9fe557b3470b2a4398f721af79
dependencies:
core_extended-actual "git://github.com/npm-opam/core_extended.git#113.33.03"
"@opam-alpha/core_kernel@>= 113.33.03 < 113.34.00":
version "113.33.3"
resolved core_kernel-113.33.3.tgz#aa062b596d1c414294d6e8955edfd3d325090c82
dependencies:
core_kernel-actual "git://github.com/npm-opam/core_kernel.git#113.33.03"
"@opam-alpha/core@113.33.3":
"@opam-alpha/core@>= 113.33.03 < 113.34.00":
version "113.33.3"
resolved core-113.33.3.tgz#f7a586a0f9a3efbe195c1b98ebd51ccaf2f8bfd9
dependencies:
@ -358,6 +364,12 @@
dependencies:
re-actual "git://github.com/npm-opam/re.git#1.6.1"
"@opam-alpha/re2@>= 113.33.03 < 113.34.00":
version "113.33.3"
resolved re2-113.33.3.tgz#7244dbd26c2ffd454734e85494372584801a63f8
dependencies:
re2-actual "git://github.com/npm-opam/re2.git#113.33.03"
"@opam-alpha/react@*", "@opam-alpha/react@>= 1.0.0":
version "1.2.0"
resolved react-1.2.0.tgz#ff94aef21609ce9cc24d45b2a2e0fae97f5234a1
@ -382,6 +394,12 @@
dependencies:
sexplib-actual "git://github.com/npm-opam/sexplib.git#113.33.03"
"@opam-alpha/textutils@>= 113.33.03 < 113.34.00":
version "113.33.3"
resolved textutils-113.33.3.tgz#76e395f71810015e894a8e24599bdf5e16f29422
dependencies:
textutils-actual "git://github.com/npm-opam/textutils.git#113.33.03"
"@opam-alpha/typerep@>= 113.33.03 < 113.34.00":
version "113.33.3"
resolved typerep-113.33.3.tgz#4754e4cdc3ab33f67b4fd2511476d61c8582b778
@ -542,7 +560,7 @@
"cmdliner-actual@git://github.com/npm-opam/cmdliner.git#0.9.8":
version "0.9.8"
resolved cmdliner.git-5a22387c9abd87e02563d16f5723d8a644d420a1#c72fafc92b68d98a242e51f618a5684afc0b814a
resolved cmdliner.git-df0ad1033fb9e5b3971fe8294d37911e93d48044#d58dc5ed83a5b4ad525d3f10993971a42f9670f8
dependencies:
"@opam-alpha/ocamlbuild" "*"
dependency-env "https://github.com/npm-ml/dependency-env.git"
@ -577,6 +595,32 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"core_extended-actual@git://github.com/npm-opam/core_extended.git#113.33.03":
version "113.33.3"
resolved core_extended.git-547ba52651d1315f9c49e8292c3be0edd2614fee#ded3bb6c418a0b5733b5bb45b2737d6cf23e9160
dependencies:
"@opam-alpha/bin_prot" ">= 113.33.03 < 113.34.00"
"@opam-alpha/core" ">= 113.33.03 < 113.34.00"
"@opam-alpha/fieldslib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/js-build-tools" ">= 113.33.04 < 113.34.00"
"@opam-alpha/ocamlbuild" "*"
"@opam-alpha/ocamlfind" ">= 1.3.2"
"@opam-alpha/ppx_assert" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_bench" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_driver" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_expect" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_inline_test" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_jane" ">= 113.33.03 < 113.34.00"
"@opam-alpha/re2" ">= 113.33.03 < 113.34.00"
"@opam-alpha/sexplib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/textutils" ">= 113.33.03 < 113.34.00"
"@opam-alpha/typerep" ">= 113.33.03 < 113.34.00"
"@opam-alpha/variantslib" ">= 113.33.03 < 113.34.00"
dependency-env "https://github.com/npm-ml/dependency-env.git"
nopam "https://github.com/yunxing/nopam.git"
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"core_kernel-actual@git://github.com/npm-opam/core_kernel.git#113.33.03":
version "113.33.3"
resolved core_kernel.git-c96de383e5a1f9587c6c2dc8ffc003afba96898a#91f40f3c3bc9cfb278f9d83b43d5c7134255c17d
@ -636,15 +680,9 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"dependency-env@https://github.com/npm-ml/dependency-env.git", "dependency-env@https://github.com/reasonml/dependency-env.git":
"dependency-env@git+https://github.com/reasonml/dependency-env.git", "dependency-env@https://github.com/npm-ml/dependency-env.git", "dependencyEnv@git+https://github.com/reasonml/dependency-env.git":
version "0.0.0"
resolved dependency-env.git-f51ae4f0d72d70f3e7f261df9fff27849dfeacde#48f6db2b606e79e9b56cde38bd5ffcca17129d5f
dependencies:
resolve "^1.1.7"
"dependencyEnv@https://github.com/reasonml/dependency-env":
version "0.0.0"
resolved dependency-env-f51ae4f0d72d70f3e7f261df9fff27849dfeacde#48f6db2b606e79e9b56cde38bd5ffcca17129d5f
resolved dependency-env.git-b6710d7ccc0ea940ce55c4149675dd4ad6a9b94b#1dfad199e8cd9fba48513f85c1383874c7e83e5e
dependencies:
resolve "^1.1.7"
@ -769,13 +807,13 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"nopam@https://github.com/reasonml/nopam.git", "nopam@https://github.com/yunxing/nopam.git":
"nopam@git+https://github.com/reasonml/nopam.git", "nopam@https://github.com/yunxing/nopam.git":
version "0.0.1"
resolved nopam.git-8584695c8e2615857d4f58a0dec7bae3a9059a54#49cd1b4ccc32d588cdd3a671d4cc6d773803396b
"ocaml@git+https://github.com/npm-opam/ocaml.git#npm-4.02.3":
version "4.2.3"
resolved ocaml.git-c67e1e708480ff0083a251a0510072285775fa29#897936d787d25a1f756ae2ad517229677afa353e
resolved ocaml.git-45e648373ad8fe246a57b97be04b23c73b79bc70#7711922ec1b1f64e54c81ca7c619138eb7278956
"ocamlfind-actual@git+https://github.com/npm-opam/ocamlfind.git#1.6.2":
version "1.6.2"
@ -807,7 +845,7 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"opam-installer-bin@https://github.com/yunxing/opam-installer-bin.git":
"opam-installer-bin@git+https://github.com/yunxing/opam-installer-bin.git", "opam-installer-bin@https://github.com/yunxing/opam-installer-bin.git":
version "0.0.0"
resolved opam-installer-bin.git-689ede681217f76fb2f82a9f4528e192a5b543ba#b7704eda021a9fe18a9a37454868e1bbf102e0a0
dependencies:
@ -1248,6 +1286,30 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"re2-actual@git://github.com/npm-opam/re2.git#113.33.03":
version "113.33.3"
resolved re2.git-78dc04b248c786958738e19f2a3e6b8f586dfa1a#74dae72ed9798a85940f8a0685f55664d1a25067
dependencies:
"@opam-alpha/bin_prot" ">= 113.33.03 < 113.34.00"
"@opam-alpha/core_kernel" ">= 113.33.03 < 113.34.00"
"@opam-alpha/fieldslib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/js-build-tools" ">= 113.33.04 < 113.34.00"
"@opam-alpha/ocamlbuild" "*"
"@opam-alpha/ocamlfind" ">= 1.3.2"
"@opam-alpha/ppx_assert" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_bench" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_driver" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_expect" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_inline_test" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_jane" ">= 113.33.03 < 113.34.00"
"@opam-alpha/sexplib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/typerep" ">= 113.33.03 < 113.34.00"
"@opam-alpha/variantslib" ">= 113.33.03 < 113.34.00"
dependency-env "https://github.com/npm-ml/dependency-env.git"
nopam "https://github.com/yunxing/nopam.git"
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"react-actual@git://github.com/npm-opam/react.git#1.2.0":
version "1.2.0"
resolved react.git-4870dc6320c332cd2e0b47ec6241ce1ad6099bca#47ef2c99683defe94d4144165f0e631c56fdc67f
@ -1321,11 +1383,35 @@ resolve@^1.1.7:
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"substs@https://github.com/yunxing/substs.git":
"substs@git+https://github.com/yunxing/substs.git", "substs@https://github.com/yunxing/substs.git":
version "0.0.1"
resolved substs.git-fd480dcdb4aed3fa9128fd819a546e3a7770040f#3a935dc6de26a5dfae899eca93a510bae55e57a4
tuareg@yunxing/tuareg:
"textutils-actual@git://github.com/npm-opam/textutils.git#113.33.03":
version "113.33.3"
resolved textutils.git-07a6c24a179f857719f98659c35760f1d57ac824#1ba178630f5c3a2a5bd07b74c27469f93f53e863
dependencies:
"@opam-alpha/bin_prot" ">= 113.33.03 < 113.34.00"
"@opam-alpha/core" ">= 113.33.03 < 113.34.00"
"@opam-alpha/fieldslib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/js-build-tools" ">= 113.33.04 < 113.34.00"
"@opam-alpha/ocamlbuild" "*"
"@opam-alpha/ocamlfind" ">= 1.3.2"
"@opam-alpha/ppx_assert" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_bench" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_driver" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_expect" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_inline_test" ">= 113.33.03 < 113.34.00"
"@opam-alpha/ppx_jane" ">= 113.33.03 < 113.34.00"
"@opam-alpha/sexplib" ">= 113.33.03 < 113.34.00"
"@opam-alpha/typerep" ">= 113.33.03 < 113.34.00"
"@opam-alpha/variantslib" ">= 113.33.03 < 113.34.00"
dependency-env "https://github.com/npm-ml/dependency-env.git"
nopam "https://github.com/yunxing/nopam.git"
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git"
"tuareg@github:yunxing/tuareg":
version "1.0.0"
resolved a90c0a2f202529a641d369c3b18b0c785a4a7e99#aa3a72a7726b1dd4fd1c809f893cc7ed6d2d420d

Loading…
Cancel
Save