Progress towards more reliable build changesets detection
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.exe
|
||||
*.bz2
|
||||
*.dmg
|
||||
*.zip
|
||||
*.bak
|
||||
*~
|
||||
*.log
|
||||
lib/source/*
|
||||
lib/singularity_revisions*
|
||||
@@ -1,7 +0,0 @@
|
||||
syntax: glob
|
||||
*.exe
|
||||
*.bak
|
||||
*~
|
||||
*.log
|
||||
lib/source/*
|
||||
lib/signularity_revisions*
|
||||
92
buildsite.css
Normal file
92
buildsite.css
Normal file
@@ -0,0 +1,92 @@
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
image {
|
||||
border: none;
|
||||
}
|
||||
|
||||
body, select {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #1e1e1e;
|
||||
font: normal 10pt "Lucida Grande","Lucida Sans Unicode",sans-serif;
|
||||
color: #a0a0a0;
|
||||
}
|
||||
|
||||
div {
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#everything {
|
||||
background: url(images/body-bg.png) top repeat-x;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
#page-wrapper {
|
||||
margin: 0 auto;
|
||||
width: 960px;
|
||||
}
|
||||
|
||||
#header {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
height: 144px;
|
||||
background: url(images/singularity_logo.gif) left top no-repeat;
|
||||
border-bottom: solid 2px black;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 5px;
|
||||
margin-bottom: 10px;
|
||||
background: url(images/container-bg.gif) top repeat-x;
|
||||
border-bottom: solid 2px black;
|
||||
background-color: #1b1b1b;
|
||||
}
|
||||
|
||||
a, a:link, a:hover, a:visited, a:active {
|
||||
text-decoration: none;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
a.dimmer {
|
||||
color: #a0a0a0;
|
||||
}
|
||||
|
||||
.bottom-links {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td, th {
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 3px 3px 3px 3px;
|
||||
vertical-align: top;
|
||||
display: table-cell;
|
||||
border: none;
|
||||
}
|
||||
|
||||
th {
|
||||
border-bottom: solid 1px #404040;
|
||||
background: url(images/container-bg.gif) top repeat-x;
|
||||
padding: 5px 3px 10px 3px;
|
||||
}
|
||||
|
||||
.build-list {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
border: solid 1px #404040;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: monospace;
|
||||
font-size: 8pt;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
126
feed.php
Normal file
126
feed.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
define("SITE_ROOT", realpath(dirname(__file__)));
|
||||
require_once SITE_ROOT . "/lib/init.php";
|
||||
|
||||
function parse_email($email)
|
||||
{
|
||||
$ret = array("name" => $email, "email" => "");
|
||||
if (preg_match("|([^\<]*)<([^>]*)>|", $email, $m)) {
|
||||
$ret["name"] = trim($m[1]);
|
||||
$ret["email"] = trim($m[2]);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function sort_by_date($a, $b)
|
||||
{
|
||||
if ($a["time"] < $b["time"]) {
|
||||
return 1;
|
||||
} else if ($a["time"] > $b["time"]) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function print_changeset($row)
|
||||
{
|
||||
$author = parse_email($row["author"]);
|
||||
$gid = md5($author["email"]);
|
||||
$avatar = (USE_SSL ? "https://secure.gravatar.com" : "http://www.gravatar.com") .
|
||||
"/avatar/$gid?r=x&d=mm&s=48";
|
||||
return '<tr><td valign="top" align="center"><img src="' . $avatar . '" alt="Avatar"/><br/>'
|
||||
. htmlspecialchars($author["name"]) . '</td>'
|
||||
. '<td valign="top"><a href="https://github.com/siana/SingularityViewer/commit/' . htmlspecialchars($row["hash"]) . '">' . htmlspecialchars($row["hash"]) . '</a><br/>'
|
||||
. htmlspecialchars($row["time"]). "<br/><br/>\n\n<pre>"
|
||||
. htmlspecialchars($row["message"]) . '</pre></td>';
|
||||
}
|
||||
|
||||
function print_changes($current, $next)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$ret = "";
|
||||
|
||||
$revs = array();
|
||||
if (!($res = $DB->query(kl_str_sql("select revisions from changes where build<=!i and build>!i order by build desc", $current->nr, $next->nr)))) {
|
||||
return $ret;
|
||||
} else {
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
$revs = array_merge($revs, explode(",", $row["revisions"]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($res = $DB->query("select * from revs where hash in ('" . implode("','", $revs) . "')")) {
|
||||
$ret .= '<table width="100%">';
|
||||
|
||||
$changesets = array();
|
||||
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
$changesets[] = $row;
|
||||
}
|
||||
|
||||
usort($changesets, "sort_by_date");
|
||||
|
||||
foreach ($changesets as $change) {
|
||||
$ret .= print_changeset($change);
|
||||
}
|
||||
|
||||
$ret .= '</table>';
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$buildFeed = new FeedWriter(ATOM);
|
||||
$buildFeed->setTitle('Singularity Automatic Development Builds');
|
||||
$buildFeed->setLink('http://files.streamgrid.net/singularity/');
|
||||
$buildFeed->setDescription('Latest automated build of the Singularity Viewer project');
|
||||
// $buildFeed->setImage('Testing the RSS writer class',
|
||||
// 'http://www.ajaxray.com/projects/rss',
|
||||
// 'http://www.rightbrainsolution.com/images/logo.gif');
|
||||
|
||||
$chan = "SingularityAlpha";
|
||||
|
||||
$pageSize = 20;
|
||||
|
||||
$builds = array();
|
||||
|
||||
if ($res = $DB->query(kl_str_sql("select * from builds where chan=!s order by nr desc limit !i", $chan, $pageSize + 1))) {
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
|
||||
$build = new stdClass;
|
||||
$DB->loadFromDbRow($build, $res, $row);
|
||||
$builds[] = $build;
|
||||
}
|
||||
}
|
||||
|
||||
$nrBuilds = count($builds);
|
||||
|
||||
if ($nrBuilds) {
|
||||
for ($i = 0; $i < $pageSize; $i++) {
|
||||
if (!isset($builds[$i])) continue;
|
||||
$newItem = $buildFeed->createNewItem();
|
||||
$newItem->setTitle("Singularity Alpha build " . $builds[$i]->nr);
|
||||
$newItem->setLink("http://files.streamgrid.net/singularity/?build_id=" . $builds[$i]->nr);
|
||||
$newItem->setDate($builds[$i]->modified);
|
||||
if (isset($builds[$i+1])) {
|
||||
$newItem->setDescription(print_changes($builds[$i], $builds[$i + 1]));
|
||||
}
|
||||
$buildFeed->addItem($newItem);
|
||||
}
|
||||
|
||||
$buildFeed->genarateFeed();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
||||
BIN
images/body-bg.png
Normal file
BIN
images/body-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 301 B |
BIN
images/container-bg.gif
Normal file
BIN
images/container-bg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 337 B |
BIN
images/dl.gif
Normal file
BIN
images/dl.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 120 B |
BIN
images/favicon.ico
Normal file
BIN
images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
BIN
images/singularity_logo.gif
Normal file
BIN
images/singularity_logo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 98 KiB |
219
index.php
Normal file
219
index.php
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
define("SITE_ROOT", realpath(dirname(__file__)));
|
||||
require_once SITE_ROOT . "/lib/init.php";
|
||||
|
||||
function parse_email($email)
|
||||
{
|
||||
$ret = array("name" => $email, "email" => "");
|
||||
if (preg_match("|([^\<]*)<([^>]*)>|", $email, $m)) {
|
||||
$ret["name"] = trim($m[1]);
|
||||
$ret["email"] = trim($m[2]);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function print_changeset($row)
|
||||
{
|
||||
$author = parse_email($row["author"]);
|
||||
$gid = md5(strtolower($author["email"]));
|
||||
$avatar = (USE_SSL ? "https://secure.gravatar.com" : "http://www.gravatar.com") .
|
||||
"/avatar/$gid?r=x&d=mm&s=48";
|
||||
print '
|
||||
<tr>
|
||||
<td rowspan="2" style="text-align: center;"><img src="' . $avatar . '" alt="Avatar"/><br />' .
|
||||
htmlspecialchars($author["name"]) . '</td>
|
||||
<td><a href="https://github.com/siana/SingularityViewer/commit/' . htmlspecialchars($row["hash"]) . '">' . htmlspecialchars($row["hash"]) . '</a></td>
|
||||
<td>' . htmlspecialchars($row["time"]).
|
||||
' (' . Layout::since(strtotime($row["time"])) . ' ago)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" width="99%"><pre>' . htmlspecialchars($row["message"]) . '</pre></td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
function sort_by_date($a, $b)
|
||||
{
|
||||
if ($a["time"] < $b["time"]) {
|
||||
return 1;
|
||||
} else if ($a["time"] > $b["time"]) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function print_changes($current, $next, $chan)
|
||||
{
|
||||
global $DB;
|
||||
$revs = array();
|
||||
if (!($res = $DB->query(kl_str_sql("select revisions from changes where chan=!s and build<=!i and build>!i order by build desc", $chan, $current->nr, $next->nr)))) {
|
||||
return;
|
||||
} else {
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
$revs = array_merge($revs, explode(",", $row["revisions"]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($res = $DB->query(kl_str_sql("select * from revs where chan=!s and hash in ('" . implode("','", $revs) . "')", $chan))) {
|
||||
|
||||
$changesets = array();
|
||||
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
$changesets[] = $row;
|
||||
}
|
||||
|
||||
if (count($changesets) == 0) return;
|
||||
|
||||
print '<table style="width: 99%;">';
|
||||
|
||||
usort($changesets, "sort_by_date");
|
||||
|
||||
foreach ($changesets as $change) {
|
||||
print_changeset($change);
|
||||
}
|
||||
|
||||
print '</table>';
|
||||
}
|
||||
}
|
||||
|
||||
Function print_build($current, $next, $buildNr, $chan)
|
||||
{
|
||||
print "
|
||||
<tr style=\"background-color: #303030;\">
|
||||
<th><a href=\"" . URL_ROOT ."?build_id={$current->nr}\">Build " . htmlspecialchars($current->nr). "</a><br/>";
|
||||
|
||||
|
||||
if ($next) {
|
||||
if (($current->linux_file && $current->osx_file && $current->linux64_file)) {
|
||||
print "<br/><br/>";
|
||||
}
|
||||
elseif (($current->linux_file && $current->osx_file)) {
|
||||
print "<br/>";
|
||||
}
|
||||
print '
|
||||
<a class="dimmer" href="javascript:void(0)" id="toggle_link_'. $current->nr . '" onclick="javascript:toggleChanges('. $current->nr . ')">' .
|
||||
($buildNr ? 'Hide changes <<' : 'Show changes >>') . '</a>';
|
||||
}
|
||||
|
||||
print "</th><th>" . htmlspecialchars($current->modified). " (" . Layout::since(strtotime($current->modified)) . " ago)</th>
|
||||
<th>" . htmlspecialchars($current->chan). "</th>
|
||||
<th><a href='" . URL_ROOT . "/" . $current->file . "'><img src=\"" . IMG_ROOT . "/dl.gif\" alt=\"Download Windows Build\"/> Windows</a>
|
||||
<a class='dimmer' href='" . URL_ROOT . "/" . $current->file . ".log'>Build Log</a>";
|
||||
|
||||
if ($current->linux_file) {
|
||||
print "<br/><a href='" . URL_ROOT . "/" . $current->linux_file . "'><img src=\"" . IMG_ROOT . "/dl.gif\" alt=\"Download Linux Build (32 bit)\"/> Linux (32 bit)</a>";
|
||||
if (file_exists($current->linux_file . ".log")) {
|
||||
print " <a class='dimmer' href='" . URL_ROOT . "/" . $current->linux_file . ".log'>Build Log</a>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($current->linux64_file) {
|
||||
print "<br/><a href='" . URL_ROOT . "/" . $current->linux64_file . "'><img src=\"" . IMG_ROOT . "/dl.gif\" alt=\"Download Linux Build (64 bit)\"/> Linux (64 bit)</a>";
|
||||
if (file_exists($current->linux64_file . ".log")) {
|
||||
print " <a class='dimmer' href='" . URL_ROOT . "/" . $current->linux64_file . ".log'>Build Log</a>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($current->osx_file) {
|
||||
print "<br/><a href='" . URL_ROOT . "/" . $current->osx_file . "'><img src=\"" . IMG_ROOT . "/dl.gif\" alt=\"Download Mac OS X Build\"/> Mac OS X</a>";
|
||||
if (file_exists($current->osx_file . ".log")) {
|
||||
print " <a class='dimmer' href='" . URL_ROOT . "/" . $current->osx_file . ".log'>Build Log</a>";
|
||||
}
|
||||
}
|
||||
|
||||
print "</th></tr>";
|
||||
|
||||
if ($next) {
|
||||
print '<tr' . ($buildNr ? '' : ' style="display: none;"') . ' id="changes_' . $current->nr . '"><td colspan="4">';
|
||||
print_changes($current, $next, $chan);
|
||||
print "</td></tr>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function chan_selector($current_chan)
|
||||
{
|
||||
// return;
|
||||
global $CHANS;
|
||||
print '<form method="get" action="index.php">';
|
||||
print 'Select channel <select name="chan" onchange="this.form.submit()">';
|
||||
foreach($CHANS as $chan => $ref) {
|
||||
print "<option value=\"$chan\"" . ($current_chan == $chan ? " selected=\"selected\"" : "") . ">$chan</option>";
|
||||
}
|
||||
print '</select><noscript><input type="submit" value="Change"/></noscript></form><br />';
|
||||
|
||||
}
|
||||
|
||||
Layout::header();
|
||||
|
||||
if (isset($_GET["chan"]) && isset($CHANS[$_GET["chan"]])) {
|
||||
$chan = $_GET["chan"];
|
||||
} else {
|
||||
// $chan = "SingularityMultiWearable";
|
||||
$chan = "SingularityAlpha";
|
||||
}
|
||||
|
||||
$pageSize = 20;
|
||||
|
||||
$builds = array();
|
||||
|
||||
$buildNr = 0;
|
||||
$where = "";
|
||||
|
||||
if (isset($_GET["build_id"])) {
|
||||
$buildNr = (int)$_GET["build_id"];
|
||||
$pageSize = 1;
|
||||
$where = kl_str_sql(" and nr <= !i ", $buildNr);
|
||||
} else {
|
||||
chan_selector($chan);
|
||||
}
|
||||
|
||||
if ($res = $DB->query(kl_str_sql("select * from builds where chan=!s $where order by nr desc limit !i", $chan, $pageSize + 1))) {
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
|
||||
$build = new stdClass;
|
||||
$DB->loadFromDbRow($build, $res, $row);
|
||||
|
||||
$file = "{$chan}_" . str_replace(".", "-", $build->version) . "_Setup.exe";
|
||||
$build->file = file_exists($file) ? $file : false;
|
||||
|
||||
$linux_file = "{$chan}-i686-{$build->version}.tar.bz2";
|
||||
$build->linux_file = file_exists($linux_file) ? $linux_file : false;
|
||||
|
||||
$linux64_file = "{$chan}-x86_64-{$build->version}.tar.bz2";
|
||||
$build->linux64_file = file_exists($linux64_file) ? $linux64_file : false;
|
||||
|
||||
$osx_file = "{$chan}_" . str_replace(".", "_", $build->version) . ".dmg";
|
||||
$build->osx_file = file_exists($osx_file) ? $osx_file : false;
|
||||
|
||||
$builds[] = $build;
|
||||
}
|
||||
}
|
||||
|
||||
$nrBuilds = count($builds);
|
||||
|
||||
if ($nrBuilds) {
|
||||
print '<table class="build-list">';
|
||||
|
||||
|
||||
for ($i = 0; $i < $pageSize; $i++) {
|
||||
if (!isset($builds[$i])) continue;
|
||||
print_build($builds[$i], $builds[$i + 1], $buildNr, $chan);
|
||||
}
|
||||
|
||||
print '</table>';
|
||||
|
||||
}
|
||||
|
||||
Layout::footer();
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
||||
11
latest.php
11
latest.php
@@ -26,5 +26,14 @@ $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
|
||||
$latest = urlencode($files[0]);
|
||||
|
||||
header("Location: http://${host}${uri}/${latest}");
|
||||
?>
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
||||
|
||||
|
||||
|
||||
20
lib/DBH.php
20
lib/DBH.php
@@ -38,7 +38,7 @@ class DBH
|
||||
$this->db_user = $db_user;
|
||||
$this->db_host = $db_host;
|
||||
|
||||
$this->dbh = @sqlite_popen($db_name, 0666, $error_msg);
|
||||
$this->dbh = @sqlite_open($db_name, 0666, $error_msg);
|
||||
|
||||
if (!$this->dbh) {
|
||||
DBH::log("[error] connection to database failed: $error_msg");
|
||||
@@ -54,7 +54,7 @@ class DBH
|
||||
|
||||
if (!$res) {
|
||||
DBH::log("[error] ".$q);
|
||||
DBH::log("[error_msg] " . $error_msg);
|
||||
DBH::log("[error_msg] " . $error_msg . " " . @sqlite_error_string(@sqlite_last_error(($this->dbh))));
|
||||
$this->last_error = $error_msg;
|
||||
|
||||
$e = debug_backtrace();
|
||||
@@ -69,15 +69,6 @@ class DBH
|
||||
|
||||
return false;
|
||||
} else {
|
||||
if ($res !== TRUE) {
|
||||
$result_id = (int)$res;
|
||||
if (!isset($this->field_desc[$result_id])) {
|
||||
$nf = sqlite_num_fields($res);
|
||||
for ($i=0; $i<$nf; $i++) {
|
||||
$this->field_desc[$result_id][sqlite_field_name($res, $i)] = sqlite_field_name($res, $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
DBH::log("[success] ".$q);
|
||||
return $res;
|
||||
}
|
||||
@@ -86,19 +77,14 @@ class DBH
|
||||
function loadFromDbRow(&$obj, $res, $row)
|
||||
{
|
||||
foreach ($row as $symbolicName => $nativeName){
|
||||
if ($nativeName && ($this->field_desc[(int)$res][$symbolicName] == "timestamp" ||
|
||||
$this->field_desc[(int)$res][$symbolicName] == "date")) {
|
||||
$obj->{$symbolicName} = strtotime($nativeName);
|
||||
} else {
|
||||
$obj->{$symbolicName} = $nativeName;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function fetchRow($res)
|
||||
{
|
||||
return @sqlite_fetch_array($res);
|
||||
return @sqlite_fetch_array($res, SQLITE_ASSOC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
167
lib/FeedItem.php
Normal file
167
lib/FeedItem.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* Univarsel Feed Writer
|
||||
*
|
||||
* FeedItem class - Used as feed element in FeedWriter class
|
||||
*
|
||||
* @package UnivarselFeedWriter
|
||||
* @author Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* @link http://www.ajaxray.com/projects/rss
|
||||
*/
|
||||
class FeedItem
|
||||
{
|
||||
private $elements = array(); //Collection of feed elements
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param contant (RSS1/RSS2/ATOM) RSS2 is default.
|
||||
*/
|
||||
function __construct($version = RSS2)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element to elements array
|
||||
*
|
||||
* @access public
|
||||
* @param srting The tag name of an element
|
||||
* @param srting The content of tag
|
||||
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
|
||||
* @return void
|
||||
*/
|
||||
public function addElement($elementName, $content, $attributes = null)
|
||||
{
|
||||
$this->elements[$elementName]['name'] = $elementName;
|
||||
$this->elements[$elementName]['content'] = $content;
|
||||
$this->elements[$elementName]['attributes'] = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set multiple feed elements from an array.
|
||||
* Elements which have attributes cannot be added by this method
|
||||
*
|
||||
* @access public
|
||||
* @param array array of elements in 'tagName' => 'tagContent' format.
|
||||
* @return void
|
||||
*/
|
||||
public function addElementArray($elementArray)
|
||||
{
|
||||
if(! is_array($elementArray)) return;
|
||||
foreach ($elementArray as $elementName => $content)
|
||||
{
|
||||
$this->addElement($elementName, $content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of elements in this feed item
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
||||
return $this->elements;
|
||||
}
|
||||
|
||||
// Wrapper functions ------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the 'dscription' element of feed item
|
||||
*
|
||||
* @access public
|
||||
* @param string The content of 'description' element
|
||||
* @return void
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$tag = ($this->version == ATOM)? 'summary' : 'description';
|
||||
$this->addElement($tag, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc Set the 'title' element of feed item
|
||||
* @access public
|
||||
* @param string The content of 'title' element
|
||||
* @return void
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->addElement('title', $title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'date' element of feed item
|
||||
*
|
||||
* @access public
|
||||
* @param string The content of 'date' element
|
||||
* @return void
|
||||
*/
|
||||
public function setDate($date)
|
||||
{
|
||||
if(! is_numeric($date))
|
||||
{
|
||||
$date = strtotime($date);
|
||||
}
|
||||
|
||||
if($this->version == ATOM)
|
||||
{
|
||||
$tag = 'updated';
|
||||
$value = date(DATE_ATOM, $date);
|
||||
}
|
||||
elseif($this->version == RSS2)
|
||||
{
|
||||
$tag = 'pubDate';
|
||||
$value = date(DATE_RSS, $date);
|
||||
}
|
||||
else
|
||||
{
|
||||
$tag = 'dc:date';
|
||||
$value = date("Y-m-d", $date);
|
||||
}
|
||||
|
||||
$this->addElement($tag, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'link' element of feed item
|
||||
*
|
||||
* @access public
|
||||
* @param string The content of 'link' element
|
||||
* @return void
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
if($this->version == RSS2 || $this->version == RSS1)
|
||||
{
|
||||
$this->addElement('link', $link);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->addElement('link','',array('href'=>$link));
|
||||
$this->addElement('id', FeedWriter::uuid($link,'urn:uuid:'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'encloser' element of feed item
|
||||
* For RSS 2.0 only
|
||||
*
|
||||
* @access public
|
||||
* @param string The url attribute of encloser tag
|
||||
* @param string The length attribute of encloser tag
|
||||
* @param string The type attribute of encloser tag
|
||||
* @return void
|
||||
*/
|
||||
public function setEncloser($url, $length, $type)
|
||||
{
|
||||
$attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);
|
||||
$this->addElement('enclosure','',$attributes);
|
||||
}
|
||||
|
||||
} // end of class FeedItem
|
||||
?>
|
||||
430
lib/FeedWriter.php
Normal file
430
lib/FeedWriter.php
Normal file
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
// RSS 0.90 Officially obsoleted by 1.0
|
||||
// RSS 0.91, 0.92, 0.93 and 0.94 Officially obsoleted by 2.0
|
||||
// So, define constants for RSS 1.0, RSS 2.0 and ATOM
|
||||
|
||||
define('RSS1', 'RSS 1.0', true);
|
||||
define('RSS2', 'RSS 2.0', true);
|
||||
define('ATOM', 'ATOM', true);
|
||||
|
||||
/**
|
||||
* Univarsel Feed Writer class
|
||||
*
|
||||
* Genarate RSS 1.0, RSS2.0 and ATOM Feed
|
||||
*
|
||||
* @package UnivarselFeedWriter
|
||||
* @author Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* @link http://www.ajaxray.com/projects/rss
|
||||
*/
|
||||
class FeedWriter
|
||||
{
|
||||
private $channels = array(); // Collection of channel elements
|
||||
private $items = array(); // Collection of items as object of FeedItem class.
|
||||
private $data = array(); // Store some other version wise data
|
||||
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA
|
||||
|
||||
private $version = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param constant the version constant (RSS1/RSS2/ATOM).
|
||||
*/
|
||||
function __construct($version = RSS2)
|
||||
{
|
||||
$this->version = $version;
|
||||
|
||||
// Setting default value for assential channel elements
|
||||
$this->channels['title'] = $version . ' Feed';
|
||||
$this->channels['link'] = 'http://www.ajaxray.com/blog';
|
||||
|
||||
//Tag names to encode in CDATA
|
||||
$this->CDATAEncoding = array('description', 'content:encoded', 'summary');
|
||||
}
|
||||
|
||||
// Start # public functions ---------------------------------------------
|
||||
|
||||
/**
|
||||
* Set a channel element
|
||||
* @access public
|
||||
* @param srting name of the channel tag
|
||||
* @param string content of the channel tag
|
||||
* @return void
|
||||
*/
|
||||
public function setChannelElement($elementName, $content)
|
||||
{
|
||||
$this->channels[$elementName] = $content ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set multiple channel elements from an array. Array elements
|
||||
* should be 'channelName' => 'channelContent' format.
|
||||
*
|
||||
* @access public
|
||||
* @param array array of channels
|
||||
* @return void
|
||||
*/
|
||||
public function setChannelElementsFromArray($elementArray)
|
||||
{
|
||||
if(! is_array($elementArray)) return;
|
||||
foreach ($elementArray as $elementName => $content)
|
||||
{
|
||||
$this->setChannelElement($elementName, $content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Genarate the actual RSS/ATOM file
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function genarateFeed()
|
||||
{
|
||||
header("Content-type: text/xml");
|
||||
|
||||
$this->printHead();
|
||||
$this->printChannels();
|
||||
$this->printItems();
|
||||
$this->printTale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FeedItem.
|
||||
*
|
||||
* @access public
|
||||
* @return object instance of FeedItem class
|
||||
*/
|
||||
public function createNewItem()
|
||||
{
|
||||
$Item = new FeedItem($this->version);
|
||||
return $Item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a FeedItem to the main class
|
||||
*
|
||||
* @access public
|
||||
* @param object instance of FeedItem class
|
||||
* @return void
|
||||
*/
|
||||
public function addItem($feedItem)
|
||||
{
|
||||
$this->items[] = $feedItem;
|
||||
}
|
||||
|
||||
|
||||
// Wrapper functions -------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set the 'title' channel element
|
||||
*
|
||||
* @access public
|
||||
* @param srting value of 'title' channel tag
|
||||
* @return void
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->setChannelElement('title', $title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'description' channel element
|
||||
*
|
||||
* @access public
|
||||
* @param srting value of 'description' channel tag
|
||||
* @return void
|
||||
*/
|
||||
public function setDescription($desciption)
|
||||
{
|
||||
$this->setChannelElement('description', $desciption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'link' channel element
|
||||
*
|
||||
* @access public
|
||||
* @param srting value of 'link' channel tag
|
||||
* @return void
|
||||
*/
|
||||
public function setLink($link)
|
||||
{
|
||||
$this->setChannelElement('link', $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'image' channel element
|
||||
*
|
||||
* @access public
|
||||
* @param srting title of image
|
||||
* @param srting link url of the imahe
|
||||
* @param srting path url of the image
|
||||
* @return void
|
||||
*/
|
||||
public function setImage($title, $link, $url)
|
||||
{
|
||||
$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the 'about' channel element. Only for RSS 1.0
|
||||
*
|
||||
* @access public
|
||||
* @param srting value of 'about' channel tag
|
||||
* @return void
|
||||
*/
|
||||
public function setChannelAbout($url)
|
||||
{
|
||||
$this->data['ChannelAbout'] = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Genarates an UUID
|
||||
* @author Anis uddin Ahmad <admin@ajaxray.com>
|
||||
* @param string an optional prefix
|
||||
* @return string the formated uuid
|
||||
*/
|
||||
public function uuid($key = null, $prefix = '')
|
||||
{
|
||||
$key = ($key == null)? uniqid(rand()) : $key;
|
||||
$chars = md5($key);
|
||||
$uuid = substr($chars,0,8) . '-';
|
||||
$uuid .= substr($chars,8,4) . '-';
|
||||
$uuid .= substr($chars,12,4) . '-';
|
||||
$uuid .= substr($chars,16,4) . '-';
|
||||
$uuid .= substr($chars,20,12);
|
||||
|
||||
return $prefix . $uuid;
|
||||
}
|
||||
// End # public functions ----------------------------------------------
|
||||
|
||||
// Start # private functions ----------------------------------------------
|
||||
|
||||
/**
|
||||
* Prints the xml and rss namespace
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function printHead()
|
||||
{
|
||||
$out = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
|
||||
|
||||
if($this->version == RSS2)
|
||||
{
|
||||
$out .= '<rss version="2.0"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
|
||||
>' . PHP_EOL;
|
||||
}
|
||||
elseif($this->version == RSS1)
|
||||
{
|
||||
$out .= '<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://purl.org/rss/1.0/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
>' . PHP_EOL;;
|
||||
}
|
||||
else if($this->version == ATOM)
|
||||
{
|
||||
$out .= '<feed xmlns="http://www.w3.org/2005/Atom">' . PHP_EOL;;
|
||||
}
|
||||
echo $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the open tags at the end of file
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function printTale()
|
||||
{
|
||||
if($this->version == RSS2)
|
||||
{
|
||||
echo '</channel>' . PHP_EOL . '</rss>';
|
||||
}
|
||||
elseif($this->version == RSS1)
|
||||
{
|
||||
echo '</rdf:RDF>';
|
||||
}
|
||||
else if($this->version == ATOM)
|
||||
{
|
||||
echo '</feed>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single node as xml format
|
||||
*
|
||||
* @access private
|
||||
* @param srting name of the tag
|
||||
* @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format
|
||||
* @param array Attributes(if any) in 'attrName' => 'attrValue' format
|
||||
* @return string formatted xml tag
|
||||
*/
|
||||
private function makeNode($tagName, $tagContent, $attributes = null)
|
||||
{
|
||||
$nodeText = '';
|
||||
$attrText = '';
|
||||
|
||||
if(is_array($attributes))
|
||||
{
|
||||
foreach ($attributes as $key => $value)
|
||||
{
|
||||
$attrText .= " $key=\"$value\" ";
|
||||
}
|
||||
}
|
||||
|
||||
if(is_array($tagContent) && $this->version == RSS1)
|
||||
{
|
||||
$attrText = ' rdf:parseType="Resource"';
|
||||
}
|
||||
|
||||
|
||||
$attrText .= (in_array($tagName, $this->CDATAEncoding) && $this->version == ATOM)? ' type="html" ' : '';
|
||||
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "<{$tagName}{$attrText}><![CDATA[" : "<{$tagName}{$attrText}>";
|
||||
|
||||
if(is_array($tagContent))
|
||||
{
|
||||
foreach ($tagContent as $key => $value)
|
||||
{
|
||||
$nodeText .= $this->makeNode($key, $value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);
|
||||
}
|
||||
|
||||
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";
|
||||
|
||||
return $nodeText . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc Print channels
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function printChannels()
|
||||
{
|
||||
//Start channel tag
|
||||
switch ($this->version)
|
||||
{
|
||||
case RSS2:
|
||||
echo '<channel>' . PHP_EOL;
|
||||
break;
|
||||
case RSS1:
|
||||
echo (isset($this->data['ChannelAbout']))? "<channel rdf:about=\"{$this->data['ChannelAbout']}\">" : "<channel rdf:about=\"{$this->channels['link']}\">";
|
||||
break;
|
||||
}
|
||||
|
||||
//Print Items of channel
|
||||
foreach ($this->channels as $key => $value)
|
||||
{
|
||||
if($this->version == ATOM && $key == 'link')
|
||||
{
|
||||
// ATOM prints link element as href attribute
|
||||
echo $this->makeNode($key,'',array('href'=>$value));
|
||||
//Add the id for ATOM
|
||||
echo $this->makeNode('id',$this->uuid($value,'urn:uuid:'));
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $this->makeNode($key, $value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//RSS 1.0 have special tag <rdf:Seq> with channel
|
||||
if($this->version == RSS1)
|
||||
{
|
||||
echo "<items>" . PHP_EOL . "<rdf:Seq>" . PHP_EOL;
|
||||
foreach ($this->items as $item)
|
||||
{
|
||||
$thisItems = $item->getElements();
|
||||
echo "<rdf:li resource=\"{$thisItems['link']['content']}\"/>" . PHP_EOL;
|
||||
}
|
||||
echo "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints formatted feed items
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function printItems()
|
||||
{
|
||||
foreach ($this->items as $item)
|
||||
{
|
||||
$thisItems = $item->getElements();
|
||||
|
||||
//the argument is printed as rdf:about attribute of item in rss 1.0
|
||||
echo $this->startItem($thisItems['link']['content']);
|
||||
|
||||
foreach ($thisItems as $feedItem )
|
||||
{
|
||||
echo $this->makeNode($feedItem['name'], $feedItem['content'], $feedItem['attributes']);
|
||||
}
|
||||
echo $this->endItem();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the starting tag of channels
|
||||
*
|
||||
* @access private
|
||||
* @param srting The vale of about tag which is used for only RSS 1.0
|
||||
* @return void
|
||||
*/
|
||||
private function startItem($about = false)
|
||||
{
|
||||
if($this->version == RSS2)
|
||||
{
|
||||
echo '<item>' . PHP_EOL;
|
||||
}
|
||||
elseif($this->version == RSS1)
|
||||
{
|
||||
if($about)
|
||||
{
|
||||
echo "<item rdf:about=\"$about\">" . PHP_EOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
die('link element is not set .\n It\'s required for RSS 1.0 to be used as about attribute of item');
|
||||
}
|
||||
}
|
||||
else if($this->version == ATOM)
|
||||
{
|
||||
echo "<entry>" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes feed item tag
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function endItem()
|
||||
{
|
||||
if($this->version == RSS2 || $this->version == RSS1)
|
||||
{
|
||||
echo '</item>' . PHP_EOL;
|
||||
}
|
||||
else if($this->version == ATOM)
|
||||
{
|
||||
echo "</entry>" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// End # private functions ----------------------------------------------
|
||||
|
||||
} // end of class FeedWriter
|
||||
|
||||
98
lib/Layout.php
Normal file
98
lib/Layout.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
|
||||
class Layout
|
||||
{
|
||||
|
||||
function since($since)
|
||||
{
|
||||
$since = time() - $since;
|
||||
$chunks = array(
|
||||
array(60 * 60 * 24 * 365 , 'year'),
|
||||
array(60 * 60 * 24 * 30 , 'month'),
|
||||
array(60 * 60 * 24 * 7, 'week'),
|
||||
array(60 * 60 * 24 , 'day'),
|
||||
array(60 * 60 , 'hour'),
|
||||
array(60 , 'minute'),
|
||||
array(1 , 'second')
|
||||
);
|
||||
|
||||
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
|
||||
$seconds = $chunks[$i][0];
|
||||
$name = $chunks[$i][1];
|
||||
if (($count = floor($since / $seconds)) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$print = ($count == 1) ? '1 '.$name : "$count {$name}s";
|
||||
return $print;
|
||||
}
|
||||
|
||||
function header()
|
||||
{ ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="<?php print URL_ROOT ?>/buildsite.css"/>
|
||||
<link href="<?php print URL_ROOT ?>/feed.php" rel="alternate" title="Singularity Automatic Development Builds" type="application/atom+xml" />
|
||||
<link rel="shortcut icon" href="<?php print IMG_ROOT ?>/favicon.ico" type="image/x-icon" />
|
||||
<title>Singularity Viewer Automated Build System</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function toggleChanges(id)
|
||||
{
|
||||
var change = document.getElementById("changes_" + id);
|
||||
var link = document.getElementById("toggle_link_" + id);
|
||||
|
||||
if (change) {
|
||||
if (change.style.display == "") {
|
||||
change.style.display = "none";
|
||||
link.innerHTML = "Show changes >>";
|
||||
} else {
|
||||
change.style.display = "";
|
||||
link.innerHTML = "Hide changes <<";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="everything">
|
||||
<div id="page-wrapper">
|
||||
<div id="header"></div>
|
||||
<div class="container"><a href="<?php print URL_ROOT ?>" style="font-size: 20px;">Automated Build System</a><br/><br/>
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
function footer()
|
||||
{
|
||||
{ ?>
|
||||
</div><!-- container -->
|
||||
<div class="container">
|
||||
<table style="width: 100%; border: none; padding: 0;"><tr>
|
||||
<td class="bottom-links"><a href="http://www.singularityviewer.org/">Singularity Main Site</a></td>
|
||||
<td class="bottom-links"><a href="http://www.singularityviewer.org/about">About</a></td>
|
||||
<td class="bottom-links"><a href="http://code.google.com/p/singularity-viewer/issues/">Issue Tracker</a></td>
|
||||
<td class="bottom-links"><a href="https://github.com/singularity-viewer/SingularityViewer">Source Tracker</a></td>
|
||||
<td width="50%" style="text-align: right;">© 2012 Singularity Viewer Project</td>
|
||||
</tr></table>
|
||||
</div>
|
||||
</div><!-- everything -->
|
||||
</div><!-- page-wrapper -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
72
lib/cleanup.php
Executable file
72
lib/cleanup.php
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
define("SITE_ROOT", realpath(dirname(__file__) . "/.."));
|
||||
require_once SITE_ROOT . "/lib/init.php";
|
||||
|
||||
|
||||
function get_old_builds($chan, $nrToKeep)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$builds = array();
|
||||
|
||||
if ($res = $DB->query(kl_str_sql("select * from builds where chan=!s and nr not in (select nr from builds where chan=!s order by nr desc limit !i)", $chan, $chan, $nrToKeep))) {
|
||||
while ($row = $DB->fetchRow($res)) {
|
||||
|
||||
$build = new stdClass;
|
||||
$DB->loadFromDbRow($build, $res, $row);
|
||||
|
||||
$file = "{$chan}_" . str_replace(".", "-", $build->version) . "_Setup.exe";
|
||||
$build->file = file_exists($file) ? $file : false;
|
||||
|
||||
$linux_file = "{$chan}-i686-{$build->version}.tar.bz2";
|
||||
$build->linux_file = file_exists($linux_file) ? $linux_file : false;
|
||||
|
||||
$linux64_file = "{$chan}-x86_64-{$build->version}.tar.bz2";
|
||||
$build->linux64_file = file_exists($linux64_file) ? $linux64_file : false;
|
||||
|
||||
$osx_file = "{$chan}_" . str_replace(".", "_", $build->version) . ".dmg";
|
||||
$build->osx_file = file_exists($osx_file) ? $osx_file : false;
|
||||
|
||||
$builds[] = $build;
|
||||
}
|
||||
}
|
||||
|
||||
return $builds;
|
||||
}
|
||||
|
||||
chdir(SITE_ROOT);
|
||||
$builds = get_old_builds("SingularityAlpha", 21);
|
||||
$nrBuilds = count($builds);
|
||||
|
||||
for ($i=0; $i<$nrBuilds; $i++) {
|
||||
|
||||
$b = $builds[$i];
|
||||
$f = array();
|
||||
if ($b->file) $f[] = $b->file;
|
||||
if ($b->linux_file) $f[] = $b->linux_file;
|
||||
if ($b->linux64_file) $f[] = $b->linux64_file;
|
||||
if ($b->osx_file) $f[] = $b->osx_file;
|
||||
|
||||
print "Cleaning build nr.: {$b->nr}\n";
|
||||
|
||||
for ($j=0; $j<count($f); $j++) {
|
||||
print " Deleting {$f[$j]}\n";
|
||||
@unlink(SITE_ROOT . "/" . $f[$j]);
|
||||
@unlink(SITE_ROOT . "/" . $f[$j] . ".log");
|
||||
}
|
||||
|
||||
$DB->query(kl_str_sql("delete from builds where nr=!i and chan=!s", $b->nr, $b->chan));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
* vim600: noet sw=4 ts=4 fdm=marker
|
||||
* vim<600: noet sw=4 ts=4
|
||||
*/
|
||||
@@ -105,6 +105,14 @@ function kl_str_sql()
|
||||
|
||||
}
|
||||
|
||||
function pre_dump($var, $die = false)
|
||||
{
|
||||
print "<pre>";
|
||||
var_dump($var);
|
||||
print "</pre>";
|
||||
if ($die) die();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
||||
38
lib/find_hash.sh
Executable file
38
lib/find_hash.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# set -x
|
||||
ROOT=/var/www/singularity
|
||||
SOURCE="$ROOT/lib/source"
|
||||
DB="$ROOT/lib/singularity_revisions.db"
|
||||
|
||||
TMP_LIST="/tmp/find_hash_tmp.lst"
|
||||
BUILD_LIST="/tmp/find_hash_tmp.bulds"
|
||||
|
||||
function update_source() {
|
||||
cd $SOURCE
|
||||
# git fetch --all
|
||||
git reset --soft FETCH_HEAD
|
||||
}
|
||||
|
||||
# main
|
||||
|
||||
chan="SingularityAlpha"
|
||||
|
||||
update_source
|
||||
git rev-list HEAD > "$TMP_LIST"
|
||||
sqlite $DB "select nr from builds where (hash = '' or hash is null) and chan='$chan' order by nr desc" > "$BUILD_LIST"
|
||||
|
||||
|
||||
cat "$BUILD_LIST" | while read build; do
|
||||
git reset --soft FETCH_HEAD
|
||||
|
||||
cat "$TMP_LIST" | while read rev; do
|
||||
git reset --soft $rev
|
||||
nr=$(git rev-list HEAD | wc -l)
|
||||
if [ "x$nr" == "x$build" ]; then
|
||||
echo "$build = $rev"
|
||||
sqlite $DB "update builds set hash='$rev' where nr='$build' and chan='$chan'"
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
@@ -9,84 +9,206 @@ if (PHP_SAPI != "cli") {
|
||||
// create table revs(id integer, hash varchar, author varchar, time timestamp, message text, diff text, primary key(id));
|
||||
// create index hash_index on revs(hash);
|
||||
|
||||
define("SITE_ROOT", dirname(__file__) . "/..");
|
||||
define("SITE_ROOT", realpath(dirname(__file__) . "/.."));
|
||||
require_once SITE_ROOT . "/lib/init.php";
|
||||
|
||||
function import_rev($id, $hash)
|
||||
function import_rev($raw, $chan)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
print "Importing revision number $id with hash $hash\n";
|
||||
$log = explode("\n", rtrim(`git log -n1 $hash`));
|
||||
$log = explode("\n", rtrim($raw));
|
||||
|
||||
$hash = $log[0];
|
||||
$author = "";
|
||||
if (preg_match("|Author:\\s*(.*)|i", $log[1], $m)) {
|
||||
$author = $m[1];
|
||||
}
|
||||
|
||||
$date = "";
|
||||
if (preg_match("|Date:\\s*(.*)|i", $log[2], $m)) {
|
||||
$date = strtotime($m[1]);
|
||||
}
|
||||
|
||||
$msg = "";
|
||||
$inMsg = false;
|
||||
$nrLog = count($log);
|
||||
for ($i=4; $i<$nrLog; $i++) {
|
||||
|
||||
for ($i=0; $i<$nrLog; $i++) {
|
||||
if ($inMsg) {
|
||||
$msg .= substr($log[$i], 4);
|
||||
if ($i<$nrLog-1) {
|
||||
$msg .= "\n";
|
||||
}
|
||||
} else {
|
||||
if (preg_match("|^author\\s*([^>]*>)\\s*([\\d]+)\\s*(.*)|i", $log[$i], $m)) {
|
||||
$author = $m[1];
|
||||
$date = (int)$m[2];
|
||||
} else if (!trim($log[$i])) {
|
||||
$inMsg = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$DB->query(
|
||||
kl_str_sql(
|
||||
"Insert into revs (id, hash, author, time, message) values (!i, !s, !s, !t, !s)",
|
||||
$id, $hash, $author, $date, $msg));
|
||||
"insert into revs (hash, chan, author, time, message) values (!s, !s, !s, !t, !s)",
|
||||
$hash, $chan, $author, $date, $msg));
|
||||
|
||||
}
|
||||
|
||||
function update_source()
|
||||
function save_build_changes($changes, $chan)
|
||||
{
|
||||
exec("git reset --hard", $out, $res);
|
||||
if ($res) {
|
||||
DBH::log("Command failed: ", implode("\n", $out));
|
||||
return;
|
||||
}
|
||||
global $DB;
|
||||
|
||||
exec("git pull", $out, $res);
|
||||
if ($res) {
|
||||
DBH::log("Command failed: ", implode("\n", $out));
|
||||
return;
|
||||
}
|
||||
|
||||
print implode("\n", $out) . "\n";
|
||||
$DB->query("begin transaction");
|
||||
foreach ($changes as $buildNr => $revs) {
|
||||
$DB->query(kl_str_sql("insert into changes (build, chan, revisions) values (!i, !s, !s)", $buildNr, $chan, implode(",", $revs)));
|
||||
}
|
||||
$DB->query("commit");
|
||||
|
||||
}
|
||||
|
||||
function update_revs()
|
||||
{
|
||||
global $DB, $CHANS;
|
||||
|
||||
$DB->query("begin transaction");
|
||||
if (!($res = $DB->query("delete from revs"))) {
|
||||
$DB->query("create table revs(hash varchar, chan varchar, author varchar, time timestamp, message text, diff text, primary key(hash))");
|
||||
}
|
||||
|
||||
$DB->query("commit");
|
||||
|
||||
$DB->query("begin transaction");
|
||||
if (!($res = $DB->query("delete from changes"))) {
|
||||
$DB->query("create table changes (build integer, chan varchar, revisions text, primary key(build, chan))");
|
||||
}
|
||||
$DB->query("commit");
|
||||
|
||||
foreach ($CHANS as $chan => $branch) {
|
||||
exec("git fetch --all 2>&1");
|
||||
if ($branch == "HEAD") {
|
||||
$branch = "FETCH_HEAD";
|
||||
}
|
||||
exec("git reset --soft $branch 2>&1");
|
||||
|
||||
$DB->query("begin transaction");
|
||||
|
||||
$revs = array_reverse(explode(chr(0), rtrim(`git rev-list HEAD --header`)));
|
||||
$nrRevs = count($revs);
|
||||
|
||||
print "Importing $nrRevs revisions for $chan\n";
|
||||
|
||||
for ($i=0; $i<$nrRevs; $i++) {
|
||||
import_rev($revs[$i], $chan);
|
||||
}
|
||||
|
||||
$res = $DB->query("commit");
|
||||
|
||||
$revs = explode("\n", rtrim(`git rev-list HEAD`));
|
||||
|
||||
$res = 0;
|
||||
$c =0;
|
||||
$changesAt = array();
|
||||
|
||||
while (true) {
|
||||
exec("git reset --soft HEAD^ 2>&1", $out, $res);
|
||||
if ($res != 0) {
|
||||
break;
|
||||
} else {
|
||||
$c++;
|
||||
$newRevs = explode("\n", rtrim(`git rev-list HEAD`));
|
||||
$changes = array_diff($revs, $newRevs);
|
||||
$nrChanges = count($changes);
|
||||
$build = count($revs);
|
||||
$revs = $newRevs;
|
||||
$changesAt[$build] = $changes;
|
||||
print $nrChanges . " changes in build $build\n";
|
||||
if ($build < 2883) break; // this is when we started building
|
||||
}
|
||||
}
|
||||
save_build_changes($changesAt, $chan);
|
||||
}
|
||||
|
||||
|
||||
print "Number resets: $c\n";
|
||||
exec("git fetch --all 2>&1");
|
||||
exec("git reset --soft $branch 2>&1");
|
||||
|
||||
}
|
||||
|
||||
function update_builds()
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$builds = glob(SITE_ROOT . "/*_*_Setup.exe");
|
||||
$latest = 0;
|
||||
|
||||
// check if table exists
|
||||
if (!($res = $DB->query("select count(*) as c from builds"))) {
|
||||
$DB->query("create table builds(nr integer, chan varchar, version varchar, hash varchar, file varchar, modified timestamp, primary key(nr, chan))");
|
||||
}
|
||||
|
||||
for ($i=0; $i<count($builds); $i++) {
|
||||
$file = basename($builds[$i]);
|
||||
if (preg_match("|^(\w+)_(\d+)-(\d+)-(\d+)-(\d+)_|", $file, $m)) {
|
||||
$chan = $m[1];
|
||||
$major = $m[2];
|
||||
$minor = $m[3];
|
||||
$maintenance = $m[4];
|
||||
$build = $m[5];
|
||||
$modified = filemtime(SITE_ROOT . "/" . $file);
|
||||
$version = "$major.$minor.$maintenance.$build";
|
||||
$res = $DB->query(kl_str_sql("select count(*) as c from builds where nr=!i and chan=!s", $build, $chan));
|
||||
$row = $DB->fetchRow($res);
|
||||
if ($row["c"] === "0") {
|
||||
$DB->query(kl_str_sql("insert into builds (nr, chan, version, file, modified) ".
|
||||
"values (!i, !s, !s, !s, !t)",
|
||||
$build, $chan, $version, $file, $modified));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function add_build($build, $chan, $version, $hash)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
// check if table exists
|
||||
if (!($res = $DB->query("select count(*) as c from builds"))) {
|
||||
$DB->query("create table builds(nr integer, chan varchar, version varchar, hash varchar, file varchar, modified timestamp, primary key(nr, chan))");
|
||||
}
|
||||
|
||||
$res = $DB->query(kl_str_sql("select count(*) as c from builds where nr=!i and chan=!s", $build, $chan));
|
||||
$row = $DB->fetchRow($res);
|
||||
if ($row["c"] === "0") {
|
||||
$DB->query(kl_str_sql("insert into builds (nr, chan, version, hash, modified) ".
|
||||
"values (!i, !s, !s, !s, !t)",
|
||||
$build, $chan, $version, $hash, time()));
|
||||
}
|
||||
}
|
||||
|
||||
/* main */
|
||||
if ($_SERVER['argc'] < 4) {
|
||||
print "Too few arguments.\nUsage: import_revs.php <channel> <version> <hash>\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$CHAN = $_SERVER['argv'][1];
|
||||
$VERSION = $_SERVER['argv'][2];
|
||||
$HASH = $_SERVER['argv'][3];
|
||||
$build_parts = explode(".", $VERSION);
|
||||
|
||||
if (count($build_parts) != 4) {
|
||||
print "Wrong version format, expected x.y.z.build\n";
|
||||
die();
|
||||
}
|
||||
$BUILD = $build_parts[3];
|
||||
|
||||
print "$CHAN $VERSION $HASH $BUILD\n";
|
||||
add_build($BUILD, $CHAN, $VERSION, $HASH);
|
||||
|
||||
$DB->query("PRAGMA synchronous = OFF");
|
||||
chdir(SITE_ROOT . "/lib/source");
|
||||
exec("git fetch --all");
|
||||
update_revs();
|
||||
|
||||
# update_source();
|
||||
|
||||
$revsStr = rtrim(`git rev-list HEAD | tac`);
|
||||
$revs = explode("\n", $revsStr);
|
||||
$nrRevs = count($revs);
|
||||
|
||||
|
||||
$latest = 0;
|
||||
$res = $DB->query("select max(id) as id from revs");
|
||||
if ($row = $DB->fetchRow($res)) {
|
||||
if ($DB->loadFromDbRow($dbLatest, $res, $row)) {
|
||||
$latest = (int)$dbLatest->id;
|
||||
}
|
||||
}
|
||||
|
||||
print "Found $nrRevs revisions\n";
|
||||
print "Latest revision in the database: $latest\n";
|
||||
|
||||
if ($latest < $nrRevs) {
|
||||
for ($rev = $latest + 1; $rev <= $nrRevs; $rev++) {
|
||||
import_rev($rev, $revs[$rev - 1]);
|
||||
}
|
||||
}
|
||||
chdir(SITE_ROOT);
|
||||
update_builds();
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
@@ -4,6 +4,7 @@ if (!defined('SITE_ROOT')) {
|
||||
}
|
||||
|
||||
error_reporting(E_ALL ^ E_NOTICE);
|
||||
ini_set("display_errors", "true");
|
||||
|
||||
if (!extension_loaded('kl')) {
|
||||
require_once SITE_ROOT.'/lib/ext_kl.php';
|
||||
@@ -19,11 +20,12 @@ function __autoload($class)
|
||||
* Example: http://www.example.com/applications/app1/
|
||||
*/
|
||||
|
||||
define('REL_DIR', '');
|
||||
define('REL_DIR', 'singularity');
|
||||
|
||||
if (!defined('URL_ROOT')) {
|
||||
$init_port = "";
|
||||
$init_ssl = strlen($_SERVER["HTTPS"]) > 0 ? true:false;
|
||||
define('USE_SSL', $init_ssl);
|
||||
|
||||
$init_url = $init_ssl ? "https://" : "http://";
|
||||
|
||||
@@ -53,9 +55,12 @@ if (!defined('IMG_ROOT')) {
|
||||
}
|
||||
|
||||
|
||||
// $CHANS = array("SingularityAlpha" => "HEAD", "SingularityMultiWearable" => "refs/remotes/shyotl/V2MultiWear");
|
||||
$CHANS = array("SingularityAlpha" => "HEAD");
|
||||
|
||||
$DB = new DBH();
|
||||
|
||||
$DB_NAME = SITE_ROOT . '/lib/signularity_revisions.db';
|
||||
$DB_NAME = SITE_ROOT . '/lib/singularity_revisions.db';
|
||||
/* $DB_USER = 'gigaprims';
|
||||
$DB_PASS = 'secrit';
|
||||
$DB_HOST = 'localhost';
|
||||
|
||||
Reference in New Issue
Block a user