+++ /dev/null
-<?php
-require_once 'Interface/CommitListener.php';
-
-class MTrackCommitCheck_BlankLines implements IMTrackCommitListener
-{
-
- function vetoCommit($msg, $files, $actions, $checker)
- {
- // should only have a list of files which have been updated/added. (not deleted)
- $ret = array();
- if (!method_exists($checker->bridge, 'getDiffStream')) { // kludge - we should use interface....
- return true;
- }
- $fp = $checker->bridge->getDiffStream();
- $diff = stream_get_contents($fp);
- $lines = explode("\n",$contents);
- $seq = 0;
- $total = 0;
-
- // probably a CRLF fix....
- if (count($lines) > 100) {
- return;
- }
-
- foreach($lines as $l) {
- $ll = trim($l);
- if ($l != '+') {
- $seq =0;
- continue;
- }
- // got blannk line
- $seq++;
-
- if ($seq > 2) {
- return "You are adding more than 2 blank lines - please remove the new blank lines you added and try again.";
- }
- }
-
-
-
- return true;
- }
-
- function postCommit($msg, $files, $actions) {
- return true;
- }
-
-}
\ No newline at end of file
<?php
-require_once 'DBSchema_SQLite.php';
-require_once 'DBSchema_pgsql.php';
-require_once 'DBSchema_Table.php';
+require_once 'DBSchema/SQLite.php';
+require_once 'DBSchema/pgsql.php';
+require_once 'DBSchema/Table.php';
class MTrackDBSchema {
var $tables;
--- /dev/null
+<?php
+
+require_once 'Interface/DBSchema_Driver.php';
+
+class MTrackDBSchema_Generic implements IMTrackDBSchema_Driver {
+ var $db;
+ var $typemap = array();
+
+ function setDB(PDO $db) {
+ $this->db = $db;
+ }
+
+ function determineVersion() {
+ try {
+ $q = $this->db->query('select version from mtrack_schema');
+ if ($q) {
+ foreach ($q as $row) {
+ return $row[0];
+ }
+ }
+ } catch (Exception $e) {
+ }
+ return null;
+ }
+
+ function computeFieldCreate($f) {
+ $str = "\t$f->name ";
+ $str .= isset($this->typemap[$f->type]) ? $this->typemap[$f->type] : $f->type;
+ if (isset($f->nullable) && $f->nullable == '0') {
+ $str .= ' NOT NULL ';
+ }
+ if (isset($f->default)) {
+ if (!strlen($f->default)) {
+ $str .= " DEFAULT ''";
+ } else {
+ $str .= " DEFAULT $f->default";
+ }
+ }
+ return $str;
+ }
+
+ function computeIndexCreate($table, $k) {
+ switch ($k->type) {
+ case 'unique':
+ $kt = ' UNIQUE ';
+ break;
+ case 'multiple':
+ default:
+ $kt = '';
+ }
+ return "CREATE $kt INDEX $k->name on $table->name (" . join(', ', $k->fields) . ")";
+ }
+
+ function createTable(MTrackDBSchema_Table $table)
+ {
+ echo "Create $table->name\n";
+
+ $pri_key = null;
+
+ $sql = array();
+ foreach ($table->fields as $f) {
+ if ($f->type == 'autoinc') {
+ $pri_key = $f->name;
+ }
+ $str = $this->computeFieldCreate($f);
+ $sql[] = $str;
+ }
+
+ if (is_array($table->keys)) foreach ($table->keys as $k) {
+ if ($k->type != 'primary') continue;
+ if ($pri_key !== null) continue;
+ $sql[] = "\tprimary key (" . join(', ', $k->fields) . ")";
+ }
+
+ $sql = "CREATE TABLE $table->name (\n" .
+ join(",\n", $sql) .
+ ")\n";
+
+# echo $sql;
+
+ $this->db->exec($sql);
+
+ if (is_array($table->keys)) foreach ($table->keys as $k) {
+ if ($k->type == 'primary') continue;
+ $this->db->exec($this->computeIndexCreate($table, $k));
+ }
+ }
+
+ function alterTable(MTrackDBSchema_Table $from, MTrackDBSchema_Table $to)
+ {
+ /* if keys have changed, we drop the old key definitions before changing the columns */
+
+ echo "Need to alter $from->name\n";
+ throw new Exception("bang!");
+ }
+
+ function dropTable(MTrackDBSchema_Table $table)
+ {
+ echo "Drop $table->name\n";
+ $this->db->exec("drop table $table->name");
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+require_once 'DBSchema/Generic.php';
+
+class MTrackDBSchema_SQLite extends MTrackDBSchema_Generic {
+
+ function determineVersion() {
+ /* older versions did not have a schema version table, so we dance
+ * around a little bit, but only for sqlite, as those older versions
+ * didn't support other databases */
+ try {
+ $q = $this->db->query('select version from mtrack_schema');
+ if ($q) {
+ foreach ($q as $row) {
+ return $row[0];
+ }
+ }
+ } catch (Exception $e) {
+ }
+
+ /* do we have any tables at all? if we do, we treat that as schema
+ * version 0 */
+ foreach ($this->db->query('select count(*) from sqlite_master') as $row) {
+ if ($row[0] > 0) {
+ $this->db->exec(
+ 'create table mtrack_schema (version integer not null)');
+ return 0;
+ }
+ }
+ return null;
+ }
+
+ var $typemap = array(
+ 'autoinc' => 'INTEGER PRIMARY KEY AUTOINCREMENT',
+ );
+
+ function createTable(MTrackDBSchema_Table $table)
+ {
+ parent::createTable($table);
+ }
+
+ function alterTable(MTrackDBSchema_Table $from, MTrackDBSchema_Table $to)
+ {
+ $tname = $from->name . '_' . uniqid();
+
+ $sql = array();
+ foreach ($to->fields as $f) {
+ if ($f->type == 'autoinc') {
+ $pri_key = $f->name;
+ }
+ $str = $this->computeFieldCreate($f);
+ $sql[] = $str;
+ }
+
+ $sql = "CREATE TEMPORARY TABLE $tname (\n" .
+ join(",\n", $sql) .
+ ")\n";
+
+ $this->db->exec($sql);
+
+ /* copy old data into this table */
+ $sql = "INSERT INTO $tname (";
+ $names = array();
+ foreach ($from->fields as $f) {
+ if (!isset($to->fields[$f->name])) continue;
+ $names[] = $f->name;
+ }
+ $sql .= join(', ', $names);
+ $sql .= ") SELECT " . join(', ', $names) . " from $from->name";
+
+ #echo "$sql\n";
+ $this->db->exec($sql);
+
+ $this->db->exec("DROP TABLE $from->name");
+ $this->createTable($to);
+ $sql = "INSERT INTO $from->name (";
+ $names = array();
+ foreach ($from->fields as $f) {
+ if (!isset($to->fields[$f->name])) continue;
+ $names[] = $f->name;
+ }
+ $sql .= join(', ', $names);
+ $sql .= ") SELECT " . join(', ', $names) . " from $tname";
+ #echo "$sql\n";
+ $this->db->exec($sql);
+ $this->db->exec("DROP TABLE $tname");
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+class MTrackDBSchema_Table {
+ var $name;
+ var $fields;
+ var $keys;
+ var $triggers;
+
+ /* compares two tables; returns true if they are identical,
+ * false if the definitions are altered */
+ function sameAs(MTrackDBSchema_Table $other) {
+ if ($this->name != $other->name) {
+ throw new Exception("can only compare tables with the same name!");
+ }
+ foreach (array('fields', 'keys', 'triggers') as $propname) {
+ if (!is_array($this->{$propname})) continue;
+ foreach ($this->{$propname} as $f) {
+ if (!isset($other->{$propname}[$f->name])) {
+# echo "$propname $f->name is new\n";
+ return false;
+ }
+ $o = clone $other->{$propname}[$f->name];
+ $f = clone $f;
+ unset($o->comment);
+ unset($f->comment);
+ if ($f != $o) {
+# echo "$propname $f->name are not equal\n";
+# var_dump($f);
+# var_dump($o);
+ return false;
+ }
+ }
+ if (!is_array($other->{$propname})) continue;
+ foreach ($other->{$propname} as $f) {
+ if (!isset($this->{$propname}[$f->name])) {
+# echo "$propname $f->name was deleted\n";
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+}
--- /dev/null
+<?php
+
+
+require_once 'DBSchema/Generic.php';
+
+class MTrackDBSchema_pgsql extends MTrackDBSchema_Generic {
+ var $typemap = array(
+ 'autoinc' => 'SERIAL UNIQUE',
+ 'timestamp' => 'timestamp with time zone',
+ 'blob' => 'bytea',
+ );
+
+ function alterTable(MTrackDBSchema_Table $from, MTrackDBSchema_Table $to)
+ {
+ $sql = array();
+ $actions = array();
+
+ /* if keys have changed, we drop the old key definitions before changing the columns */
+ if (is_array($from->keys)) foreach ($from->keys as $k) {
+ if (!isset($to->keys[$k->name]) || $to->keys[$k->name] != $k) {
+ if ($k->type == 'primary') {
+ $actions[] = "DROP CONSTRAINT {$from->name}_pkey";
+ } else {
+ $sql[] = "DROP INDEX $k->name";
+ }
+ }
+ }
+
+ foreach ($from->fields as $f) {
+ if (!isset($to->fields[$f->name])) {
+ $actions[] = "DROP COLUMN $f->name";
+ continue;
+ }
+ }
+ foreach ($to->fields as $f) {
+ if (isset($from->fields[$f->name])) continue;
+ $actions[] = "ADD COLUMN " . $this->computeFieldCreate($f);
+ }
+
+ /* changed and new keys */
+ if (is_array($from->keys)) foreach ($from->keys as $k) {
+ if (isset($to->keys[$k->name]) && $to->keys[$k->name] != $k) {
+ if ($k->type == 'primary') {
+ $actions[] = "ADD primary key (" . join(', ', $k->fields) . ")";
+ } else {
+ $sql[] = $this->computeIndexCreate($to, $k);
+ }
+ }
+ }
+ if (is_array($to->keys)) foreach ($to->keys as $k) {
+ if (isset($from->keys[$k->name])) continue;
+ if ($k->type == 'primary') {
+ $actions[] = "ADD primary key (" . join(', ', $k->fields) . ")";
+ } else {
+ $sql[] = $this->computeIndexCreate($to, $k);
+ }
+ }
+
+ if (count($actions)) {
+ $sql[] = "ALTER TABLE $from->name " . join(",\n", $actions);
+ }
+ echo "Need to alter $from->name\n";
+ echo "SQL:\n";
+ var_dump($sql);
+ foreach ($sql as $s) {
+ $this->db->exec($s);
+ }
+ }
+}
\ No newline at end of file