2018-06-29 16:08:08 +04:00
|
|
|
(*****************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Open Source License *)
|
|
|
|
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
|
|
(* *)
|
|
|
|
(* Permission is hereby granted, free of charge, to any person obtaining a *)
|
|
|
|
(* copy of this software and associated documentation files (the "Software"),*)
|
|
|
|
(* to deal in the Software without restriction, including without limitation *)
|
|
|
|
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
|
|
|
|
(* and/or sell copies of the Software, and to permit persons to whom the *)
|
|
|
|
(* Software is furnished to do so, subject to the following conditions: *)
|
|
|
|
(* *)
|
|
|
|
(* The above copyright notice and this permission notice shall be included *)
|
|
|
|
(* in all copies or substantial portions of the Software. *)
|
|
|
|
(* *)
|
|
|
|
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
|
|
|
|
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
|
|
|
|
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
|
|
|
|
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
|
|
|
|
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
|
|
|
|
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
|
|
|
|
(* DEALINGS IN THE SOFTWARE. *)
|
|
|
|
(* *)
|
|
|
|
(*****************************************************************************)
|
2016-09-08 21:13:10 +04:00
|
|
|
|
|
|
|
(* Tezos Command line interface - Configuration and Arguments Parsing *)
|
|
|
|
|
2017-09-19 13:31:35 +04:00
|
|
|
type error += Invalid_block_argument of string
|
2017-11-23 18:57:27 +04:00
|
|
|
type error += Invalid_protocol_argument of string
|
2017-09-19 13:31:35 +04:00
|
|
|
type error += Invalid_port_arg of string
|
2018-05-26 15:41:16 +04:00
|
|
|
type error += Invalid_remote_signer_argument of string
|
2018-04-21 13:31:19 +04:00
|
|
|
type error += Invalid_wait_arg of string
|
2017-09-19 13:31:35 +04:00
|
|
|
let () =
|
|
|
|
register_error_kind
|
|
|
|
`Branch
|
2017-11-23 18:57:27 +04:00
|
|
|
~id: "badBlockArgument"
|
|
|
|
~title: "Bad Block Argument"
|
|
|
|
~description: "Block argument could not be parsed"
|
2017-09-19 13:31:35 +04:00
|
|
|
~pp:
|
|
|
|
(fun ppf s ->
|
2018-02-13 20:56:47 +04:00
|
|
|
Format.fprintf ppf "Value %s is not a value block reference." s)
|
2017-09-19 13:31:35 +04:00
|
|
|
Data_encoding.(obj1 (req "value" string))
|
|
|
|
(function Invalid_block_argument s -> Some s | _ -> None)
|
|
|
|
(fun s -> Invalid_block_argument s) ;
|
2017-11-23 18:57:27 +04:00
|
|
|
register_error_kind
|
|
|
|
`Branch
|
|
|
|
~id: "badProtocolArgument"
|
|
|
|
~title: "Bad Protocol Argument"
|
|
|
|
~description: "Protocol argument could not be parsed"
|
|
|
|
~pp:
|
|
|
|
(fun ppf s ->
|
2018-02-13 20:56:47 +04:00
|
|
|
Format.fprintf ppf "Value %s does not correspond to any known protocol." s)
|
2017-11-23 18:57:27 +04:00
|
|
|
Data_encoding.(obj1 (req "value" string))
|
|
|
|
(function Invalid_protocol_argument s -> Some s | _ -> None)
|
|
|
|
(fun s -> Invalid_protocol_argument s) ;
|
2017-09-19 13:31:35 +04:00
|
|
|
register_error_kind
|
|
|
|
`Branch
|
|
|
|
~id: "invalidPortArgument"
|
|
|
|
~title: "Bad Port Argument"
|
|
|
|
~description: "Port argument could not be parsed"
|
|
|
|
~pp:
|
|
|
|
(fun ppf s ->
|
2018-02-13 20:56:47 +04:00
|
|
|
Format.fprintf ppf "Value %s is not a valid TCP port." s)
|
2017-09-19 13:31:35 +04:00
|
|
|
Data_encoding.(obj1 (req "value" string))
|
|
|
|
(function Invalid_port_arg s -> Some s | _ -> None)
|
2018-05-26 15:41:16 +04:00
|
|
|
(fun s -> Invalid_port_arg s) ;
|
|
|
|
register_error_kind
|
|
|
|
`Branch
|
|
|
|
~id: "invalid_remote_signer_argument"
|
|
|
|
~title: "Unexpected URI of remote signer"
|
|
|
|
~description: "The remote signer argument could not be parsed"
|
|
|
|
~pp:
|
|
|
|
(fun ppf s ->
|
|
|
|
Format.fprintf ppf "Value '%s' is not a valid URI." s)
|
|
|
|
Data_encoding.(obj1 (req "value" string))
|
|
|
|
(function Invalid_remote_signer_argument s -> Some s | _ -> None)
|
2018-04-21 13:31:19 +04:00
|
|
|
(fun s -> Invalid_remote_signer_argument s) ;
|
|
|
|
register_error_kind
|
|
|
|
`Branch
|
|
|
|
~id: "invalidWaitArgument"
|
|
|
|
~title: "Bad Wait Argument"
|
|
|
|
~description: "Wait argument could not be parsed"
|
|
|
|
~pp:
|
|
|
|
(fun ppf s ->
|
|
|
|
Format.fprintf ppf "Value %s is not a valid number of confirmation, nor 'none'." s)
|
|
|
|
Data_encoding.(obj1 (req "value" string))
|
|
|
|
(function Invalid_wait_arg s -> Some s | _ -> None)
|
|
|
|
(fun s -> Invalid_wait_arg s)
|
2017-09-19 13:31:35 +04:00
|
|
|
|
2018-05-26 15:41:16 +04:00
|
|
|
let home = try Sys.getenv "HOME" with Not_found -> "/root"
|
2017-09-19 13:31:35 +04:00
|
|
|
|
2018-02-14 18:20:03 +04:00
|
|
|
let default_base_dir =
|
|
|
|
Filename.concat home ".tezos-client"
|
|
|
|
|
2018-03-14 20:16:18 +04:00
|
|
|
let default_block = `Head 0
|
2018-02-14 18:20:03 +04:00
|
|
|
|
2017-03-31 02:42:13 +04:00
|
|
|
let (//) = Filename.concat
|
2017-03-15 04:17:20 +04:00
|
|
|
|
|
|
|
module Cfg_file = struct
|
2017-03-31 02:42:13 +04:00
|
|
|
|
|
|
|
type t = {
|
|
|
|
base_dir: string ;
|
|
|
|
node_addr: string ;
|
|
|
|
node_port: int ;
|
|
|
|
tls: bool ;
|
|
|
|
web_port: int ;
|
2018-05-26 15:41:16 +04:00
|
|
|
remote_signer: Uri.t option ;
|
2018-04-21 13:31:19 +04:00
|
|
|
confirmations: int option ;
|
2018-08-02 19:35:34 +04:00
|
|
|
password_filename: string option ;
|
2017-03-31 02:42:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
let default = {
|
2018-02-14 18:20:03 +04:00
|
|
|
base_dir = default_base_dir ;
|
2017-12-12 18:32:58 +04:00
|
|
|
node_addr = "localhost" ;
|
2017-03-31 02:42:13 +04:00
|
|
|
node_port = 8732 ;
|
|
|
|
tls = false ;
|
|
|
|
web_port = 8080 ;
|
2018-05-26 15:41:16 +04:00
|
|
|
remote_signer = None ;
|
2018-04-21 13:31:19 +04:00
|
|
|
confirmations = Some 0 ;
|
2018-08-02 19:35:34 +04:00
|
|
|
password_filename = None ;
|
2017-03-31 02:42:13 +04:00
|
|
|
}
|
|
|
|
|
2017-03-15 04:17:20 +04:00
|
|
|
open Data_encoding
|
|
|
|
|
|
|
|
let encoding =
|
|
|
|
conv
|
2018-04-21 13:31:19 +04:00
|
|
|
(fun { base_dir ; node_addr ; node_port ; tls ; web_port ;
|
2018-08-02 19:35:34 +04:00
|
|
|
remote_signer ; confirmations ; password_filename } ->
|
2018-04-21 13:31:19 +04:00
|
|
|
(base_dir, Some node_addr, Some node_port,
|
2018-08-02 19:35:34 +04:00
|
|
|
Some tls, Some web_port, remote_signer, confirmations, password_filename ))
|
2018-04-21 13:31:19 +04:00
|
|
|
(fun (base_dir, node_addr, node_port, tls, web_port,
|
2018-08-02 19:35:34 +04:00
|
|
|
remote_signer, confirmations, password_filename) ->
|
2018-04-21 13:31:19 +04:00
|
|
|
let node_addr = Option.unopt ~default:default.node_addr node_addr in
|
|
|
|
let node_port = Option.unopt ~default:default.node_port node_port in
|
|
|
|
let tls = Option.unopt ~default:default.tls tls in
|
|
|
|
let web_port = Option.unopt ~default:default.web_port web_port in
|
|
|
|
{ base_dir ; node_addr ; node_port ; tls ; web_port ;
|
2018-08-02 19:35:34 +04:00
|
|
|
remote_signer ; confirmations ; password_filename })
|
|
|
|
(obj8
|
2017-09-19 13:31:35 +04:00
|
|
|
(req "base_dir" string)
|
|
|
|
(opt "node_addr" string)
|
|
|
|
(opt "node_port" int16)
|
|
|
|
(opt "tls" bool)
|
2018-05-26 15:41:16 +04:00
|
|
|
(opt "web_port" int16)
|
2018-04-21 13:31:19 +04:00
|
|
|
(opt "remote_signer" RPC_client.uri_encoding)
|
2018-08-02 19:35:34 +04:00
|
|
|
(opt "confirmations" int8)
|
|
|
|
(opt "password_filename" string)
|
|
|
|
)
|
2017-03-15 04:17:20 +04:00
|
|
|
|
|
|
|
let from_json json =
|
|
|
|
Data_encoding.Json.destruct encoding json
|
|
|
|
|
|
|
|
let read fp =
|
2018-02-08 13:51:01 +04:00
|
|
|
Lwt_utils_unix.Json.read_file fp >>=? fun json ->
|
2017-03-15 04:17:20 +04:00
|
|
|
return (from_json json)
|
|
|
|
|
|
|
|
let write out cfg =
|
2018-02-08 13:51:02 +04:00
|
|
|
Lwt_utils_unix.Json.write_file out
|
|
|
|
(Data_encoding.Json.construct encoding cfg)
|
2017-03-31 02:42:13 +04:00
|
|
|
|
2017-03-15 04:17:20 +04:00
|
|
|
end
|
2016-09-08 21:13:10 +04:00
|
|
|
|
2017-09-19 13:31:35 +04:00
|
|
|
type cli_args = {
|
2018-04-22 16:40:44 +04:00
|
|
|
block: Shell_services.block ;
|
2018-04-21 13:31:19 +04:00
|
|
|
confirmations: int option ;
|
2018-08-02 19:35:34 +04:00
|
|
|
password_filename: string option ;
|
2017-11-23 18:57:27 +04:00
|
|
|
protocol: Protocol_hash.t option ;
|
2017-09-19 13:31:35 +04:00
|
|
|
print_timings: bool ;
|
|
|
|
log_requests: bool ;
|
|
|
|
}
|
|
|
|
|
|
|
|
let default_cli_args = {
|
2018-02-14 18:20:03 +04:00
|
|
|
block = default_block ;
|
2018-04-21 13:31:19 +04:00
|
|
|
confirmations = Some 0 ;
|
2018-08-02 19:35:34 +04:00
|
|
|
password_filename = None ;
|
2017-11-23 18:57:27 +04:00
|
|
|
protocol = None ;
|
2017-09-19 13:31:35 +04:00
|
|
|
print_timings = false ;
|
|
|
|
log_requests = false ;
|
|
|
|
}
|
|
|
|
|
2017-11-07 20:38:11 +04:00
|
|
|
|
2018-04-03 13:39:09 +04:00
|
|
|
open Clic
|
2017-09-19 13:31:35 +04:00
|
|
|
|
2018-02-16 21:10:18 +04:00
|
|
|
let string_parameter () : (string, #Client_context.full) parameter =
|
2017-09-27 11:55:20 +04:00
|
|
|
parameter (fun _ x -> return x)
|
|
|
|
|
2018-02-11 22:17:39 +04:00
|
|
|
let block_parameter () =
|
2017-09-27 11:55:20 +04:00
|
|
|
parameter
|
2018-03-14 20:16:18 +04:00
|
|
|
(fun _ block ->
|
|
|
|
match Block_services.parse_block block with
|
2017-11-23 18:57:27 +04:00
|
|
|
| Error _ -> fail (Invalid_block_argument block)
|
2017-09-27 11:55:20 +04:00
|
|
|
| Ok block -> return block)
|
|
|
|
|
2018-04-21 13:31:19 +04:00
|
|
|
let wait_parameter () =
|
|
|
|
parameter
|
|
|
|
(fun _ wait ->
|
|
|
|
match wait with
|
2018-06-27 06:05:42 +04:00
|
|
|
| "no" | "none" -> return_none
|
2018-04-21 13:31:19 +04:00
|
|
|
| _ ->
|
|
|
|
try
|
|
|
|
let w = int_of_string wait in
|
|
|
|
if 0 <= w then
|
2018-06-27 06:05:42 +04:00
|
|
|
return_some w
|
2018-04-21 13:31:19 +04:00
|
|
|
else
|
|
|
|
fail (Invalid_wait_arg wait)
|
|
|
|
with _ -> fail (Invalid_wait_arg wait))
|
|
|
|
|
2018-02-11 22:17:39 +04:00
|
|
|
let protocol_parameter () =
|
2017-11-23 18:57:27 +04:00
|
|
|
parameter
|
|
|
|
(fun _ arg ->
|
|
|
|
try
|
|
|
|
let (hash,_commands) =
|
|
|
|
List.find (fun (hash,_commands) ->
|
2018-03-14 20:16:18 +04:00
|
|
|
String.has_prefix ~prefix:arg
|
|
|
|
(Protocol_hash.to_b58check hash))
|
|
|
|
(Client_commands.get_versions ())
|
2017-11-23 18:57:27 +04:00
|
|
|
in
|
2018-06-27 06:05:42 +04:00
|
|
|
return_some hash
|
2017-11-23 18:57:27 +04:00
|
|
|
with Not_found -> fail (Invalid_protocol_argument arg)
|
|
|
|
)
|
|
|
|
|
2017-09-19 13:31:35 +04:00
|
|
|
(* Command-line only args (not in config file) *)
|
2018-02-11 22:17:39 +04:00
|
|
|
let base_dir_arg () =
|
2018-01-12 04:10:12 +04:00
|
|
|
arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"base-dir"
|
|
|
|
~short:'d'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"path"
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:("client data directory\n\
|
|
|
|
The directory where the Tezos client will store all its data.\n\
|
2018-02-14 18:20:03 +04:00
|
|
|
By default: '" ^ default_base_dir ^"'.")
|
2018-02-11 22:17:39 +04:00
|
|
|
(string_parameter ())
|
|
|
|
let config_file_arg () =
|
2017-09-19 13:31:35 +04:00
|
|
|
arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"config-file"
|
|
|
|
~short:'c'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"path"
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"configuration file"
|
2018-02-11 22:17:39 +04:00
|
|
|
(string_parameter ())
|
|
|
|
let timings_switch () =
|
2017-09-19 13:31:35 +04:00
|
|
|
switch
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"timings"
|
|
|
|
~short:'t'
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"show RPC request times"
|
2018-02-14 02:50:24 +04:00
|
|
|
()
|
2018-02-11 22:17:39 +04:00
|
|
|
let block_arg () =
|
2017-09-19 13:31:35 +04:00
|
|
|
default_arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"block"
|
|
|
|
~short:'b'
|
2018-01-29 13:43:07 +04:00
|
|
|
~placeholder:"hash|tag"
|
|
|
|
~doc:"block on which to apply contextual commands"
|
2018-01-26 16:07:49 +04:00
|
|
|
~default:(Block_services.to_string default_cli_args.block)
|
2018-02-11 22:17:39 +04:00
|
|
|
(block_parameter ())
|
2018-04-21 13:31:19 +04:00
|
|
|
let wait_arg () =
|
|
|
|
arg
|
|
|
|
~long:"wait"
|
|
|
|
~short:'w'
|
|
|
|
~placeholder:"none|<int>"
|
|
|
|
~doc:"how many confirmation blocks before to consider an operation as included"
|
|
|
|
(wait_parameter ())
|
2018-02-11 22:17:39 +04:00
|
|
|
let protocol_arg () =
|
2017-11-23 18:57:27 +04:00
|
|
|
arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"protocol"
|
|
|
|
~short:'p'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"hash"
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"use commands of a specific protocol"
|
2018-02-11 22:17:39 +04:00
|
|
|
(protocol_parameter ())
|
|
|
|
let log_requests_switch () =
|
2017-09-19 13:31:35 +04:00
|
|
|
switch
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"log-requests"
|
|
|
|
~short:'l'
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"log all requests to the node"
|
2018-02-14 02:50:24 +04:00
|
|
|
()
|
2017-09-19 13:31:35 +04:00
|
|
|
|
|
|
|
(* Command-line args which can be set in config file as well *)
|
2018-02-11 22:17:39 +04:00
|
|
|
let addr_arg () =
|
2017-12-12 19:48:24 +04:00
|
|
|
arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"addr"
|
|
|
|
~short:'A'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"IP addr|host"
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"IP address of the node"
|
2018-02-11 22:17:39 +04:00
|
|
|
(string_parameter ())
|
|
|
|
let port_arg () =
|
2017-12-12 19:48:24 +04:00
|
|
|
arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"port"
|
|
|
|
~short:'P'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"number"
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"RPC port of the node"
|
2017-09-27 11:55:20 +04:00
|
|
|
(parameter
|
|
|
|
(fun _ x -> try
|
2017-11-13 19:34:00 +04:00
|
|
|
return (int_of_string x)
|
|
|
|
with Failure _ ->
|
|
|
|
fail (Invalid_port_arg x)))
|
2018-02-11 22:17:39 +04:00
|
|
|
let tls_switch () =
|
2017-09-19 13:31:35 +04:00
|
|
|
switch
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"tls"
|
|
|
|
~short:'S'
|
2018-01-29 13:43:07 +04:00
|
|
|
~doc:"use TLS to connect to node."
|
2018-02-14 02:50:24 +04:00
|
|
|
()
|
2018-05-26 15:41:16 +04:00
|
|
|
let remote_signer_arg () =
|
|
|
|
arg
|
|
|
|
~long:"remote-signer"
|
|
|
|
~short:'R'
|
|
|
|
~placeholder:"uri"
|
|
|
|
~doc:"URI of the remote signer"
|
|
|
|
(parameter
|
2018-05-27 15:27:29 +04:00
|
|
|
(fun _ x -> Tezos_signer_backends.Remote.parse_base_uri x))
|
2018-08-02 19:35:34 +04:00
|
|
|
let password_filename_arg () =
|
|
|
|
arg
|
|
|
|
~long:"password-filename"
|
|
|
|
~short:'f'
|
|
|
|
~placeholder:"filename"
|
|
|
|
~doc:"path to the passowrd filename"
|
|
|
|
(string_parameter ())
|
2017-09-19 13:31:35 +04:00
|
|
|
|
2018-02-08 13:51:02 +04:00
|
|
|
let read_config_file config_file =
|
|
|
|
Lwt_utils_unix.Json.read_file config_file >>=? fun cfg_json ->
|
|
|
|
try return @@ Cfg_file.from_json cfg_json
|
|
|
|
with exn ->
|
|
|
|
failwith
|
|
|
|
"Can't parse the configuration file: %s@,%a"
|
|
|
|
config_file (fun ppf exn -> Json_encoding.print_error ppf exn) exn
|
2018-01-12 04:10:12 +04:00
|
|
|
|
|
|
|
let default_config_file_name = "config"
|
|
|
|
|
|
|
|
let commands config_file cfg =
|
2018-04-03 13:39:09 +04:00
|
|
|
let open Clic in
|
|
|
|
let group = { Clic.name = "config" ;
|
2018-02-14 18:54:52 +04:00
|
|
|
title = "Commands for editing and viewing the client's config file" } in
|
2018-01-29 13:43:07 +04:00
|
|
|
[ command ~group ~desc:"Show the config file."
|
2018-01-12 04:10:12 +04:00
|
|
|
no_options
|
|
|
|
(fixed [ "config" ; "show" ])
|
2018-02-16 21:10:18 +04:00
|
|
|
(fun () (cctxt : #Client_context.full) ->
|
2018-02-08 13:51:01 +04:00
|
|
|
let pp_cfg ppf cfg = Format.fprintf ppf "%a" Data_encoding.Json.pp (Data_encoding.Json.construct Cfg_file.encoding cfg) in
|
2018-01-12 04:10:12 +04:00
|
|
|
if not @@ Sys.file_exists config_file then
|
|
|
|
cctxt#warning
|
|
|
|
"@[<v 2>Warning: no config file at %s,@,\
|
|
|
|
displaying the default configuration.@]"
|
|
|
|
config_file >>= fun () ->
|
|
|
|
cctxt#warning "%a@," pp_cfg Cfg_file.default >>= return
|
|
|
|
else
|
|
|
|
read_config_file config_file >>=? fun cfg ->
|
|
|
|
cctxt#message "%a@," pp_cfg cfg >>= return) ;
|
|
|
|
|
2018-01-29 13:43:07 +04:00
|
|
|
command ~group ~desc:"Reset the config file to the factory defaults."
|
2018-01-12 04:10:12 +04:00
|
|
|
no_options
|
|
|
|
(fixed [ "config" ; "reset" ])
|
|
|
|
(fun () _cctxt ->
|
2018-02-08 13:51:02 +04:00
|
|
|
Cfg_file.(write config_file default)) ;
|
2018-01-12 04:10:12 +04:00
|
|
|
|
2018-01-29 13:43:07 +04:00
|
|
|
command ~group
|
|
|
|
~desc:"Update the config based on the current cli values.\n\
|
|
|
|
Loads the current configuration (default or as specified \
|
|
|
|
with `-config-file`), applies alterations from other \
|
|
|
|
command line arguments (such as the node's address, \
|
|
|
|
etc.), and overwrites the updated configuration file."
|
2018-01-12 04:10:12 +04:00
|
|
|
no_options
|
|
|
|
(fixed [ "config" ; "update" ])
|
|
|
|
(fun () _cctxt ->
|
2018-02-08 13:51:02 +04:00
|
|
|
Cfg_file.(write config_file cfg)) ;
|
2018-01-12 04:10:12 +04:00
|
|
|
|
2018-01-29 13:43:07 +04:00
|
|
|
command ~group
|
|
|
|
~desc:"Create a config file based on the current CLI values.\n\
|
|
|
|
If the `-file` option is not passed, this will initialize \
|
|
|
|
the default config file, based on default parameters, \
|
|
|
|
altered by other command line options (such as the node's \
|
|
|
|
address, etc.).\n\
|
|
|
|
Otherwise, it will create a new config file, based on the \
|
|
|
|
default parameters (or the the ones specified with \
|
|
|
|
`-config-file`), altered by other command line \
|
|
|
|
options.\n\
|
|
|
|
The command will always fail if the file already exists."
|
2018-01-12 04:10:12 +04:00
|
|
|
(args1
|
|
|
|
(default_arg
|
2018-02-14 02:50:24 +04:00
|
|
|
~long:"output"
|
|
|
|
~short:'o'
|
2018-01-27 21:32:40 +04:00
|
|
|
~placeholder:"path"
|
2018-01-12 04:10:12 +04:00
|
|
|
~doc:"path at which to create the file"
|
|
|
|
~default:(cfg.base_dir // default_config_file_name)
|
|
|
|
(parameter (fun _ctx str -> return str))))
|
|
|
|
(fixed [ "config" ; "init" ])
|
|
|
|
(fun config_file _cctxt ->
|
|
|
|
if not (Sys.file_exists config_file)
|
2018-02-08 13:51:02 +04:00
|
|
|
then Cfg_file.(write config_file cfg) (* Should be default or command would have failed *)
|
2018-01-12 04:10:12 +04:00
|
|
|
else failwith "Config file already exists at location") ;
|
|
|
|
]
|
|
|
|
|
2018-02-11 22:17:39 +04:00
|
|
|
let global_options () =
|
2018-08-02 19:35:34 +04:00
|
|
|
args12
|
2018-05-26 15:41:16 +04:00
|
|
|
(base_dir_arg ())
|
2018-02-11 22:17:39 +04:00
|
|
|
(config_file_arg ())
|
|
|
|
(timings_switch ())
|
|
|
|
(block_arg ())
|
2018-04-21 13:31:19 +04:00
|
|
|
(wait_arg ())
|
2018-02-11 22:17:39 +04:00
|
|
|
(protocol_arg ())
|
|
|
|
(log_requests_switch ())
|
|
|
|
(addr_arg ())
|
|
|
|
(port_arg ())
|
|
|
|
(tls_switch ())
|
2018-05-26 15:41:16 +04:00
|
|
|
(remote_signer_arg ())
|
2018-08-02 19:35:34 +04:00
|
|
|
(password_filename_arg ())
|
2017-09-19 13:31:35 +04:00
|
|
|
|
2018-02-16 21:10:18 +04:00
|
|
|
let parse_config_args (ctx : #Client_context.full) argv =
|
2018-02-13 20:56:47 +04:00
|
|
|
parse_global_options
|
2018-02-11 22:17:39 +04:00
|
|
|
(global_options ())
|
2017-09-19 13:31:35 +04:00
|
|
|
ctx
|
2018-01-12 04:10:12 +04:00
|
|
|
argv >>=?
|
2017-09-19 13:31:35 +04:00
|
|
|
fun ((base_dir,
|
|
|
|
config_file,
|
|
|
|
timings,
|
|
|
|
block,
|
2018-04-21 13:31:19 +04:00
|
|
|
confirmations,
|
2017-11-23 18:57:27 +04:00
|
|
|
protocol,
|
2017-09-19 13:31:35 +04:00
|
|
|
log_requests,
|
|
|
|
node_addr,
|
|
|
|
node_port,
|
2018-05-26 15:41:16 +04:00
|
|
|
tls,
|
2018-08-02 19:35:34 +04:00
|
|
|
remote_signer,
|
|
|
|
password_filename), remaining) ->
|
2018-01-12 04:10:12 +04:00
|
|
|
begin match base_dir with
|
|
|
|
| None ->
|
2018-02-14 18:20:03 +04:00
|
|
|
let base_dir = default_base_dir in
|
2018-02-08 13:51:02 +04:00
|
|
|
unless (Sys.file_exists base_dir) begin fun () ->
|
|
|
|
Lwt_utils_unix.create_dir base_dir >>= return
|
|
|
|
end >>=? fun () ->
|
2018-01-12 04:10:12 +04:00
|
|
|
return base_dir
|
|
|
|
| Some dir ->
|
|
|
|
if not (Sys.file_exists dir)
|
|
|
|
then failwith "Specified -base-dir does not exist. Please create the directory and try again."
|
|
|
|
else if Sys.is_directory dir
|
|
|
|
then return dir
|
|
|
|
else failwith "Specified -base-dir must be a directory"
|
|
|
|
end >>=? fun base_dir ->
|
|
|
|
begin match config_file with
|
|
|
|
| None -> return @@ base_dir // default_config_file_name
|
|
|
|
| Some config_file ->
|
|
|
|
if Sys.file_exists config_file
|
|
|
|
then return config_file
|
|
|
|
else failwith "Config file specified in option does not exist. Use `client config init` to create one."
|
|
|
|
end >>=? fun config_file ->
|
2017-03-31 02:42:13 +04:00
|
|
|
let config_dir = Filename.dirname config_file in
|
2017-11-23 18:57:27 +04:00
|
|
|
let protocol =
|
|
|
|
match protocol with
|
|
|
|
| None -> None
|
|
|
|
| Some p -> p
|
|
|
|
in
|
2018-01-12 04:10:12 +04:00
|
|
|
begin
|
2017-03-31 02:42:13 +04:00
|
|
|
if not (Sys.file_exists config_file) then
|
2018-01-12 04:10:12 +04:00
|
|
|
return { Cfg_file.default with base_dir = base_dir }
|
2017-03-31 02:42:13 +04:00
|
|
|
else
|
2018-01-12 04:10:12 +04:00
|
|
|
read_config_file config_file
|
2018-02-08 13:51:02 +04:00
|
|
|
end >>=? fun cfg ->
|
2017-09-19 13:31:35 +04:00
|
|
|
let tls = cfg.tls || tls in
|
2017-12-12 19:48:24 +04:00
|
|
|
let node_addr = Option.unopt ~default:cfg.node_addr node_addr in
|
|
|
|
let node_port = Option.unopt ~default:cfg.node_port node_port in
|
2018-05-27 15:27:29 +04:00
|
|
|
Tezos_signer_backends.Remote.read_base_uri_from_env () >>=? fun remote_signer_env ->
|
|
|
|
let remote_signer =
|
|
|
|
Option.first_some remote_signer
|
|
|
|
(Option.first_some remote_signer_env cfg.remote_signer) in
|
2018-04-21 13:31:19 +04:00
|
|
|
let confirmations = Option.unopt ~default:cfg.confirmations confirmations in
|
|
|
|
let cfg = { cfg with tls ; node_port ; node_addr ;
|
2018-08-02 19:35:34 +04:00
|
|
|
remote_signer ; confirmations ; password_filename } in
|
2017-03-31 02:42:13 +04:00
|
|
|
if Sys.file_exists base_dir && not (Sys.is_directory base_dir) then begin
|
2018-01-12 04:10:12 +04:00
|
|
|
Format.eprintf "%s is not a directory.@." base_dir ;
|
2017-03-31 02:42:13 +04:00
|
|
|
exit 1 ;
|
|
|
|
end ;
|
|
|
|
if Sys.file_exists config_dir && not (Sys.is_directory config_dir) then begin
|
2018-01-12 04:10:12 +04:00
|
|
|
Format.eprintf "%s is not a directory.@." config_dir ;
|
2017-03-31 02:42:13 +04:00
|
|
|
exit 1 ;
|
|
|
|
end ;
|
2018-02-08 13:51:02 +04:00
|
|
|
Lwt_utils_unix.create_dir config_dir >>= fun () ->
|
|
|
|
return
|
|
|
|
(cfg,
|
2018-08-02 19:35:34 +04:00
|
|
|
{ block ; confirmations ; password_filename ;
|
2018-04-21 13:31:19 +04:00
|
|
|
print_timings = timings ; log_requests ; protocol },
|
2018-02-08 13:51:02 +04:00
|
|
|
commands config_file cfg, remaining)
|