diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b28720b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.exe
+*.bz2
+*.dmg
+*.zip
+*.bak
+*~
+*.log
+lib/source/*
+lib/singularity_revisions*
diff --git a/.hgignore b/.hgignore
deleted file mode 100644
index 6c2cfbb..0000000
--- a/.hgignore
+++ /dev/null
@@ -1,7 +0,0 @@
-syntax: glob
-*.exe
-*.bak
-*~
-*.log
-lib/source/*
-lib/signularity_revisions*
\ No newline at end of file
diff --git a/buildsite.css b/buildsite.css
new file mode 100644
index 0000000..f465405
--- /dev/null
+++ b/buildsite.css
@@ -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;
+}
\ No newline at end of file
diff --git a/feed.php b/feed.php
new file mode 100644
index 0000000..0d12385
--- /dev/null
+++ b/feed.php
@@ -0,0 +1,126 @@
+ $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 '
 '
+ . htmlspecialchars($author["name"]) . ' | '
+ . '' . htmlspecialchars($row["hash"]) . ' '
+ . htmlspecialchars($row["time"]). "
\n\n"
+ . htmlspecialchars($row["message"]) . ' | ';
+}
+
+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 .= '';
+
+ $changesets = array();
+
+ while ($row = $DB->fetchRow($res)) {
+ $changesets[] = $row;
+ }
+
+ usort($changesets, "sort_by_date");
+
+ foreach ($changesets as $change) {
+ $ret .= print_changeset($change);
+ }
+
+ $ret .= '
';
+ }
+
+ 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
+ */
diff --git a/images/body-bg.png b/images/body-bg.png
new file mode 100644
index 0000000..6731269
Binary files /dev/null and b/images/body-bg.png differ
diff --git a/images/container-bg.gif b/images/container-bg.gif
new file mode 100644
index 0000000..fe2b531
Binary files /dev/null and b/images/container-bg.gif differ
diff --git a/images/dl.gif b/images/dl.gif
new file mode 100644
index 0000000..e94f1f0
Binary files /dev/null and b/images/dl.gif differ
diff --git a/images/favicon.ico b/images/favicon.ico
new file mode 100644
index 0000000..f145db8
Binary files /dev/null and b/images/favicon.ico differ
diff --git a/images/singularity_logo.gif b/images/singularity_logo.gif
new file mode 100644
index 0000000..a5f3023
Binary files /dev/null and b/images/singularity_logo.gif differ
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..74fc9bc
--- /dev/null
+++ b/index.php
@@ -0,0 +1,219 @@
+ $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 '
+
+  ' .
+ htmlspecialchars($author["name"]) . ' |
+ ' . htmlspecialchars($row["hash"]) . ' |
+ ' . htmlspecialchars($row["time"]).
+ ' (' . Layout::since(strtotime($row["time"])) . ' ago) |
+
+
+ ' . htmlspecialchars($row["message"]) . ' |
+
';
+}
+
+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 '';
+
+ usort($changesets, "sort_by_date");
+
+ foreach ($changesets as $change) {
+ print_changeset($change);
+ }
+
+ print '
';
+ }
+}
+
+Function print_build($current, $next, $buildNr, $chan)
+{
+ print "
+
+ nr}\">Build " . htmlspecialchars($current->nr). " ";
+
+
+ if ($next) {
+ if (($current->linux_file && $current->osx_file && $current->linux64_file)) {
+ print "
";
+ }
+ elseif (($current->linux_file && $current->osx_file)) {
+ print " ";
+ }
+ print '
+ ' .
+ ($buildNr ? 'Hide changes <<' : 'Show changes >>') . '';
+ }
+
+ print " | " . htmlspecialchars($current->modified). " (" . Layout::since(strtotime($current->modified)) . " ago) |
+ " . htmlspecialchars($current->chan). " |
+ Windows
+ Build Log";
+
+ if ($current->linux_file) {
+ print "
Linux (32 bit)";
+ if (file_exists($current->linux_file . ".log")) {
+ print " Build Log";
+ }
+
+ }
+
+
+ if ($current->linux64_file) {
+ print "
Linux (64 bit)";
+ if (file_exists($current->linux64_file . ".log")) {
+ print " Build Log";
+ }
+ }
+
+ if ($current->osx_file) {
+ print "
Mac OS X";
+ if (file_exists($current->osx_file . ".log")) {
+ print " Build Log";
+ }
+ }
+
+ print " |
";
+
+ if ($next) {
+ print '| ';
+ print_changes($current, $next, $chan);
+ print " |
";
+ }
+
+}
+
+function chan_selector($current_chan)
+{
+ // return;
+ global $CHANS;
+ print '
';
+
+}
+
+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 '';
+
+
+ for ($i = 0; $i < $pageSize; $i++) {
+ if (!isset($builds[$i])) continue;
+ print_build($builds[$i], $builds[$i + 1], $buildNr, $chan);
+ }
+
+ print '
';
+
+}
+
+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
+ */
diff --git a/latest.php b/latest.php
index 000fe1e..1f33588 100644
--- a/latest.php
+++ b/latest.php
@@ -8,16 +8,16 @@ header("Content-Type: text/plain");
$chan = "SingularityAlpha";
if (isset($_GET["chan"])) {
- $chan = preg_replace("%[^\\w_-]%i", "", $_GET["chan"]);
+ $chan = preg_replace("%[^\\w_-]%i", "", $_GET["chan"]);
}
$files = glob($chan . "_*.exe");
if (count($files) === 0) {
- header("HTTP/1.0 404 Not Found");
- header("Content-Type: text/plain");
- print "Requested channel was not found";
- die();
+ header("HTTP/1.0 404 Not Found");
+ header("Content-Type: text/plain");
+ print "Requested channel was not found";
+ die();
}
$files = array_reverse($files);
@@ -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
+ */
+
diff --git a/lib/DBH.php b/lib/DBH.php
index 906fed3..ea91326 100644
--- a/lib/DBH.php
+++ b/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;
- }
+ $obj->{$symbolicName} = $nativeName;
}
return true;
}
function fetchRow($res)
{
- return @sqlite_fetch_array($res);
+ return @sqlite_fetch_array($res, SQLITE_ASSOC);
}
}
diff --git a/lib/FeedItem.php b/lib/FeedItem.php
new file mode 100644
index 0000000..a9fe931
--- /dev/null
+++ b/lib/FeedItem.php
@@ -0,0 +1,167 @@
+
+ * @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
+?>
diff --git a/lib/FeedWriter.php b/lib/FeedWriter.php
new file mode 100644
index 0000000..70d01d0
--- /dev/null
+++ b/lib/FeedWriter.php
@@ -0,0 +1,430 @@
+
+ * @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
+ * @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 = '' . "\n";
+
+ if($this->version == RSS2)
+ {
+ $out .= '' . PHP_EOL;
+ }
+ elseif($this->version == RSS1)
+ {
+ $out .= '' . PHP_EOL;;
+ }
+ else if($this->version == ATOM)
+ {
+ $out .= '' . 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 '' . PHP_EOL . '';
+ }
+ elseif($this->version == RSS1)
+ {
+ echo '';
+ }
+ else if($this->version == ATOM)
+ {
+ echo '';
+ }
+
+ }
+
+ /**
+ * 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}>";
+
+ 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 '' . PHP_EOL;
+ break;
+ case RSS1:
+ echo (isset($this->data['ChannelAbout']))? "data['ChannelAbout']}\">" : "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 with channel
+ if($this->version == RSS1)
+ {
+ echo "" . PHP_EOL . "" . PHP_EOL;
+ foreach ($this->items as $item)
+ {
+ $thisItems = $item->getElements();
+ echo "" . PHP_EOL;
+ }
+ echo "" . PHP_EOL . "" . PHP_EOL . "" . 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 '- ' . PHP_EOL;
+ }
+ elseif($this->version == RSS1)
+ {
+ if($about)
+ {
+ echo "
- " . 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 "" . PHP_EOL;
+ }
+ }
+
+ /**
+ * Closes feed item tag
+ *
+ * @access private
+ * @return void
+ */
+ private function endItem()
+ {
+ if($this->version == RSS2 || $this->version == RSS1)
+ {
+ echo '
' . PHP_EOL;
+ }
+ else if($this->version == ATOM)
+ {
+ echo "" . PHP_EOL;
+ }
+ }
+
+
+
+ // End # private functions ----------------------------------------------
+
+ } // end of class FeedWriter
+
diff --git a/lib/Layout.php b/lib/Layout.php
new file mode 100644
index 0000000..fd6c484
--- /dev/null
+++ b/lib/Layout.php
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+ Singularity Viewer Automated Build System
+
+
+
+
+
+
+
+
+
+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; $jquery(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
+ */
diff --git a/lib/ext_kl.php b/lib/ext_kl.php
index edea75c..da2b36a 100644
--- a/lib/ext_kl.php
+++ b/lib/ext_kl.php
@@ -104,6 +104,14 @@ function kl_str_sql()
return $res;
}
+
+function pre_dump($var, $die = false)
+{
+ print "";
+ var_dump($var);
+ print "
";
+ if ($die) die();
+}
/*
* Local variables:
diff --git a/lib/find_hash.sh b/lib/find_hash.sh
new file mode 100755
index 0000000..5904554
--- /dev/null
+++ b/lib/find_hash.sh
@@ -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
diff --git a/lib/import_revs.php b/lib/import_revs.php
index 4b77290..a78e733 100755
--- a/lib/import_revs.php
+++ b/lib/import_revs.php
@@ -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++) {
- $msg .= substr($log[$i], 4);
- if ($i<$nrLog-1) {
- $msg .= "\n";
+
+ 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; $iquery(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 \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:
diff --git a/lib/init.php b/lib/init.php
index bbb335b..10105f9 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -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';