2 * Copyright (C) 2012 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 variables : variables;
29 (*--- below here is "internal" state ---*)
31 jobmap : job StringMap.t; (* job name -> job structure *)
33 (* Map variable names to jobs which depend on that variable. This
34 * gives us a quick way to tell which jobs might need to be reevaluated
35 * when a variable is set.
37 dependencies : string list StringMap.t; (* variable -> list of job names *)
39 (* For each job, if it has run, we store the previous variables
40 * at that time. This is used to implement {i previous}, {i changes} etc.
42 prev_variables : variables StringMap.t; (* job name -> variables *)
44 (* For each job, if it has been evaluated before (see {!job_evaluate})
45 * then we store the previous result of evaluation here. This is
46 * used to implement edge-triggering.
48 prev_eval_result : bool StringMap.t; (* job name -> bool *)
52 variables = StringMap.empty;
54 jobmap = StringMap.empty;
55 dependencies = StringMap.empty;
56 prev_variables = StringMap.empty;
57 prev_eval_result = StringMap.empty;
61 let deps = dependencies_of_job job in
62 let dependencies' = List.fold_left (
64 let names = try StringMap.find d map with Not_found -> [] in
65 StringMap.add d (job.job_name :: names) map
66 ) t.dependencies deps in
70 jobmap = StringMap.add job.job_name job t.jobmap;
71 dependencies = dependencies'
74 let set_variable t name value =
75 { t with variables = StringMap.add name value t.variables }
77 let copy_variables old t =
78 { t with variables = StringMap.fold StringMap.add old.variables t.variables }
80 let get_variable t name =
81 try StringMap.find name t.variables with Not_found -> T_string ""
86 if value <> T_string "" then (name, value) :: xs else xs
89 let get_variable_names t =
91 fun name value xs -> if value <> T_string "" then name :: xs else xs
94 let nr_jobs t = List.length t.jobs
96 let get_dependencies t name =
97 let jobnames = try StringMap.find name t.dependencies with Not_found -> [] in
100 let j = StringMap.find jn t.jobmap in
101 (* If this asserts false, then there is a bug in {!add_job}. *)
102 assert (match j.job_cond with When_job _ -> true | _ -> false);
105 (* This should never happen. It would indicate some bug in the
106 * {!add_job} function.
112 List.filter (function { job_cond = When_job _ } -> true | _ -> false) t.jobs
114 let get_everyjobs t =
115 List.filter (function { job_cond = Every_job _ } -> true | _ -> false) t.jobs
117 let get_job t jobname =
118 try StringMap.find jobname t.jobmap with Not_found -> assert false
120 let evaluate_whenjob ?(onload = false) t job =
122 | { job_cond = Every_job _ } -> assert false
123 | { job_cond = When_job whenexpr; job_name = jobname } ->
125 try Some (StringMap.find jobname t.prev_variables)
126 with Not_found -> None in
129 eval_whenexpr_as_bool t.variables prev_variables onload whenexpr in
131 let prev_eval_result =
132 try Some (StringMap.find jobname t.prev_eval_result)
133 with Not_found -> None in
135 let t = { t with prev_eval_result =
136 StringMap.add jobname result t.prev_eval_result } in
138 (* Because jobs are edge-triggered, we're only interested in the
139 * case where the evaluation state changes from false -> true.
141 match prev_eval_result, result with
145 | Some true, false ->
149 | Some false, true ->
150 let t = { t with prev_variables =
151 StringMap.add jobname t.variables t.prev_variables } in