Skip to content

Commit

Permalink
make temp dir configurable
Browse files Browse the repository at this point in the history
Summary: It would be useful during development to run multiple versions of flow (`flow` and `flow-dev`, for instance), even though we generally want to only run a single version. This restriction is currently enforced by `FlowConfig.lock_file` (and friends) which hardcodes the temp dir path so that the pid/lock/socket files that the client and server use to communicate exist in exactly one place, preventing two instances from running on the same root dir.

By changing the base temp dir, we can create an entire separate environment for these files, so that `flow` and `flow-dev` can't see each other. This diff adds a `--temp-dir` command line option and threads that around to all of the places that create lock files and sockets.

Reviewed By: @gabelevi

Differential Revision: D2277560
  • Loading branch information
mroch authored and facebook-github-bot-0 committed Jul 29, 2015
1 parent 942e2f9 commit fdc3ec3
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 49 deletions.
35 changes: 25 additions & 10 deletions src/commands/commandUtils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ let json_flags prev = CommandSpec.ArgSpec.(
|> flag "--json" no_arg ~doc:"Output results in JSON format"
)

let temp_dir_flag prev = CommandSpec.ArgSpec.(
prev
|> flag "--temp-dir" string
~doc:"Directory in which to store temp files (default: /tmp/flow/)"
)

(* relativize a loc's source path to a given root whenever strip_root is set *)
let relativize strip_root root loc =
if not strip_root then loc else Loc.({
Expand All @@ -124,9 +130,10 @@ type command_params = {
retry_if_init : bool;
timeout : int;
no_auto_start : bool;
temp_dir : string;
}

let collect_server_flags main timeout from retries retry_if_init no_auto_start =
let collect_server_flags main timeout from retries retry_if_init no_auto_start temp_dir =
let default def = function
| Some x -> x
| None -> def in
Expand All @@ -136,6 +143,7 @@ let collect_server_flags main timeout from retries retry_if_init no_auto_start =
retry_if_init = (default true retry_if_init);
timeout = (default 0 timeout);
no_auto_start = no_auto_start;
temp_dir = (default FlowConfig.default_temp_dir temp_dir);
}


Expand All @@ -152,20 +160,27 @@ let server_flags prev = CommandSpec.ArgSpec.(
~doc:"retry if the server is initializing (default: true)"
|> flag "--no-auto-start" no_arg
~doc:"If the server if it is not running, do not start it; just exit"
|> temp_dir_flag
)

let start_flow_server root =
let start_flow_server ?temp_dir root =
Printf.fprintf stderr "Flow server launched for %s\n%!"
(Path.to_string root);
let flow_server = Printf.sprintf "%s start %s 1>&2"
let temp_dir_arg = match temp_dir with
| Some dir -> Printf.sprintf "--temp-dir=%s " (Filename.quote dir)
| None -> ""
in
let flow_server = Printf.sprintf "%s start %s%s 1>&2"
(Filename.quote (Sys.argv.(0)))
temp_dir_arg
(Filename.quote (Path.to_string root)) in
match Unix.system flow_server with
| Unix.WEXITED 0 -> ()
| _ -> (Printf.fprintf stderr "Could not start flow server!\n"; exit 77)


let server_exists root = not (Lock.check (FlowConfig.lock_file root))
let server_exists ~tmp_dir root =
not (Lock.check (FlowConfig.lock_file ~tmp_dir root))

let wait_on_server_restart ic =
try
Expand All @@ -181,12 +196,12 @@ let wait_on_server_restart ic =
()

(* Function connecting to hh_server *)
let connect root =
if not (server_exists root)
let connect ~tmp_dir root =
if not (server_exists ~tmp_dir root)
then raise CommandExceptions.Server_missing;
let ic, oc, cstate =
try
let sock_name = Socket.get_path (FlowConfig.socket_file root) in
let sock_name = Socket.get_path (FlowConfig.socket_file ~tmp_dir root) in
let sockaddr = Unix.ADDR_UNIX sock_name in
let ic, oc = Unix.open_connection sockaddr in
try
Expand All @@ -198,7 +213,7 @@ let connect root =
close_in_noerr ic;
raise e
with _ ->
if not (Lock.check (FlowConfig.init_file root))
if not (Lock.check (FlowConfig.init_file ~tmp_dir root))
then raise CommandExceptions.Server_initializing
else raise CommandExceptions.Server_cant_connect
in
Expand All @@ -222,7 +237,7 @@ let connect root =
let rec connect_with_autostart server_flags root =
check_timeout ();
try
connect root
connect ~tmp_dir:server_flags.temp_dir root
with
| CommandExceptions.Server_initializing ->
let init_msg = "flow server still initializing. If it was " ^
Expand All @@ -246,7 +261,7 @@ let rec connect_with_autostart server_flags root =
| CommandExceptions.Server_missing ->
if not server_flags.no_auto_start
then (
start_flow_server root;
start_flow_server ~temp_dir:server_flags.temp_dir root;
retry server_flags root
3 "The flow server will be ready in a moment."
) else (
Expand Down
9 changes: 8 additions & 1 deletion src/commands/serverCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module OptionParser(Config : CONFIG) = struct
~doc:"Do not include embedded declarations"
|> flag "--munge-underscore-members" no_arg
~doc:"Treat any class member name with a leading underscore as private"
|> temp_dir_flag
|> anon "root" (optional string) ~doc:"Root directory"
)

Expand Down Expand Up @@ -105,7 +106,8 @@ module OptionParser(Config : CONFIG) = struct

let result = ref None
let main error_flags json profile quiet log_file debug verbose verbose_indent
all weak traces strip_root lib no_flowlib munge_underscore_members root () =
all weak traces strip_root lib no_flowlib munge_underscore_members
temp_dir root () =
let root = CommandUtils.guess_root root in
let flowconfig = FlowConfig.get root in
let opt_module = FlowConfig.(match flowconfig.options.moduleSystem with
Expand Down Expand Up @@ -134,6 +136,10 @@ module OptionParser(Config : CONFIG) = struct
| None ->
FlowConfig.(flowconfig.options.log_file)
in
let opt_temp_dir = match temp_dir with
| Some x -> x
| None -> FlowConfig.default_temp_dir (* TODO: add flowconfig option *)
in

result := Some {
Options.opt_check_mode = Config.(mode = Check);
Expand All @@ -159,6 +165,7 @@ module OptionParser(Config : CONFIG) = struct
Options.opt_libs;
Options.opt_no_flowlib = no_flowlib;
Options.opt_munge_underscores = opt_munge_underscores;
Options.opt_temp_dir;
};
()

Expand Down
9 changes: 8 additions & 1 deletion src/commands/singleCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ let spec = {
|> flag "--munge-underscore-members" no_arg
~doc:"Treat any class member name with a leading underscore as private"
|> error_flags
|> temp_dir_flag
|> anon "root" (required string)
~doc:"Root"
)
}

let main all weak debug verbose verbose_indent json profile quiet module_
lib no_flowlib munge_underscore_members error_flags root () =
lib no_flowlib munge_underscore_members error_flags temp_dir root () =
let opt_libs = match lib with
| None -> []
| Some lib -> [Path.make lib]
Expand All @@ -71,6 +72,11 @@ let main all weak debug verbose verbose_indent json profile quiet module_
let munge_underscores = munge_underscore_members ||
FlowConfig.(flowconfig.options.munge_underscores) in

let opt_temp_dir = match temp_dir with
| Some x -> x
| None -> FlowConfig.default_temp_dir (* TODO: add flowconfig option *)
in

let options = {
Options.opt_error_flags = error_flags;
Options.opt_root = Path.make root;
Expand All @@ -95,6 +101,7 @@ let main all weak debug verbose verbose_indent json profile quiet module_
Options.opt_libs;
Options.opt_no_flowlib = no_flowlib;
Options.opt_munge_underscores = munge_underscores;
Options.opt_temp_dir;
} in

if ! Sys.interactive
Expand Down
23 changes: 14 additions & 9 deletions src/commands/stopCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ let spec = {
CommandUtils.exe_name;
args = CommandSpec.ArgSpec.(
empty
|> CommandUtils.temp_dir_flag
|> anon "root" (optional string) ~doc:"Root directory"
)
}
Expand All @@ -41,13 +42,13 @@ let kill (ic, oc) =
ServerProt.cmd_to_channel oc ServerProt.KILL;
ServerProt.response_from_channel ic

let nice_kill (ic, oc) root =
let nice_kill (ic, oc) ~tmp_dir root =
Printf.eprintf "Attempting to nicely kill server for %s\n%!"
(Path.to_string root);
let response = kill (ic, oc) in
if is_expected response then begin
let i = ref 0 in
while CommandUtils.server_exists root do
while CommandUtils.server_exists ~tmp_dir root do
incr i;
if !i < 5 then ignore @@ Unix.sleep 1
else raise FailedToKill
Expand All @@ -60,11 +61,11 @@ let nice_kill (ic, oc) root =
raise FailedToKill
end

let mean_kill root =
let mean_kill ~tmp_dir root =
Printf.fprintf stderr "Attempting to meanly kill server for %s\n%!"
(Path.to_string root);
let pids =
try PidLog.get_pids (FlowConfig.pids_file root)
try PidLog.get_pids (FlowConfig.pids_file ~tmp_dir root)
with PidLog.FailedToGetPids -> Printf.fprintf stderr
"Unable to figure out pids of running Flow server. \
Try manually killing it with 'pkill %s' (be careful on shared \
Expand All @@ -79,18 +80,22 @@ let mean_kill root =
()
) pids;
ignore(Unix.sleep 1);
if CommandUtils.server_exists root
if CommandUtils.server_exists ~tmp_dir root
then raise FailedToKill
else Printf.fprintf stderr "Successfully killed server for %s\n%!"
(Path.to_string root)

let main root () =
let main temp_dir root () =
let root = CommandUtils.guess_root root in
let root_s = Path.to_string root in
let tmp_dir = match temp_dir with
| Some x -> x
| None -> FlowConfig.default_temp_dir (* TODO: add flowconfig option *)
in
try
let conn = CommandUtils.connect root in
let conn = CommandUtils.connect ~tmp_dir root in
begin
try nice_kill conn root
try nice_kill conn ~tmp_dir root
with FailedToKill ->
Printf.eprintf "Failed to kill server nicely for %s\n%!" root_s;
exit 1
Expand All @@ -102,7 +107,7 @@ let main root () =
Printf.eprintf "Successfully killed server for %s\n%!" root_s
| CommandExceptions.Server_busy
| CommandExceptions.Server_initializing ->
try mean_kill root
try mean_kill ~tmp_dir root
with FailedToKill ->
Printf.eprintf "Failed to kill server meanly for %s\n%!" root_s;
exit 1
Expand Down
4 changes: 2 additions & 2 deletions src/common/files_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,14 @@ let get_all =
in
fun next -> get_all_rec next SSet.empty

let init libs =
let init ~tmp_dir libs =
match !lib_files with
| Some libs -> ()
| None -> (
let libs = if Modes_js.modes.no_flowlib
then libs
else
let root = Path.make (Tmp.temp_dir FlowConfig.tmp_dir "flowlib") in
let root = Path.make (Tmp.temp_dir tmp_dir "flowlib") in
if Flowlib.extract_flowlib root
then root::libs
else (print_endline "Could not locate flowlib files"; exit 1)
Expand Down
2 changes: 1 addition & 1 deletion src/common/files_js.mli
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ val flow_extensions: string list
val is_flow_file: string -> bool

(* name of library directory defining builtins *)
val init: Path.t list -> unit
val init: tmp_dir:string -> Path.t list -> unit

(* names of library files defining builtins *)
val get_lib_files: unit -> Utils.SSet.t
Expand Down
14 changes: 7 additions & 7 deletions src/common/flowConfig.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,24 @@ type config = {
root: Path.t;
}

let tmp_dir = "/tmp/flow/"
let default_temp_dir = "/tmp/flow/"

let file_of_root root extension =
let file_of_root ~tmp_dir root extension =
let tmp_dir = if tmp_dir.[String.length tmp_dir - 1] <> '/'
then tmp_dir ^ "/"
else tmp_dir in
Tmp.mkdir tmp_dir; (* TODO: move this to places that write this file *)
let root_part = Path.slash_escaped_string_of_path root in
Printf.sprintf "%s%s.%s" tmp_dir root_part extension

let init_file root = file_of_root root "init"
let lock_file root = file_of_root root "lock"
let pids_file root = file_of_root root "pids"
let socket_file root = file_of_root root "sock"
let init_file ~tmp_dir root = file_of_root ~tmp_dir root "init"
let lock_file ~tmp_dir root = file_of_root ~tmp_dir root "lock"
let pids_file ~tmp_dir root = file_of_root ~tmp_dir root "pids"
let socket_file ~tmp_dir root = file_of_root ~tmp_dir root "sock"

let default_log_file root =
let root_part = Path.slash_escaped_string_of_path root in
Path.make (Printf.sprintf "%s%s.log" tmp_dir root_part)
Path.make (Printf.sprintf "%s%s.log" default_temp_dir root_part)

let default_module_system = Node

Expand Down
10 changes: 5 additions & 5 deletions src/common/flowConfig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type options = {
log_file: Path.t;
}

val default_temp_dir: string
val default_module_system: moduleSystem
val default_options: Path.t -> options

Expand All @@ -46,11 +47,10 @@ val get: Path.t -> config
val get_unsafe: unit -> config
val fullpath: Path.t -> string

val tmp_dir: string
val init_file: Path.t -> string
val lock_file: Path.t -> string
val pids_file: Path.t -> string
val socket_file: Path.t -> string
val init_file: tmp_dir:string -> Path.t -> string
val lock_file: tmp_dir:string -> Path.t -> string
val pids_file: tmp_dir:string -> Path.t -> string
val socket_file: tmp_dir:string -> Path.t -> string

val init: Path.t -> string list -> unit

Expand Down
2 changes: 2 additions & 0 deletions src/common/options.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type options = {
opt_no_flowlib: bool;
opt_module_name_mappers: (Str.regexp * string) list;
opt_munge_underscores: bool;
opt_temp_dir: string;
}

let error_flags opts = opts.opt_error_flags
Expand All @@ -38,3 +39,4 @@ let log_file opts = opts.opt_log_file
let root opts = opts.opt_root
let should_detach opts = opts.opt_should_detach
let should_indent_verbose opts = opts.opt_verbose_indent
let temp_dir opts = opts.opt_temp_dir
Loading

0 comments on commit fdc3ec3

Please sign in to comment.