1 (* Various useful functions for handling Fedora packages & rebuilds. *)
10 (* Get the current version of a package. *)
11 let fedora_verrel pkg branch =
15 " (fedora_repo pkg branch)
17 (* Note most of these assume that the package is already cloned
18 * under ~/d/fedora using:
21 * fedpkg clone -B pkgname
24 (* Take a list of Fedora source packages and work out the dependencies
25 * (only within the list of source packages). Returns a list of
26 * (package, [list of deps...])
28 let dependencies branch source_packages =
29 (* For each source package, get the list of binary packages that it
30 * provides. XXX Not sure if this is totally technically correct, but
38 shlines "rpmspec -q --provides %s | awk '{print $1}'"
39 (fedora_specfile pkg branch) in
40 List.map (fun bin -> (bin, pkg)) provides
44 (* For each package, get the list of build requires that appear
45 * elsewhere in the list of packages.
47 let mem dep = List.mem dep source_packages in
52 shlines "rpmspec -q --buildrequires %s | awk '{print $1}'"
53 (fedora_specfile pkg branch) in
56 try List.assoc dep bin_to_src
57 with Not_found -> "xxx" (* filtered out in next line *)
59 let deps = Utils.sort_uniq (List.filter mem deps) in
60 (* eprintf "%s <- %s\n" pkg (String.concat " " deps); *)
64 let contains_substring substr str =
65 try ignore (String.find str substr); true
66 with Invalid_string -> false
68 (* Not helped by the fact that the 'koji' tool actively
69 * resists automation: RHBZ#760924.
72 (* XXX koji_build_state verrel: If you do a build and it fails, then
73 * do another build without bumping the release field, 'koji buildinfo'
74 * seems to always return the failed build, at least until the second
75 * build completes. This means the code below fails. Unclear how it
76 * can be fixed, but best to always bump the release to avoid the
80 (* Get build state. *)
81 let rec koji_build_state verrel =
82 fst (koji_build_state_task verrel)
84 (* Get build state and task ID. *)
85 and koji_build_state_task =
86 let state = Pcre.regexp "State: (\\w+)" in
87 let task_id = Pcre.regexp "Task: (\\d+)" in
88 let no_such_build = contains_substring "No such build" in
90 (* For speed, if a build is complete memoize it. *)
91 let key = sprintf "koji_build_complete_%s" verrel in
92 if memory_exists key then
95 let out = shout "timeout 120 koji buildinfo %s 2>&1 ||:" verrel in
96 if no_such_build out then
101 let subs = Pcre.exec ~rex:state out in
102 match Pcre.get_substring subs 1 with
103 | "BUILDING" -> `Building
104 | "COMPLETE" -> `Complete
105 | "DELETED" -> `Deleted
106 | "FAILED" -> `Failed
107 | "CANCELED" -> `Canceled
109 failwith (sprintf "koji_build_state_task: %s: unknown build state '%s'"
113 failwith (sprintf "koji_build_state_task: %s: no build state found"
117 let subs = Pcre.exec ~rex:task_id out in
118 Some (int_of_string (Pcre.get_substring subs 1))
122 if state == `Complete then
129 (* Perform a Koji build and wait until it finishes. If it fails,
130 * throw an exception.
133 let created_task = Pcre.regexp "Created task: (\\d+)" in
134 let name_or_service_not_known =
135 contains_substring "Name or service not known" in
136 let completed_successfully = contains_substring "completed successfully" in
137 let failed = contains_substring "FAILED" in
138 fun ?(wait = true) ?side_tag pkg branch ->
139 let repodir = fedora_repo pkg branch in
143 fedpkg build%s%s 2>&1
145 (if not wait then " --nowait" else "")
146 (match side_tag with None -> "" | Some t -> " --target " ^ t)
149 (* Just check the task was created. *)
150 if not (Pcre.pmatch ~rex:created_task out) then (
151 failwith "fedpkg build: build failed to start"
156 let subs = Pcre.exec ~rex:created_task out in
157 int_of_string (Pcre.get_substring subs 1)
159 failwith "could not find task ID in fedpkg build output" in
161 if name_or_service_not_known out then (
163 shout "cd %s && koji watch-task %d 2>&1 ||:" repodir task_id in
166 else if completed_successfully out then
168 else if failed out then (
169 failwith "koji build failed"
172 failwith (sprintf "koji_build: unknown output: %s" out)
178 let successfully_waited = contains_substring "Successfully waited" in
180 let out = shout "koji wait-repo %s --build=%s 2>&1 ||:" target verrel in
181 if successfully_waited out then
184 failwith (sprintf "koji_wait_repo: unknown output: %s" out)