1 (* Various useful functions for handling Fedora packages & rebuilds. *)
9 let fedora_dir = Sys.getenv "HOME" // "d/fedora"
10 let fedora_repo pkg branch = fedora_dir // pkg // branch
11 let fedora_specfile pkg branch =
12 sprintf "%s/%s.spec" (fedora_repo pkg branch) pkg
14 (* Get the current version of a package. *)
15 let fedora_verrel pkg branch =
19 " (fedora_repo pkg branch)
21 (* Note most of these assume that the package is already cloned
22 * under ~/d/fedora using:
25 * fedpkg clone -B pkgname
28 (* Take a list of Fedora source packages and work out the dependencies
29 * (only within the list of source packages). Returns a list of
30 * (package, [list of deps...])
32 let dependencies branch source_packages =
33 (* For each source package, get the list of binary packages that it
34 * provides. XXX Not sure if this is totally technically correct, but
42 shlines "rpmspec -q --provides %s | awk '{print $1}'"
43 (fedora_specfile pkg branch) in
44 List.map (fun bin -> (bin, pkg)) provides
48 (* For each package, get the list of build requires that appear
49 * elsewhere in the list of packages.
51 let mem dep = List.mem dep source_packages in
56 shlines "rpmspec -q --buildrequires %s | awk '{print $1}'"
57 (fedora_specfile pkg branch) in
60 try List.assoc dep bin_to_src
61 with Not_found -> "xxx" (* filtered out in next line *)
63 let deps = Utils.sort_uniq (List.filter mem deps) in
64 (* eprintf "%s <- %s\n" pkg (String.concat " " deps); *)
68 let contains_substring substr str =
69 try ignore (String.find str substr); true
70 with Invalid_string -> false
72 (* Not helped by the fact that the 'koji' tool actively
73 * resists automation: RHBZ#760924.
76 (* Get build state. *)
77 let rec koji_build_state verrel =
78 fst (koji_build_state_task verrel)
80 (* Get build state and task ID. *)
81 and koji_build_state_task =
82 let state = Pcre.regexp "State: (\\w+)" in
83 let task_id = Pcre.regexp "Task: (\\d+)" in
84 let no_such_build = contains_substring "No such build" in
86 (* For speed, if a build is complete memoize it. *)
87 let key = sprintf "koji_build_complete_%s" verrel in
88 if memory_exists key then
91 let out = shout "timeout 120 koji buildinfo %s 2>&1 ||:" verrel in
92 if no_such_build out then
93 failwith (sprintf "koji_build_state_task: %s: no such build" verrel);
96 let subs = Pcre.exec ~rex:state out in
97 match Pcre.get_substring subs 1 with
98 | "BUILDING" -> `Building
99 | "COMPLETE" -> `Complete
100 | "DELETED" -> `Deleted
101 | "FAILED" -> `Failed
102 | "CANCELED" -> `Canceled
104 failwith (sprintf "koji_build_state_task: %s: unknown build state '%s'"
108 failwith (sprintf "koji_build_state_task: %s: no build state found"
112 let subs = Pcre.exec ~rex:task_id out in
113 Some (int_of_string (Pcre.get_substring subs 1))
117 if state == `Complete then
123 (* Perform a Koji build and wait until it finishes. If it fails,
124 * throw an exception.
127 let created_task = Pcre.regexp "Created task: (\\d+)" in
128 let name_or_service_not_known =
129 contains_substring "Name or service not known" in
130 let completed_successfully = contains_substring "completed successfully" in
131 let failed = contains_substring "FAILED" in
132 fun ?(wait = true) pkg branch ->
133 let repodir = fedora_repo pkg branch in
137 fedpkg build%s 2>&1 ||:
138 " repodir (if not wait then " --nowait" else "")
143 let subs = Pcre.exec ~rex:created_task out in
144 int_of_string (Pcre.get_substring subs 1)
146 failwith "could not find task ID in fedpkg build output" in
148 if name_or_service_not_known out then (
150 shout "cd %s && koji watch-task %d 2>&1 ||:" repodir task_id in
153 else if completed_successfully out then
155 else if failed out then (
156 eprintf "%s\n%!" out;
157 failwith "koji build failed"
160 failwith (sprintf "koji_build: unknown output: %s" out)
166 let successfully_waited = contains_substring "Successfully waited" in
168 let out = shout "koji wait-repo %s --build=%s 2>&1 ||:" target verrel in
169 if successfully_waited out then
172 failwith (sprintf "koji_wait_repo: unknown output: %s" out)