From 2f2b5efdf699e4bc0723079dcd2f68a0fd44ce07 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 29 Feb 2012 14:58:57 +0000 Subject: [PATCH] Copy previous variables / eval result across file reloads. This makes functions like prev(), changes() etc behave more predictably when the file is reloaded. --- daemon/daemon.ml | 1 + lib/whenstate.ml | 30 ++++++++++++++++++++++++++++++ lib/whenstate.mli | 11 +++++++++++ tools/whenjobs.pod | 5 +++++ 4 files changed, 47 insertions(+) diff --git a/daemon/daemon.ml b/daemon/daemon.ml index ac0f1ff..925ad7e 100644 --- a/daemon/daemon.ml +++ b/daemon/daemon.ml @@ -192,6 +192,7 @@ and reload_file () = | exn -> failwith (Printexc.to_string exn) in + let s = Whenstate.copy_prev_state !state s in state := s; (* Re-evaluate all when jobs. *) diff --git a/lib/whenstate.ml b/lib/whenstate.ml index fe53a16..e3aad07 100644 --- a/lib/whenstate.ml +++ b/lib/whenstate.ml @@ -77,6 +77,36 @@ let set_variable t name value = let copy_variables old t = { t with variables = StringMap.fold StringMap.add old.variables t.variables } +let copy_prev_state old t = + let is_explicit jobname = + String.length jobname < 4 || String.sub jobname 0 4 <> "job$" + in + + let prev_variables = StringMap.fold ( + fun jobname _ map -> + try + if not (is_explicit jobname) then raise Not_found; + (* See if we can find a job with the same name in the old state. *) + let old_vars = StringMap.find jobname old.prev_variables in + StringMap.add jobname old_vars map + with + Not_found -> map + ) t.jobmap t.prev_variables in + + let prev_eval_result = StringMap.fold ( + fun jobname _ map -> + try + if not (is_explicit jobname) then raise Not_found; + (* See if we can find a job with the same name in the old state. *) + let old_result = StringMap.find jobname old.prev_eval_result in + StringMap.add jobname old_result map + with + Not_found -> map + ) t.jobmap t.prev_eval_result in + + { t with + prev_variables = prev_variables; prev_eval_result = prev_eval_result } + let get_variable t name = try StringMap.find name t.variables with Not_found -> T_string "" diff --git a/lib/whenstate.mli b/lib/whenstate.mli index 084cd49..15df0c1 100644 --- a/lib/whenstate.mli +++ b/lib/whenstate.mli @@ -47,6 +47,17 @@ val copy_variables : t -> t -> t the variables from [old_state], adding them to [current_state], returning a new state. Note the order of arguments. *) +val copy_prev_state : t -> t -> t +(** [copy_prev_state old_state current_state -> new_state] is an + obscure function used to make the [prev] function work predictably + across file reloads. Since a file reload creates a new state + object, it would normally "forget" that jobs had run previously, + so any job that used [prev], [changes] etc would run again + unnecessarily. This function copies the prev state, allowing us + to remember which jobs ran previously and the state of the + variables at that time, making these functions work predictably. + State is only copied for jobs that have explicit names. *) + val get_variable : t -> string -> Whenexpr.variable (** Return the value of a variable, when unknown variables defaulting to empty string. *) diff --git a/tools/whenjobs.pod b/tools/whenjobs.pod index fe3041b..0f777d4 100644 --- a/tools/whenjobs.pod +++ b/tools/whenjobs.pod @@ -403,6 +403,11 @@ that it had last time this when-job ran. If the when-job has not run yet, then this returns C<"">. +Job state is preserved across file reloads, but I for jobs that +are explicitly named. If you find that jobs using C, C +etc are running unnecessarily when the jobs file is edited or +uploaded, try giving the jobs an explicit name. + =item B I If the named variable has changed since this job last ran, then this -- 1.8.3.1