summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--buildmaster/blacklist.php63
-rw-r--r--buildmaster/build-list-links.php231
-rw-r--r--buildmaster/build-list.php583
-rw-r--r--buildmaster/build-slaves.php216
-rw-r--r--buildmaster/deletion-links.php246
-rw-r--r--buildmaster/dependencies.php190
-rw-r--r--buildmaster/gpg-keys.php48
-rw-r--r--buildmaster/index.php80
-rw-r--r--buildmaster/log.php93
-rw-r--r--buildmaster/mysql-issues.php183
-rw-r--r--buildmaster/statistics.php200
-rw-r--r--buildmaster/status.php144
-rw-r--r--buildmaster/to-delete.php77
-rw-r--r--buildmaster/todos.php97
-rw-r--r--init.php2
-rw-r--r--lib/.htaccess1
-rw-r--r--lib/format.php58
-rw-r--r--lib/helper.php195
-rw-r--r--lib/http.php17
-rw-r--r--lib/mysql-joins.php1438
-rw-r--r--lib/mysql.php90
-rw-r--r--lib/style.php74
-rw-r--r--mirrors/index.php135
-rw-r--r--mirrors/status.php84
-rw-r--r--packages/favicon.icobin0 -> 501 bytes
-rw-r--r--packages/index.php532
-rw-r--r--packages/pkginfo.php701
-rw-r--r--pkgapi/index.html5
-rw-r--r--pkgapi/pacman-i486.conf64
-rw-r--r--pkgapi/pacman-i686.conf64
-rw-r--r--pkgapi/pkginfo.php53
-rw-r--r--static/archnav32.pngbin0 -> 5508 bytes
-rw-r--r--static/archweb.css703
-rw-r--r--static/favicon.icobin0 -> 501 bytes
-rw-r--r--static/style.css1
36 files changed, 6669 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6bfe6b1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+log
diff --git a/buildmaster/blacklist.php b/buildmaster/blacklist.php
new file mode 100644
index 0000000..24247e8
--- /dev/null
+++ b/buildmaster/blacklist.php
@@ -0,0 +1,63 @@
+<?php
+require_once "../init.php";
+
+require_once BASE . "/lib/mysql.php";
+
+ $result = mysql_run_query(
+ "SELECT DISTINCT" .
+ " GROUP_CONCAT(`architectures`.`name`) AS `architectures`," .
+ "`package_sources`.`pkgbase`," .
+ "`build_assignments`.`is_black_listed` " .
+ "FROM `build_assignments` " .
+ mysql_join_build_assignments_architectures() .
+ mysql_join_build_assignments_package_sources() .
+ "WHERE `build_assignments`.`is_black_listed` IS NOT NULL " .
+ "GROUP BY CONCAT(to_base64(`package_sources`.`pkgbase`),\" - \",to_base64(`build_assignments`.`is_black_listed`)) " .
+ "ORDER BY `package_sources`.`pkgbase`"
+ );
+
+?>
+<html>
+ <head>
+ <title>Blacklisted packages</title>
+ <link rel="stylesheet" type="text/css" href="/static/style.css">
+ </head>
+ <body>
+<?php show_warning_on_offline_slave(); ?>
+ <table>
+ <tr>
+ <th>architectures</th>
+ <th>package</th>
+ <th>reason</th>
+ </tr>
+<?php
+
+if ($result -> num_rows > 0) {
+ while($row = $result->fetch_assoc()) {
+ print " <tr>\n";
+ print " <td>";
+ print $row["architectures"];
+ print "</td>\n";
+ print " <td>";
+ print $row["pkgbase"];
+ print "</td>\n";
+ print " <td>";
+ print preg_replace(
+ array (
+ "/FS32#(\\d+)/",
+ "/FS#(\\d+)/"
+ ),
+ array (
+ "<a href=\"https://bugs.archlinux32.org/index.php?do=details&task_id=$1\">$0</a>",
+ "<a href=\"https://bugs.archlinux.org/task/$1\">$0</a>"
+ ),
+ $row["is_black_listed"]
+ );
+ print "</td>\n";
+ print " </tr>\n";
+ }
+}
+?>
+ </table>
+ </body>
+</html>
diff --git a/buildmaster/build-list-links.php b/buildmaster/build-list-links.php
new file mode 100644
index 0000000..e3d2779
--- /dev/null
+++ b/buildmaster/build-list-links.php
@@ -0,0 +1,231 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+$edges = "";
+$knots = "";
+
+if (!isset($_GET["raw"]))
+ $limit = " LIMIT 150";
+
+$query =
+ "CREATE TEMPORARY TABLE `ba` (" .
+ "`id` BIGINT, " .
+ "`group` VARCHAR(256), " .
+ "`color` VARCHAR(7), " .
+ "UNIQUE KEY `id` (`id`), " .
+ "KEY `group` (`group`)" .
+ ")";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "INSERT IGNORE INTO `ba` (`id`,`color`)" .
+ " SELECT DISTINCT" .
+ " `build_assignments`.`id`," .
+ "IF(`build_assignments`.`is_broken`,\"#ff0000\",IF(`build_assignments`.`is_blocked` IS NULL,\"#000000\",\"#800000\"))" .
+ " FROM `binary_packages_in_repositories`" .
+ mysql_join_binary_packages_in_repositories_binary_packages() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_binary_packages_build_assignments() .
+ " WHERE `repositories`.`name`=\"build-list\"" .
+ $limit;
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "CREATE TEMPORARY TABLE `ba_copy` (" .
+ "`id` BIGINT, " .
+ "`group` VARCHAR(256), " .
+ "`color` VARCHAR(7), " .
+ "UNIQUE KEY `id` (`id`)" .
+ ")";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "INSERT IGNORE INTO `ba_copy` (`id`,`color`)" .
+ " SELECT `ba`.`id`,`ba`.`color`" .
+ " FROM `ba`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "CREATE TEMPORARY TABLE `ba_links` (" .
+ "`from` BIGINT, " .
+ "`to` BIGINT, " .
+ "`type` MEDIUMINT, " .
+ "UNIQUE KEY `content` (`from`,`to`,`type`)" .
+ ")";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "INSERT IGNORE INTO `ba_links` (`from`,`to`,`type`)" .
+ "SELECT `i_bp`.`build_assignment`," .
+ "`d_bp`.`build_assignment`," .
+ "`dependencies`.`dependency_type`" .
+ " FROM `ba`" .
+ mysql_join_build_assignments_binary_packages('ba','d_bp') .
+ mysql_join_binary_packages_dependencies('d_bp') .
+ mysql_join_dependencies_install_target_providers() .
+ mysql_join_install_target_providers_binary_packages('','i_bp') .
+ " JOIN `ba_copy` ON `i_bp`.`build_assignment`=`ba_copy`.`id`" .
+ " WHERE `d_bp`.`build_assignment`!=`i_bp`.`build_assignment`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "CREATE TEMPORARY TABLE `ba_links_copy` (" .
+ "`from` BIGINT, " .
+ "`to` BIGINT, " .
+ "`type` MEDIUMINT, " .
+ "UNIQUE KEY `content` (`from`,`to`,`type`)" .
+ ")";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "INSERT IGNORE INTO `ba_links_copy` (`from`,`to`,`type`)" .
+ " SELECT `ba_links`.`from`,`ba_links`.`to`,`ba_links`.`type` FROM `ba_links`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "UPDATE `ba`" .
+ " JOIN (" .
+ "SELECT" .
+ " `ba_copy`.`id`," .
+ "SHA2(" .
+ "GROUP_CONCAT(CONCAT(" .
+ "IFNULL(`ba_copy`.`color`,\"0\"),\":\"," .
+ "IFNULL(`ba_links`.`to`,\"0\"),\":\"," .
+ "IFNULL(`ba_links`.`type`,\"0\"),\":\"," .
+ "IFNULL(`ba_links_copy`.`from`,\"0\"),\":\"," .
+ "IFNULL(`ba_links_copy`.`type`,\"0\")" .
+ "))" .
+ ",256) AS `hash`" .
+ " FROM `ba_copy`" .
+ " LEFT JOIN `ba_links` ON `ba_links`.`from`=`ba_copy`.`id`" .
+ " LEFT JOIN `ba_links_copy` ON `ba_links_copy`.`to`=`ba_copy`.`id`" .
+ " GROUP BY `ba_copy`.`id`" .
+ ") AS `grouped_ba` ON `grouped_ba`.`id`=`ba`.`id`" .
+ " SET `ba`.`group`=`grouped_ba`.`hash`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "UPDATE `ba_copy`" .
+ " JOIN `ba` ON `ba`.`id`=`ba_copy`.`id`" .
+ " SET `ba_copy`.`group`=`ba`.`group`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+mysql_run_query($query);
+
+$query =
+ "SELECT MAX(`build_assignments`.`id`) AS `id`," .
+ "GROUP_CONCAT(CONCAT(" .
+ "`architectures`.`name`,\"/\"," .
+ "`package_sources`.`pkgbase`" .
+ ") SEPARATOR \",\n\") AS `name`," .
+ " `ba`.`color`" .
+ " FROM `ba`" .
+ " JOIN `build_assignments` ON `ba`.`id`=`build_assignments`.`id`" .
+ mysql_join_build_assignments_package_sources() .
+ mysql_join_build_assignments_architectures() .
+ " GROUP BY `ba`.`group`";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+$result = mysql_run_query($query);
+
+while ($row = $result->fetch_assoc())
+ $knots .=
+ "\"ba" .
+ $row["id"] .
+ "\" [label = \"" .
+ $row["name"] .
+ "\",
+ fontcolor = \"" .
+ $row["color"] .
+ "\"];\n";
+
+$query =
+ "SELECT MAX(`ba_links`.`to`) AS `dependent`," .
+ "`dependency_types`.`name` AS `dep_type`," .
+ "MAX(`ba_links`.`from`) AS `depending_on`" .
+ " FROM `ba_links`" .
+ " JOIN `dependency_types` ON `ba_links`.`type`=`dependency_types`.`id`" .
+ " JOIN `ba` ON `ba_links`.`from`=`ba`.`id`" .
+ " JOIN `ba_copy` ON `ba_links`.`to`=`ba_copy`.`id`" .
+ " GROUP BY CONCAT(`ba`.`group`,\"-\",`ba_copy`.`group`)";
+if (isset($_GET["raw"]))
+ print $query . ";\n";
+$result = mysql_run_query($query);
+
+while ($row = $result->fetch_assoc()) {
+ $edges .=
+ "\"ba" .
+ $row["depending_on"] .
+ "\" -> \"ba" .
+ $row["dependent"] .
+ "\" [color = \"";
+ switch ($row["dep_type"]) {
+ case "run":
+ $edges .= "#000000";
+ break;
+ case "make":
+ $edges .= "#0000ff";
+ break;
+ case "link":
+ $edges .= "#008000";
+ break;
+ case "check":
+ $edges .= "#000080";
+ break;
+ default:
+ $edges .= "#ff00ff";
+ }
+ $edges .=
+ "#000080";
+ $edges .=
+ "\"];\n";
+}
+
+if (isset($_GET["raw"])) {
+ print
+ "digraph dependencies {\n" .
+ "rankdir=LR;\n" .
+ "fontname=dejavu;\n" .
+ $knots .
+ $edges .
+ "}\n";
+} else {
+ $input_file = tempnam("/tmp", "build-list-links.");
+
+ $handle = fopen($input_file,"w");
+ fwrite($handle,
+ "digraph dependencies {\n" .
+ "rankdir=LR;\n" .
+ "fontname=dejavu;\n" .
+ $knots .
+ $edges .
+ "}\n"
+ );
+ fclose($handle);
+
+ header ("Content-type: image/png");
+ passthru(
+ "timeout 30 dot -Tpng -o/dev/stdout " . $input_file
+ );
+
+ unlink($input_file);
+}
diff --git a/buildmaster/build-list.php b/buildmaster/build-list.php
new file mode 100644
index 0000000..79313e4
--- /dev/null
+++ b/buildmaster/build-list.php
@@ -0,0 +1,583 @@
+<?php
+require_once "../init.php";
+
+require_once BASE . "/lib/helper.php";
+require_once BASE . "/lib/mysql.php";
+require_once BASE . "/lib/style.php";
+
+$filter = " WHERE ";
+
+if (isset($_GET["invq"]))
+ $filter .= "NOT ";
+
+if (isset($_GET["q"]))
+ $filter .= "`ba_q`.`pkgbase` LIKE from_base64(\"".base64_encode("%".$_GET["q"]."%")."\")";
+else
+ $filter .= "1";
+
+$multi_select_search_criteria = array(
+ "arch" => array(
+ "name" => "arch",
+ "title" => "CPU architecture",
+ "label" => "Arch",
+ "source_table" => "architectures",
+ "query_pre" => "`ba_q`.`arch` IN (",
+ "query_in_pre" => "\"",
+ "query_in_post" => "\",",
+ "query_post" => "\"\")",
+ "values" => array()
+ ),
+ "repo" => array(
+ "name" => "repo",
+ "title" => "Repository",
+ "label" => "Repo",
+ "source_table" => "upstream_repositories",
+ "query_pre" => "`ba_q`.`package_repository` IN (",
+ "query_in_pre" => "\"",
+ "query_in_post" => "\",",
+ "query_post" => "\"\")",
+ "values" => array()
+ ),
+ "failures" => array(
+ "name" => "failures",
+ "title" => "Fail Reasons",
+ "label" => "Failures",
+ "source_table" => "fail_reasons",
+ "query_pre" => "(0",
+ "query_in_pre" => " OR `fr_q`.`fail_reasons_raw` LIKE \"%,",
+ "query_in_post" => ",%\"",
+ "query_post" => ")",
+ "values" => array()
+ )
+);
+
+foreach ( $multi_select_search_criteria as $criterium => $content ) {
+ $result = mysql_run_query(
+ "SELECT `name` FROM `" . $content["source_table"] . "` ORDER BY `name`"
+ );
+ while ($row = $result -> fetch_assoc())
+ $multi_select_search_criteria[$criterium]["values"][] = $row["name"];
+}
+
+foreach ( $multi_select_search_criteria as $criterium ) {
+ if (isset($_GET[$criterium["name"]])) {
+ $filter .= " AND " . $criterium["query_pre"];
+ foreach ($criterium["values"] as $value)
+ if (strpos("&" . $_SERVER["QUERY_STRING"] . "&", "&" . $criterium["name"] . "=" . urlencode($value) . "&") !== false)
+ $filter .= $criterium["query_in_pre"] . $value . $criterium["query_in_post"];
+ $filter .= $criterium["query_post"];
+ }
+}
+$single_select_search_criteria = array(
+ "broken" => array(
+ "name" => "broken",
+ "label" => "Is Broken",
+ "title" => "is broken",
+ "options" => array(
+ "All" => "1",
+ "Broken" => "(`ba_q`.`is_broken` OR `ba_q`.`is_blocked` IS NOT NULL)",
+ "Not Broken" => "NOT (`ba_q`.`is_broken` OR `ba_q`.`is_blocked` IS NOT NULL)"
+ )
+ ),
+ "next" => array(
+ "name" => "next",
+ "label" => "Can Be Built",
+ "title" => "can be built",
+ "options" => array(
+ "All" => "1",
+ "Can" => "(`l_q`.`loops` IS NOT NULL OR (`rd_q`.`run_dependencies_pending` IS NULL AND `md_q`.`make_dependencies_pending` IS NULL))",
+ "Can't" => "NOT (`l_q`.`loops` IS NOT NULL OR (`rd_q`.`run_dependencies_pending` IS NULL AND `md_q`.`make_dependencies_pending` IS NULL))"
+ )
+ )
+);
+
+foreach ($single_select_search_criteria as $criterium)
+ if (isset($_GET[$criterium["name"]]) &&
+ isset($criterium["options"][$_GET[$criterium["name"]]]))
+ $filter .= " AND " . $criterium["options"][$_GET[$criterium["name"]]];
+
+$columns = array(
+ "priority" => array(
+ "label" => "Priority",
+ "mysql_name" => "priority",
+ "mysql_query" => "`ba_q`.`priority`",
+ "sort" => "priority",
+ "title" => "priority"
+ ),
+ "deps" => array(
+ "label" => "Deps",
+ "mysql_name" => "dependencies_pending",
+ "mysql_query" => "IFNULL(`rd_q`.`run_dependencies_pending`,0)+IFNULL(`md_q`.`make_dependencies_pending`,0)",
+ "sort" => "deps",
+ "title" => "number of dependencies on the build-list"
+ ),
+ "arch" => array(
+ "label" => "Arch",
+ "mysql_name" => "arch",
+ "mysql_query" => "`ba_q`.`arch`",
+ "sort" => "arch",
+ "title" => "arch"
+ ),
+ "pkgbase" => array(
+ "label" => "Package",
+ "mysql_name" => "pkgbase_print",
+ "mysql_query" =>
+ "CONCAT(" .
+ "\"<a href=\\\"/buildmaster/dependencies.php?b=\"," .
+ mysql_url_encode("`ba_q`.`pkgbase`") . "," .
+ "\"&a=\"," .
+ mysql_url_encode("`ba_q`.`arch`") . ",".
+ "\"&r=build-list\\\">\"," .
+ "`ba_q`.`pkgbase`," .
+ "\"</a>\"" .
+ ")",
+ "sort" => "pkgbase",
+ "title" => "package"
+ ),
+ "git_rev" => array(
+ "label" => "Git Revision",
+ "mysql_name" => "git_revision_print",
+ "mysql_query" =>
+ "IF(`ba_q`.`uses_upstream`," .
+ "CONCAT(" .
+ "\"<a href=\\\"https://git.archlinux.org/svntogit/\"," .
+ mysql_url_encode("`ba_q`.`git_repository`") . "," .
+ "\".git/tree/\"," .
+ mysql_url_encode("`ba_q`.`pkgbase`") . "," .
+ "\"/repos/\"," .
+ mysql_url_encode("`ba_q`.`package_repository`") . "," .
+ "\"-\"," .
+ mysql_url_encode("IF(`ba_q`.`arch`=\"any\",\"any\",\"x86_64\")") . "," .
+ "\"?id=\"," .
+ mysql_url_encode("`ba_q`.`git_revision`") . "," .
+ "\"\\\">\"," .
+ "`ba_q`.`git_revision`," .
+ "\"</a>\"" .
+ ")," .
+ "`ba_q`.`git_revision`" .
+ ")",
+ "sort" => "git_rev",
+ "title" => "revision hash of upstream git repository"
+ ),
+ "mod_git_rev" => array(
+ "label" => "Modification Git Revision",
+ "mysql_name" => "mod_git_revision_print",
+ "mysql_query" =>
+ "IF(`ba_q`.`uses_modification`," .
+ "CONCAT(" .
+ "\"<a href=\\\"" .
+ git_url(
+ "packages",
+ "tree",
+ "\"," . mysql_url_encode("`ba_q`.`mod_git_revision`") . ",\"",
+ "\"," . mysql_url_encode("`ba_q`.`package_repository`") . ",\"/\"," .
+ mysql_url_encode("`ba_q`.`pkgbase`") . ",\"",
+ null,
+ true
+ ) .
+ "\\\">\"," .
+ "`ba_q`.`mod_git_revision`," .
+ "\"</a>\"" .
+ ")," .
+ "`ba_q`.`mod_git_revision`" .
+ ")" ,
+ "sort" => "mod_git_rev",
+ "title" => "revision hash of modification git repository"
+ ),
+ "repo" => array(
+ "label" => "Repository",
+ "mysql_name" => "package_repository",
+ "mysql_query" => "`ba_q`.`package_repository`",
+ "sort" => "repo",
+ "title" => "package repository"
+ ),
+ "commit_time" => array(
+ "label" => "Commit Time",
+ "mysql_name" => "commit_time",
+ "mysql_query" => "`ba_q`.`commit_time`",
+ "sort" => "commit_time",
+ "title" => "commit time of the source"
+ ),
+ "trials" => array(
+ "label" => "Compilations",
+ "mysql_name" => "trials",
+ "mysql_query" => "IFNULL(`t_q`.`trials`,0)",
+ "sort" => "trials",
+ "title" => "number of compilations"
+ ),
+ "loops" => array(
+ "label" => "Loops",
+ "mysql_name" => "loops",
+ "mysql_query" => "IFNULL(`l_q`.`loops`,0)",
+ "sort" => "loops",
+ "title" => "number of loops"
+ ),
+ "failure" => array(
+ "label" => "Failures",
+ "mysql_name" => "fail_reasons",
+ "mysql_query" => "`fr_q`.`fail_reasons_print`",
+ "sort" => "failure",
+ "title" => "reason of build failure"
+ ),
+ "blocked" => array(
+ "label" => "Blocked",
+ "mysql_name" => "is_blocked",
+ "mysql_query" => "`ba_q`.`is_blocked`",
+ "sort" => "blocked",
+ "title" => "block reason"
+ ),
+ "build_slave" => array(
+ "label" => "Build Slave",
+ "mysql_name" => "build_slave",
+ "mysql_query" => "`bs_q`.`build_slave`",
+ "sort" => "build_slave",
+ "title" => "whom it is handed out to"
+ )
+);
+
+if (!isset($_GET["sort"]))
+ $_GET["sort"]="trials";
+
+if (substr($_GET["sort"],0,1) == "-") {
+ $direction = " DESC";
+ $sort = substr($_GET["sort"],1);
+} else {
+ $direction = " ASC";
+ $sort = $_GET["sort"];
+}
+
+if (isset($columns[$sort]))
+ $order = "IFNULL(" . $columns[$sort]["mysql_name"] . ",0) " . $direction . ",";
+else
+ $order = "";
+
+function combine_fields($cln) {
+ return $cln["mysql_query"] . " AS `" . $cln["mysql_name"] . "`";
+}
+
+$result = mysql_run_query(
+ "SELECT " .
+ implode(",",array_map("combine_fields",$columns)) .
+ " FROM" .
+ " (" .
+ "SELECT DISTINCT " .
+ "`build_assignments`.`id`," .
+ "`build_assignments`.`is_blocked`," .
+ "`build_assignments`.`is_broken`," .
+ "`build_assignments`.`priority`," .
+ "`package_sources`.`pkgbase`," .
+ "`package_sources`.`git_revision`," .
+ "`package_sources`.`mod_git_revision`," .
+ "`package_sources`.`uses_upstream`," .
+ "`package_sources`.`uses_modification`," .
+ "`package_sources`.`commit_time`," .
+ "`upstream_repositories`.`name` AS `package_repository`," .
+ "`git_repositories`.`name` AS `git_repository`," .
+ "`architectures`.`name` AS `arch`" .
+ " FROM `build_assignments`" .
+ mysql_join_build_assignments_architectures() .
+ mysql_join_build_assignments_package_sources() .
+ mysql_join_package_sources_upstream_repositories() .
+ mysql_join_upstream_repositories_git_repositories() .
+ mysql_join_build_assignments_binary_packages() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " WHERE `repositories`.`name`=\"build-list\"" .
+ ") AS `ba_q`".
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`dependent_bp`.`build_assignment`," .
+ "COUNT(DISTINCT `dependency_bp`.`build_assignment`) AS `run_dependencies_pending`" .
+ " FROM `binary_packages` AS `dependent_bp`" .
+ mysql_join_binary_packages_dependencies('dependent_bp') .
+ mysql_join_dependencies_dependency_types() .
+ mysql_join_dependencies_install_target_providers() .
+ mysql_join_install_target_providers_binary_packages('','dependency_bp') .
+ mysql_join_binary_packages_binary_packages_in_repositories('dependency_bp') .
+ mysql_join_binary_packages_build_assignments('dependent_bp','dependent_ba') .
+ mysql_join_binary_packages_build_assignments('dependency_bp','dependency_ba') .
+ " JOIN `architecture_compatibilities` AS `ac_a`".
+ " ON `ac_a`.`fully_compatible`".
+ " AND `ac_a`.`built_for`=`dependency_ba`.`architecture`".
+ " JOIN `architecture_compatibilities` AS `ac_b`".
+ " ON `ac_b`.`fully_compatible`".
+ " AND `ac_b`.`built_for`=`dependent_ba`.`architecture`".
+ " AND `ac_b`.`runs_on`=`ac_a`.`runs_on`".
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " WHERE `dependency_bp`.`build_assignment` != `dependent_bp`.`build_assignment`" .
+ " AND `dependency_types`.`relevant_for_building`" .
+ " AND `dependency_types`.`relevant_for_binary_packages`" .
+ " AND `repositories`.`name`=\"build-list\"" .
+ " GROUP BY `dependent_bp`.`build_assignment`" .
+ ") AS `rd_q` ON `rd_q`.`build_assignment`=`ba_q`.`id`" .
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`dependent_bp`.`build_assignment`," .
+ "COUNT(DISTINCT `dependencies`.`id`) AS `make_dependencies_pending`" .
+ " FROM `binary_packages` AS `dependent_bp`" .
+ mysql_join_binary_packages_dependencies('dependent_bp') .
+ mysql_join_dependencies_dependency_types() .
+ mysql_join_binary_packages_build_assignments('dependent_bp','dependent_ba') .
+ " JOIN `architecture_compatibilities` AS `ac_b`".
+ " ON `ac_b`.`fully_compatible`".
+ " AND `ac_b`.`built_for`=`dependent_ba`.`architecture`".
+ " WHERE NOT EXISTS(" .
+ "SELECT 1 FROM `install_target_providers`" .
+ mysql_join_install_target_providers_binary_packages('','dependency_bp') .
+ mysql_join_binary_packages_binary_packages_in_repositories('dependency_bp','dependency_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('dependency_bpir') .
+ mysql_join_binary_packages_build_assignments('dependency_bp','dependency_ba') .
+ " JOIN `architecture_compatibilities` AS `ac_a`".
+ " ON `ac_a`.`fully_compatible`".
+ " AND `ac_a`.`built_for`=`dependency_ba`.`architecture`".
+ " WHERE `install_target_providers`.`install_target` = `dependencies`.`depending_on`" .
+ " AND `repositories`.`is_on_master_mirror`" .
+ " AND `ac_b`.`runs_on`=`ac_a`.`runs_on`".
+ ")" .
+ " AND `dependency_types`.`relevant_for_building`" .
+ " AND NOT `dependency_types`.`relevant_for_binary_packages`" .
+ " GROUP BY `dependent_bp`.`build_assignment`" .
+ ") AS `md_q` ON `md_q`.`build_assignment`=`ba_q`.`id`" .
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`build_dependency_loops`.`build_assignment`," .
+ "COUNT(1) AS `loops`" .
+ " FROM `build_dependency_loops`" .
+ " GROUP BY `build_dependency_loops`.`build_assignment`" .
+ ") AS `l_q` ON `l_q`.`build_assignment`=`ba_q`.`id`" .
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`rfb`.`build_assignment`," .
+ "GROUP_CONCAT(" .
+ "CONCAT(" .
+ "\"<a href=\\\"https://buildmaster.archlinux32.org/build-logs/error/\"," .
+ mysql_url_encode("`rfb`.`log_file`") . "," .
+ "\"\\\">\"," .
+ "`fail_reasons`.`name`," .
+ "\"</a>\"" .
+ ")" .
+ " ORDER BY `fail_reasons`.`name`" .
+ ") AS `fail_reasons_print`," .
+ "CONCAT(" .
+ "\",\"," .
+ "GROUP_CONCAT(" .
+ "`fail_reasons`.`name`" .
+ ")," .
+ "\",\"" .
+ ") AS `fail_reasons_raw`" .
+ " FROM (" .
+ "SELECT " .
+ "`failed_builds`.`build_assignment`," .
+ "`failed_builds`.`reason`," .
+ "MAX(`failed_builds`.`date`) AS `max_date`" .
+ " FROM `failed_builds`" .
+ " GROUP BY `failed_builds`.`build_assignment`,`failed_builds`.`reason`" .
+ ") AS `cfb`" .
+ " JOIN" .
+ " (" .
+ "SELECT DISTINCT " .
+ "`failed_builds`.*" .
+ " FROM `failed_builds`" .
+ " GROUP BY `failed_builds`.`build_assignment`,`failed_builds`.`reason`,`failed_builds`.`date`" .
+ ") AS `rfb`" .
+ " ON `cfb`.`build_assignment`=`rfb`.`build_assignment`" .
+ " AND `cfb`.`reason`=`rfb`.`reason`" .
+ " AND `cfb`.`max_date`=`rfb`.`date`" .
+ mysql_join_failed_builds_fail_reasons('rfb') .
+ " GROUP BY `rfb`.`build_assignment`" .
+ ") AS `fr_q` ON `fr_q`.`build_assignment`=`ba_q`.`id`" .
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`failed_builds`.`build_assignment`," .
+ "COUNT(`failed_builds`.`id`) AS `trials`" .
+ " FROM `failed_builds`" .
+ " GROUP BY `failed_builds`.`build_assignment`" .
+ ") AS `t_q` ON `t_q`.`build_assignment`=`ba_q`.`id`" .
+ " LEFT JOIN" .
+ " (" .
+ "SELECT " .
+ "`build_slaves`.`currently_building`," .
+ "GROUP_CONCAT(`build_slaves`.`name`) AS `build_slave`" .
+ " FROM `build_slaves`" .
+ " GROUP BY `build_slaves`.`currently_building`" .
+ ") AS `bs_q` ON `bs_q`.`currently_building`=`ba_q`.`id`" .
+ $filter .
+ " ORDER BY " . $order . "`trials` " . $direction . ",`dependencies_pending` " . $direction . ",`is_blocked` " . $direction . ",`pkgbase` " . $direction
+);
+
+$count = 0;
+
+while($row = $result->fetch_assoc()) {
+
+ foreach ($row as $name => $value) {
+ if (!isset($row[$name]))
+ $rows[$count][$name] = "&nbsp;";
+ elseif ($name == "is_blocked")
+ $rows[$count][$name] = preg_replace(
+ array (
+ "/FS32#(\\d+)/",
+ "/FS#(\\d+)/"
+ ),
+ array (
+ "<a href=\"https://bugs.archlinux32.org/index.php?do=details&task_id=$1\">$0</a>",
+ "<a href=\"https://bugs.archlinux.org/task/$1\">$0</a>"
+ ),
+ $value
+ );
+ else
+ $rows[$count][$name] = $value;
+ }
+
+ $count++;
+}
+
+print_header("List of Package Builds");
+
+?>
+ <a href="https://buildmaster.archlinux32.org/build-logs/">build logs</a>
+ <div id="pkglist-search" class="box filter-criteria">
+ <h2>Package Build Search</h2>
+ <form id="pkg-search" method="get" action="/buildmaster/build-list.php">
+ <p><input id="id_sort" name="sort" type="hidden" /></p>
+ <fieldset>
+ <legend>Enter search criteria</legend>
+<?php
+
+foreach ($multi_select_search_criteria as $criterium) {
+ print " <div>\n";
+ print " <label for=\"id_" . $criterium["name"] . "\" title=\"Limit results to a specific " . $criterium["title"] . "\">";
+ print $criterium["label"];
+ print "</label>\n";
+ print " <select multiple=\"multiple\" id=\"id_" . $criterium["name"] . "\" name=\"" . $criterium["name"] . "\">\n";
+ foreach ($criterium["values"] as $value) {
+ print " <option value=\"" . $value . "\"";
+ if (strpos( "&" . $_SERVER["QUERY_STRING"] . "&", "&" . $criterium["name"] . "=" . urlencode($value) . "&") !== false)
+ print " selected=\"selected\"";
+ print ">" . $value . "</option>\n";
+ }
+ print " </select>\n";
+ print " </div>\n";
+}
+
+?>
+ <div>
+ <label for="id_q" title="Enter keywords as desired">Keywords</label>
+ <input id="id_q" name="q" size="30" type="text" <?php
+if (isset($_GET["q"]))
+ print "value=\"".$_GET["q"]."\"";
+?>/><br>
+ <input id="id_invq" name="invq" type="checkbox" value="invq" title="list all non-matching package builds"<?php
+if (isset($_GET["invq"]))
+ print " checked";
+?>>
+ invert match
+ </div>
+<?php
+
+foreach ($single_select_search_criteria as $criterium) {
+ print " <div>\n";
+ print " <label for=\"id_";
+ print $criterium["name"];
+ print "\" title=\"Limit results based on ";
+ print $criterium["title"];
+ print "\">";
+ print $criterium["label"];
+ print "</label><select id=\"id_";
+ print $criterium["name"];
+ print "\" name=\"";
+ print $criterium["name"];
+ print "\">\n";
+ foreach ($criterium["options"] as $label => $option) {
+ print " <option value=\"";
+ if ($label != "All")
+ print $label;
+ print "\"";
+ if (array_key_exists($criterium["name"],$_GET) && ($_GET[$criterium["name"]]==$label))
+ print " selected=\"selected\"";
+ print ">" . $label . "</option>\n";
+ }
+ print " </select>\n";
+ print " </div>\n";
+}
+?>
+ <div>
+ <label>&nbsp;</label>
+ <input title="Search for packages using this criteria" type="submit" value="Search">
+ </div>
+ </fieldset>
+ </form>
+ </div>
+<?php
+
+if ($count > 0) {
+
+?>
+ <div id="pkglist-results" class="box">
+ <table class="results">
+ <thead>
+ <tr>
+<?php
+
+foreach ($columns as $column) {
+
+ print " <th>\n";
+ print " <a href=\"?";
+ print substr(
+ str_replace(
+ "&sort=".$_GET["sort"]."&",
+ "&",
+ "&" . $_SERVER["QUERY_STRING"] . "&"
+ ),
+ 1
+ ) . "sort=";
+ if ($column["sort"] == $_GET["sort"])
+ print "-";
+ print $column["sort"] . "\" ";
+ print "title=\"Sort build assignments by " . $column["title"] . "\">\n";
+ print " " . $column["label"] . "\n";
+ print " </a>\n";
+ print " </th>\n";
+
+}
+
+?>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+
+$oddity = "odd";
+
+foreach($rows as $row) {
+
+ print " <tr class=\"" . $oddity . "\">\n";
+
+ foreach ($columns as $column) {
+
+ print " <td>\n";
+ print " " . $row[$column["mysql_name"]] . "\n";
+ print " </td>\n";
+
+ }
+ print " </tr>\n";
+
+ if ($oddity == "odd" )
+ $oddity = "even";
+ else
+ $oddity = "odd";
+
+}
+
+?>
+ </tbody>
+ </table>
+ </div>
+<?php
+}
+
+print_footer();
diff --git a/buildmaster/build-slaves.php b/buildmaster/build-slaves.php
new file mode 100644
index 0000000..36a1522
--- /dev/null
+++ b/buildmaster/build-slaves.php
@@ -0,0 +1,216 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/style.php";
+require_once BASE . "/lib/mysql.php";
+
+$columns = array(
+ "name" => array(
+ "label" => "name",
+ "mysql_name" => "name",
+ "mysql_query" => "`build_slaves`.`name`",
+ "sort" => "name",
+ "title" => "name"
+ ),
+ "operator" => array(
+ "label" => "operator",
+ "mysql_name" => "operator",
+ "mysql_query" => "`persons`.`name`",
+ "sort" => "operator",
+ "title" => "operator"
+ ),
+ "currently_building" => array(
+ "label" => "currently building",
+ "mysql_name" => "cb",
+ "mysql_query" => "`ba_q`.`cb`",
+ "mysql_ba_q_name" => "cb",
+ "mysql_ba_q_query" => "CONCAT(`architectures`.`name`,\"/\",`package_sources`.`pkgbase`)",
+ "sort" => "currently_building",
+ "title" => "pkgbase of currently building package"
+ ),
+ "last_connection" => array(
+ "label" => "last connection",
+ "mysql_name" => "lc",
+ "mysql_query" => "`sl_q`.`lc`",
+ "mysql_sl_q_name" => "lc",
+ "mysql_sl_q_query" => "MAX(`ssh_log`.`date`)",
+ "sort" => "last_connection",
+ "title" => "time of last connection"
+ ),
+ "building_since" => array(
+ "label" => "building since",
+ "mysql_name" => "bs",
+ "mysql_query" => "`sl_q`.`bs`",
+ "mysql_sl_q_name" => "bs",
+ "mysql_sl_q_query" => "MAX(IF(`ssh_log`.`action`=\"get-assignment\",`ssh_log`.`date`,NULL))",
+ "sort" => "building_since",
+ "title" => "start of build"
+ ),
+ "trials" => array(
+ "label" => "trials",
+ "mysql_name" => "trials",
+ "mysql_query" => "`build_slaves`.`trials`",
+ "sort" => "trials",
+ "title" => "number of trials"
+ ),
+ "logged_lines" => array(
+ "label" => "logged lines",
+ "mysql_name" => "ll",
+ "mysql_query" => "`build_slaves`.`logged_lines`",
+ "sort" => "logged_lines",
+ "title" => "number of logged lines so far"
+ ),
+ "last_action" => array(
+ "label" => "last action",
+ "mysql_name" => "la",
+ "mysql_query" => "`build_slaves`.`last_action`",
+ "sort" => "last_action",
+ "title" => "last action"
+ )
+);
+
+if (!isset($_GET["sort"]))
+ $_GET["sort"]="-last_connection";
+
+if (substr($_GET["sort"],0,1) == "-") {
+ $direction = " DESC";
+ $sort = substr($_GET["sort"],1);
+} else {
+ $direction = " ASC";
+ $sort = $_GET["sort"];
+}
+
+if (isset($columns[$sort]))
+ $order = "IFNULL(`sub_query`.`" . $columns[$sort]["mysql_name"] . "`,0) " . $direction . ",";
+else
+ $order = "";
+
+function combine_fields($cln) {
+ return $cln["mysql_query"] . " AS `" . $cln["mysql_name"] . "`";
+}
+
+function combine_ba_q_fields($cln) {
+ if (isset($cln["mysql_ba_q_query"]) && isset($cln["mysql_ba_q_name"]))
+ return $cln["mysql_ba_q_query"] . " AS `" . $cln["mysql_ba_q_name"] . "`";
+}
+
+function combine_sl_q_fields($cln) {
+ if (isset($cln["mysql_sl_q_query"]) && isset($cln["mysql_sl_q_name"]))
+ return $cln["mysql_sl_q_query"] . " AS `" . $cln["mysql_sl_q_name"] . "`";
+}
+
+function non_empty($val) {
+ return ! empty($val);
+}
+
+$result = mysql_run_query(
+ "SELECT `sub_query`.* FROM (" .
+ "SELECT " .
+ implode(",",array_map("combine_fields",$columns)) .
+ " FROM `build_slaves`" .
+ mysql_join_build_slaves_ssh_keys() .
+ mysql_join_ssh_keys_persons().
+
+ " LEFT JOIN (" .
+ "SELECT " .
+ "`build_assignments`.`id` AS `id`," .
+ implode(",",array_filter(array_map("combine_ba_q_fields",$columns),"non_empty")) .
+ " FROM `build_assignments`" .
+ mysql_join_build_assignments_package_sources() .
+ mysql_join_build_assignments_architectures() .
+ ") AS `ba_q`" .
+ " ON `ba_q`.`id`=`build_slaves`.`currently_building`" .
+
+ " LEFT JOIN (" .
+ "SELECT " .
+ "`ssh_log`.`build_slave` AS `build_slave`," .
+ implode(",",array_filter(array_map("combine_sl_q_fields",$columns),"non_empty")) .
+ " FROM `ssh_log`" .
+ " WHERE `ssh_log`.`date`>=ADDDATE(NOW(),\"-5 00:00:00\")" .
+ " GROUP BY `ssh_log`.`build_slave`" .
+ ") AS `sl_q`" .
+ " ON `sl_q`.`build_slave`=`build_slaves`.`id`" .
+ ") AS `sub_query`" .
+ " ORDER BY " . $order . "`sub_query`.`name`"
+);
+
+$count = 0;
+
+while($row = $result->fetch_assoc()) {
+
+ foreach ($row as $name => $value) {
+ if (!isset($row[$name]))
+ $rows[$count][$name] = "&nbsp;";
+ else
+ $rows[$count][$name] = $value;
+ }
+ $rows[$count]["name"] =
+ "<a href=\"/buildmaster/log.php?show=ssh&slave=" .
+ $row["name"] .
+ "\">" .
+ $row["name"] .
+ "</a>";
+
+ $count++;
+}
+
+print_header("List of Build Slaves");
+
+if ($count > 0) {
+
+?>
+ <div id="buildslaveslist-results" class="box">
+ <table class="results">
+ <thead>
+ <tr>
+<?php
+
+foreach ($columns as $column) {
+
+ print " <th>\n";
+ print " <a href=\"?sort=";
+ if ($column["sort"] == $_GET["sort"])
+ print "-";
+ print $column["sort"] . "\" ";
+ print "title=\"Sort build assignments by " . $column["title"] . "\">\n";
+ print " " . $column["label"] . "\n";
+ print " </a>\n";
+ print " </th>\n";
+
+}
+
+?>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+
+$oddity = "odd";
+
+foreach($rows as $row) {
+
+ print " <tr class=\"" . $oddity . "\">\n";
+
+ foreach ($columns as $column) {
+
+ print " <td>\n";
+ print " " . $row[$column["mysql_name"]] . "\n";
+ print " </td>\n";
+
+ }
+ print " </tr>\n";
+
+ if ($oddity == "odd" )
+ $oddity = "even";
+ else
+ $oddity = "odd";
+
+}
+
+?>
+ </tbody>
+ </table>
+ </div>
+<?php
+}
+
+print_footer();
diff --git a/buildmaster/deletion-links.php b/buildmaster/deletion-links.php
new file mode 100644
index 0000000..066bf8d
--- /dev/null
+++ b/buildmaster/deletion-links.php
@@ -0,0 +1,246 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+$edges = "";
+$knots = "";
+
+if (isset($_GET["show_all"]))
+ $available_filter = " LEFT";
+else
+ $available_filter = "";
+
+if (isset($_GET["pkgname"]))
+ $filter = " AND `binary_packages`.`pkgname` REGEXP from_base64(\"" . base64_encode($_GET["pkgname"]) . "\")";
+else
+ $filter = "";
+
+$memcache = new Memcache;
+$memcache->connect('localhost', 11211) or die ('Memcached Connection Error');
+$available_upstream_packages = $memcache->get('available_upstream_packages');
+if ($available_upstream_packages === false) {
+ $available_upstream_packages = explode(
+ "\n",
+ shell_exec(
+ "find /var/lib/pacman/ -name '*.db' -exec tar -tzf {} \; " .
+ "| sed -n 's,-[^-]\+-[^-]\+/$,,;T;p' " .
+ "| sort -u"
+ )
+ );
+ $memcache->set('available_upstream_packages',$available_upstream_packages,0,1800);
+}
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `available` (" .
+ "`pkgname` VARCHAR(88), " .
+ "UNIQUE KEY `name` (`pkgname`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT INTO `available` (`pkgname`) VALUES (\"" .
+ implode(array_map("base64_encode", $available_upstream_packages), "\"),(\"") .
+ "\")"
+);
+
+mysql_run_query(
+ "DELETE FROM `available` WHERE `available`.`pkgname`=\"\""
+);
+
+mysql_run_query(
+ "UPDATE `available` SET `available`.`pkgname`=from_base64(`available`.`pkgname`)"
+);
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `d_bpir` (" .
+ "`id` BIGINT, " .
+ "`group` VARCHAR(256), " .
+ "`color` VARCHAR(7), " .
+ "UNIQUE KEY `id` (`id`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `d_bpir` (`id`,`color`)" .
+ " SELECT" .
+ " `binary_packages_in_repositories`.`id`," .
+ "IF(" .
+ "`available`.`pkgname` IS NULL," .
+ "\"#00ff00\"," .
+ "IF(" .
+ "`build_assignments`.`is_black_listed` IS NULL," .
+ "\"#800000\"," .
+ "\"#ff0000\"" .
+ ")" .
+ ") AS `color`" .
+ " FROM `binary_packages_in_repositories`" .
+ mysql_join_binary_packages_in_repositories_binary_packages() .
+ mysql_join_binary_packages_build_assignments() .
+ $available_filter .
+ " JOIN `available` ON `available`.`pkgname`=`binary_packages`.`pkgname`" .
+ " WHERE `binary_packages_in_repositories`.`is_to_be_deleted`" .
+ " AND `binary_packages`.`pkgname` NOT LIKE \"lib32-%\"" .
+ $filter
+);
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `d_bpir_copy` (" .
+ "`id` BIGINT, " .
+ "`group` VARCHAR(256), " .
+ "`color` VARCHAR(7), " .
+ "UNIQUE KEY `id` (`id`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `d_bpir_copy` (`id`,`color`)" .
+ " SELECT `d_bpir`.`id`,`d_bpir`.`color`" .
+ " FROM `d_bpir`"
+);
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `d_bpir_links` (" .
+ "`dependent` BIGINT, " .
+ "`depending_on` BIGINT, " .
+ "`dep_type` SMALLINT, " .
+ "UNIQUE KEY `content` (`dependent`,`depending_on`,`dep_type`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `d_bpir_links` (`dependent`,`depending_on`,`dep_type`)" .
+ " SELECT `d_bpir`.`id`," .
+ " `itp_bpir`.`id`," .
+ " `dependencies`.`dependency_type`" .
+ " FROM `d_bpir`" .
+ " JOIN `binary_packages_in_repositories` ON `d_bpir`.`id`=`binary_packages_in_repositories`.`id`" .
+ mysql_join_binary_packages_in_repositories_dependencies() .
+ mysql_join_dependencies_install_target_providers() .
+ mysql_join_install_target_providers_binary_packages_in_repositories('','itp_bpir') .
+ " JOIN `d_bpir_copy` ON `itp_bpir`.`id`=`d_bpir_copy`.`id`" .
+ " WHERE `dependencies`.`dependent`!=`install_target_providers`.`package`"
+);
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `d_bpir_links_copy` (" .
+ "`dependent` BIGINT, " .
+ "`depending_on` BIGINT, " .
+ "`dep_type` SMALLINT, " .
+ "UNIQUE KEY `content` (`dependent`,`depending_on`,`dep_type`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `d_bpir_links_copy` (`dependent`,`depending_on`,`dep_type`)" .
+ " SELECT `d_bpir_links`.`dependent`,`d_bpir_links`.`depending_on`,`d_bpir_links`.`dep_type`" .
+ " FROM `d_bpir_links`"
+);
+
+mysql_run_query(
+ "UPDATE `d_bpir`" .
+ " JOIN (" .
+ "SELECT" .
+ " `d_bpir_copy`.`id`," .
+ "SHA2(" .
+ "GROUP_CONCAT(CONCAT(" .
+ "IFNULL(`d_bpir_copy`.`color`,\"0\"),\":\"," .
+ "IFNULL(`d_bpir_links`.`depending_on`,\"0\"),\":\"," .
+ "IFNULL(`d_bpir_links`.`dep_type`,\"0\"),\":\"," .
+ "IFNULL(`d_bpir_links_copy`.`dependent`,\"0\"),\":\"," .
+ "IFNULL(`d_bpir_links_copy`.`dep_type`,\"0\")" .
+ "))" .
+ ",256) AS `hash`" .
+ " FROM `d_bpir_copy`" .
+ " LEFT JOIN `d_bpir_links` ON `d_bpir_links`.`dependent`=`d_bpir_copy`.`id`" .
+ " LEFT JOIN `d_bpir_links_copy` ON `d_bpir_links_copy`.`depending_on`=`d_bpir_copy`.`id`" .
+ " GROUP BY `d_bpir_copy`.`id`" .
+ ") AS `grouped_d_bpir` ON `grouped_d_bpir`.`id`=`d_bpir`.`id`" .
+ " SET `d_bpir`.`group`=`grouped_d_bpir`.`hash`"
+);
+
+mysql_run_query(
+ "UPDATE `d_bpir_copy`" .
+ " JOIN `d_bpir` ON `d_bpir`.`id`=`d_bpir_copy`.`id`" .
+ " SET `d_bpir_copy`.`group`=`d_bpir`.`group`"
+);
+
+$result = mysql_run_query(
+ "SELECT MAX(`d_bpir`.`id`) AS `id`," .
+ "GROUP_CONCAT(CONCAT(" .
+ "`architectures`.`name`,\"/\"," .
+ "`repositories`.`name`,\"/\"," .
+ "`binary_packages`.`pkgname`" .
+ ") SEPARATOR \",\n\") AS `name`," .
+ "`d_bpir`.`color`" .
+ " FROM `d_bpir`" .
+ " JOIN `binary_packages_in_repositories` ON `d_bpir`.`id`=`binary_packages_in_repositories`.`id`" .
+ mysql_join_binary_packages_in_repositories_binary_packages() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_architectures() .
+ " GROUP BY `d_bpir`.`group`"
+);
+
+while ($row = $result->fetch_assoc())
+ $knots .=
+ "\"p" .
+ $row["id"] .
+ "\" [label = \"" .
+ $row["name"] .
+ "\",
+ fontcolor = \"" .
+ $row["color"] .
+ "\"];\n";
+
+$result = mysql_run_query(
+ "SELECT MAX(`d_bpir_links`.`dependent`) AS `dependent`," .
+ "`dependency_types`.`name` AS `dep_type`," .
+ "MAX(`d_bpir_links`.`depending_on`) AS `depending_on`" .
+ " FROM `d_bpir_links`" .
+ " JOIN `dependency_types` ON `d_bpir_links`.`dep_type`=`dependency_types`.`id`" .
+ " JOIN `d_bpir` ON `d_bpir`.`id`=`d_bpir_links`.`dependent`" .
+ " JOIN `d_bpir_copy` ON `d_bpir_copy`.`id`=`d_bpir_links`.`depending_on`" .
+ " GROUP BY CONCAT(`d_bpir`.`group`,\"-\",`d_bpir_copy`.`group`)"
+);
+
+while ($row = $result->fetch_assoc()) {
+ $edges .=
+ "\"p" .
+ $row["depending_on"] .
+ "\" -> \"p" .
+ $row["dependent"] .
+ "\" [color = \"";
+ switch ($row["dep_type"]) {
+ case "run":
+ $edges .= "#000000";
+ break;
+ case "make":
+ $edges .= "#0000ff";
+ break;
+ case "link":
+ $edges .= "#008000";
+ break;
+ case "check":
+ $edges .= "#000080";
+ break;
+ default:
+ $edges .= "#ff00ff";
+ }
+ $edges .=
+ "#000080";
+ $edges .=
+ "\"];\n";
+}
+
+header ("Content-type: image/png");
+passthru(
+ "echo '" . base64_encode(
+ "digraph dependencies {\n" .
+ "rankdir=LR;\n" .
+ "fontname=dejavu;\n" .
+ $knots .
+ $edges .
+ "}\n"
+ ) . "' | " .
+ "base64 -d | " .
+ "timeout 30 dot -Tpng -o/dev/stdout /dev/stdin"
+);
diff --git a/buildmaster/dependencies.php b/buildmaster/dependencies.php
new file mode 100644
index 0000000..a8beb5d
--- /dev/null
+++ b/buildmaster/dependencies.php
@@ -0,0 +1,190 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+$match = "";
+
+function dependency_arch_join($name) {
+ if (isset($_GET["ba_a"])) {
+ return
+ " JOIN `architecture_compatibilities`" .
+ " ON `architecture_compatibilities`.`fully_compatible`" .
+ " AND `architecture_compatibilities`.`built_for`=`" . $name . "`.`architecture`" .
+ " JOIN `architectures` AS `ba_a`" .
+ " ON `architecture_compatibilities`.`runs_on`=`ba_a`.`id`" .
+ " AND `ba_a`.`name`=from_base64(\"" . base64_encode($_GET["ba_a"]) . "\")";
+ } elseif (isset($_GET["a"])) {
+ return
+ " JOIN `architecture_compatibilities` AS `ac_1`" .
+ " ON `ac_1`.`fully_compatible`" .
+ " AND `ac_1`.`built_for`=`" . $name . "`.`architecture`" .
+ " JOIN `architecture_compatibilities` AS `ac_2`" .
+ " ON `ac_2`.`fully_compatible`" .
+ " AND `ac_1`.`runs_on`=`ac_2`.`runs_on`" .
+ " AND `ac_2`.`built_for`=`architectures`.`id`";
+ } else
+ return "";
+}
+
+if (isset($_GET["a"]))
+ $match .= " AND `architectures`.`name`=from_base64(\"" . base64_encode($_GET["a"]) . "\")";
+if (isset($_GET["b"]))
+ $match .= " AND `package_sources`.`pkgbase`=from_base64(\"" . base64_encode($_GET["b"]) . "\")";
+if (isset($_GET["p"]))
+ $match .= " AND `binary_packages`.`pkgname`=from_base64(\"" . base64_encode($_GET["p"]) . "\")";
+if (isset($_GET["r"]))
+ $match .= " AND `repositories`.`name`=from_base64(\"" . base64_encode($_GET["r"]) . "\")";
+
+$ignore_install_targets = " AND NOT `install_targets`.`name` IN (\"base\",\"base-devel\")";
+
+$colors["stable"]="#000000";
+$colors["testing"]="#008000";
+$colors["staging"]="#00ff00";
+$colors["standalone"]="#000000";
+$colors["unbuilt"]="#ff0000";
+$colors["forbidden"]="#808080";
+$colors["virtual"]="#800080";
+
+$limit=200;
+
+mysql_run_query(
+ "CREATE TEMPORARY TABLE `cons` (" .
+ "`dep` BIGINT, " .
+ "`itp` BIGINT, " .
+ "UNIQUE KEY `content` (`dep`,`itp`)" .
+ ")"
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `cons` (`dep`,`itp`)" .
+ " SELECT `dependencies`.`id`,`install_target_providers`.`id`".
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_build_assignments() .
+ mysql_join_build_assignments_package_sources() .
+ $match .
+ mysql_join_binary_packages_dependencies() .
+ mysql_join_dependencies_dependency_types() .
+ mysql_join_dependencies_install_targets() .
+ $ignore_install_targets .
+ mysql_join_dependencies_install_target_providers() .
+ mysql_join_install_target_providers_binary_packages('','itp_bp') .
+ dependency_arch_join('itp_bp') .
+ " WHERE (`dependency_types`.`relevant_for_binary_packages` OR `repository_stabilities`.`name`=\"unbuilt\")" .
+ " LIMIT " . $limit
+);
+
+mysql_run_query(
+ "INSERT IGNORE INTO `cons` (`dep`,`itp`)" .
+ " SELECT `dependencies`.`id`,`install_target_providers`.`id`".
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_build_assignments() .
+ mysql_join_build_assignments_package_sources() .
+ $match .
+ mysql_join_binary_packages_install_target_providers() .
+ mysql_join_install_target_providers_dependencies() .
+ mysql_join_dependencies_binary_packages('','d_bp') .
+ dependency_arch_join('d_bp') .
+ mysql_join_binary_packages_binary_packages_in_repositories('d_bp','d_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('d_bpir','d_r') .
+ mysql_join_repositories_repository_stabilities('d_r','d_rs') .
+ mysql_join_dependencies_dependency_types() .
+ " WHERE (`dependency_types`.`relevant_for_binary_packages` OR `d_rs`.`name`=\"unbuilt\")" .
+ " LIMIT " . $limit
+);
+
+$edges = "";
+$knots = "";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT `install_target_providers`.`install_target`,`install_target_providers`.`package`" .
+ " FROM `cons`" .
+ " JOIN `install_target_providers` ON `cons`.`itp`=`install_target_providers`.`id`"
+);
+
+while ($row = $result->fetch_assoc())
+ $edges .= "\"p" . $row["package"] . "\" -> \"i" . $row["install_target"] . "\" [color = \"#000080\"];\n";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT `dependencies`.`dependent`,`dependencies`.`depending_on`,`dependency_types`.`name`" .
+ " FROM `cons`" .
+ " JOIN `dependencies` ON `cons`.`dep`=`dependencies`.`id`" .
+ mysql_join_dependencies_dependency_types()
+);
+
+while ($row = $result->fetch_assoc())
+ $edges .= "\"i" . $row["depending_on"] . "\" -> \"p" . $row["dependent"] . "\" [taillabel = \"" . $row["name"] . "\"];\n";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT `install_targets`.`id`,`install_targets`.`name`" .
+ " FROM `cons`" .
+ " JOIN `dependencies` ON `cons`.`dep`=`dependencies`.`id`" .
+ mysql_join_dependencies_install_targets()
+);
+
+while ($row = $result->fetch_assoc())
+ $knots .= "\"i" . $row["id"] . "\" [label = \"" . $row["name"] . "\", fontcolor = \"#000080\"];\n";
+
+$pkgfile_query =
+ "CONCAT(".
+ "`repositories`.`name`,\"/\"," .
+ "`binary_packages`.`pkgname`,\"-\"," .
+ mysql_query_package_version("binary_packages") .
+ ",\"-\"," .
+ "`architectures`.`name`" .
+ ") AS `filename`";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`binary_packages`.`id`," .
+ "`repository_stabilities`.`name` AS `stability`," .
+ $pkgfile_query .
+ " FROM `cons`" .
+ " JOIN `dependencies` ON `cons`.`dep`=`dependencies`.`id`" .
+ mysql_join_dependencies_binary_packages() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities()
+);
+
+while ($row = $result->fetch_assoc())
+ $knots .= "\"p" . $row["id"] . "\" [label = \"" . $row["filename"] . "\", fontcolor = \"" . $colors[$row["stability"]] . "\"];\n";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`binary_packages`.`id`," .
+ "`repository_stabilities`.`name` AS `stability`," .
+ $pkgfile_query .
+ " FROM `cons`" .
+ " JOIN `install_target_providers` ON `cons`.`itp`=`install_target_providers`.`id`" .
+ mysql_join_install_target_providers_binary_packages() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities()
+);
+
+while ($row = $result->fetch_assoc())
+ $knots .= "\"p" . $row["id"] . "\" [label = \"" . $row["filename"] . "\", fontcolor = \"" . $colors[$row["stability"]] . "\"];\n";
+
+$knots = str_replace("\$","\\\$",$knots);
+$edges = str_replace("\$","\\\$",$edges);
+
+header ("Content-type: image/png");
+passthru(
+ "timeout 30 dot -Tpng -o/dev/stdout /dev/stdin <<EOF\n" .
+ "digraph dependencies {\n" .
+ "rankdir=LR;\n" .
+ "fontname=dejavu;\n" .
+ $knots .
+ $edges .
+ "}\n" .
+ "EOF\n"
+);
diff --git a/buildmaster/gpg-keys.php b/buildmaster/gpg-keys.php
new file mode 100644
index 0000000..db990c2
--- /dev/null
+++ b/buildmaster/gpg-keys.php
@@ -0,0 +1,48 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+ $result = mysql_run_query(
+ "SELECT" .
+ " GROUP_CONCAT(`email_actions`.`name`) AS `action`," .
+ "`persons`.`name` AS `person`," .
+ "`gpg_keys`.`fingerprint`" .
+ " FROM `email_actions`" .
+ mysql_join_email_actions_allowed_email_actions() .
+ " RIGHT" . mysql_join_allowed_email_actions_gpg_keys() .
+ mysql_join_gpg_keys_persons() .
+ " GROUP BY `gpg_keys`.`id`" .
+ " ORDER BY `persons`.`name`"
+ );
+
+?>
+<html>
+ <head>
+ <title>list of gpg-keys</title>
+ </head>
+ <body>
+<?php
+show_warning_on_offline_slave();
+
+ print "<table border=1>\n";
+ if ($result->num_rows > 0) {
+ print "<tr><th>person</th><th>action</th><th>fingerprint</th></tr>\n";
+ while ($row = $result -> fetch_assoc()) {
+ foreach ($row as $key => $value) {
+ if ($value=="") {
+ $row[$key]="&nbsp;";
+ }
+ }
+ print "<tr>";
+ print "<td>" . $row["person"] . "</td>";
+ print "<td>" . $row["action"] . "</td>";
+ print "<td><a href=\"http://pgp.mit.edu/pks/lookup?op=get&search=0x" .
+ substr($row["fingerprint"],-16) .
+ "\">" . $row["fingerprint"] . "</a></td>";
+ print "</tr>\n";
+ }
+ }
+ print "</table>\n";
+
+?>
+</body></html>
diff --git a/buildmaster/index.php b/buildmaster/index.php
new file mode 100644
index 0000000..0ea0376
--- /dev/null
+++ b/buildmaster/index.php
@@ -0,0 +1,80 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+if (array_key_exists("arch",$_GET)) {
+ $archs = array();
+ foreach (explode("&",$_SERVER["QUERY_STRING"]) as $param) {
+ if (strpos($param,"arch=")!==0)
+ continue;
+ $param = substr($param,5);
+ if ($param == "")
+ continue;
+ $archs[$param] = $param;
+ }
+ if (count($archs)==0) {
+ $archs = array("i486" => "i486", "i686" => "i686", "any" => "any");
+ }
+} else {
+ $archs = array("i686" => "i686", "any" => "any");
+}
+
+function encode_arch($a) {
+ return "arch=" . urlencode($a);
+}
+
+$sarch_param = implode("&",array_map('encode_arch',$archs));
+$march_param = "";
+if ($sarch_param != "") {
+ $march_param = "&" . $sarch_param;
+ $sarch_param = "?" . $sarch_param;
+}
+
+?>
+<html>
+ <head>
+ <title>Buildmaster for Archlinux32 packages (<?php print implode(", ",$archs); ?>)</title>
+ </head>
+ <body>
+<?php show_warning_on_offline_slave(); ?>
+ <a href="/buildmaster/build-list.php<?php print $sarch_param; ?>">build list</a>
+ as <a href="/buildmaster/build-list-links.php">graph</a> --
+ <a href="/buildmaster/build-list.php?broken=Broken<?php print $march_param; ?>">broken packages</a> --
+ <a href="/buildmaster/build-list.php?next=Can<?php print $march_param; ?>">buildable packages</a><br>
+ <a href="/buildmaster/build-slaves.php">build-slaves</a> --
+ <a href="/buildmaster/gpg-keys.php">gpg-keys</a> --
+ <a href="/buildmaster/status.php">status</a><br>
+ <a href="https://buildmaster.archlinux32.org/build-logs/">build logs</a> --
+ <a href="/buildmaster/log.php?show=ssh">ssh-log</a> --
+ <a href="/buildmaster/log.php?show=email">email-log</a><br>
+ sanity: of <a href="https://buildmaster.archlinux32.org/master-sanity.html">state files</a>,
+ of <a href="https://buildmaster.archlinux32.org/mysql-sanity.html">mysql database</a> and
+ <a href="/buildmaster/mysql-issues.php?ignore-i486">broken dependencies in the database</a><br>
+ <a href="/buildmaster/todos.php">todos</a>
+ as <a href="/buildmaster/todos.php?graph">graph</a><br>
+ <a href="https://buildmaster.archlinux32.org/database-layout.png">database layout</a><br>
+ <a href="/buildmaster/blacklist.php">blacklisted packages</a> --
+ <a href="/buildmaster/to-delete.php">packages to be deleted</a>
+ and <a href="/buildmaster/deletion-links.php">links between them</a><br>
+ <img src="/buildmaster/statistics.php?log<?php print $march_param; ?>"><br>
+<?php
+
+foreach (array("any", "i486", "i686", "") as $a) {
+ print " <a href=\"?arch=" . $a . "\">";
+ switch ($a) {
+ case "":
+ print "all packages";
+ break;
+ case "any":
+ print "architecture independent packages";
+ break;
+ default:
+ print "packages for " . $a;
+ }
+ print "</a>\n";
+}
+
+?><br>
+ <img src="https://buildmaster.archlinux32.org/vnstat.png"><br>
+ </body>
+</html>
diff --git a/buildmaster/log.php b/buildmaster/log.php
new file mode 100644
index 0000000..f6de94b
--- /dev/null
+++ b/buildmaster/log.php
@@ -0,0 +1,93 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+
+ $filter = "";
+ if (isset($_GET["show"]) &&
+ ($_GET["show"] == "ssh")) {
+ $to_show = "ssh";
+ $columns = array(
+ "date" => "`ssh_log`.`date`",
+ "build slave" => "`build_slaves`.`name`",
+ "action" => "`ssh_log`.`action`",
+ "parameters" => "`ssh_log`.`parameters`"
+ );
+ $join = " LEFT" . mysql_join_ssh_log_build_slaves();
+ if (isset($_GET["action"]))
+ $filter .= " AND `ssh_log`.`action` LIKE from_base64(\"" . base64_encode($_GET["action"]) . "\")";
+ if (isset($_GET["slave"]))
+ $filter .= " AND `build_slaves`.`name` LIKE from_base64(\"" . base64_encode($_GET["slave"]) . "\")";
+ } else {
+ $to_show = "email";
+ $columns = array(
+ "date" => "`email_log`.`date`",
+ "action" => "`email_actions`.`name`",
+ "count" => "`email_log`.`count`",
+ "success" => "`email_log`.`success`",
+ "person" => "`persons`.`name`",
+ "comment" => "`email_log`.`comment`"
+ );
+ $join =
+ " LEFT" . mysql_join_email_log_email_actions() .
+ " LEFT JOIN (" .
+ "`gpg_keys`" .
+ mysql_join_gpg_keys_persons() .
+ ") ON `email_log`.`gpg_key`=`gpg_keys`.`id`";
+ }
+
+ if (isset($_GET["from"]))
+ $min_time = $_GET["from"];
+ elseif ($to_show == "email")
+ $min_time = "1 00:00:00";
+ else
+ $min_time = "00:42:00";
+
+ $query = "SELECT ";
+ foreach ($columns as $name => $column)
+ $query .= $column . " AS `".$name."`,";
+
+ $query = substr($query,0,-1);
+ $query .= " FROM `" . $to_show . "_log`" . $join .
+ " WHERE TIMEDIFF((" .
+ // NOW() is wrong here - due to differing time zones O.o
+ "SELECT MAX(`l`.`date`) FROM `" . $to_show . "_log` AS `l`" .
+ "),`" . $to_show . "_log`.`date`) < from_base64(\"" . base64_encode( $min_time ) . "\")" .
+ $filter .
+ " ORDER BY `" . $to_show . "_log`.`date` DESC";
+
+ $result = mysql_run_query($query);
+
+?>
+<html>
+ <head>
+ <title><?php print $to_show; ?>-log</title>
+ <link rel="stylesheet" type="text/css" href="/static/style.css">
+ </head>
+ <body>
+ <table>
+ <tr>
+<?php
+ foreach ($columns as $label => $column) {
+ print " <th>\n";
+ print " " . $label . "\n";
+ print " </th>\n";
+ }
+?>
+ </tr>
+<?php
+
+ while ($row = $result -> fetch_assoc()) {
+ print " <tr>\n";
+ foreach ($row as $val) {
+ print " <td>\n";
+ print " " . $val . "\n";
+ print " </td>\n";
+ }
+ print " </tr>\n";
+ }
+
+?>
+ </table>
+ </body>
+</html>
diff --git a/buildmaster/mysql-issues.php b/buildmaster/mysql-issues.php
new file mode 100644
index 0000000..1397141
--- /dev/null
+++ b/buildmaster/mysql-issues.php
@@ -0,0 +1,183 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+ $ignore = "";
+
+ if (isset($_GET["ignore-haskell"]))
+ $ignore .= " AND `install_targets`.`name` NOT LIKE \"libHS%\"";
+
+ if (isset($_GET["ignore-i486"]))
+ $ignore .= " AND `r_a`.`name` != \"i486\"";
+
+ ob_start();
+
+?>
+<html>
+ <head>
+ <title>More and less critical issues with the database</title>
+ <link rel="stylesheet" type="text/css" href="/static/style.css">
+ </head>
+ <body>
+<?php show_warning_on_offline_slave(); ?>
+ <a href="https://buildmaster.archlinux32.org/">Start page</a><br>
+<?php
+
+ $limit = " LIMIT 10001";
+
+ $result = mysql_run_query(
+ "SELECT CONCAT(" .
+ "`r_a`.`name`,\"/\"," .
+ "`repositories`.`name`,\"/\"," .
+ "`binary_packages`.`pkgname`,\"-\"," .
+ mysql_query_package_version("binary_packages") .
+ ",\"-\"," .
+ "`architectures`.`name`) AS `pkgfile`," .
+ "`install_targets`.`name` AS `install_target`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`," .
+ "`subst_r`.`name` AS `subst_repository`," .
+ "`subst_buildlist_bp`.`id` AS `subst_buildlist`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " AND `repositories`.`is_on_master_mirror`" .
+ mysql_join_repositories_architectures('','r_a') .
+ mysql_join_binary_packages_dependencies() .
+ mysql_join_dependencies_dependency_types() .
+ " AND `dependency_types`.`relevant_for_binary_packages`" .
+ mysql_join_dependencies_install_targets() .
+ mysql_join_binary_packages_architectures() .
+ " LEFT JOIN (" .
+ "`binary_packages` AS `subst_bp`" .
+ mysql_join_binary_packages_binary_packages_in_repositories('subst_bp','subst_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('subst_bpir','subst_r') .
+ " JOIN `repository_stability_relations` ON `repository_stability_relations`.`less_stable`=`subst_r`.`stability`" .
+ ")" .
+ " ON `subst_bp`.`pkgname`=`binary_packages`.`pkgname`" .
+ " AND `subst_bp`.`id`!=`binary_packages`.`id`" .
+ " AND `repository_stability_relations`.`more_stable`=`repositories`.`stability`" .
+ " AND `subst_r`.`architecture`=`repositories`.`architecture`" .
+ " LEFT JOIN (" .
+ "`binary_packages` AS `subst_buildlist_bp`" .
+ mysql_join_binary_packages_binary_packages_in_repositories('subst_buildlist_bp','subst_buildlist_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('subst_buildlist_bpir','subst_buildlist_r') .
+ " AND `subst_buildlist_r`.`name`=\"build-list\"".
+ ") ON `subst_buildlist_bp`.`pkgname`=`binary_packages`.`pkgname`" .
+ " AND `subst_bp`.`architecture`=`binary_packages`.`architecture`" .
+ " WHERE NOT EXISTS (" .
+ "SELECT 1 FROM `install_target_providers`" .
+ mysql_join_install_target_providers_binary_packages_in_repositories('','i_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('i_bpir','i_r') .
+ " JOIN `architecture_compatibilities` ON `architecture_compatibilities`.`fully_compatible`" .
+ " AND `architecture_compatibilities`.`built_for`=`i_r`.`architecture`" .
+ " WHERE `install_target_providers`.`install_target`=`dependencies`.`depending_on`" .
+ " AND `repositories`.`architecture`=`architecture_compatibilities`.`runs_on`" .
+ ")" .
+ $ignore .
+ " ORDER BY " .
+ "`binary_packages_in_repositories`.`is_to_be_deleted`," .
+ "`repositories`.`name`," .
+ "`binary_packages`.`pkgname`," .
+ "`install_targets`.`name`" .
+ $limit
+ );
+
+ if ($result -> num_rows > 10000)
+ print " Found >10000 serious issues.<br>\n";
+ else
+ print " Found " . $result -> num_rows . " serious issues.<br>\n";
+
+ while ( $row = $result -> fetch_assoc() ) {
+ if ($row["is_to_be_deleted"]==1)
+ print " <font color=\"#00ff00\">(marked as to-be-deleted) ";
+ else
+ print " <font color=\"#ff0000\">";
+ print $row["pkgfile"] . " depends on " . htmlspecialchars($row["install_target"]) . " which is not provided by any package";
+ if (isset($row["subst_repository"]))
+ print " - but can be replaced by the one in " . $row["subst_repository"];
+ elseif (isset($row["subst_buildlist"]))
+ print " - but is already rescheduled";
+ print ".<br>";
+ print "</font>\n";
+ unset($row);
+ }
+
+ $result = mysql_run_query(
+ "SELECT CONCAT(" .
+ "`r_a`.`name`,\"/\"," .
+ "`repositories`.`name`,\"/\"," .
+ "`binary_packages`.`pkgname`,\"-\"," .
+ mysql_query_package_version("binary_packages") .
+ ",\"-\"," .
+ "`architectures`.`name`) AS `pkgfile`," .
+ "`install_targets`.`name` AS `install_target`," .
+ "`repository_stabilities`.`name` AS `stability`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " AND `repositories`.`is_on_master_mirror`" .
+ mysql_join_repositories_architectures('','r_a') .
+ mysql_join_repositories_repository_stabilities() .
+ mysql_join_binary_packages_dependencies() .
+ mysql_join_dependencies_dependency_types() .
+ " AND `dependency_types`.`relevant_for_binary_packages`" .
+ mysql_join_dependencies_install_targets() .
+ mysql_join_binary_packages_architectures() .
+ " WHERE EXISTS (" .
+ "SELECT 1 FROM `install_target_providers`" .
+ mysql_join_install_target_providers_binary_packages_in_repositories('','prov_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('prov_bpir','prov_r') .
+ " JOIN `architecture_compatibilities` ON `architecture_compatibilities`.`built_for`=`prov_r`.`architecture`" .
+ " AND `architecture_compatibilities`.`fully_compatible`" .
+ " WHERE `install_target_providers`.`install_target` = `dependencies`.`depending_on`" .
+ " AND `architecture_compatibilities`.`runs_on`=`repositories`.`architecture`" .
+ ")" .
+ " AND NOT EXISTS (" .
+ "SELECT 1 FROM `install_target_providers`" .
+ mysql_join_install_target_providers_binary_packages('','prov_bp') .
+ mysql_join_binary_packages_binary_packages_in_repositories('prov_bp','prov_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('prov_bpir','prov_r') .
+ " JOIN `repository_stability_relations` ON `prov_r`.`stability`=`repository_stability_relations`.`more_stable`" .
+ " WHERE `install_target_providers`.`install_target` = `dependencies`.`depending_on`" .
+ " AND `repositories`.`stability`=`repository_stability_relations`.`less_stable`" .
+ " AND `repositories`.`architecture`=`prov_r`.`architecture`" .
+ " AND NOT EXISTS (" .
+ "SELECT 1 FROM `binary_packages` AS `sup_bp`" .
+ mysql_join_binary_packages_binary_packages_in_repositories('sup_bp','sup_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('sup_bpir','sup_r') .
+ " JOIN `repository_stability_relations` AS `sup_rra` ON `sup_r`.`stability`=`sup_rra`.`more_stable`" .
+ " JOIN `repository_stability_relations` AS `sup_rrb` ON `sup_r`.`stability`=`sup_rrb`.`less_stable`" .
+ " WHERE `sup_bp`.`pkgname` = `prov_bp`.`pkgname`" .
+ " AND `sup_bp`.`architecture` = `prov_bp`.`architecture`" .
+ " AND `sup_bp`.`id` != `prov_bp`.`id`" .
+ " AND `repositories`.`stability`=`sup_rra`.`less_stable`" .
+ " AND `prov_r`.`stability`=`sup_rrb`.`more_stable`" .
+ " AND `prov_r`.`architecture`=`sup_r`.`architecture`" .
+ ")" .
+ ")" .
+ $ignore .
+ " ORDER BY `binary_packages_in_repositories`.`is_to_be_deleted`,`binary_packages`.`pkgname`,`install_targets`.`name`" .
+ $limit
+ );
+
+ if ($result -> num_rows > 10000)
+ print " Found >10000 stability issues.<br>\n";
+ else
+ print " Found " . $result -> num_rows . " stability issues.<br>\n";
+
+ while ( $row = $result -> fetch_assoc() ) {
+ if ($row["is_to_be_deleted"]==1)
+ print " <font color=\"#00ff00\">(marked as to-be-deleted) ";
+ else
+ print " <font color=\"#800000\">";
+ print $row["pkgfile"] . " depends on " . htmlspecialchars($row["install_target"]) . " which is not provided by any package installable from enabled " . $row["stability"] . " repositories.<br>";
+ print "</font>\n";
+ unset($row);
+ }
+
+ ob_end_flush();
+
+?>
+ </body>
+</html>
diff --git a/buildmaster/statistics.php b/buildmaster/statistics.php
new file mode 100644
index 0000000..4f2398b
--- /dev/null
+++ b/buildmaster/statistics.php
@@ -0,0 +1,200 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+if (array_key_exists("from",$_GET))
+ $min_time="from_base64(\"" . base64_encode("-".$_GET["from"]) . "\")";
+else
+ $min_time="\"-7 00:00:00\"";
+
+if (array_key_exists("arch",$_GET)) {
+ $arch_filter="`architectures`.`name` IN (\"\"";
+ foreach (explode("&",$_SERVER["QUERY_STRING"]) as $param) {
+ if (strpos($param,"arch=")!==0)
+ continue;
+ $arch_filter .= ",from_base64(\"" . base64_encode(substr($param,5)) . "\")";
+ }
+ $arch_filter .= ")";
+ $combiner_left="";
+ $combiner_right="";
+ $grouper="";
+ $joiner=" JOIN `architectures` ON `statistics`.`architecture`=`architectures`.`id`";
+} else {
+ $arch_filter="1";
+ $combiner_left="SUM(";
+ $combiner_right=")";
+ $grouper=" GROUP BY `statistics`.`date`";
+ $joiner="";
+};
+
+$column_list = array(
+ "pending_tasks_count",
+ "pending_packages_count",
+ "staging_packages_count",
+ "testing_packages_count",
+ "tested_packages_count",
+ "broken_tasks_count",
+ "dependency_loops_count",
+ "dependency_looped_tasks_count",
+ "locked_tasks_count",
+ "blocked_tasks_count",
+ "next_tasks_count"
+);
+
+function combine_column($name) {
+ global $combiner_left;
+ global $combiner_right;
+ return $combiner_left . "`statistics`.`" . $name . "`" . $combiner_right . " AS `" . $name . "`";
+}
+
+$result = mysql_run_query(
+ "SELECT DISTINCT ".
+ "UNIX_TIMESTAMP(`statistics`.`date`) AS `date`," .
+ implode(",",array_map("combine_column",$column_list)) .
+ "FROM `statistics` " .
+ $joiner .
+ "WHERE `statistics`.`date`>=ADDDATE(NOW()," . $min_time . ") " .
+ "AND " . $arch_filter .
+ $grouper .
+ "ORDER BY `statistics`.`date`"
+);
+
+$t_min = -1;
+$t_max = -1;
+$val_max = -1;
+
+while($vals = $result->fetch_assoc()) {
+ if ($t_min == -1)
+ $t_min = $vals["date"];
+ $t_max = $vals["date"];
+ foreach ($vals as $column => $val)
+ if ($column != "date") {
+ $values[$column][$vals["date"]] = $val;
+ $val_max = max($val_max,$val);
+ }
+};
+$print_columns = array_keys($values);
+
+$max_len = 0;
+foreach ($print_columns as $column) {
+ $len = strlen($values[$column][$t_max])+1;
+ if ($len > $max_len)
+ $max_len = $len;
+}
+
+$width = 1600;
+$height = 600;
+$border = 5;
+$legend_line_length = 10;
+$legend_height = 2 * ImageFontHeight(5) + $legend_line_length;
+
+$im = @ImageCreate ($width + $legend_line_length + $max_len * ImageFontWidth(5), $height + $legend_height)
+ or die ("Cannot create new gd-image-stream");
+
+$background_color = ImageColorAllocate ($im, 255, 255, 255);
+$foreground_color = ImageColorAllocate ($im, 0, 0, 0);
+
+$colors['stable_packages_count'] = ImageColorAllocate ($im, 0, 0, 0);
+$colors['pending_tasks_count'] = ImageColorAllocate ($im, 0, 0, 128);
+$colors['pending_packages_count'] = ImageColorAllocate ($im, 0, 0, 255);
+$colors['staging_packages_count'] = ImageColorAllocate ($im, 0, 100, 0);
+$colors['testing_packages_count'] = ImageColorAllocate ($im, 0, 200, 0);
+$colors['tested_packages_count'] = ImageColorAllocate ($im, 100, 255, 0);
+$colors['broken_tasks_count'] = ImageColorAllocate ($im, 255, 0, 0);
+$colors['dependency_loops_count'] = ImageColorAllocate ($im, 128, 128, 0);
+$colors['dependency_looped_tasks_count'] = ImageColorAllocate ($im, 255, 128, 128);
+$colors['locked_tasks_count'] = ImageColorAllocate ($im, 128, 128, 128);
+$colors['blocked_tasks_count'] = ImageColorAllocate ($im, 128, 0, 0);
+$colors['next_tasks_count'] = ImageColorAllocate ($im, 0, 255, 255);
+
+function scale($x, $x_min, $x_max, $scale, $log) {
+ if ($log) {
+ $x = log($x + 10);
+ $x_min = log($x_min + 10);
+ $x_max = log($x_max + 10);
+ };
+ if ($x_max == $x_min)
+ $frac = 0;
+ else
+ $frac = ($x - $x_min)/($x_max - $x_min);
+ if ($scale < 0)
+ return ($frac-1) * $scale;
+ else
+ return $frac * $scale;
+};
+
+function print_graph($data, $color) {
+ global $width, $height, $im, $t_min, $t_max, $val_max, $border, $legend_line_length;
+ ksort($data);
+ $last_t = -1;
+ $last_val = -1;
+ foreach ($data as $t => $val) {
+ if ($last_t != -1)
+ ImageLine(
+ $im,
+ scale($last_t,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ scale($last_val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ scale($t,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $color
+ );
+ $last_t = $t;
+ $last_val = $val;
+ }
+ ImageString(
+ $im,
+ 5,
+ $width+$legend_line_length,
+ scale($last_val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border - ImageFontHeight(5)/2,
+ " ".$data[$t_max],
+ $color
+ );
+};
+
+ImageRectangle($im, $legend_line_length, 0, $width-1+$legend_line_length, $height-1, $foreground_color);
+
+$xpos = $legend_line_length;
+foreach ($print_columns as $column) {
+ print_graph($values[$column], $colors[$column]);
+ ImageString($im, 5, $xpos, $height + $legend_line_length + ImageFontHeight(5), substr($column,0,-strlen("_count")), $colors[$column]);
+ $xpos += (strlen($column) - strlen("_count") + 1.75) * ImageFontWidth(5);
+}
+
+ImageString($im, 5, $legend_line_length, $height + $legend_line_length, date('Y-m-d H:i', $t_min), $foreground_color);
+$s = date('Y-m-d H:i', $t_max);
+ImageString($im, 5, $width+$legend_line_length - strlen($s)*ImageFontWidth(5), $height + $legend_line_length, $s, $foreground_color);
+
+for ($t=ceil($t_min/24/60/60); $t<=floor($t_max/24/60/60); $t++)
+ ImageLine(
+ $im,
+ scale($t*24*60*60,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ $height,
+ scale($t*24*60*60,$t_min,$t_max,$width-2*$border,false)+$border+$legend_line_length,
+ $height+$legend_line_length,
+ $foreground_color
+ );
+
+for ($val=0; $val<=$val_max;) {
+ ImageLine(
+ $im,
+ 0,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $legend_line_length,
+ scale($val,0,$val_max,-$height+2*$border,isset($_GET["log"]))+$border,
+ $foreground_color
+ );
+ if (! isset($_GET["log"]))
+ $val+=pow(10,round(log($val_max)/log(10))-1);
+ elseif ($val==0)
+ $val++;
+ else
+ $val=$val*10;
+}
+
+// ImageString ($im, 1, 5, 5, "Test-String ".rand(), $foreground_color);
+
+header ("Content-type: image/png");
+
+ImagePNG ($im);
+
+?>
diff --git a/buildmaster/status.php b/buildmaster/status.php
new file mode 100644
index 0000000..05a4455
--- /dev/null
+++ b/buildmaster/status.php
@@ -0,0 +1,144 @@
+<?php
+require_once "../init.php";
+include BASE . "/lib/mysql.php";
+include BASE . "/lib/style.php";
+include BASE . "/lib/helper.php";
+
+$result = mysql_run_query(
+ "SELECT MAX(`package_sources`.`commit_time`) AS `last_commit`" .
+ " FROM `package_sources`"
+);
+
+if ($result -> num_rows > 0) {
+ $result = $result->fetch_assoc();
+ $last_commit = $result["last_commit"];
+}
+
+$result = mysql_run_query(
+ "SELECT MAX(`build_assignments`.`return_date`) AS `last_return`" .
+ " FROM `build_assignments`"
+);
+
+if ($result -> num_rows > 0) {
+ $result = $result->fetch_assoc();
+ $last_return = $result["last_return"];
+}
+
+$result = mysql_run_query(
+ "SELECT MAX(`binary_packages_in_repositories`.`last_moved`) AS `last_moved`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_build_assignments() .
+ " WHERE `binary_packages_in_repositories`.`last_moved`>`build_assignments`.`return_date`"
+);
+
+if ($result -> num_rows > 0) {
+ $result = $result->fetch_assoc();
+ $last_moved = $result["last_moved"];
+}
+
+$age_queries = array(
+ array(
+ "label" => "age of build-list-packages",
+ "column" => "`package_sources`.`commit_time`",
+ "table" =>
+ "`package_sources`" .
+ " JOIN (" .
+ "SELECT " .
+ "`build_assignments`.`package_source`" .
+ " FROM `build_assignments`" .
+ mysql_join_build_assignments_binary_packages() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " WHERE `repositories`.`name`=\"build-list\"" .
+ " AND `build_assignments`.`is_blocked` IS NULL" .
+ " GROUP BY `build_assignments`.`package_source`" .
+ ") AS `build_assignments_grouped`" .
+ " ON `build_assignments_grouped`.`package_source`=`package_sources`.`id`"
+ ),
+ array(
+ "label" => "age of staging-packages",
+ "column" => "`binary_packages_in_repositories`.`first_last_moved`",
+ "table" =>
+ "`binary_packages`" .
+ " JOIN (" .
+ "SELECT " .
+ "`binary_packages_in_repositories`.`package`," .
+ "MIN(`binary_packages_in_repositories`.`last_moved`) AS `first_last_moved`" .
+ " FROM `binary_packages_in_repositories`" .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities() .
+ " WHERE `repository_stabilities`.`name`=\"staging\"" .
+ " GROUP BY `binary_packages_in_repositories`.`package`" .
+ ") AS `binary_packages_in_repositories`" .
+ " ON `binary_packages_in_repositories`.`package`=`binary_packages`.`id`"
+ ),
+ array(
+ "label" => "age of testing-packages",
+ "column" => "`binary_packages_in_repositories`.`first_last_moved`",
+ "table" =>
+ "`binary_packages`" .
+ " JOIN (" .
+ "SELECT " .
+ "`binary_packages_in_repositories`.`package`," .
+ "MIN(`binary_packages_in_repositories`.`last_moved`) AS `first_last_moved`" .
+ " FROM `binary_packages_in_repositories`" .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities() .
+ " WHERE `repository_stabilities`.`name`=\"testing\"" .
+ " GROUP BY `binary_packages_in_repositories`.`package`" .
+ ") AS `binary_packages_in_repositories`" .
+ " ON `binary_packages_in_repositories`.`package`=`binary_packages`.`id`" .
+ " WHERE NOT `binary_packages`.`has_issues`" .
+ " AND NOT `binary_packages`.`is_tested`"
+ ),
+ array(
+ "label" => "age of tested-packages",
+ "column" => "`binary_packages_in_repositories`.`first_last_moved`",
+ "table" =>
+ "`binary_packages`" .
+ " JOIN (" .
+ "SELECT " .
+ "`binary_packages_in_repositories`.`package`," .
+ "MIN(`binary_packages_in_repositories`.`last_moved`) AS `first_last_moved`" .
+ " FROM `binary_packages_in_repositories`" .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities() .
+ " WHERE `repository_stabilities`.`name`=\"testing\"" .
+ " GROUP BY `binary_packages_in_repositories`.`package`" .
+ ") AS `binary_packages_in_repositories`" .
+ " ON `binary_packages_in_repositories`.`package`=`binary_packages`.`id`"
+ )
+);
+
+foreach ($age_queries as $age_query) {
+ $result = mysql_run_query(
+ "SELECT " .
+ "AVG(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(" . $age_query["column"] . ")) AS `avg`," .
+ "STDDEV(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(" . $age_query["column"] . ")) AS `stddev`" .
+ " FROM " . $age_query["table"]
+ );
+ if ($result -> num_rows > 0) {
+ $result = $result->fetch_assoc();
+ foreach ($result as $key => $val)
+ $ages[$age_query["label"]][$key] = format_time_duration($val);
+ };
+};
+
+print_header("Build Master Status");
+
+if (isset($last_commit))
+ print " latest package source is from " . $last_commit . ".<br>\n";
+
+if (isset($last_return))
+ print " latest built package is from " . $last_return . ".<br>\n";
+
+if (isset($last_moved))
+ print " latest package move was on " . $last_moved . ".<br>\n";
+
+foreach ($ages as $label => $value)
+ print " " . $label . ": " .
+ $value["avg"] . " &pm; " .
+ $value["stddev"] . ".<br>\n";
+
+print_footer();
diff --git a/buildmaster/to-delete.php b/buildmaster/to-delete.php
new file mode 100644
index 0000000..df11750
--- /dev/null
+++ b/buildmaster/to-delete.php
@@ -0,0 +1,77 @@
+<?php
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+ $result = mysql_run_query(
+ "SELECT " .
+ "`repositories`.`name` AS `repo`," .
+ "`binary_packages`.`pkgname`," .
+ "`binary_packages`.`epoch`," .
+ "`binary_packages`.`pkgver`," .
+ "`binary_packages`.`pkgrel`," .
+ "`binary_packages`.`sub_pkgrel`," .
+ "`architectures`.`name` AS `arch`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ "WHERE `binary_packages_in_repositories`.`is_to_be_deleted` " .
+ "AND `repositories`.`is_on_master_mirror`"
+ );
+
+ $available = explode(
+ "\n",
+ shell_exec("find /var/lib/pacman/ -name '*.db' -exec tar -tzf {} \; | sed -n 's,-[^-]\+-[^-]\+/$,,;T;p'")
+ );
+ $available = array_combine( $available, $available);
+?>
+<html>
+<head>
+<title>List of packages to be deleted</title>
+<link rel="stylesheet" type="text/css" href="/static/style.css">
+</head>
+<body>
+<?php
+
+show_warning_on_offline_slave();
+
+if ($result -> num_rows > 0) {
+
+ $count = 0;
+
+ while ($row = $result->fetch_assoc()) {
+
+ if (isset($available[$row["pkgname"]]))
+ $color = "#FF0000";
+ else
+ $color = "#00FF00";
+
+ $rows[$count] =
+ "<font color=\"" . $color . "\">" .
+ $row["repo"] . "/" .
+ $row["pkgname"] . "-";
+ if ($row["epoch"] != "0")
+ $rows[$count] =
+ $rows[$count] .
+ $row["epoch"] . ":";
+ $rows[$count] =
+ $rows[$count] .
+ $row["pkgver"] . "-" .
+ $row["pkgrel"] . "." .
+ $row["sub_pkgrel"] . "-" .
+ $row["arch"] . ".pkg.tar.xz</font>";
+ $count++;
+ }
+
+ sort($rows);
+
+ foreach ($rows as $row) {
+ print $row."<br>\n";
+ }
+} else {
+ print "No packages are to be deleted.\n";
+}
+
+?>
+</body>
+</html>
diff --git a/buildmaster/todos.php b/buildmaster/todos.php
new file mode 100644
index 0000000..bf77f08
--- /dev/null
+++ b/buildmaster/todos.php
@@ -0,0 +1,97 @@
+<?php
+require_once "../init.php";
+
+include BASE . "/lib/helper.php";
+include BASE . "/lib/mysql.php";
+
+$result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`todos`.`id`," .
+ "`todos`.`file`," .
+ "`todos`.`line`," .
+ "`todos`.`description` " .
+ "FROM `todos`;"
+);
+
+if (isset($_GET["graph"])) {
+
+ if ($result -> num_rows > 0) {
+
+ while ($row = $result->fetch_assoc())
+ $knot_rows[$row["id"]] =
+ $row["file"]. " (line ".$row["line"].") #".$row["id"].":\\n".
+ str_replace("\"","\\\"",$row["description"]);
+
+ $knots="";
+ foreach ($knot_rows as $knot)
+ $knots=$knots . "\"" . $knot . "\";\n";
+
+ }
+
+ $result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`todo_links`.`dependent`," .
+ "`todo_links`.`depending_on` " .
+ "FROM `todo_links`;"
+ );
+
+ if ($result -> num_rows > 0) {
+ $count = 0;
+ while ($row = $result->fetch_assoc()) {
+ $link_rows[$count]["dependent"] =
+ $knot_rows[$row["dependent"]];
+ $link_rows[$count]["depending_on"] =
+ $knot_rows[$row["depending_on"]];
+ $count++;
+ }
+
+ $edges="";
+ foreach ($link_rows as $link)
+ $edges=$edges . "\"" . $link["depending_on"] . "\" -> \"" . $link["dependent"] . "\";\n";
+ }
+
+ header ("Content-type: image/png");
+ passthru(
+ "echo \"" . base64_encode(
+ "digraph dependencies {\n" .
+ "rankdir=LR;\n" .
+ "fontname=dejavu;\n" .
+ $knots .
+ $edges .
+ "}\n"
+ ) . "\" | " .
+ "base64 -d | " .
+ "timeout 30 dot -Tpng -o/dev/stdout /dev/stdin"
+ );
+
+} else { // isset($_GET["graph"])
+
+ if ($result -> num_rows > 0) {
+
+ print "<html>\n";
+ print "<head>\n";
+ print "<title>Todos in the build scripts</title>\n";
+ print "</head>\n";
+ print "<body>\n";
+ show_warning_on_offline_slave();
+
+ while ($row = $result->fetch_assoc()) {
+ print "<a href=\"#TODO" . $row["id"] . "\" name=\"TODO" . $row["id"] ."\">TODO #" . $row["id"] . "</a>";
+ print " - ";
+ print "<a href=\"";
+ print git_url("builder","tree","master",$row["file"],$row["line"]);
+ print "\">" . $row["file"] . "(line " . $row["line"] . ")</a>";
+ print ":<br>\n";
+ print str_replace("\\n","<br>\n",$row["description"]);
+ print "<br>\n";
+ print "<br>\n";
+ }
+
+ print "</body>\n";
+ print "</html>\n";
+
+ }
+
+}
+
+?>
diff --git a/init.php b/init.php
new file mode 100644
index 0000000..6c8a8f4
--- /dev/null
+++ b/init.php
@@ -0,0 +1,2 @@
+<?php
+define("BASE", __DIR__);
diff --git a/lib/.htaccess b/lib/.htaccess
new file mode 100644
index 0000000..3a42882
--- /dev/null
+++ b/lib/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/lib/format.php b/lib/format.php
new file mode 100644
index 0000000..00e8296
--- /dev/null
+++ b/lib/format.php
@@ -0,0 +1,58 @@
+<?php
+
+# do not include twice
+if (function_exists("export_as_requested"))
+ return;
+
+require_once "../init.php";
+include_once BASE . "/lib/http.php";
+
+function export_as_requested($content) {
+ if (isset($content["All"])) {
+ $content["json"]=$content["All"];
+ $content["tsv"]=$content["All"];
+ unset($content["All"]);
+ }
+ if (isset($content["json"]) && isset($_GET["json"])) {
+ header ("Content-type: application/json");
+ print json_encode(
+ $content["json"],
+ JSON_UNESCAPED_SLASHES
+ );
+ } elseif (isset($content["tsv"]) && isset($_GET["tsv"])) {
+ header ("Content-type: text/tab-separated-values");
+ if (! isset($_GET["no-headers"]))
+ print implode("\t",array_keys($content["tsv"][0])) . "\n";
+ print implode(
+ "",
+ array_map(
+ function($row){
+ return implode("\t",$row) . "\n";
+ },
+ $content["tsv"]
+ )
+ );
+ } else {
+ throw_http_error(
+ 406,
+ "Not Acceptable",
+ implode(
+ "<br>\n",
+ array_merge(
+ array(
+ "Unknown output format.",
+ "Accepted:"
+ ),
+ array_map(
+ function($type){
+ return "<a href=\"?" . $type . "\">" . $type . "</a>";
+ },
+ array_keys(
+ $content
+ )
+ )
+ )
+ )
+ );
+ }
+}
diff --git a/lib/helper.php b/lib/helper.php
new file mode 100644
index 0000000..8296cd9
--- /dev/null
+++ b/lib/helper.php
@@ -0,0 +1,195 @@
+<?php
+
+# do not include twice
+if (function_exists("format_time_duration"))
+ return;
+
+require_once "../init.php";
+
+function format_time_duration($val) {
+ $val = floor($val);
+ $result = "";
+ $result =
+ sprintf(
+ "%02d",
+ $val % 60
+ );
+ $val = floor($val / 60);
+ if ($val == 0)
+ return $result;
+ $result =
+ sprintf(
+ "%02d:%s",
+ $val % 60,
+ $result
+ );
+ $val = floor($val / 60);
+ if ($val == 0)
+ return $result;
+ $result =
+ sprintf(
+ "%d:%s",
+ $val % 24,
+ $result
+ );
+ $val = floor($val / 24);
+ if ($val == 0)
+ return $result;
+ $tmp = $val % 7;
+ $printed_conjunction = true;
+ if ($tmp > 1)
+ $result =
+ sprintf(
+ "%d days and %s",
+ $tmp,
+ $result
+ );
+ elseif ($tmp == 1)
+ $result =
+ sprintf(
+ "%d day and %s",
+ $tmp,
+ $result
+ );
+ else
+ $printed_conjunction = false;
+ $val = floor($val / 7);
+ if ($val == 0)
+ return $result;
+ if ($printed_conjunction)
+ $result =
+ sprintf(
+ ", %s",
+ $result
+ );
+ else
+ $result =
+ sprintf(
+ " and %s",
+ $result
+ );
+ if ($val>1)
+ $result =
+ sprintf(
+ "%d weeks%s",
+ $val,
+ $result
+ );
+ else
+ $result =
+ sprintf(
+ "%d week%s",
+ $val,
+ $result
+ );
+ return $result;
+};
+
+function git_url($repository,$type,$commit,$path,$line = null,$commit_is_hash = null) {
+ global $git_available;
+ if (!isset($git_available)) {
+ $memcache = new Memcache;
+ $memcache->connect('localhost', 11211) or die ('Memcached Connection Error');
+ $git_available = $memcache->get('git_available');
+ if ($git_available === false) {
+ $git_available =
+ preg_match(
+ "/ 200 OK$/",
+ get_headers("https://git.archlinux32.org/archlinux32/packages")[0]
+ );
+ $memcache->set('git_available',$git_available,0,120);
+ };
+ $git_available = $git_available == 1;
+ }
+ if (!isset($commit_is_hash))
+ $commit_is_hash = preg_match("/^[0-9a-f]{40}$/",$commit)==1;
+ if ($git_available) {
+ if (isset($line))
+ $line = "#L" . $line;
+ else
+ $line = "";
+ if ($commit_is_hash)
+ $commit = "commit/" . $commit;
+ else
+ $commit = "branch/" . $commit;
+ switch ($type) {
+ case "tree":
+ return
+ "https://git.archlinux32.org/archlinux32/" .
+ $repository .
+ "/src/" .
+ $commit .
+ "/" .
+ $path .
+ $line;
+ case "log":
+ return
+ "https://git.archlinux32.org/archlinux32/" .
+ $repository .
+ "/commits/" .
+ $commit .
+ "/" .
+ $path .
+ $line;
+ }
+
+ } else {
+ if (isset($line))
+ $line = "#n" . $line;
+ else
+ $line = "";
+ if ($commit_is_hash)
+ $commit = "?id=" . $commit;
+ else
+ $commit = "?h=" . $commit;
+ switch ($type) {
+ case "tree":
+ return
+ "https://git2.archlinux32.org/Archlinux32/" .
+ $repository .
+ "/tree/" .
+ $path .
+ $commit .
+ $line;
+ case "log":
+ return
+ "https://git2.archlinux32.org/Archlinux32/" .
+ $repository .
+ "/log/" .
+ $path .
+ $commit .
+ $line;
+ }
+ };
+};
+
+function if_unset($array, $index, $default) {
+ if (isset($array[$index]))
+ return $array[$index];
+ else
+ return $default;
+};
+
+function site_is_reachable($url) {
+ $scd = stream_context_get_default();
+ stream_context_set_default(array('timeout' => 10));
+ $headers = get_headers($url);
+ stream_context_set_default($scd);
+ if (is_array($headers))
+ foreach ($headers as $header) {
+ if (!(strpos($header, 'HTTP/') === 0))
+ continue;
+ if (explode(' ', $header)[1] == '200')
+ return true;
+ return false;
+ }
+ return false;
+}
+
+function add_fancy_unit($value, $unit) {
+ $suffixes = array("z", "y", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "Y", "Z");
+ if ($value==0)
+ return $value . " " . $unit;
+ $exponent = max(0,min(count($suffixes)-1,round(log(abs($value))/log(1024)-1)));
+ return sprintf("%.2f %s%s", $value / pow(1024,$exponent), $suffixes[8 + $exponent], $unit);
+}
diff --git a/lib/http.php b/lib/http.php
new file mode 100644
index 0000000..9b63337
--- /dev/null
+++ b/lib/http.php
@@ -0,0 +1,17 @@
+<?php
+
+# do not include twice
+if (function_exists("throw_http_error"))
+ return;
+
+function throw_http_error($error_number, $error_message, $extra_message = "") {
+ header("Status: " . $error_number . " " . $error_message);
+ print "Error " . $error_number . ": " . $error_message . "\n";
+ if ($extra_message != "")
+ print "<br>\n" . $extra_message;
+ die();
+};
+
+function die_500($message) {
+ throw_http_error(500, "Internal Server Error", $message);
+};
diff --git a/lib/mysql-joins.php b/lib/mysql-joins.php
new file mode 100644
index 0000000..751f1a0
--- /dev/null
+++ b/lib/mysql-joins.php
@@ -0,0 +1,1438 @@
+<?php
+
+/**
+ * generate below content with
+ * php mysql-joins.php
+ * executed from the builder directory
+ **/
+
+if (!isset($_SERVER["SERVER_ADDR"])) {
+ foreach (array('.', '../builder', '../../builder') as $base_dir)
+ if (file_exists($base_dir . '/lib/mysql-functions')) {
+ putenv('base_dir=' . $base_dir);
+ break;
+ }
+ $new_output =
+ "\n" .
+ trim(
+ shell_exec(
+ '. ${base_dir}/lib/mysql-functions;' .
+ 'declare -f $(' .
+ 'declare -F | cut -d" " -f3 | grep "^mysql_join_[a-z]" | grep -v "with_version"' .
+ ')'
+ )
+ );
+ $output = "";
+ $i = 5;
+ while ((strcmp($new_output,$output)!=0) && ($i > 0)) {
+ $output = $new_output;
+ $new_output =
+ preg_replace(
+ array(
+ '/ \[ -n "([^"]+)" \]; then/',
+ '/(\n\s*printf '."'[^'%]*)%s([^']*'".') "(\$[0-9]+)"/',
+ '/(\n\s*if [^\n]*)(\n([^\n]*;\n)+\s*)(else)(\n([^\n]*;\n)+\s*)fi;?\n/',
+ '/(\n\s*if [^\n]*)(\n([^\n]*;\n)+\s*)fi;?\n/'
+ ),
+ array(
+ ' (!empty(\1))',
+ '\1'."'".'.\3.'."'".'\2',
+ '\1 {\2} \4 {\5}'."\n",
+ '\1 {\2}'."\n"
+ ),
+ $output
+ );
+ $i--;
+ }
+ $output =
+ preg_replace(
+ array(
+ '/\$1/',
+ '/\$2/',
+ '/(\n)(\S+) \(\)\s*\n{/',
+ '/(\n})/',
+ '/(\s)printf(\s)/'
+ ),
+ array(
+ '$table_left',
+ '$table_right',
+ '\1function \2 ($table_left="", $table_right="") {'."\n".' $result = "";',
+ "\n".' return $result;\1',
+ '\1$result .=\2'
+ ),
+ $output
+ );
+ print $output . "\n";
+ die();
+}
+
+// auto-generated content below
+
+function mysql_join_allowed_email_actions_email_actions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `email_actions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`action`=';
+ } else {
+ $result .= ' ON `allowed_email_actions`.`action`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`email_actions`.`id`';
+ }
+ return $result;
+}
+function mysql_join_allowed_email_actions_gpg_keys ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `gpg_keys`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`gpg_key`=';
+ } else {
+ $result .= ' ON `allowed_email_actions`.`gpg_key`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`gpg_keys`.`id`';
+ }
+ return $result;
+}
+function mysql_join_architectures_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `architectures`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`architecture`';
+ } else {
+ $result .= '`binary_packages`.`architecture`';
+ }
+ return $result;
+}
+function mysql_join_architectures_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `architectures`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`architecture`';
+ } else {
+ $result .= '`build_assignments`.`architecture`';
+ }
+ return $result;
+}
+function mysql_join_architectures_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `architectures`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`architecture`';
+ } else {
+ $result .= '`repositories`.`architecture`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_architectures ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `architectures`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`architecture`=';
+ } else {
+ $result .= ' ON `binary_packages`.`architecture`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`architectures`.`id`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_binary_packages_in_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages_in_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `binary_packages`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package`';
+ } else {
+ $result .= '`binary_packages_in_repositories`.`package`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `binary_packages`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_assignments`.`id`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_build_dependency_loops ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_dependency_loops`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `binary_packages`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`build_dependency_loops`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_build_slaves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_slaves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `binary_packages`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`currently_building`';
+ } else {
+ $result .= '`build_slaves`.`currently_building`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `binary_packages`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`dependent`';
+ } else {
+ $result .= '`dependencies`.`dependent`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_in_repositories_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package`=';
+ } else {
+ $result .= ' ON `binary_packages_in_repositories`.`package`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`binary_packages`.`id`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_in_repositories_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package`=';
+ } else {
+ $result .= ' ON `binary_packages_in_repositories`.`package`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`dependent`';
+ } else {
+ $result .= '`dependencies`.`dependent`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_in_repositories_install_target_providers ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_target_providers`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package`=';
+ } else {
+ $result .= ' ON `binary_packages_in_repositories`.`package`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package`';
+ } else {
+ $result .= '`install_target_providers`.`package`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_in_repositories_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`repository`=';
+ } else {
+ $result .= ' ON `binary_packages_in_repositories`.`repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`repositories`.`id`';
+ }
+ return $result;
+}
+function mysql_join_binary_packages_install_target_providers ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_target_providers`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `binary_packages`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package`';
+ } else {
+ $result .= '`install_target_providers`.`package`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_architectures ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `architectures`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`architecture`=';
+ } else {
+ $result .= ' ON `build_assignments`.`architecture`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`architectures`.`id`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_assignments`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`binary_packages`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_build_dependency_loops ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_dependency_loops`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_assignments`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`build_dependency_loops`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_build_slaves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_slaves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_assignments`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`currently_building`';
+ } else {
+ $result .= '`build_slaves`.`currently_building`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_failed_builds ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `failed_builds`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_assignments`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`failed_builds`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_build_assignments_package_sources ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `package_sources`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package_source`=';
+ } else {
+ $result .= ' ON `build_assignments`.`package_source`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`package_sources`.`id`';
+ }
+ return $result;
+}
+function mysql_join_build_dependency_loops_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `build_dependency_loops`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`binary_packages`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_build_dependency_loops_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `build_dependency_loops`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_assignments`.`id`';
+ }
+ return $result;
+}
+function mysql_join_build_slaves_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`currently_building`=';
+ } else {
+ $result .= ' ON `build_slaves`.`currently_building`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_assignment`';
+ } else {
+ $result .= '`binary_packages`.`build_assignment`';
+ }
+ return $result;
+}
+function mysql_join_build_slaves_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`currently_building`=';
+ } else {
+ $result .= ' ON `build_slaves`.`currently_building`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_assignments`.`id`';
+ }
+ return $result;
+}
+function mysql_join_build_slaves_failed_builds ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `failed_builds`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_slaves`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_slave`';
+ } else {
+ $result .= '`failed_builds`.`build_slave`';
+ }
+ return $result;
+}
+function mysql_join_build_slaves_ssh_keys ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `ssh_keys`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`ssh_key`=';
+ } else {
+ $result .= ' ON `build_slaves`.`ssh_key`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`ssh_keys`.`id`';
+ }
+ return $result;
+}
+function mysql_join_build_slaves_ssh_log ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `ssh_log`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `build_slaves`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`build_slave`';
+ } else {
+ $result .= '`ssh_log`.`build_slave`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`dependent`=';
+ } else {
+ $result .= ' ON `dependencies`.`dependent`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`binary_packages`.`id`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_binary_packages_in_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages_in_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`dependent`=';
+ } else {
+ $result .= ' ON `dependencies`.`dependent`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package`';
+ } else {
+ $result .= '`binary_packages_in_repositories`.`package`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_dependency_types ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependency_types`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`dependency_type`=';
+ } else {
+ $result .= ' ON `dependencies`.`dependency_type`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`dependency_types`.`id`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_install_target_providers ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_target_providers`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`depending_on`=';
+ } else {
+ $result .= ' ON `dependencies`.`depending_on`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`install_target`';
+ } else {
+ $result .= '`install_target_providers`.`install_target`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_install_targets ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_targets`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`depending_on`=';
+ } else {
+ $result .= ' ON `dependencies`.`depending_on`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`install_targets`.`id`';
+ }
+ return $result;
+}
+function mysql_join_dependencies_versions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `versions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`version`=';
+ } else {
+ $result .= ' ON `dependencies`.`version`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`versions`.`id`';
+ }
+ return $result;
+}
+function mysql_join_dependency_types_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `dependency_types`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`dependency_type`';
+ } else {
+ $result .= '`dependencies`.`dependency_type`';
+ }
+ return $result;
+}
+function mysql_join_email_actions_allowed_email_actions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `allowed_email_actions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `email_actions`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`action`';
+ } else {
+ $result .= '`allowed_email_actions`.`action`';
+ }
+ return $result;
+}
+function mysql_join_email_actions_email_log ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `email_log`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `email_actions`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`action`';
+ } else {
+ $result .= '`email_log`.`action`';
+ }
+ return $result;
+}
+function mysql_join_email_log_email_actions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `email_actions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`action`=';
+ } else {
+ $result .= ' ON `email_log`.`action`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`email_actions`.`id`';
+ }
+ return $result;
+}
+function mysql_join_email_log_gpg_keys ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `gpg_keys`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`gpg_key`=';
+ } else {
+ $result .= ' ON `email_log`.`gpg_key`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`gpg_keys`.`id`';
+ }
+ return $result;
+}
+function mysql_join_fail_reasons_failed_builds ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `failed_builds`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `fail_reasons`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`reason`';
+ } else {
+ $result .= '`failed_builds`.`reason`';
+ }
+ return $result;
+}
+function mysql_join_failed_builds_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_assignment`=';
+ } else {
+ $result .= ' ON `failed_builds`.`build_assignment`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_assignments`.`id`';
+ }
+ return $result;
+}
+function mysql_join_failed_builds_build_slaves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_slaves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_slave`=';
+ } else {
+ $result .= ' ON `failed_builds`.`build_slave`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_slaves`.`id`';
+ }
+ return $result;
+}
+function mysql_join_failed_builds_fail_reasons ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `fail_reasons`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`reason`=';
+ } else {
+ $result .= ' ON `failed_builds`.`reason`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`fail_reasons`.`id`';
+ }
+ return $result;
+}
+function mysql_join_git_repositories_upstream_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `upstream_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `git_repositories`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`git_repository`';
+ } else {
+ $result .= '`upstream_repositories`.`git_repository`';
+ }
+ return $result;
+}
+function mysql_join_gpg_keys_allowed_email_actions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `allowed_email_actions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `gpg_keys`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`gpg_key`';
+ } else {
+ $result .= '`allowed_email_actions`.`gpg_key`';
+ }
+ return $result;
+}
+function mysql_join_gpg_keys_email_log ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `email_log`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `gpg_keys`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`gpg_key`';
+ } else {
+ $result .= '`email_log`.`gpg_key`';
+ }
+ return $result;
+}
+function mysql_join_gpg_keys_persons ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `persons`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`owner`=';
+ } else {
+ $result .= ' ON `gpg_keys`.`owner`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`persons`.`id`';
+ }
+ return $result;
+}
+function mysql_join_install_target_providers_binary_packages ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package`=';
+ } else {
+ $result .= ' ON `install_target_providers`.`package`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`binary_packages`.`id`';
+ }
+ return $result;
+}
+function mysql_join_install_target_providers_binary_packages_in_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages_in_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`package`=';
+ } else {
+ $result .= ' ON `install_target_providers`.`package`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package`';
+ } else {
+ $result .= '`binary_packages_in_repositories`.`package`';
+ }
+ return $result;
+}
+function mysql_join_install_target_providers_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`install_target`=';
+ } else {
+ $result .= ' ON `install_target_providers`.`install_target`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`depending_on`';
+ } else {
+ $result .= '`dependencies`.`depending_on`';
+ }
+ return $result;
+}
+function mysql_join_install_target_providers_install_targets ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_targets`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`install_target`=';
+ } else {
+ $result .= ' ON `install_target_providers`.`install_target`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`install_targets`.`id`';
+ }
+ return $result;
+}
+function mysql_join_install_target_providers_versions ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `versions`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`version`=';
+ } else {
+ $result .= ' ON `install_target_providers`.`version`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`versions`.`id`';
+ }
+ return $result;
+}
+function mysql_join_install_targets_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `install_targets`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`depending_on`';
+ } else {
+ $result .= '`dependencies`.`depending_on`';
+ }
+ return $result;
+}
+function mysql_join_install_targets_install_target_providers ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_target_providers`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `install_targets`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`install_target`';
+ } else {
+ $result .= '`install_target_providers`.`install_target`';
+ }
+ return $result;
+}
+function mysql_join_package_sources_build_assignments ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_assignments`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `package_sources`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`package_source`';
+ } else {
+ $result .= '`build_assignments`.`package_source`';
+ }
+ return $result;
+}
+function mysql_join_package_sources_repository_moves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repository_moves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`upstream_package_repository`=';
+ } else {
+ $result .= ' ON `package_sources`.`upstream_package_repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`upstream_package_repository`';
+ } else {
+ $result .= '`repository_moves`.`upstream_package_repository`';
+ }
+ return $result;
+}
+function mysql_join_package_sources_toolchain_order ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `toolchain_order`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`pkgbase`=';
+ } else {
+ $result .= ' ON `package_sources`.`pkgbase`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`pkgbase`';
+ } else {
+ $result .= '`toolchain_order`.`pkgbase`';
+ }
+ return $result;
+}
+function mysql_join_package_sources_upstream_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `upstream_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`upstream_package_repository`=';
+ } else {
+ $result .= ' ON `package_sources`.`upstream_package_repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`upstream_repositories`.`id`';
+ }
+ return $result;
+}
+function mysql_join_persons_gpg_keys ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `gpg_keys`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `persons`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`owner`';
+ } else {
+ $result .= '`gpg_keys`.`owner`';
+ }
+ return $result;
+}
+function mysql_join_persons_ssh_keys ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `ssh_keys`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `persons`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`owner`';
+ } else {
+ $result .= '`ssh_keys`.`owner`';
+ }
+ return $result;
+}
+function mysql_join_repositories_architectures ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `architectures`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`architecture`=';
+ } else {
+ $result .= ' ON `repositories`.`architecture`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`architectures`.`id`';
+ }
+ return $result;
+}
+function mysql_join_repositories_binary_packages_in_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `binary_packages_in_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `repositories`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`repository`';
+ } else {
+ $result .= '`binary_packages_in_repositories`.`repository`';
+ }
+ return $result;
+}
+function mysql_join_repositories_repository_stabilities ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repository_stabilities`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`stability`=';
+ } else {
+ $result .= ' ON `repositories`.`stability`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`repository_stabilities`.`id`';
+ }
+ return $result;
+}
+function mysql_join_repository_moves_package_sources ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `package_sources`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`upstream_package_repository`=';
+ } else {
+ $result .= ' ON `repository_moves`.`upstream_package_repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`upstream_package_repository`';
+ } else {
+ $result .= '`package_sources`.`upstream_package_repository`';
+ }
+ return $result;
+}
+function mysql_join_repository_moves_upstream_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `upstream_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`upstream_package_repository`=';
+ } else {
+ $result .= ' ON `repository_moves`.`upstream_package_repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`upstream_repositories`.`id`';
+ }
+ return $result;
+}
+function mysql_join_repository_stabilities_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `repository_stabilities`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`stability`';
+ } else {
+ $result .= '`repositories`.`stability`';
+ }
+ return $result;
+}
+function mysql_join_ssh_keys_build_slaves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_slaves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `ssh_keys`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`ssh_key`';
+ } else {
+ $result .= '`build_slaves`.`ssh_key`';
+ }
+ return $result;
+}
+function mysql_join_ssh_keys_persons ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `persons`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`owner`=';
+ } else {
+ $result .= ' ON `ssh_keys`.`owner`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`persons`.`id`';
+ }
+ return $result;
+}
+function mysql_join_ssh_log_build_slaves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `build_slaves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`build_slave`=';
+ } else {
+ $result .= ' ON `ssh_log`.`build_slave`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`build_slaves`.`id`';
+ }
+ return $result;
+}
+function mysql_join_toolchain_order_package_sources ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `package_sources`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`pkgbase`=';
+ } else {
+ $result .= ' ON `toolchain_order`.`pkgbase`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`pkgbase`';
+ } else {
+ $result .= '`package_sources`.`pkgbase`';
+ }
+ return $result;
+}
+function mysql_join_upstream_repositories_git_repositories ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `git_repositories`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`git_repository`=';
+ } else {
+ $result .= ' ON `upstream_repositories`.`git_repository`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`id`';
+ } else {
+ $result .= '`git_repositories`.`id`';
+ }
+ return $result;
+}
+function mysql_join_upstream_repositories_package_sources ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `package_sources`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `upstream_repositories`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`upstream_package_repository`';
+ } else {
+ $result .= '`package_sources`.`upstream_package_repository`';
+ }
+ return $result;
+}
+function mysql_join_upstream_repositories_repository_moves ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `repository_moves`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `upstream_repositories`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`upstream_package_repository`';
+ } else {
+ $result .= '`repository_moves`.`upstream_package_repository`';
+ }
+ return $result;
+}
+function mysql_join_versions_dependencies ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `dependencies`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `versions`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`version`';
+ } else {
+ $result .= '`dependencies`.`version`';
+ }
+ return $result;
+}
+function mysql_join_versions_install_target_providers ($table_left="", $table_right="") {
+ $result = "";
+ $result .= ' JOIN `install_target_providers`';
+ if (!empty($table_right)) {
+ $result .= ' AS `'.$table_right.'`';
+ }
+ if (!empty($table_left)) {
+ $result .= ' ON `'.$table_left.'`.`id`=';
+ } else {
+ $result .= ' ON `versions`.`id`=';
+ }
+ if (!empty($table_right)) {
+ $result .= '`'.$table_right.'`.`version`';
+ } else {
+ $result .= '`install_target_providers`.`version`';
+ }
+ return $result;
+}
diff --git a/lib/mysql.php b/lib/mysql.php
new file mode 100644
index 0000000..19d0dae
--- /dev/null
+++ b/lib/mysql.php
@@ -0,0 +1,90 @@
+<?php
+
+# do not include twice
+if (isset($mysql))
+ return;
+
+require_once "../init.php";
+include_once BASE . "/lib/http.php";
+include_once BASE . "/lib/mysql-joins.php";
+
+$mysql = new mysqli("localhost", "webserver", "empty", "buildmaster");
+if ( $mysql -> connect_error ) {
+ die_500( "Connection failed: " . $mysql -> connect_error );
+}
+
+function print_important_trace_components($call) {
+ return substr($call['file'], strlen(BASE)+1) . '(' . $call['line'] . ')';
+}
+
+function mysql_log_duration_and_trace($start) {
+ $start = round((microtime(true) - $start) * 1000000);
+ $trace = debug_backtrace();
+ array_shift($trace);
+ // silently fail if logfile is unavailable
+ if (($fp = fopen(BASE . '/log', 'a')) !== false) {
+ flock($fp, LOCK_EX);
+ fwrite($fp,
+ date('Y-m-d H:i:s') . " " .
+ $start . " " .
+ implode(' ', array_map('print_important_trace_components', $trace)) . " - " .
+ $trace[0]['args'][0] . "\n"
+ );
+ flock($fp, LOCK_UN);
+ fclose($fp);
+ }
+}
+
+function mysql_run_query($query) {
+ global $mysql;
+ $start = microtime(true);
+ if ( ! $result = $mysql -> query($query) )
+ die_500( "Query failed: " . $mysql -> error );
+ mysql_log_duration_and_trace($start);
+ return $result;
+}
+
+function mysql_prepare_query($query) {
+ global $mysql;
+ $start = microtime(true);
+ if ( ! $result = $mysql -> prepare($query) )
+ die_500( "Prepare failed: " . $mysql -> error );
+ mysql_log_duration_and_trace($start);
+ return $result;
+}
+
+function show_warning_on_offline_slave() {
+ $result = mysql_run_query("SHOW STATUS LIKE \"Slave_running\"");
+ if (($result -> num_rows == 0) ||
+ ($result -> fetch_assoc() ["Value"] != "ON")) {
+ print "<div><font color=\"ff0000\">The replication slave is currently not running. The database might be outdated.</font></div>\n";
+ }
+}
+
+function mysql_url_encode($input) {
+ return
+ "REPLACE(" . $input . ",\"+\",\"%2B\")";
+}
+
+function mysql_query_package_version($table) {
+ return
+ "CONCAT(" .
+ "IF(" .
+ "`" .$table . "`.`epoch`=\"0\"," .
+ "\"\"," .
+ "CONCAT(" .
+ "`" . $table . "`.`epoch`," .
+ "\":\"" .
+ ")" .
+ ")," .
+ "`" . $table . "`.`pkgver`,\"-\"," .
+ "`" . $table . "`.`pkgrel`," .
+ "IF(`" . $table . "`.`sub_pkgrel_omitted`," .
+ "\"\"," .
+ "CONCAT(" .
+ "\".\"," .
+ "`" . $table . "`.`sub_pkgrel`" .
+ ")" .
+ ")" .
+ ")";
+}
diff --git a/lib/style.php b/lib/style.php
new file mode 100644
index 0000000..29659f6
--- /dev/null
+++ b/lib/style.php
@@ -0,0 +1,74 @@
+<?php
+
+if (function_exists("print_header"))
+ return;
+
+require_once "../init.php";
+require_once BASE . "/lib/mysql.php";
+
+function print_header($title) {
+?>
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <title>Arch Linux 32 - <?php print $title; ?></title>
+ <link rel="stylesheet" type="text/css" href="/static/archweb.css" media="screen, projection" />
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico" />
+ <link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
+ <link rel="stylesheet" type="text/css" href="/static/flags/fam.47411010d402.css" media="screen, projection" />
+ </head>
+ <body class="">
+ <div id="archnavbar" class="anb-packages">
+ <div id="archnavbarlogo">
+ <h1><a href="/" title="Return to the main page">Arch Linux</a></h1>
+ </div>
+ <div id="archnavbarmenu">
+ <ul id="archnavbarlist">
+ <li id="anb-home"><a href="https://www.archlinux32.org/">Home</a></li>
+ <li id="anb-news"><a href="https://news.archlinux32.org/">News</a></li>
+ <li id="anb-packages"><a href="https://packages.archlinux32.org/">Packages</a></li>
+ <li id="anb-forums"><a href="https://bbs.archlinux32.org/">Forums</a></li>
+ <li id="anb-bugs"><a href="https://bugs.archlinux32.org/" title="Report and track bugs">Bugs</a></li>
+ <li id="anb-mailing-list"><a href="https://lists.archlinux.org/listinfo/arch-ports">Mailing List</a></li>
+ <li id="anb-download"><a href="https://www.archlinux32.org/download/" title="Get Arch Linux">Download</a></li>
+ <li id="anb-arch-linux-official"><a href="https://www.archlinux.org/">Arch Linux Official</a></li>
+ </ul>
+ </div>
+ </div>
+ <div id="content">
+<?php
+ show_warning_on_offline_slave();
+}
+
+function print_footer() {
+?>
+ <div id="footer">
+ <p>
+ Copyright © 2002-2018 <a href="mailto:jvinet@zeroflux.org" title="Contact Judd Vinet">Judd Vinet</a> and <a href="mailto:aaron@archlinux.org" title="Contact Aaron Griffin">Aaron Griffin</a>.
+ Copyright © 2018 <a href="mailto:arch@eckner.net" title="Contact Erich Eckner">Erich Eckner</a>.
+ </p>
+ <p>
+ The Arch Linux name and logo are recognized <a href="https://wiki.archlinux.org/index.php/DeveloperWiki:TrademarkPolicy" title="Arch Linux Trademark Policy">trademarks</a>. Some rights reserved.
+ </p>
+ <p>
+ The registered trademark Linux® is used pursuant to a sublicense from LMI, the exclusive licensee of Linus Torvalds, owner of the mark on a world-wide basis.
+ </p>
+ </div>
+ </div>
+ <script type="application/ld+json">
+ {
+ "@context": "http://schema.org",
+ "@type": "WebSite",
+ "url": "/",
+ "potentialAction": {
+ "@type": "SearchAction",
+ "target": "/?q={search_term}",
+ "query-input": "required name=search_term"
+ }
+ }
+ </script>
+ </body>
+</html>
+<?php
+}
diff --git a/mirrors/index.php b/mirrors/index.php
new file mode 100644
index 0000000..b74b25c
--- /dev/null
+++ b/mirrors/index.php
@@ -0,0 +1,135 @@
+<?php
+require_once "../init.php";
+
+require_once BASE . "/lib/mysql.php";
+require_once BASE . "/lib/style.php";
+
+$cutoff = 3600;
+
+$sorts = array(
+ "server" => array(
+ "title" => "server",
+ "label" => "Server",
+ "mysql" => "`url`"
+ ),
+ "country" => array(
+ "title" => "country",
+ "label" => "Country",
+ "mysql" => "`l_ms`.`country_code`"
+ ),
+ "isos" => array(
+ "title" => "wether isos are available",
+ "label" => "ISOs",
+ "mysql" => "`l_ms`.`isos`"
+ ),
+ "protocols" => array(
+ "title" => "available protocols",
+ "label" => "Protocols",
+ "mysql" => "`protocols`"
+ )
+);
+
+$query =
+ "SELECT " .
+ "GROUP_CONCAT(`l_ms`.`protocol`) AS `protocols`," .
+ "SUBSTRING(`l_ms`.`url`,LENGTH(`l_ms`.`protocol`)+4) AS `url`," .
+ "`l_ms`.`country`," .
+ "`l_ms`.`country_code`," .
+ "`l_ms`.`isos`," .
+ "`l_ms`.`ipv4`," .
+ "`l_ms`.`ipv6`" .
+ " FROM (" .
+ "SELECT " .
+ "`mirror_statuses`.`url`," .
+ "MAX(`mirror_statuses`.`start`) AS `start`" .
+ " FROM `mirror_statuses`" .
+ " WHERE `mirror_statuses`.`start` > UNIX_TIMESTAMP(NOW())-" . $cutoff .
+ " GROUP BY `mirror_statuses`.`url`" .
+ ") AS `ls`" .
+ " JOIN `mirror_statuses` AS `l_ms`" .
+ " ON `ls`.`url`=`l_ms`.`url`" .
+ " AND `ls`.`start`=`l_ms`.`start`" .
+ " GROUP BY `url`" .
+ " ORDER BY ";
+
+if (isset($_GET["sort"])) {
+ if (isset($sorts[$_GET["sort"]]["mysql"]))
+ $query .= $sorts[$_GET["sort"]]["mysql"] . ",";
+ elseif (isset($sorts[substr($_GET["sort"],1)]["mysql"]))
+ $query .= $sorts[substr($_GET["sort"],1)]["mysql"] . " DESC,";
+}
+
+$query .= "`url`";
+
+$result = mysql_run_query(
+ $query
+);
+
+$last_check = 0;
+$max_count = 0;
+
+while($row = $result->fetch_assoc())
+ $rows[] = $row;
+
+print_header("Mirror Overview");
+
+?>
+ <div id="dev-mirrorlist" class="box">
+ <h2>Mirror Overview</h2>
+ <table class="results">
+ <thead>
+ <tr>
+<?php
+ foreach ($sorts as $get => $sort) {
+ print " <th>\n";
+ print " <a href=\"/mirrors/?";
+ print substr(str_replace(
+ "&sort=".$_GET["sort"]."&",
+ "&",
+ "&".$_SERVER["QUERY_STRING"]."&"
+ ),1)."sort=";
+ if ($_GET["sort"] == $get)
+ print "-";
+ print $get."\" title=\"Sort package by ".$sort["title"]."\">".$sort["label"]."</a>\n";
+ print " </th>\n";
+ }
+?>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+
+$oddity = "odd";
+foreach ($rows as $row) {
+ print " <tr class=\"" . $oddity ."\">\n";
+ print " <td>\n";
+ print " " . $row["url"] . "\n";
+ print " </td>\n";
+ print " <td class=\"country\">\n";
+ print " <span class=\"fam-flag fam-flag-" . $row["country_code"] . "\" title=\"" . $row["country"] . "\">\n";
+ print " </span>\n";
+ print " " . $row["country"] . "\n";
+ print " </td>\n";
+ print " <td>\n";
+ if ($row["isos"])
+ print " Yes\n";
+ else
+ print " No\n";
+ print " </td>\n";
+ print " <td class=\"wrap\">\n";
+ print " " . $row["protocols"] . "\n";
+ print " </td>\n";
+ print " </tr>\n";
+ if ($oddity == "odd")
+ $oddity = "even";
+ else
+ $oddity = "odd";
+}
+
+?>
+ </tbody>
+ </table>
+ </div>
+<?php
+
+ print_footer();
diff --git a/mirrors/status.php b/mirrors/status.php
new file mode 100644
index 0000000..ddf922f
--- /dev/null
+++ b/mirrors/status.php
@@ -0,0 +1,84 @@
+<?php
+require_once "../init.php";
+
+require_once BASE . "/lib/mysql.php";
+require_once BASE . "/lib/format.php";
+
+$cutoff = 86400;
+
+$result = mysql_run_query(
+ "SELECT " .
+ "`l_ms`.`protocol`," .
+ "`l_ms`.`url`," .
+ "`l_ms`.`country`," .
+ "`l_ms`.`country_code`," .
+ "`l_ms`.`last_sync`," .
+ "`l_ms`.`start`," .
+ "AVG(IF(`a_ms`.`active`,(`a_ms`.`start`-`a_ms`.`last_sync`)/3600,NULL)) AS `delay`," .
+ "AVG(IF(`a_ms`.`active`,(`a_ms`.`stop`-`a_ms`.`start`)/3600,NULL)) AS `duration_avg`," .
+ "STD(IF(`a_ms`.`active`,(`a_ms`.`stop`-`a_ms`.`start`)/3600,NULL)) AS `duration_stddev`," .
+ "`l_ms`.`isos`," .
+ "`l_ms`.`ipv4`," .
+ "`l_ms`.`ipv6`," .
+ "`l_ms`.`active`," .
+ "(`l_ms`.`active` AND (`l_ms`.`start` > UNIX_TIMESTAMP(NOW()) - 3600)) AS `recently_active`," .
+ "AVG(IF(`a_ms`.`active`,1,0)) AS `completion_pct`," .
+ "COUNT(1) AS `count`" .
+ " FROM (" .
+ "SELECT " .
+ "`mirror_statuses`.`url`," .
+ "MAX(`mirror_statuses`.`start`) AS `start`" .
+ " FROM `mirror_statuses`" .
+ " WHERE `mirror_statuses`.`start` > UNIX_TIMESTAMP(NOW())-" . $cutoff .
+ " GROUP BY `mirror_statuses`.`url`" .
+ ") AS `ls`" .
+ " JOIN `mirror_statuses` AS `l_ms`" .
+ " ON `ls`.`url`=`l_ms`.`url`" .
+ " AND `ls`.`start`=`l_ms`.`start`" .
+ " JOIN `mirror_statuses` AS `a_ms`" .
+ " ON `a_ms`.`url`=`l_ms`.`url`" .
+ " AND `a_ms`.`start` > UNIX_TIMESTAMP(NOW())-" . $cutoff .
+ " GROUP BY `l_ms`.`id`"
+);
+
+$last_check = 0;
+$max_count = 0;
+
+while($row = $result->fetch_assoc()) {
+ foreach (array(
+ "start",
+ "delay",
+ "duration_avg",
+ "duration_stddev",
+ "completion_pct",
+ "count",
+ "isos",
+ "ipv4",
+ "ipv6",
+ "active",
+ "recently_active"
+ ) as $key)
+ $row[$key] = floatval($row[$key]);
+ $row["last_sync"] = gmdate("Y-m-d\TH:i:s\Z", $row["last_sync"]);
+ $row["score"] =
+ ($row["delay"] + $row["duration_avg"] + $row["duration_stddev"]) / $row["completion_pct"];
+ $urls[] = $row;
+ $last_check = max ($row["start"], $last_check);
+ $max_count = max ($row["count"], $max_count);
+}
+
+$content = array(
+ "cutoff" => $cutoff,
+ "check_frequency" => $cutoff/$max_count,
+ "num_checks" => $max_count,
+ "last_check" => gmdate("Y-m-d\TH:i:s.v\Z",$last_check), //"2018-06-15T07:25:06.741Z",
+// "version" => 3,
+ "urls" => $urls
+);
+
+export_as_requested(
+ array(
+ "json" => $content,
+ "tsv" => $urls
+ )
+);
diff --git a/packages/favicon.ico b/packages/favicon.ico
new file mode 100644
index 0000000..8ef6f13
--- /dev/null
+++ b/packages/favicon.ico
Binary files differ
diff --git a/packages/index.php b/packages/index.php
new file mode 100644
index 0000000..1d3acca
--- /dev/null
+++ b/packages/index.php
@@ -0,0 +1,532 @@
+<?php
+require_once "../init.php";
+
+require_once BASE . "/lib/mysql.php";
+require_once BASE . "/lib/style.php";
+require_once BASE . "/lib/format.php";
+
+
+ foreach (array("bugs","sort","del","uses_upstream","uses_modification") as $expected_param)
+ if (! isset($_GET[$expected_param]))
+ $_GET[$expected_param] = "";
+
+ $multi_select_search_criteria = array(
+ "arch" => array(
+ "name" => "arch",
+ "title" => "CPU architecture",
+ "label" => "Arch",
+ "table" => "architectures",
+ "column" => "`architectures`.`name`",
+ "extra_condition" => "",
+ "values" => array()
+ ),
+ "repo" => array(
+ "name" => "repo",
+ "title" => "respository",
+ "label" => "Repository",
+ "table" => "repositories",
+ "column" => "CONCAT(`architectures`.`name`,\"/\",`repositories`.`name`)",
+ "extra_condition" => mysql_join_repositories_architectures() . " WHERE `repositories`.`is_on_master_mirror`",
+ "values" => array()
+ )
+ );
+
+ foreach ( $multi_select_search_criteria as $criterium => $content ) {
+ $result = mysql_run_query(
+ "SELECT " . $content["column"] . " AS `name` FROM `" . $content["table"] . "`" . $content["extra_condition"] . " ORDER BY `name`"
+ );
+ while ($row = $result -> fetch_assoc())
+ $multi_select_search_criteria[$criterium]["values"][] = $row["name"];
+ }
+
+ $float_columns = array(
+ "has_issues",
+ "is_to_be_deleted"
+ );
+
+ $filter = " WHERE 1";
+ foreach ($multi_select_search_criteria as $criterium)
+ if (isset($_GET[$criterium["name"]])) {
+ $filter .= " AND " . $criterium["column"] . " IN (";
+ foreach ($criterium["values"] as $value)
+ if (strpos("&" . urldecode($_SERVER["QUERY_STRING"]) . "&", "&" . $criterium["name"] . "=" . $value . "&") !== false)
+ $filter .= "\"" . $value . "\",";
+ $filter .= "\"\")";
+ }
+
+ $single_select_search_criteria = array(
+ "bugs" => array(
+ "name" => "bugs",
+ "label" => "Bugs",
+ "title" => "bug-tracker status",
+ "options" => array(
+ "All" => "1",
+ "Bugs" => "`binary_packages`.`has_issues`",
+ "No Bugs" => "NOT `binary_packages`.`has_issues`"
+ )
+ ),
+ "del" => array(
+ "name" => "del",
+ "label" => "To Be Deleted",
+ "title" => "to-be-deleted status",
+ "options" => array(
+ "All" => "1",
+ "To Be Deleted" => "`binary_packages_in_repositories`.`is_to_be_deleted`",
+ "Not To Be Deleted" => "NOT `binary_packages_in_repositories`.`is_to_be_deleted`"
+ )
+ ),
+ "uses_upstream" => array(
+ "name" => "uses_upstream",
+ "label" => "Upstream",
+ "title" => "wether upstream source exists",
+ "options" => array(
+ "All" => "1",
+ "Uses Upstream" => "`package_sources`.`uses_upstream`",
+ "Does Not Use Upstream" => "NOT `package_sources`.`uses_upstream`"
+ )
+ ),
+ "uses_modification" => array(
+ "name" => "uses_modification",
+ "label" => "Modification",
+ "title" => "wether modification exists",
+ "options" => array(
+ "All" => "1",
+ "Uses Modification" => "`package_sources`.`uses_modification`",
+ "Does Not Use Modification" => "NOT `package_sources`.`uses_modification`"
+ )
+ )
+ );
+
+ foreach ($single_select_search_criteria as $criterium)
+ if (isset($_GET[$criterium["name"]]) &&
+ isset($criterium["options"][$_GET[$criterium["name"]]]))
+ $filter .= " AND " . $criterium["options"][$_GET[$criterium["name"]]];
+
+ if (isset($_GET["q"])) {
+ $exact_filter = " AND `binary_packages`.`pkgname` = from_base64(\"".base64_encode($_GET["q"])."\")";
+ $fuzzy_filter = " AND `binary_packages`.`pkgname` LIKE from_base64(\"".base64_encode("%".$_GET["q"]."%")."\")";
+ } else {
+ $exact_filter = " AND 0";
+ $fuzzy_filter = "";
+ }
+
+ $query = " FROM `binary_packages`" .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " AND `repositories`.`is_on_master_mirror`" .
+ mysql_join_repositories_architectures("","r_a") .
+ mysql_join_binary_packages_build_assignments() .
+ mysql_join_build_assignments_package_sources() .
+ $filter . $exact_filter .
+ " ORDER BY ";
+
+ $query .= "`binary_packages`.`pkgname`,`repositories`.`stability`,`repositories`.`name`,`architectures`.`name`";
+
+ $result = mysql_run_query(
+ "SELECT " .
+ "`binary_packages`.`pkgname`," .
+ "`package_sources`.`pkgbase`," .
+ "CONCAT(`r_a`.`name`,\"/\",`repositories`.`name`) AS `repo`," .
+ "`architectures`.`name` AS `arch`," .
+ mysql_query_package_version("binary_packages") .
+ " AS `version`," .
+ "IF(`binary_packages`.`has_issues`,1,0) AS `has_issues`," .
+ "`build_assignments`.`return_date` AS `build_date`," .
+ "`binary_packages_in_repositories`.`last_moved` AS `move_date`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`" .
+ $query
+ );
+ $exact_matches = array();
+ while ($row = $result -> fetch_assoc()) {
+ foreach ($float_columns as $float_column)
+ $row[$float_column] = floatval($row[$float_column]);
+ $exact_matches[] = $row;
+ }
+
+ $sorts = array(
+ "arch" => array(
+ "title" => "architecture",
+ "label" => "Arch",
+ "mysql" => "`architectures`.`name`"
+ ),
+ "repo" => array(
+ "title" => "repository",
+ "label" => "Repo",
+ "mysql" => "CONCAT(`r_a`.`name`,\"/\",`repositories`.`name`)"
+ ),
+ "pkgname" => array(
+ "title" => "package name",
+ "label" => "Name",
+ "mysql" => "`binary_packages`.`pkgname`"
+ ),
+ "pkgver" => array(
+ "title" => "package version",
+ "label" => "Version",
+ "mysql" => mysql_query_package_version("binary_packages")
+ ),
+ "bugs" => array(
+ "title" => "bug status",
+ "label" => "Bugs",
+ "mysql" => "NOT `binary_packages`.`has_issues`"
+ ),
+ "build_date" => array(
+ "title" => "build date",
+ "label" => "Build Date",
+ "mysql" => "IFNULL(`build_assignments`.`return_date`,\"00-00-0000 00:00:00\")"
+ ),
+ "move_date" => array(
+ "title" => "last update",
+ "label" => "Last Updated",
+ "mysql" => "IFNULL(`binary_packages_in_repositories`.`last_moved`,\"00-00-0000 00:00:00\")"
+ ),
+ "del" => array(
+ "title" => "to be deleted",
+ "label" => "Delete",
+ "mysql" => "`binary_packages_in_repositories`.`is_to_be_deleted`"
+ )
+ );
+
+ $query = " FROM `binary_packages`" .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " AND `repositories`.`is_on_master_mirror`" .
+ mysql_join_repositories_architectures("","r_a") .
+ mysql_join_binary_packages_build_assignments() .
+ mysql_join_build_assignments_package_sources() .
+ $filter . $fuzzy_filter .
+ " ORDER BY ";
+
+ if (isset($_GET["sort"])) {
+ if (isset($sorts[$_GET["sort"]]["mysql"]))
+ $query .= $sorts[$_GET["sort"]]["mysql"] . ",";
+ elseif (isset($sorts[substr($_GET["sort"],1)]["mysql"]))
+ $query .= $sorts[substr($_GET["sort"],1)]["mysql"] . " DESC,";
+ }
+
+ $query .= "`binary_packages`.`pkgname`,`repositories`.`stability`,`repositories`.`name`,`architectures`.`name`";
+
+ $result = mysql_run_query(
+ "SELECT COUNT(1)" . $query
+ );
+ $num_results = implode($result -> fetch_assoc());
+
+ $pages = max(ceil($num_results / 100), 1);
+ if (isset($_GET["page"]))
+ $page = max(min($_GET["page"]+0, $pages),1);
+ else
+ $page = 1;
+
+ $result = mysql_run_query(
+ "SELECT " .
+ "`binary_packages`.`pkgname`," .
+ "`package_sources`.`pkgbase`," .
+ "CONCAT(`r_a`.`name`,\"/\",`repositories`.`name`) AS `repo`," .
+ "`architectures`.`name` AS `arch`," .
+ mysql_query_package_version("binary_packages") .
+ " AS `version`," .
+ "IF(`binary_packages`.`has_issues`,1,0) AS `has_issues`," .
+ "`build_assignments`.`return_date` AS `build_date`," .
+ "`binary_packages_in_repositories`.`last_moved` AS `move_date`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`" .
+ $query .
+ " LIMIT " . (($page-1)*100) . ", 100"
+ );
+ $fuzzy_matches = array();
+ while ($row = $result -> fetch_assoc()) {
+ foreach ($float_columns as $float_column)
+ $row[$float_column] = floatval($row[$float_column]);
+ $fuzzy_matches[] = $row;
+ }
+
+ function print_results($results) {
+ $oddity="odd";
+ foreach ($results as $row) {
+ print " <tr class=\"" . $oddity . "\">\n";
+ print " <td>\n";
+ print " " . $row["arch"] . "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " " . $row["repo"] . "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " <a href=\"/" . $row["repo"] . "/" . $row["pkgname"] ."/\" ";
+ print "title=\"View package details for " . $row["pkgname"] . "\">" . $row["pkgname"] . "</a>\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " " . $row["version"] . "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " ";
+ if ($row["has_issues"])
+ print "has open bug reports";
+ else
+ print "&nbsp;";
+ print "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " ";
+ if (isset($row["build_date"]))
+ print $row["build_date"];
+ else
+ print "&nbsp;";
+ print "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " ";
+ if (isset($row["move_date"]))
+ print $row["move_date"];
+ else
+ print "&nbsp;";
+ print "\n";
+ print " </td>\n";
+ print " <td>\n";
+ print " ";
+ if ($row["is_to_be_deleted"])
+ print "to be deleted";
+ else
+ print "&nbsp;";
+ print "\n";
+ print " </td>\n";
+ print " </tr>\n";
+ if ($oddity == "odd" )
+ $oddity = "even";
+ else
+ $oddity = "odd";
+ }
+ }
+
+ function header_and_footer() {
+
+ global $page, $pages, $num_results;
+
+ print " <div class=\"pkglist-stats\">\n";
+ print " <p>\n";
+ print " " . $num_results . " matching package";
+ if ($num_results != 1)
+ print "s";
+ print " found.\n";
+
+ if ($pages != 1)
+ print " Page " . $page . " of " . $pages . ".\n";
+
+ print " </p>\n";
+
+ if ($pages != 1) {
+ print " <div class=\"pkglist-nav\">\n";
+ print " <span class=\"prev\">\n";
+
+ print " ";
+ if ($page > 1) {
+ print "<a href=\"?";
+ print substr(str_replace(
+ "&page=".$page."&",
+ "&",
+ "&".$_SERVER["QUERY_STRING"]."&"
+ ),1)."page=".($page-1);
+ print "\" title=\"Go to previous page\">";
+ };
+ print "&lt; Prev";
+ if ($page > 1)
+ print "</a>";
+ print "\n";
+ print " </span>\n";
+ print " <span class=\"next\">\n";
+
+ print " ";
+ if ($page < $pages) {
+ print "<a href=\"?";
+ print substr(str_replace(
+ "&page=".$page."&",
+ "&",
+ "&".$_SERVER["QUERY_STRING"]."&"
+ ),1)."page=".($page+1);
+ print "\" title=\"Go to next page\">";
+ };
+ print "Next &gt;";
+ if ($page < $pages)
+ print "</a>";
+ print "\n";
+ print " </span>\n";
+ print " </div>\n";
+ };
+ print " </div>\n";
+
+ };
+
+ if (isset($_GET["exact"])) {
+ export_as_requested(
+ array(
+ "All" => $exact_matches
+ )
+ );
+ die();
+ };
+
+ if (isset($_GET["fuzzy"])) {
+ export_as_requested(
+ array(
+ "All" => $fuzzy_matches
+ )
+ );
+ die();
+ };
+
+ print_header("Package Search");
+
+?>
+ <div id="pkglist-search" class="box filter-criteria">
+ <h2>Package Search</h2>
+ <form id="pkg-search" method="get" action="/">
+ <p><input id="id_sort" name="sort" type="hidden" /></p>
+ <fieldset>
+ <legend>Enter search criteria</legend>
+<?php
+ foreach ($multi_select_search_criteria as $criterium) {
+ print " <div>\n";
+ print " <label for=\"id_" . $criterium["name"] . "\" title=\"Limit results to a specific " . $criterium["title"] . "\">";
+ print $criterium["label"];
+ print "</label>\n";
+ print " <select multiple=\"multiple\" id=\"id_" . $criterium["name"] . "\" name=\"" . $criterium["name"] . "\">\n";
+ foreach ($criterium["values"] as $value) {
+ print " <option value=\"" . $value . "\"";
+ if (strpos( "&" . urldecode($_SERVER["QUERY_STRING"]) . "&", "&" . $criterium["name"] . "=" . $value . "&") !== false)
+ print " selected=\"selected\"";
+ print ">" . $value . "</option>\n";
+ }
+ print " </select>\n";
+ print " </div>\n";
+ }
+?>
+ <div>
+ <label for="id_q" title="Enter keywords as desired">Keywords</label>
+ <input id="id_q" name="q" size="30" type="text" <?php
+if (isset($_GET["q"]))
+ print "value=\"".$_GET["q"]."\"";
+?>/>
+ </div>
+<?php
+ foreach ($single_select_search_criteria as $criterium) {
+
+ print " <div>\n";
+ print " <label for=\"id_";
+ print $criterium["name"];
+ print "\" title=\"Limit results based on ";
+ print $criterium["title"];
+ print "\">";
+ print $criterium["label"];
+ print "</label><select id=\"id_";
+ print $criterium["name"];
+ print "\" name=\"";
+ print $criterium["name"];
+ print "\">\n";
+
+ foreach ($criterium["options"] as $label => $option) {
+ print " <option value=\"";
+ if ($label != "All")
+ print $label;
+ print "\"";
+ if ($_GET[$criterium["name"]]==$label)
+ print " selected=\"selected\"";
+ print ">" . $label . "</option>\n";
+ }
+ print " </select>\n";
+ print " </div>\n";
+ }
+?>
+ <div>
+ <label>&nbsp;</label>
+ <input title="Search for packages using this criteria" type="submit" value="Search">
+ </div>
+ </fieldset>
+ </form>
+ </div>
+<?php
+
+if (count($exact_matches) > 0) {
+?>
+ <div id="exact-matches" class="box">
+ <div class="pkglist-stats">
+ <p><?php print count($exact_matches); ?> exact match<?php if (count($exact_matches) != 1) print "es"; ?> found.</p>
+ </div>
+ <table class="results">
+ <thead>
+ <tr>
+<?php
+
+ foreach ($sorts as $get => $sort) {
+ print " <th>\n";
+ print " ".$sort["label"]."\n";
+ print " </th>\n";
+ }
+?>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+ print_results($exact_matches);
+?>
+ </tbody>
+ </table>
+ </div>
+<?php
+}
+
+?>
+ <div id="pkglist-results" class="box">
+<?php
+
+ header_and_footer();
+
+?>
+ <table class="results">
+ <thead>
+ <tr>
+<?php
+
+ foreach ($sorts as $get => $sort) {
+ print " <th>\n";
+ print " <a href=\"/?";
+ print substr(str_replace(
+ "&sort=".$_GET["sort"]."&",
+ "&",
+ "&".$_SERVER["QUERY_STRING"]."&"
+ ),1)."sort=";
+ if ($_GET["sort"] == $get)
+ print "-";
+ print $get."\" title=\"Sort package by ".$sort["title"]."\">".$sort["label"]."</a>\n";
+ print " </th>\n";
+ }
+?>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+
+ print_results($fuzzy_matches);
+
+?>
+ </tbody>
+ </table>
+<?php
+
+ header_and_footer();
+
+?>
+ </div>
+ <div id="pkglist-about" class="box">
+ <p>
+ Can't find what you are looking for? Try searching again
+ using different criteria, or try
+ searching the <a href="https://aur.archlinux.org/">AUR</a>
+ to see if the package can be found there.
+ </p>
+ <p>
+ You are browsing the Arch Linux 32 package database. From here you can find
+ detailed information about packages located in the 32 bit repositories.
+ </p>
+ </div>
+<?php
+
+ print_footer();
diff --git a/packages/pkginfo.php b/packages/pkginfo.php
new file mode 100644
index 0000000..0717aa1
--- /dev/null
+++ b/packages/pkginfo.php
@@ -0,0 +1,701 @@
+<?php
+require_once "../init.php";
+
+if (($_GET['repo']=='i686') || ($_GET['repo']=='i486') || ($_GET['repo']=='any')) {
+ header('Location: /' . $_GET['repo'] . '/' . $_GET['repo_arch'] . '/' . $_GET['pkgname'] . '/');
+ error_log('needed redirect URL: ' . $_SERVER['REQUEST_URI'] . ', HTTP_USER_AGENT: ' . $_SERVER['HTTP_USER_AGENT'] . ', HTTP_REFERER: ' . $_SERVER['HTTP_REFERER']);
+ die();
+}
+
+require_once BASE . "/lib/helper.php";
+require_once BASE . "/lib/mysql.php";
+require_once BASE . "/lib/style.php";
+
+ $memcache = new Memcache;
+ $memcache -> connect('localhost', 11211) or die ('Memcached Connection Error');
+ $pkgapi_reachable = $memcache -> get('pkgapi_reachable');
+ $tld = explode('.', $_SERVER['HTTP_HOST']);
+ end($tld);
+ $tld = current($tld);
+ if ((array_key_exists('HTTPS', $_SERVER) &&
+ ($_SERVER['HTTPS'] == 'on')) ||
+ (array_key_exists('HTTP_X_FORWARDED_PROTO', $_SERVER) &&
+ ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')))
+ $protocol = 'https';
+ else
+ $protocol = 'http';
+ if ($pkgapi_reachable === false) {
+ if (site_is_reachable($protocol . '://pkgapi.archlinux32.' . $tld . '/'))
+ $pkgapi_reachable = 'YES';
+ else
+ $pkgapi_reachable = 'NO';
+ $memcache -> set('pkgapi_reachable', $pkgapi_reachable, 0, 300);
+ }
+ if ($pkgapi_reachable == 'YES')
+ $skip_json_checks = false;
+ else
+ $skip_json_checks = true;
+
+ if (!array_key_exists("repo_arch",$_GET)) {
+ $_GET["repo_arch"] = $_GET["arch"];
+ unset($_GET["arch"]);
+ }
+
+ if (!$skip_json_checks) {
+ $json_content = json_decode(
+ file_get_contents(
+ $protocol . '://pkgapi.archlinux32.' . $tld . '/' .
+ urlencode($_GET["repo_arch"]) . '/' .
+ urlencode($_GET["repo"]) . '/' .
+ urlencode($_GET["pkgname"])
+ ),
+ true
+ );
+
+ if (!isset($json_content) || !array_key_exists('Name', $json_content)) {
+ //throw_http_error(404, "Package Not Found In Sync Database");
+ unset($json_content);
+ $skip_json_checks = true;
+ };
+ }
+
+ $mysql_result = mysql_run_query(
+ "SELECT " .
+ "`binary_packages`.`id`," .
+ "`binary_packages`.`pkgname`," .
+ "`sp_q`.`split_packages`," .
+ "`package_sources`.`pkgbase`," .
+ mysql_query_package_version("binary_packages") .
+ " AS `version`," .
+ "`repositories`.`stability` AS `repo_stability`," .
+ "`repository_stabilities`.`name` AS `repo_stability_name`," .
+ "`repositories`.`name` AS `repo`," .
+ "`r_a`.`name` AS `repo_arch`," .
+ "`architectures`.`name` AS `arch`," .
+ "`git_repositories`.`name` AS `git_repo`," .
+ "`package_sources`.`uses_upstream`," .
+ "`package_sources`.`uses_modification`," .
+ "MAX(`binary_packages_in_repositories`.`last_moved`) AS `last_moved`," .
+ "`sr`.`name` AS `stable_repo`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_repository_stabilities() .
+ mysql_join_repositories_architectures("","r_a") .
+ mysql_join_binary_packages_build_assignments() .
+ mysql_join_build_assignments_package_sources() .
+ mysql_join_package_sources_upstream_repositories() .
+ mysql_join_upstream_repositories_git_repositories() .
+ mysql_join_upstream_repositories_repository_moves() .
+ " JOIN `repositories` AS `sr` ON `sr`.`id`=`repository_moves`.`to_repository`" .
+ " JOIN (" .
+ "SELECT DISTINCT `binary_packages`.`build_assignment`," .
+ "GROUP_CONCAT(" .
+ "CONCAT(" .
+ "\"\\\"\",`binary_packages`.`id`,\"\\\": {" .
+ "\\\"pkgname\\\":" .
+ " \\\"\",`binary_packages`.`pkgname`,\"\\\"," .
+ "\\\"repository\\\":" .
+ " \\\"\",`repositories`.`name`,\"\\\"," .
+ "\\\"repo_arch\\\":" .
+ " \\\"\",`architectures`.`name`,\"\\\"" .
+ "}\"" .
+ ")" .
+ ") AS `split_packages`" .
+ " FROM `binary_packages`" .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_architectures() .
+ " GROUP BY `binary_packages`.`build_assignment`" .
+ ") AS `sp_q`" .
+ " ON `sp_q`.`build_assignment`=`build_assignments`.`id`" .
+ " WHERE `binary_packages`.`pkgname`=from_base64(\"" . base64_encode($_GET["pkgname"]) . "\")" .
+ " AND `r_a`.`name`=from_base64(\"" . base64_encode($_GET["repo_arch"]) . "\")" .
+ " AND `repositories`.`name`=from_base64(\"" . base64_encode($_GET["repo"]) . "\")" .
+ " AND NOT EXISTS (" .
+ "SELECT 1" .
+ " FROM `repository_moves` AS `rm`" .
+ " WHERE `rm`.`from_repository`=`sr`.`id`" .
+ ")" .
+ " GROUP BY `binary_packages`.`id`"
+ );
+
+ if ($mysql_result -> num_rows != 1)
+ throw_http_error(404, "Package Not Found In Buildmaster's Database");
+
+ $mysql_content = $mysql_result -> fetch_assoc();
+ $mysql_content["split_packages"] = array_map("unserialize", array_unique(array_map("serialize", json_decode("{".$mysql_content["split_packages"]."}",true))));
+
+ if (!$skip_json_checks) {
+ $same_keys = array (
+ array("mysql" => "pkgname", "json" => "Name"),
+ array("mysql" => "version", "json" => "Version", "suffix_diff" => ".0"),
+ array("mysql" => "repo", "json" => "Repository"),
+ array("mysql" => "arch", "json" => "Architecture")
+ );
+
+ foreach ($same_keys as $same_key)
+ if (($mysql_content[$same_key["mysql"]] != $json_content[$same_key["json"]]) &&
+ ((!array_key_exists('suffix_diff', $same_key)) ||
+ ($mysql_content[$same_key["mysql"]] != $json_content[$same_key["json"]].$same_key["suffix_diff"])))
+ die_500("Inconsistency in Database found:<br>\n" .
+ "buildmaster[" . $same_key["mysql"] . "] != repositories[" . $same_key["json"] . "]:<br>\n" .
+ "\"" . $mysql_content[$same_key["mysql"]] . "\" != \"" . $json_content[$same_key["json"]] . "\"");
+ }
+
+ // query _all_ dependencies
+
+ $mysql_result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`dependency_types`.`name` AS `dependency_type`," .
+ "GROUP_CONCAT(" .
+ "CONCAT(\"\\\"\",`install_target_providers`.`id`,\"\\\": \",\"{\\n\"," .
+ "\" \\\"repo\\\": \\\"\",`repositories`.`name`,\"\\\",\\n\"," .
+ "\" \\\"repo_arch\\\": \\\"\",`r_a`.`name`,\"\\\",\\n\"," .
+ "\" \\\"arch\\\": \\\"\",`architectures`.`name`,\"\\\",\\n\"," .
+ "\" \\\"pkgname\\\": \\\"\",`binary_packages`.`pkgname`,\"\\\",\\n\"," .
+ "\" \\\"is_to_be_deleted\\\": \\\"\",IF(`binary_packages_in_repositories`.`is_to_be_deleted`,\"1\",\"0\"),\"\\\"\\n\"," .
+ "\"}\"" .
+ ")) AS `deps`," .
+ "IF(" .
+ "(" .
+ "`versions`.`order`=1 AND `dependencies`.`version_relation`=\">=\"" .
+ ") OR (" .
+ "`versions`.`epoch`=8388607 AND `dependencies`.`version_relation`=\"<\"" .
+ ")," .
+ "\"\"," .
+ "CONCAT(" .
+ "`dependencies`.`version_relation`," .
+ "IF(" .
+ "`versions`.`epoch`=0," .
+ "\"\"," .
+ "CONCAT(" .
+ "`versions`.`epoch`," .
+ "\":\"" .
+ ")" .
+ ")," .
+ "`versions`.`version`" .
+ ")" .
+ ") AS `version`," .
+ "`install_targets`.`name` AS `install_target`" .
+ " FROM `dependencies`" .
+ " LEFT JOIN (".
+ "`binary_packages_in_repositories` AS `bpir`" .
+ mysql_join_binary_packages_in_repositories_repositories('bpir','r') .
+ mysql_join_repositories_architectures('r','r_a') .
+ ") ON `bpir`.`package`=`dependencies`.`dependent`" .
+ mysql_join_dependencies_dependency_types() .
+ mysql_join_dependencies_install_targets() .
+ " AND `install_targets`.`name` NOT IN (\"base\",\"base-devel\")" .
+ mysql_join_dependencies_versions() .
+ " LEFT JOIN (" .
+ "`install_target_providers`" .
+ mysql_join_install_target_providers_binary_packages() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " JOIN `repository_stability_relations` ON `repository_stability_relations`.`more_stable`=`repositories`.`stability`" .
+ " AND `repository_stability_relations`.`less_stable`=" . $mysql_content["repo_stability"] .
+ ") ON `install_target_providers`.`install_target`=`dependencies`.`depending_on`" .
+ " AND `repositories`.`architecture`=`r`.`architecture`" .
+ " WHERE `dependencies`.`dependent`=" . $mysql_content["id"] .
+ " AND NOT EXISTS (" .
+ "SELECT 1 FROM `binary_packages` AS `subst_bp`" .
+ mysql_join_binary_packages_binary_packages_in_repositories('subst_bp','subst_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('subst_bpir','subst_r') .
+ // the substitue must be truly less stable than the dependency
+ " JOIN `repository_stability_relations` AS `subst_rsr` ON `subst_rsr`.`less_stable`=`subst_r`.`stability`" .
+ " AND `subst_rsr`.`less_stable`!=`subst_rsr`.`more_stable`" .
+ // and more (or equally) stable than us
+ " JOIN `repository_stability_relations` AS `subst_rsr2` ON `subst_rsr2`.`more_stable`=`subst_r`.`stability`" .
+ " WHERE `subst_bp`.`pkgname`=`binary_packages`.`pkgname`" .
+ " AND `subst_rsr`.`more_stable`=`repositories`.`stability`" .
+ " AND `subst_rsr2`.`less_stable`=" . $mysql_content["repo_stability"] .
+ ")" .
+ " GROUP BY CONCAT(`install_targets`.`id`,\"-\",`versions`.`id`),`dependency_types`.`id`" .
+ " ORDER BY FIELD (`dependency_types`.`name`,\"run\",\"make\",\"check\",\"link\"), `install_targets`.`name`"
+ );
+
+ $dependencies = array();
+ while ($row = $mysql_result -> fetch_assoc()) {
+ $row["deps"] = array_map("unserialize", array_unique(array_map("serialize", json_decode("{".$row["deps"]."}",true))));
+ $dependencies[] = $row;
+ }
+
+ if (!$skip_json_checks) {
+ function dependency_is_runtime($dep) {
+ return $dep["dependency_type"]=="run";
+ };
+
+ function dependency_extract_name($dep) {
+ return $dep["install_target"];
+ };
+
+ $dep_it = array_filter( $dependencies, "dependency_is_runtime");
+ $dep_it = array_map("dependency_extract_name", $dep_it);
+ $dep_it = preg_replace("/[<=>].*$/","",$dep_it);
+ if (array_key_exists("Depends On",$json_content))
+ $js_dep = preg_replace("/[<=>].*$/","",$json_content["Depends On"]);
+ elseif (array_key_exists("Requires",$json_content))
+ $js_dep = preg_replace("/[<=>].*$/","",$json_content["Requires"]);
+ else
+ $js_dep = array();
+ if (!is_array($js_dep))
+ $js_dep = array();
+ if (!isset($dep_it))
+ $dep_it = array();
+ $dep_errors = implode(
+ ", ",
+ array_diff(
+ array_merge($dep_it,$js_dep),
+ $dep_it
+ )
+ );
+
+ if ($dep_errors != "")
+ die_500(
+ "Dependencies differ: " . $dep_errors. "<br>\n" .
+ "mysql: " . implode(", ",$dep_it) . "<br>\n" .
+ "json: " . implode(", ",$js_dep)
+ );
+
+ foreach ($dependencies as $key => $dep) {
+ if ($dep["dependency_type"]!="run") {
+ $dependencies[$key]["json"]="not required";
+ continue;
+ }
+ foreach ($js_dep as $js)
+ if ($js == preg_replace("/[<=>].*$/","",$dep["install_target"]))
+ $dependencies[$key]["json"]=$js;
+ }
+ }
+
+ // query dependent packages
+
+ $mysql_result = mysql_run_query(
+ "SELECT DISTINCT " .
+ "`dependency_types`.`name` AS `dependency_type`," .
+ "`install_targets`.`name` AS `install_target`," .
+ "`repositories`.`name` AS `repo`," .
+ "`repositories`.`is_on_master_mirror`," .
+ "`r_a`.`name` AS `repo_arch`," .
+ "`architectures`.`name` AS `arch`," .
+ "`binary_packages`.`pkgname`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`" .
+ " FROM `install_target_providers`" .
+ " LEFT JOIN (".
+ "`binary_packages_in_repositories` AS `bpir`" .
+ mysql_join_binary_packages_in_repositories_repositories('bpir','r') .
+ ") ON `bpir`.`package`=`install_target_providers`.`package`" .
+ mysql_join_install_target_providers_install_targets() .
+ " AND `install_targets`.`name` NOT IN (\"base\",\"base-devel\")" .
+ mysql_join_install_target_providers_dependencies() .
+ mysql_join_dependencies_dependency_types() .
+ mysql_join_dependencies_binary_packages() .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ " AND `repositories`.`architecture`=`r`.`architecture`" .
+ mysql_join_repositories_architectures("","r_a") .
+ " JOIN `repository_stability_relations` ON `repository_stability_relations`.`less_stable`=`repositories`.`stability`" .
+ " AND `repository_stability_relations`.`more_stable`=" . $mysql_content["repo_stability"] .
+ " WHERE `install_target_providers`.`package`=" . $mysql_content["id"] .
+ " AND NOT EXISTS (" .
+ "SELECT 1 FROM `binary_packages` AS `subst_bp`" .
+ mysql_join_binary_packages_binary_packages_in_repositories('subst_bp','subst_bpir') .
+ mysql_join_binary_packages_in_repositories_repositories('subst_bpir','subst_r') .
+ // the substitue must be truly less stable than we
+ " JOIN `repository_stability_relations` AS `subst_rsr` ON `subst_rsr`.`less_stable`=`subst_r`.`stability`" .
+ " AND `subst_rsr`.`less_stable`!=`subst_rsr`.`more_stable`" .
+ // and more (or equally) stable than the required-by
+ " JOIN `repository_stability_relations` AS `subst_rsr2` ON `subst_rsr2`.`more_stable`=`subst_r`.`stability`" .
+ " WHERE `subst_bp`.`pkgname`=from_base64(\"" . base64_encode($mysql_content["pkgname"]) . "\")" .
+ " AND `subst_rsr2`.`less_stable`=`repositories`.`stability`" .
+ " AND `subst_rsr`.`more_stable`=" . $mysql_content["repo_stability"] .
+ ")" .
+ " GROUP BY `binary_packages`.`id`,`dependency_types`.`id`" .
+ " ORDER BY" .
+ " FIELD (`dependency_types`.`name`,\"run\",\"make\",\"check\",\"link\")," .
+ " `install_targets`.`name`!=`binary_packages`.`pkgname`," .
+ " `install_targets`.`name`," .
+ " `binary_packages`.`pkgname`," .
+ " `repositories`.`stability`," .
+ " `repositories`.`name`"
+ );
+
+ $dependent = array();
+ while ($row = $mysql_result -> fetch_assoc())
+ $dependent[] = $row;
+
+ if ($skip_json_checks)
+ $content = $mysql_content;
+ else
+ $content = array_merge($mysql_content,$json_content);
+
+ foreach (array("Download Size", "Installed Size") as $key) {
+ $content["Print " . $key] =
+ add_fancy_unit($content[$key], "B");
+ }
+
+ // query substitutes
+
+ $mysql_result = mysql_run_query(
+ "SELECT " .
+ "`binary_packages`.`pkgname` AS `pkgname`," .
+ "IF(`binary_packages_in_repositories`.`is_to_be_deleted`,1,0) AS `is_to_be_deleted`," .
+ "`repositories`.`name` AS `repo`," .
+ "`repositories`.`is_on_master_mirror`," .
+ "`architectures`.`name` AS `arch`," .
+ "`r_a`.`name` AS `repo_arch`," .
+ mysql_query_package_version("binary_packages") .
+ " AS `version`" .
+ " FROM `binary_packages` " .
+ mysql_join_binary_packages_architectures() .
+ mysql_join_binary_packages_binary_packages_in_repositories() .
+ mysql_join_binary_packages_in_repositories_repositories() .
+ mysql_join_repositories_architectures("","r_a") .
+ " JOIN `binary_packages` AS `original`" .
+ " ON `binary_packages`.`pkgname`=`original`.`pkgname`" .
+ " AND `binary_packages`.`id`!=`original`.`id`" .
+ " WHERE `original`.`id`=" . $mysql_content["id"]
+ );
+
+ $elsewhere = array();
+ while ($row = $mysql_result -> fetch_assoc())
+ $elsewhere[] = $row;
+
+ print_header($content["pkgname"] . " " . $content["version"] . " (" . $content["arch"] . ")");
+
+?>
+ <div id="archdev-navbar">
+ </div>
+ <div id="pkgdetails" class="box">
+ <h2><?php print $content["pkgname"]." ".$content["version"]; ?></h2>
+ <div id="detailslinks" class="listing">
+ <div id="actionlist">
+ <h4>Package Actions</h4>
+ <ul class="small">
+<?php
+ if ($content["uses_upstream"]) {
+ print " <li>\n";
+ print " <a href=\"https://projects.archlinux.org/svntogit/";
+ print $content["git_repo"];
+ print ".git/tree/trunk?h=packages/";
+ print $content["pkgbase"];
+ print "\" title=\"View upstream's source files for ";
+ print $content["pkgname"];
+ print "\">Upstream's Source Files</a> /\n";
+ print " <a href=\"https://projects.archlinux.org/svntogit/";
+ print $content["git_repo"];
+ print ".git/log/trunk?h=packages/";
+ print $content["pkgbase"];
+ print "\" title=\"View upstream's changes for ";
+ print $content["pkgname"];
+ print "\">Upstream's Changes</a>\n";
+ print " </li>\n";
+ }
+ if ($content["uses_modification"]) {
+ print " <li>\n";
+ print " <a href=\"";
+ print git_url("packages","tree","master",$content["stable_repo"]."/".$content["pkgbase"]);
+ print "\" title=\"View archlinux32's source files for ";
+ print $content["pkgname"];
+ print "\">Archlinux32's Source Files</a> /\n";
+ print " <a href=\"";
+ print git_url("packages","log","master",$content["stable_repo"]."/".$content["pkgbase"]);
+ print "\" title=\"View upstream's changes for ";
+ print $content["pkgname"];
+ print "\">Archlinux32's Changes</a>\n";
+ print " </li>\n";
+ }
+?>
+ <li>
+<?php
+ print " <a href=\"https://www.archlinux.org/packages/?sort=&q=";
+ print $content["pkgname"];
+ print "&maintainer=&flagged=\">";
+ print "Search for ".$content["pkgname"]." upstream";
+ print "</a>\n";
+?>
+ </li>
+ <li>
+<?php
+ print " <a href=\"https://bugs.archlinux32.org/index.php?string=";
+ print $content["pkgname"];
+ print "\" title=\"View existing bug tickets for ";
+ print $content["pkgname"];
+ print "\">Bug Reports</a> / \n";
+ print " <a href=\"https://bugs.archlinux32.org/index.php?do=newtask&project=1&product_category=";
+ if ($content["repo_stability_name"]=="stable")
+ print "8"; // stable
+ elseif ($content["repo_stability_name"]=="testing")
+ print "6"; // testing
+ elseif ($content["repo_stability_name"]=="unbuilt")
+ print "7"; // build-list
+ else
+ print "1"; // packages
+ print "&item_summary=%5B";
+ print $content["pkgname"];
+ print "%5D+PLEASE+ENTER+SUMMARY\" title=\"Report new bug for ";
+ print $content["pkgname"];
+ print "\">Add New Bug</a>\n";
+?>
+ </li>
+ <li>
+ <a href="http://pool.mirror.archlinux32.org/<?php
+ print $content["repo_arch"]."/".$content["repo"]."/".$content["pkgname"]."-".$content["version"]."-".$content["arch"];
+?>.pkg.tar.xz" rel="nofollow" title="Download <?php print $content["pkgname"]; ?> from mirror">Download From Mirror</a>
+ </li>
+ </ul>
+ </div>
+<?php
+
+if (count($elsewhere)>0) {
+ print " <div id=\"elsewhere\" class=\"widget\">\n";
+ print " <h4>Versions Elsewhere</h4>\n";
+ foreach ($elsewhere as $subst) {
+ print " <ul>\n";
+ print " <li>\n";
+ if ($subst["is_on_master_mirror"]) {
+ print " <a href=\"/" . $subst["repo_arch"] . "/" . $subst["repo"] . "/" . $subst["pkgname"] ."/\"";
+ print " title=\"Package details for " . $subst["pkgname"] ."\">";
+ }
+ if ($subst["is_to_be_deleted"])
+ print "<s>";
+ print $subst["pkgname"] . "-" . $subst["version"] . " [" . $subst["repo"] . "] (" . $subst["arch"] . ")";
+ if ($subst["is_to_be_deleted"])
+ print "</s>";
+ if ($subst["is_on_master_mirror"])
+ print "</a>\n";
+ print " </li>\n";
+ print " </ul>\n";
+ }
+ print " </div>\n";
+}
+
+?>
+ </div>
+ <div itemscope itemtype="http://schema.org/SoftwareApplication">
+ <meta itemprop="name" content="<?php print $content["pkgname"]; ?>"/>
+ <meta itemprop="version" content="<?php print $content["version"]; ?>"/>
+ <meta itemprop="softwareVersion" content="<?php print $content["version"]; ?>"/>
+ <meta itemprop="fileSize" content="<?php print if_unset($content, "Download Size", "0"); ?>"/>
+ <meta itemprop="dateCreated" content="<?php print if_unset($content,"Build Date","0"); ?>"/>
+ <meta itemprop="datePublished" content="<?php print $content["last_moved"]; ?>"/>
+ <meta itemprop="operatingSystem" content="Arch Linux 32"/>
+ <table id="pkginfo">
+ <tr>
+ <th>
+ Architecture:
+ </th>
+ <td>
+ <a href="/?arch=<?php
+ print $content["arch"];
+ ?>" title="Browse packages for <?php
+ print $content["arch"];
+ ?> architecture"><?php
+ print $content["arch"];
+ ?></a>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Repository:
+ </th>
+ <td>
+ <a href="/?repo=<?php
+ print urlencode($content["repo_arch"] . "/" . $content["repo"]);
+ ?>" title="Browse the <?php
+ print $content["repo_arch"] . "/" . $content["repo"];
+ ?> repository"><?php
+ print $content["repo_arch"] . "/" . $content["repo"];
+ ?></a>
+ </td>
+ </tr>
+<?php
+$count = count($content["split_packages"]);
+if ($count > 1 || $content["pkgname"] != $content["pkgbase"]) {
+ print " <tr>\n";
+ print " <th>\n";
+ print " Split Packages:\n";
+ print " </th>\n";
+ print " <td>\n";
+ foreach ($content["split_packages"] as $split_package) {
+ print " ";
+ if ($split_package["pkgname"] != $content["pkgname"]) {
+ print "<a href=\"/" . $split_package["repo_arch"];
+ print "/" . $split_package["repository"];
+ print "/" . $split_package["pkgname"];
+ print "/\">";
+ }
+ print $split_package["pkgname"];
+ $count --;
+ if ($split_package["pkgname"] != $content["pkgname"])
+ print "</a>";
+ if ($count > 0)
+ print ", ";
+ }
+ if ($content["pkgname"] != $content["pkgbase"])
+ print " (" . $content["pkgbase"] . ")";
+ print "\n";
+ print " </td>\n";
+ print " </tr>\n";
+}
+?>
+ <tr>
+ <th>
+ Description:
+ </th>
+ <td class="wrap" itemprop="description">
+ <?php print if_unset($content, "Description", "<font color=\"#ff0000\">not found in pkg-api</font>")."\n"; ?>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Upstream URL:
+ </th>
+ <td>
+ <a itemprop="url" href="<?php print if_unset($content, "URL", ""); ?>" title="Visit the website for <?php print $content["pkgname"]; ?>"><?php print if_unset($content, "URL", "<font color=\"#ff0000\">not found in pkg-api</font>"); ?></a>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ License(s):
+ </th>
+ <td class="wrap">
+ <?php
+ $licenses = if_unset($content, "Licenses", "<font color=\"#ff0000\">not found in pkg-api</font>");
+ if (is_array($licenses))
+ print implode(", ",$licenses);
+ else
+ print $licenses;
+ print "\n";
+?>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Package Size:
+ </th>
+ <td>
+ <?php print if_unset($content, "Print Download Size", "<font color=\"#ff0000\">not found in pkg-api</font>")."\n"; ?>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Installed Size:
+ </th>
+ <td>
+ <?php print if_unset($content, "Print Installed Size", "<font color=\"#ff0000\">not found in pkg-api</font>")."\n"; ?>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Build Date:
+ </th>
+ <td>
+ <?php print if_unset($content, "Build Date", "<font color=\"#ff0000\">not found in pkg-api</font>")."\n"; ?>
+ </td>
+ </tr>
+ <tr>
+ <th>
+ Last Updated:
+ </th>
+ <td>
+ <?php print $content["last_moved"]."\n"; ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div id="metadata">
+ <div id="pkgdeps" class="listing">
+ <h3 title="<?php print $content["pkgname"]; ?> has the following dependencies">
+ Dependencies (<?php print count($dependencies); ?>)
+ </h3>
+ <ul id="pkgdepslist">
+<?php
+ foreach ($dependencies as $dep) {
+ print " <li>\n";
+ if (!$skip_json_checks && !array_key_exists ('json', $dep))
+ print " (in database only)\n";
+ if (count($dep["deps"]) == 0) {
+ print " <font color=\"#ff0000\">not satisfiable dependency: \"" . $dep["install_target"] . $dep["version"] . "\"</font>\n";
+ } else {
+ $virtual_dep = (
+ (count($dep["deps"]) > 1) ||
+ (array_values($dep["deps"])[0]["pkgname"] != $dep["install_target"])
+ );
+ print " ";
+ if ($virtual_dep) {
+ print $dep["install_target"] . $dep["version"];
+ print " <span class=\"virtual-dep\">(";
+ };
+ $first = true;
+ foreach ($dep["deps"] as $d_p) {
+ if (!$first)
+ print ", ";
+ $first = false;
+ print "<a href=\"/".$d_p["repo_arch"]."/".$d_p["repo"]."/".$d_p["pkgname"]."/\" ";
+ print "title=\"View package details for ".$d_p["pkgname"]."\">";
+ if ($d_p["is_to_be_deleted"])
+ print "<s>";
+ print $d_p["pkgname"];
+ if ($d_p["is_to_be_deleted"])
+ print "</s>";
+ print "</a>";
+ if (!$virtual_dep)
+ print $dep["version"];
+ }
+ if ($virtual_dep)
+ print ")</span>";
+ print "\n";
+ };
+ if ($dep["dependency_type"]!="run")
+ print " <span class=\"" . $dep["dependency_type"] . "-dep\">(" . $dep["dependency_type"] . ")</span>\n";
+ print " </li>\n";
+ }
+?>
+ </ul>
+ </div>
+ <div id="pkgreqs" class="listing">
+ <h3 title="Packages that require <?php print $content["pkgname"]; ?>">
+ Required By (<?php print count($dependent); ?>)
+ </h3>
+ <ul id="pkgreqslist">
+<?php
+ foreach ($dependent as $dep) {
+ print " <li>\n";
+ print " ";
+ if ($dep["install_target"] != $content["pkgname"])
+ print $dep["install_target"] . " (";
+ if ($dep["is_on_master_mirror"]=="1") {
+ print "<a href=\"/".$dep["repo_arch"]."/".$dep["repo"]."/".$dep["pkgname"]."/\" ";
+ print "title=\"View package details for ".$dep["pkgname"]."\">";
+ }
+ if ($dep["is_to_be_deleted"])
+ print "<s>";
+ print $dep["pkgname"];
+ if ($dep["is_to_be_deleted"])
+ print "</s>";
+ if ($dep["repo"] != $content["repo"])
+ print " [" . $dep["repo"] . "]";
+ if ($dep["is_on_master_mirror"]=="1")
+ print "</a>";
+ if ($dep["install_target"] != $content["pkgname"])
+ print ")\n";
+ if ($dep["dependency_type"] != "run")
+ print " <span class=\"" . $dep["dependency_type"] . "-dep\">(" . $dep["dependency_type"] . ")</span>";
+ print "\n";
+ print " </li>\n";
+ }
+?>
+ </ul>
+ </div>
+ <div id="pkgfiles">
+ </div>
+ </div>
+ </div>
+<?php
+
+ print_footer();
diff --git a/pkgapi/index.html b/pkgapi/index.html
new file mode 100644
index 0000000..aca92a7
--- /dev/null
+++ b/pkgapi/index.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ This is the pkgapi for archlinux32 - query it <a href="/i486/core/gcc">like so.</a>
+ </bod>
+</html>
diff --git a/pkgapi/pacman-i486.conf b/pkgapi/pacman-i486.conf
new file mode 100644
index 0000000..3dee4f9
--- /dev/null
+++ b/pkgapi/pacman-i486.conf
@@ -0,0 +1,64 @@
+#
+# /etc/pacman.conf
+#
+# See the pacman.conf(5) manpage for option and repository directives
+
+#
+# GENERAL OPTIONS
+#
+[options]
+# The following paths are commented out with their default values listed.
+# If you wish to use different paths, uncomment and update the paths.
+#RootDir = /
+DBPath = /var/lib/pacman-i486/
+CacheDir = /var/cache/pacman-i486/pkg/
+LogFile = /dev/null
+#GPGDir = /etc/pacman.d/gnupg/
+#HookDir = /etc/pacman.d/hooks/
+HoldPkg = pacman glibc
+#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
+#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
+#CleanMethod = KeepInstalled
+#UseDelta = 0.7
+Architecture = i486
+
+# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
+#IgnorePkg =
+#IgnoreGroup =
+
+#NoUpgrade =
+#NoExtract =
+
+# Misc options
+#UseSyslog
+#Color
+#TotalDownload
+CheckSpace
+#VerbosePkgLists
+
+# By default, pacman accepts packages signed by keys that its local keyring
+# trusts (see pacman-key and its man page), as well as unsigned packages.
+SigLevel = Required DatabaseOptional
+LocalFileSigLevel = Optional
+#RemoteFileSigLevel = Required
+
+[staging]
+Include = /etc/pacman.d/mirrorlist32
+
+[community-staging]
+Include = /etc/pacman.d/mirrorlist32
+
+[testing]
+Include = /etc/pacman.d/mirrorlist32
+
+[community-testing]
+Include = /etc/pacman.d/mirrorlist32
+
+[core]
+Include = /etc/pacman.d/mirrorlist32
+
+[extra]
+Include = /etc/pacman.d/mirrorlist32
+
+[community]
+Include = /etc/pacman.d/mirrorlist32
diff --git a/pkgapi/pacman-i686.conf b/pkgapi/pacman-i686.conf
new file mode 100644
index 0000000..442b10e
--- /dev/null
+++ b/pkgapi/pacman-i686.conf
@@ -0,0 +1,64 @@
+#
+# /etc/pacman.conf
+#
+# See the pacman.conf(5) manpage for option and repository directives
+
+#
+# GENERAL OPTIONS
+#
+[options]
+# The following paths are commented out with their default values listed.
+# If you wish to use different paths, uncomment and update the paths.
+#RootDir = /
+DBPath = /var/lib/pacman-i686/
+CacheDir = /var/cache/pacman-i686/pkg/
+LogFile = /dev/null
+#GPGDir = /etc/pacman.d/gnupg/
+#HookDir = /etc/pacman.d/hooks/
+HoldPkg = pacman glibc
+#XferCommand = /usr/bin/curl -L -C - -f -o %o %u
+#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u
+#CleanMethod = KeepInstalled
+#UseDelta = 0.7
+Architecture = i686
+
+# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
+#IgnorePkg =
+#IgnoreGroup =
+
+#NoUpgrade =
+#NoExtract =
+
+# Misc options
+#UseSyslog
+#Color
+#TotalDownload
+CheckSpace
+#VerbosePkgLists
+
+# By default, pacman accepts packages signed by keys that its local keyring
+# trusts (see pacman-key and its man page), as well as unsigned packages.
+SigLevel = Required DatabaseOptional
+LocalFileSigLevel = Optional
+#RemoteFileSigLevel = Required
+
+[staging]
+Include = /etc/pacman.d/mirrorlist32
+
+[community-staging]
+Include = /etc/pacman.d/mirrorlist32
+
+[testing]
+Include = /etc/pacman.d/mirrorlist32
+
+[community-testing]
+Include = /etc/pacman.d/mirrorlist32
+
+[core]
+Include = /etc/pacman.d/mirrorlist32
+
+[extra]
+Include = /etc/pacman.d/mirrorlist32
+
+[community]
+Include = /etc/pacman.d/mirrorlist32
diff --git a/pkgapi/pkginfo.php b/pkgapi/pkginfo.php
new file mode 100644
index 0000000..d9301ed
--- /dev/null
+++ b/pkgapi/pkginfo.php
@@ -0,0 +1,53 @@
+<?php
+require_once "../init.php";
+
+include BASE . "/lib/http.php";
+
+foreach (array('arch', 'repo', 'pkgname') as $must_have_key) {
+ if (!array_key_exists($must_have_key, $_GET))
+ throw_http_error(400, 'Malformed request', 'Key ' . $must_have_key . ' was not given.');
+ if (!preg_match('/^[-+_.a-zA-Z0-9]+$/', $_GET[$must_have_key]))
+ throw_http_error(400, 'Malformed request', 'Value for ' . $must_have_key . ' is invalid.');
+}
+
+if (($_GET['arch'] != 'i486') && ($_GET['arch'] != 'i686'))
+ throw_http_error(400, 'Malformed request', 'Architecture ' . $_GET['arch'] . ' is unkown.');
+
+$infos = trim(
+ shell_exec(
+ 'pacinfo' .
+ ' --config=' . BASE . '/pkgapi/pacman-' . $_GET['arch'] . '.conf ' .
+ $_GET['repo'] . '/' .
+ $_GET['pkgname'] .
+ ' | grep "^Build Date:"; ' .
+ 'pacinfo' .
+ ' --raw' .
+ ' --config=' . BASE . '/pkgapi/pacman-' . $_GET['arch'] . '.conf ' .
+ $_GET['repo'] . '/' .
+ $_GET['pkgname'] .
+ ' | grep -v "^Build Date:"'
+ )
+);
+
+if (!isset($infos))
+ throw_http_error(404, 'Package not found.');
+
+function parse_pacinfo_line($line) {
+ return preg_split('/: +/', $line, 2);
+}
+
+function extract_first($array) {
+ return $array[0];
+}
+
+$infos = explode("\n", $infos);
+$infos = array_map('parse_pacinfo_line', $infos);
+$merged_infos = array();
+foreach ($infos as $info)
+ $merged_infos = array_merge_recursive($merged_infos, array($info[0] => $info[1]));
+
+header ("Content-type: application/json");
+print json_encode(
+ $merged_infos,
+ JSON_UNESCAPED_SLASHES
+);
diff --git a/static/archnav32.png b/static/archnav32.png
new file mode 100644
index 0000000..a7fd0d8
--- /dev/null
+++ b/static/archnav32.png
Binary files differ
diff --git a/static/archweb.css b/static/archweb.css
new file mode 100644
index 0000000..29b7172
--- /dev/null
+++ b/static/archweb.css
@@ -0,0 +1,703 @@
+#archnavbar{
+height:40px!important;
+padding:10px 15px!important;
+background:#333!important;
+border-bottom:5px #08c solid!important}
+#archnavbarlogo{
+float:left!important;
+margin:0!important;
+padding:0!important;
+height:40px!important;
+width:230px!important;
+background:url(archnav32.png) no-repeat!important}
+#archnavbarlogo h1{
+margin:0!important;
+padding:0!important;
+text-indent:-9999px!important}
+#archnavbarlogo a{
+display:block!important;
+height:40px!important;
+width:230px!important}
+#archnavbarlist{
+display:inline!important;
+float:right!important;
+list-style:none!important;
+margin:0!important;
+padding:0!important}
+#archnavbarlist li{
+float:left!important;
+font-size:14px!important;
+font-family:sans-serif!important;
+line-height:45px!important;
+padding-right:15px!important;
+padding-left:15px!important}
+#archnavbarlist li a{
+color:#999;
+font-weight:bold!important;
+text-decoration:none!important}
+#archnavbarlist li a:hover{
+color:white!important;
+text-decoration:underline!important}
+*{
+margin:0;
+padding:0;
+line-height:1.4}
+body{
+min-width:650px;
+background:#f6f9fc;
+color:#222;
+font:normal 100% sans-serif;
+text-align:center}
+p{
+margin:.33em 0 1em}
+ol,
+ul{
+margin-bottom:1em;
+padding-left:2em}
+ul{
+list-style:square}
+code{
+font:1.2em monospace;
+background:#ffd;
+padding:.15em .25em}
+pre{
+font:1.2em monospace;
+border:1px solid #bdb;
+background:#dfd;
+padding:.5em;
+margin:1em}
+pre code{
+display:block;
+background:none;
+overflow:auto}
+blockquote{
+margin:1.5em 2em}
+input{
+vertical-align:middle}
+select[multiple]{
+padding:1px 0}
+select[multiple] option{
+padding:0 .5em 0 .3em}
+input[type=submit]{
+padding:0 .6em}
+.clear{
+clear:both}
+.hide{
+display:none}
+hr{
+border:none;
+border-top:1px solid #888}
+img{
+border:0}
+#content{
+font-size:.812em}
+a{
+text-decoration:none}
+a:link,
+th a:visited{
+color:#07b}
+a:visited{
+color:#666}
+a:hover{
+text-decoration:underline;
+color:#666}
+a:active{
+color:#e90}
+a.headerlink{
+visibility:hidden;
+padding-left:.5em}
+h3:hover>a.headerlink{
+visibility:visible}
+h2{
+font-size:1.5em;
+margin-bottom:.5em;
+border-bottom:1px solid #888}
+h3{
+font-size:1.25em;
+margin-top:.5em}
+h4{
+font-size:1.15em;
+margin-top:1em}
+h5{
+font-size:1em;
+margin-top:1em}
+#content{
+width:95%;
+margin:0 auto;
+text-align:left}
+#content-left-wrapper{
+float:left;
+width:100%}
+#content-left{
+margin:0 340px 0 0}
+#content-right{
+float:left;
+width:300px;
+margin-left:-300px}
+div.box{
+margin-bottom:1.5em;
+padding:.65em;
+background:#ecf2f5;
+border:1px solid #bcd}
+#footer{
+clear:both;
+margin:2em 0 1em}
+#footer p{
+margin:0;
+text-align:center;
+font-size:.85em}
+div.center,
+table.center,
+img.center{
+width:auto;
+margin-left:auto;
+margin-right:auto}
+p.center,
+td.center,
+th.center{
+text-align:center}
+table{
+width:100%;
+border-collapse:collapse}
+table .wrap{
+white-space:normal}
+th,
+td{
+white-space:nowrap;
+text-align:left}
+th{
+vertical-align:middle;
+font-weight:bold}
+td{
+vertical-align:top}
+table.pretty1{
+width:auto;
+margin-top:.25em;
+margin-bottom:.5em;
+border-collapse:collapse;
+border:1px solid #bcd}
+.pretty1 th{
+padding:.35em;
+background:#e4eeff;
+border:1px solid #bcd}
+.pretty1 td{
+padding:.35em;
+border:1px dotted #bcd}
+table.pretty2{
+width:auto;
+margin-top:.25em;
+margin-bottom:.5em;
+border-collapse:collapse;
+border:1px solid #bbb}
+.pretty2 th{
+padding:.35em;
+background:#eee;
+border:1px solid #bbb}
+.pretty2 td{
+padding:.35em;
+border:1px dotted #bbb}
+table.compact{
+width:auto}
+.compact td{
+padding:.25em 0 .25em 1.5em}
+dl{
+clear:both}
+dl dt,
+dl dd{
+margin-bottom:4px;
+padding:8px 0 4px;
+font-weight:bold;
+border-top:1px dotted #bbb}
+dl dt{
+color:#333;
+float:left;
+padding-right:15px}
+form p{
+margin:.5em 0}
+fieldset{
+border:0}
+label{
+width:12em;
+vertical-align:top;
+display:inline-block;
+font-weight:bold}
+input[type=text],
+input[type=password],
+textarea{
+padding:.10em}
+form.general-form label,
+form.general-form .form-help{
+width:10em;
+vertical-align:top;
+display:inline-block}
+form.general-form input[type=text],
+form.general-form textarea{
+width:45%}
+#archdev-navbar{
+margin:1.5em 0}
+#archdev-navbar ul{
+list-style:none;
+margin:-0.5em 0;
+padding:0}
+#archdev-navbar li{
+display:inline;
+margin:0;
+padding:0;
+font-size:.9em}
+#archdev-navbar li a{
+padding:0 .5em;
+color:#07b}
+#sys-message{
+width:35em;
+text-align:center;
+margin:1em auto;
+padding:.5em;
+background:#fff;
+border:1px solid #f00}
+#sys-message p{
+margin:0}
+ul.errorlist{
+color:red}
+form ul.errorlist{
+margin:.5em 0}
+table th.tablesorter-header{
+padding-right:20px;
+background-image:url(data:image/gif;
+base64,
+R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw==);
+background-repeat:no-repeat;
+background-position:center right;
+cursor:pointer}
+table thead th.tablesorter-headerAsc{
+background-color:#e4eeff;
+background-image:url(data:image/gif;
+base64,
+R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjI8Bya2wnINUMopZAQA7)}
+table thead th.tablesorter-headerDesc{
+background-color:#e4eeff;
+background-image:url(data:image/gif;
+base64,
+R0lGODlhFQAEAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAQAAAINjB+gC+jP2ptn0WskLQA7)}
+table thead th.sorter-false{
+background-image:none;
+cursor:default}
+#intro p.readmore{
+margin:-0.5em 0 0 0;
+font-size:.9em;
+text-align:right}
+#news{
+margin-top:1.5em}
+#news h3{
+float:left;
+padding-bottom:.5em}
+#news div{
+margin-bottom:1em}
+#news div p{
+margin-bottom:.5em}
+#news .more{
+font-weight:normal}
+#news .rss-icon{
+float:right;
+margin-top:1em}
+#news h4{
+clear:both;
+font-size:1em;
+margin-top:1.5em;
+border-bottom:1px dotted #bbb}
+#news .timestamp{
+float:right;
+font-size:.85em;
+margin:-1.8em .5em 0 0}
+#news h3 a{
+display:block;
+background:#1794D1;
+font-size:15px;
+padding:2px 10px;
+color:white}
+#news a:active{
+color:white}
+h3 span.arrow{
+display:block;
+width:0;
+height:0;
+border-left:6px solid transparent;
+border-right:6px solid transparent;
+border-top:6px solid #1794D1;
+margin:0 auto;
+font-size:0;
+line-height:0}
+#pkgsearch{
+padding:1em .75em;
+background:#3ad;
+color:#fff;
+border:1px solid #08b}
+#pkgsearch label{
+width:auto;
+padding:.1em 0}
+#pkgsearch input{
+width:10em;
+float:right;
+font-size:1em;
+color:#000;
+background:#fff;
+border:1px solid #09c}
+.pkgsearch-typeahead{
+position:absolute;
+top:100%;
+left:0;
+z-index:1000;
+display:none;
+float:left;
+padding:.15em .1em;
+margin:0;
+min-width:10em;
+font-size:.812em;
+text-align:left;
+list-style:none;
+background-color:#f6f9fc;
+border:1px solid #09c}
+.pkgsearch-typeahead li a{
+color:#000}
+.pkgsearch-typeahead li.active a{
+color:#07b}
+#pkg-updates h3{
+margin:0 0 .3em}
+#pkg-updates .more{
+font-weight:normal}
+#pkg-updates .rss-icon{
+float:right;
+margin:-2em 0 0 0}
+#pkg-updates table{
+margin:0}
+#pkg-updates td.pkg-name{
+white-space:normal}
+#pkg-updates td.pkg-arch{
+text-align:right}
+#pkg-updates span.testing{
+font-style:italic}
+#pkg-updates span.staging{
+font-style:italic;
+color:#ff8040}
+#nav-sidebar ul{
+list-style:none;
+margin:.5em 0 .5em 1em;
+padding:0}
+#arch-sponsors img{
+padding:.3em 0}
+div.widget{
+margin-bottom:1.5em}
+#konami{
+position:fixed;
+top:0;
+left:0;
+width:100%;
+height:100%;
+text-align:center;
+opacity:.6}
+#rss-feeds .rss{
+padding-right:20px;
+background:url(rss.c5ebdc5318d6.png) top right no-repeat}
+#artwork img.inverted{
+background:#333;
+padding:0}
+#artwork div.imagelist img{
+display:inline;
+margin:.75em}
+.news-nav{
+float:right;
+margin-top:-2.2em}
+.news-nav .prev,
+.news-nav .next{
+margin:0 1em}
+div.news-article .article-info{
+margin:0;
+color:#999}
+#newsform{
+width:60em}
+#newsform input[type=text],
+#newsform textarea{
+width:75%}
+.todolist-nav{
+float:right;
+margin-top:-2.2em}
+.todolist-nav .prev,
+.todolist-nav .next{
+margin:0 1em}
+#donor-list ul{
+width:100%}
+#donor-list li{
+float:left;
+width:25%;
+min-width:20em}
+#arch-downloads h3{
+border-bottom:1px dotted #bbb}
+table.results{
+font-size:.846em;
+border-top:1px dotted #999;
+border-bottom:1px dotted #999}
+.results th{
+padding:.5em 1em .25em .25em;
+border-bottom:1px solid #999;
+white-space:nowrap;
+background-color:#fff}
+.results td{
+padding:.3em 1em .3em 3px}
+.results tr.odd{
+background:#fff}
+.results tr.even{
+background:#e4eeff}
+.results .flagged{
+color:red}
+.results tr.empty td{
+text-align:center}
+#pkglist-about{
+margin-top:1.5em}
+.pkglist-stats{
+font-size:.85em}
+#pkglist-results .pkglist-nav{
+float:right;
+margin-top:-2.2em}
+.pkglist-nav .prev{
+margin-right:1em}
+.pkglist-nav .next{
+margin-right:1em}
+.filter-criteria{
+margin-bottom:1em}
+.filter-criteria h3{
+font-size:1em;
+margin-top:0}
+.filter-criteria div{
+float:left;
+margin-right:1.65em;
+font-size:.85em}
+.filter-criteria legend{
+display:none}
+.filter-criteria label{
+width:auto;
+display:block;
+font-weight:normal}
+#pkgdetails #detailslinks{
+float:right}
+#pkgdetails #detailslinks h4{
+margin-top:0;
+margin-bottom:.25em}
+#pkgdetails #detailslinks ul{
+list-style:none;
+padding:0;
+margin-bottom:0;
+font-size:.846em}
+#pkgdetails #detailslinks>div{
+padding:.5em;
+margin-bottom:1em;
+background:#eee;
+border:1px solid #bbb}
+#pkgdetails #actionlist .flagged{
+color:red;
+font-size:.9em;
+font-style:italic}
+#pkgdetails #pkginfo{
+width:auto}
+#pkgdetails #pkginfo td{
+padding:.25em 0 .25em 1.5em}
+#pkgdetails #pkginfo .userdata{
+font-size:.85em;
+padding:.5em}
+#flag-pkg-form label{
+width:10em}
+#flag-pkg-form textarea,
+#flag-pkg-form input[type=text]{
+width:45%}
+#pkgdetails #metadata{
+clear:both}
+#pkgdetails #metadata h3{
+background:#555;
+color:#fff;
+font-size:1em;
+margin-bottom:.5em;
+padding:.2em .35em}
+#pkgdetails #metadata ul{
+list-style:none;
+margin:0;
+padding:0}
+#pkgdetails #metadata li{
+padding-left:.5em}
+#pkgdetails #metadata p{
+padding-left:.5em}
+#pkgdetails #metadata .message{
+font-style:italic}
+#pkgdetails #metadata br{
+clear:both}
+#pkgdetails #pkgdeps{
+float:left;
+width:48%;
+margin-right:2%}
+#pkgdetails #metadata .virtual-dep,
+#pkgdetails #metadata .testing-dep,
+#pkgdetails #metadata .staging-dep,
+#pkgdetails #metadata .opt-dep,
+#pkgdetails #metadata .make-dep,
+#pkgdetails #metadata .link-dep,
+#pkgdetails #metadata .check-dep,
+#pkgdetails #metadata .dep-desc{
+font-style:italic}
+#pkgdetails #pkgreqs{
+float:left;
+width:50%}
+#pkgdetails #pkgfiles{
+clear:left;
+padding-top:1em}
+#pkgfilelist li.d{
+color:#666}
+#pkgfilelist li.f{
+}
+table td.country{
+white-space:normal}
+#list-generator div ul{
+list-style:none;
+display:inline;
+padding-left:0}
+#list-generator div ul li{
+display:inline}
+.visualize-mirror .axis path,
+.visualize-mirror .axis line{
+fill:none;
+stroke:#000;
+stroke-width:3px;
+shape-rendering:crispEdges}
+.visualize-mirror .url-dot{
+stroke:#000}
+.visualize-mirror .url-line{
+fill:none;
+stroke-width:1.5px}
+#arch-bio-toc{
+width:75%;
+margin:0 auto;
+text-align:center}
+#arch-bio-toc a{
+white-space:nowrap}
+.arch-bio-entry{
+width:75%;
+min-width:640px;
+margin:0 auto}
+.arch-bio-entry td.pic{
+vertical-align:top;
+padding-right:15px;
+padding-top:2.25em}
+.arch-bio-entry td.pic img{
+padding:4px;
+border:1px solid #ccc}
+.arch-bio-entry td h3{
+border-bottom:1px dotted #ccc;
+margin-bottom:.5em}
+.arch-bio-entry table.bio{
+margin-bottom:2em}
+.arch-bio-entry table.bio th{
+color:#666;
+font-weight:normal;
+text-align:right;
+padding-right:.5em;
+vertical-align:top;
+white-space:nowrap}
+.arch-bio-entry table.bio td{
+width:100%;
+padding-bottom:.25em;
+white-space:normal}
+#dev-login{
+width:auto}
+#dash-pkg-notify{
+text-align:right;
+padding:1em 0 0;
+margin-top:1em;
+font-size:.85em;
+border-top:1px dotted #bbb}
+#dash-pkg-notify label{
+width:auto;
+font-weight:normal}
+#dash-pkg-notify input{
+vertical-align:middle;
+margin:0 .25em}
+#dash-pkg-notify input[type=submit]{
+margin-top:-0.25em}
+#dash-pkg-notify p{
+margin:0}
+table.dash-stats .key{
+width:50%}
+ul.admin-actions{
+float:right;
+list-style:none;
+margin-top:-2.5em}
+ul.admin-actions li{
+display:inline;
+padding-left:1.5em}
+.todo-table .complete,
+.signoff-yes,
+#key-status .signed-yes,
+#releng-result .success-yes,
+#release-list .available-yes{
+color:green}
+.todo-table .incomplete,
+.signoff-no,
+#key-status .signed-no,
+#releng-result .success-no,
+#release-list .available-no{
+color:red}
+.todo-table .inprogress,
+.signoff-bad{
+color:darkorange}
+.todo-info{
+color:#999;
+border-bottom:1px dotted #bbb}
+.todo-description{
+margin-top:1em;
+padding-left:2em;
+max-width:900px}
+.todo-pkgbases{
+border-top:1px dotted #bbb}
+.todo-list h4{
+margin-top:0;
+margin-bottom:.4em}
+#dev-signoffs tr:hover{
+background:#ffd}
+ul.signoff-list{
+list-style:none;
+margin:0;
+padding:0}
+.signoff-yes{
+font-weight:bold}
+.signoff-disabled{
+color:gray}
+#releng-feedback label{
+width:auto;
+display:inline;
+font-weight:normal}
+#releng-feedback ul{
+padding-left:1em}
+#releng-feedback li{
+list-style:none}
+#releng-feedback ul+.helptext{
+position:relative;
+top:-0.9em}
+#archnavbar.anb-home ul li#anb-home a,
+#archnavbar.anb-packages ul li#anb-packages a,
+#archnavbar.anb-download ul li#anb-download a{
+color:white!important}
+.visualize-buttons{
+margin:.5em .33em}
+.visualize-buttons button.active{
+depressed:true}
+.visualize-chart{
+position:relative;
+height:500px;
+margin:.33em}
+#visualize-archrepo .treemap-cell{
+border:solid 1px white;
+overflow:hidden;
+position:absolute}
+#visualize-archrepo .treemap-cell span{
+padding:3px;
+font-size:.85em;
+line-height:1em}
+#visualize-keys svg{
+width:100%;
+height:100%}
+
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644
index 0000000..8ef6f13
--- /dev/null
+++ b/static/favicon.ico
Binary files differ
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..90432d2
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1 @@
+tr:nth-child(even) { background-color: #f2f2f2}