From 31e81118ddc6629995d0a3d0c0851b7a697b19e2 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Fri, 13 Aug 2010 11:20:03 +0200 Subject: [PATCH 1/3] Follow IDFs coding standards and tweak opening curly braces as well as quoting where possible --- src/IDF/Form/UserAccount.php | 36 ++---- src/IDF/Key.php | 3 +- src/IDF/Scm/Monotone.php | 210 +++++++++++++-------------------- src/IDF/Scm/Monotone/Stdio.php | 103 +++++++--------- src/IDF/Scm/Monotone/Usher.php | 82 ++++++------- src/IDF/Tests/TestMonotone.php | 21 ++-- src/IDF/Views/Admin.php | 33 ++---- 7 files changed, 189 insertions(+), 299 deletions(-) diff --git a/src/IDF/Form/UserAccount.php b/src/IDF/Form/UserAccount.php index 8e57199..176e74e 100644 --- a/src/IDF/Form/UserAccount.php +++ b/src/IDF/Form/UserAccount.php @@ -210,32 +210,27 @@ class IDF_Form_UserAccount extends Pluf_Form public static function checkPublicKey($key, $type, $user=0) { $key = trim($key); - if (strlen($key) == 0) - { + if (strlen($key) == 0) { return ''; } - if ($type == 'ssh') - { + if ($type == 'ssh') { $key = str_replace(array("\n", "\r"), '', $key); - if (!preg_match('#^ssh\-[a-z]{3}\s\S+\s\S+$#', $key)) - { + if (!preg_match('#^ssh\-[a-z]{3}\s\S+\s\S+$#', $key)) { throw new Pluf_Form_Invalid( __('The format of the key is not valid. It must start '. 'with ssh-dss or ssh-rsa, a long string on a single '. 'line and at the end a comment.') ); } - if (Pluf::f('idf_strong_key_check', false)) - { + if (Pluf::f('idf_strong_key_check', false)) { $tmpfile = Pluf::f('tmp_folder', '/tmp').'/'.$user.'-key'; file_put_contents($tmpfile, $key, LOCK_EX); $cmd = Pluf::f('idf_exec_cmd_prefix', ''). 'ssh-keygen -l -f '.escapeshellarg($tmpfile).' > /dev/null 2>&1'; exec($cmd, $out, $return); unlink($tmpfile); - if ($return != 0) - { + if ($return != 0) { throw new Pluf_Form_Invalid( __('Please check the key as it does not appears '. 'to be a valid key.') @@ -243,18 +238,15 @@ class IDF_Form_UserAccount extends Pluf_Form } } } - else if ($type == 'mtn') - { - if (!preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) - { + else if ($type == 'mtn') { + if (!preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) { throw new Pluf_Form_Invalid( __('The format of the key is not valid. It must start '. 'with [pubkey KEYNAME], contain a long string on a single '. 'line and end with [end] in the final third line.') ); } - if (Pluf::f('idf_strong_key_check', false)) - { + if (Pluf::f('idf_strong_key_check', false)) { // if monotone can read it, it should be valid $mtn_opts = implode(' ', Pluf::f('mtn_opts', array())); $cmd = Pluf::f('idf_exec_cmd_prefix', ''). @@ -264,8 +256,7 @@ class IDF_Form_UserAccount extends Pluf_Form fwrite($fp, $key); $return = pclose($fp); - if ($return != 0) - { + if ($return != 0) { throw new Pluf_Form_Invalid( __('Please check the key as it does not appears '. 'to be a valid key.') @@ -279,15 +270,12 @@ class IDF_Form_UserAccount extends Pluf_Form } // If $user, then check if not the same key stored - if ($user) - { + if ($user) { $ruser = Pluf::factory('Pluf_User', $user); - if ($ruser->id > 0) - { + if ($ruser->id > 0) { $sql = new Pluf_SQL('content=%s AND type=%s', array($key, $type)); $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen())); - if (count($keys) > 0) - { + if (count($keys) > 0) { throw new Pluf_Form_Invalid( __('You already have uploaded this key.') ); diff --git a/src/IDF/Key.php b/src/IDF/Key.php index 3fcdd79..1e84ced 100644 --- a/src/IDF/Key.php +++ b/src/IDF/Key.php @@ -184,8 +184,7 @@ class IDF_Key extends Pluf_Model public static function getAvailableKeyTypes() { $key_types = array(__("SSH") => 'ssh'); - if (array_key_exists('mtn', Pluf::f('allowed_scm', array()))) - { + if (array_key_exists('mtn', Pluf::f('allowed_scm', array()))) { $key_types[__("monotone")] = 'mtn'; } return $key_types; diff --git a/src/IDF/Scm/Monotone.php b/src/IDF/Scm/Monotone.php index b58a277..dd3679f 100644 --- a/src/IDF/Scm/Monotone.php +++ b/src/IDF/Scm/Monotone.php @@ -54,8 +54,7 @@ class IDF_Scm_Monotone extends IDF_Scm // FIXME: this obviously won't work with remote databases - upstream // needs to implement mtn db info in automate at first $repo = sprintf(Pluf::f('mtn_repositories'), $this->project->shortname); - if (!file_exists($repo)) - { + if (!file_exists($repo)) { return 0; } @@ -74,7 +73,7 @@ class IDF_Scm_Monotone extends IDF_Scm { try { - $out = $this->stdio->exec(array("interface_version")); + $out = $this->stdio->exec(array('interface_version')); return floatval($out) >= self::$MIN_INTERFACE_VERSION; } catch (IDF_Scm_Exception $e) {} @@ -92,15 +91,14 @@ class IDF_Scm_Monotone extends IDF_Scm } // FIXME: we could / should introduce handling of suspended // (i.e. dead) branches here by hiding them from the user's eye... - $out = $this->stdio->exec(array("branches")); + $out = $this->stdio->exec(array('branches')); // note: we could expand each branch with one of its head revisions // here, but these would soon become bogus anyway and we cannot // map multiple head revisions here either, so we just use the // selector as placeholder $res = array(); - foreach (preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY) as $b) - { + foreach (preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY) as $b) { $res["h:$b"] = $b; } @@ -123,8 +121,7 @@ class IDF_Scm_Monotone extends IDF_Scm $branch = "*"; } - if (count($this->_resolveSelector("h:$branch")) == 0) - { + if (count($this->_resolveSelector("h:$branch")) == 0) { throw new IDF_Scm_Exception( "Branch $branch is empty" ); @@ -142,7 +139,7 @@ class IDF_Scm_Monotone extends IDF_Scm */ private function _resolveSelector($selector) { - $out = $this->stdio->exec(array("select", $selector)); + $out = $this->stdio->exec(array('select', $selector)); return preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); } @@ -157,16 +154,13 @@ class IDF_Scm_Monotone extends IDF_Scm $pos = 0; $stanzas = array(); - while ($pos < strlen($in)) - { + while ($pos < strlen($in)) { $stanza = array(); - while ($pos < strlen($in)) - { + while ($pos < strlen($in)) { if ($in[$pos] == "\n") break; - $stanzaLine = array("key" => "", "values" => array(), "hash" => null); - while ($pos < strlen($in)) - { + $stanzaLine = array('key' => '', 'values' => array(), 'hash' => null); + while ($pos < strlen($in)) { $ch = $in[$pos]; if ($ch == '"' || $ch == '[') break; ++$pos; @@ -174,8 +168,7 @@ class IDF_Scm_Monotone extends IDF_Scm $stanzaLine['key'] .= $ch; } - if ($in[$pos] == '[') - { + if ($in[$pos] == '[') { ++$pos; // opening square bracket $stanzaLine['hash'] = substr($in, $pos, 40); $pos += 40; @@ -184,12 +177,10 @@ class IDF_Scm_Monotone extends IDF_Scm else { $valCount = 0; - while ($in[$pos] == '"') - { + while ($in[$pos] == '"') { ++$pos; // opening quote - $stanzaLine['values'][$valCount] = ""; - while ($pos < strlen($in)) - { + $stanzaLine['values'][$valCount] = ''; + while ($pos < strlen($in)) { $ch = $in[$pos]; $pr = $in[$pos-1]; if ($ch == '"' && $pr != '\\') break; ++$pos; @@ -197,15 +188,13 @@ class IDF_Scm_Monotone extends IDF_Scm } ++$pos; // closing quote - if ($in[$pos] == ' ') - { + if ($in[$pos] == ' ') { ++$pos; // space ++$valCount; } } - for ($i = 0; $i <= $valCount; $i++) - { + for ($i = 0; $i <= $valCount; $i++) { $stanzaLine['values'][$i] = str_replace( array("\\\\", "\\\""), array("\\", "\""), @@ -234,28 +223,22 @@ class IDF_Scm_Monotone extends IDF_Scm { static $certCache = array(); - if (!array_key_exists($rev, $certCache)) - { - $out = $this->stdio->exec(array("certs", $rev)); + if (!array_key_exists($rev, $certCache)) { + $out = $this->stdio->exec(array('certs', $rev)); $stanzas = self::_parseBasicIO($out); $certs = array(); - foreach ($stanzas as $stanza) - { + foreach ($stanzas as $stanza) { $certname = null; - foreach ($stanza as $stanzaline) - { + foreach ($stanza as $stanzaline) { // luckily, name always comes before value - if ($stanzaline['key'] == "name") - { + if ($stanzaline['key'] == 'name') { $certname = $stanzaline['values'][0]; continue; } - if ($stanzaline['key'] == "value") - { - if (!array_key_exists($certname, $certs)) - { + if ($stanzaline['key'] == 'value') { + if (!array_key_exists($certname, $certs)) { $certs[$certname] = array(); } @@ -282,13 +265,11 @@ class IDF_Scm_Monotone extends IDF_Scm private function _getUniqueCertValuesFor($revs, $certName, $prefix) { $certValues = array(); - foreach ($revs as $rev) - { + foreach ($revs as $rev) { $certs = $this->_getCerts($rev); if (!array_key_exists($certName, $certs)) continue; - foreach ($certs[$certName] as $certValue) - { + foreach ($certs[$certName] as $certValue) { $certValues[] = "$prefix$certValue"; } } @@ -306,19 +287,16 @@ class IDF_Scm_Monotone extends IDF_Scm private function _getLastChangeFor($file, $startrev) { $out = $this->stdio->exec(array( - "get_content_changed", $startrev, $file + 'get_content_changed', $startrev, $file )); $stanzas = self::_parseBasicIO($out); // FIXME: we only care about the first returned content mark // everything else seem to be very, very rare cases - foreach ($stanzas as $stanza) - { - foreach ($stanza as $stanzaline) - { - if ($stanzaline['key'] == "content_mark") - { + foreach ($stanzas as $stanza) { + foreach ($stanza as $stanzaline) { + if ($stanzaline['key'] == 'content_mark') { return $stanzaline['hash']; } } @@ -333,7 +311,7 @@ class IDF_Scm_Monotone extends IDF_Scm { $revs = $this->_resolveSelector($commit); if (count($revs) == 0) return array(); - return $this->_getUniqueCertValuesFor($revs, "branch", "h:"); + return $this->_getUniqueCertValuesFor($revs, 'branch', 'h:'); } /** @@ -341,32 +319,26 @@ class IDF_Scm_Monotone extends IDF_Scm */ public function getTags() { - if (isset($this->cache['tags'])) - { + if (isset($this->cache['tags'])) { return $this->cache['tags']; } - $out = $this->stdio->exec(array("tags")); + $out = $this->stdio->exec(array('tags')); $tags = array(); $stanzas = self::_parseBasicIO($out); - foreach ($stanzas as $stanza) - { + foreach ($stanzas as $stanza) { $tagname = null; - foreach ($stanza as $stanzaline) - { + foreach ($stanza as $stanzaline) { // revision comes directly after the tag stanza - if ($stanzaline['key'] == "tag") - { + if ($stanzaline['key'] == 'tag') { $tagname = $stanzaline['values'][0]; continue; } - if ($stanzaline['key'] == "revision") - { + if ($stanzaline['key'] == 'revision') { // FIXME: warn if multiple revisions have // equally named tags - if (!array_key_exists("t:$tagname", $tags)) - { + if (!array_key_exists("t:$tagname", $tags)) { $tags["t:$tagname"] = $tagname; } break; @@ -385,7 +357,7 @@ class IDF_Scm_Monotone extends IDF_Scm { $revs = $this->_resolveSelector($commit); if (count($revs) == 0) return array(); - return $this->_getUniqueCertValuesFor($revs, "tag", "t:"); + return $this->_getUniqueCertValuesFor($revs, 'tag', 't:'); } /** @@ -394,22 +366,20 @@ class IDF_Scm_Monotone extends IDF_Scm public function getTree($commit, $folder='/', $branch=null) { $revs = $this->_resolveSelector($commit); - if (count($revs) == 0) - { + if (count($revs) == 0) { return array(); } $out = $this->stdio->exec(array( - "get_manifest_of", $revs[0] + 'get_manifest_of', $revs[0] )); $files = array(); $stanzas = self::_parseBasicIO($out); $folder = $folder == '/' || empty($folder) ? '' : $folder.'/'; - foreach ($stanzas as $stanza) - { - if ($stanza[0]['key'] == "format_version") + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'format_version') continue; $path = $stanza[0]['values'][0]; @@ -421,21 +391,19 @@ class IDF_Scm_Monotone extends IDF_Scm $file['fullpath'] = $path; $file['efullpath'] = self::smartEncode($path); - if ($stanza[0]['key'] == "dir") - { - $file['type'] = "tree"; + if ($stanza[0]['key'] == 'dir') { + $file['type'] = 'tree'; $file['size'] = 0; } else { - $file['type'] = "blob"; + $file['type'] = 'blob'; $file['hash'] = $stanza[1]['hash']; $file['size'] = strlen($this->getFile((object)$file)); } $rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]); - if ($rev !== null) - { + if ($rev !== null) { $file['rev'] = $rev; $certs = $this->_getCerts($rev); @@ -482,17 +450,14 @@ class IDF_Scm_Monotone extends IDF_Scm $scm = IDF_Scm::get($project); $branch = $scm->getMainBranch(); - if (!empty($commit)) - { + if (!empty($commit)) { $revs = $scm->_resolveSelector($commit); - if (count($revs) > 0) - { + if (count($revs) > 0) { $certs = $scm->_getCerts($revs[0]); // for the very seldom case that a revision // has no branch certificate - if (count($certs['branch']) == 0) - { - $branch = "*"; + if (count($certs['branch']) == 0) { + $branch = '*'; } else { @@ -502,12 +467,11 @@ class IDF_Scm_Monotone extends IDF_Scm } $remote_url = Pluf::f('mtn_remote_url', ''); - if (empty($remote_url)) - { + if (empty($remote_url)) { return ''; } - return sprintf($remote_url, $project->shortname)."?".$branch; + return sprintf($remote_url, $project->shortname).'?'.$branch; } /** @@ -527,8 +491,7 @@ class IDF_Scm_Monotone extends IDF_Scm */ public static function factory($project) { - if (!array_key_exists($project->shortname, self::$instances)) - { + if (!array_key_exists($project->shortname, self::$instances)) { self::$instances[$project->shortname] = new IDF_Scm_Monotone($project); } @@ -558,15 +521,14 @@ class IDF_Scm_Monotone extends IDF_Scm return false; $out = $this->stdio->exec(array( - "get_manifest_of", $revs[0] + 'get_manifest_of', $revs[0] )); $files = array(); $stanzas = self::_parseBasicIO($out); - foreach ($stanzas as $stanza) - { - if ($stanza[0]['key'] == "format_version") + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'format_version') continue; $path = $stanza[0]['values'][0]; @@ -576,15 +538,14 @@ class IDF_Scm_Monotone extends IDF_Scm $file = array(); $file['fullpath'] = $path; - if ($stanza[0]['key'] == "dir") - { + if ($stanza[0]['key'] == "dir") { $file['type'] = "tree"; $file['hash'] = null; $file['size'] = 0; } else { - $file['type'] = "blob"; + $file['type'] = 'blob'; $file['hash'] = $stanza[1]['hash']; $file['size'] = strlen($this->getFile((object)$file)); } @@ -593,8 +554,7 @@ class IDF_Scm_Monotone extends IDF_Scm $file['file'] = $pathinfo['basename']; $rev = $this->_getLastChangeFor($file['fullpath'], $revs[0]); - if ($rev !== null) - { + if ($rev !== null) { $file['rev'] = $rev; $certs = $this->_getCerts($rev); @@ -619,12 +579,11 @@ class IDF_Scm_Monotone extends IDF_Scm public function getFile($def, $cmd_only=false) { // this won't work with remote databases - if ($cmd_only) - { + if ($cmd_only) { throw new Pluf_Exception_NotImplemented(); } - return $this->stdio->exec(array("get_file", $def->hash)); + return $this->stdio->exec(array('get_file', $def->hash)); } /** @@ -637,8 +596,7 @@ class IDF_Scm_Monotone extends IDF_Scm */ private function _getDiff($target, $source = null) { - if (empty($source)) - { + if (empty($source)) { $source = "p:$target"; } @@ -647,20 +605,18 @@ class IDF_Scm_Monotone extends IDF_Scm $targets = $this->_resolveSelector($target); $sources = $this->_resolveSelector($source); - if (count($targets) == 0 || count($sources) == 0) - { - return ""; + if (count($targets) == 0 || count($sources) == 0) { + return ''; } // if target contains a root revision, we cannot produce a diff - if (empty($sources[0])) - { - return ""; + if (empty($sources[0])) { + return ''; } return $this->stdio->exec( - array("content_diff"), - array("r" => array($sources[0], $targets[0])) + array('content_diff'), + array('r' => array($sources[0], $targets[0])) ); } @@ -676,7 +632,7 @@ class IDF_Scm_Monotone extends IDF_Scm $certs = $this->_getCerts($revs[0]); // FIXME: this assumes that author, date and changelog are always given - $res['author'] = implode(", ", $certs['author']); + $res['author'] = implode(', ', $certs['author']); $dates = array(); foreach ($certs['date'] as $date) @@ -697,9 +653,8 @@ class IDF_Scm_Monotone extends IDF_Scm */ public function isCommitLarge($commit=null) { - if (empty($commit)) - { - $commit = "h:"+$this->getMainBranch(); + if (empty($commit)) { + $commit = 'h:'.$this->getMainBranch(); } $revs = $this->_resolveSelector($commit); @@ -707,15 +662,14 @@ class IDF_Scm_Monotone extends IDF_Scm return false; $out = $this->stdio->exec(array( - "get_revision", $revs[0] + 'get_revision', $revs[0] )); $newAndPatchedFiles = 0; $stanzas = self::_parseBasicIO($out); - foreach ($stanzas as $stanza) - { - if ($stanza[0]['key'] == "patch" || $stanza[0]['key'] == "add_file") + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'patch' || $stanza[0]['key'] == 'add_file') $newAndPatchedFiles++; } @@ -731,11 +685,9 @@ class IDF_Scm_Monotone extends IDF_Scm $initialBranches = array(); $logs = array(); - while (!empty($horizont) && $n > 0) - { - if (count($horizont) > 1) - { - $out = $this->stdio->exec(array("toposort") + $horizont); + while (!empty($horizont) && $n > 0) { + if (count($horizont) > 1) { + $out = $this->stdio->exec(array('toposort') + $horizont); $horizont = preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); } @@ -743,14 +695,12 @@ class IDF_Scm_Monotone extends IDF_Scm $certs = $this->_getCerts($rev); // read in the initial branches we should follow - if (count($initialBranches) == 0) - { + if (count($initialBranches) == 0) { $initialBranches = $certs['branch']; } // only add it to our log if it is on one of the initial branches - if (count(array_intersect($initialBranches, $certs['branch'])) > 0) - { + if (count(array_intersect($initialBranches, $certs['branch'])) > 0) { --$n; $log = array(); @@ -771,7 +721,7 @@ class IDF_Scm_Monotone extends IDF_Scm $logs[] = (object)$log; } - $out = $this->stdio->exec(array("parents", $rev)); + $out = $this->stdio->exec(array('parents', $rev)); $horizont += preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); } diff --git a/src/IDF/Scm/Monotone/Stdio.php b/src/IDF/Scm/Monotone/Stdio.php index c1628f7..391133a 100644 --- a/src/IDF/Scm/Monotone/Stdio.php +++ b/src/IDF/Scm/Monotone/Stdio.php @@ -70,29 +70,26 @@ class IDF_Scm_Monotone_Stdio if (is_resource($this->proc)) $this->stop(); - $remote_db_access = Pluf::f('mtn_db_access', 'remote') == "remote"; + $remote_db_access = Pluf::f('mtn_db_access', 'remote') == 'remote'; $cmd = Pluf::f('idf_exec_cmd_prefix', '') . Pluf::f('mtn_path', 'mtn') . ' '; $opts = Pluf::f('mtn_opts', array()); - foreach ($opts as $opt) - { + foreach ($opts as $opt) { $cmd .= sprintf('%s ', escapeshellarg($opt)); } // FIXME: we might want to add an option for anonymous / no key // access, but upstream bug #30237 prevents that for now - if ($remote_db_access) - { + if ($remote_db_access) { $host = sprintf(Pluf::f('mtn_remote_url'), $this->project->shortname); $cmd .= sprintf('automate remote_stdio %s', escapeshellarg($host)); } else { $repo = sprintf(Pluf::f('mtn_repositories'), $this->project->shortname); - if (!file_exists($repo)) - { + if (!file_exists($repo)) { throw new IDF_Scm_Exception( "repository file '$repo' does not exist" ); @@ -101,19 +98,18 @@ class IDF_Scm_Monotone_Stdio } $descriptors = array( - 0 => array("pipe", "r"), - 1 => array("pipe", "w"), - 2 => array("pipe", "w"), + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), ); - $env = array("LANG" => "en_US.UTF-8"); + $env = array('LANG' => 'en_US.UTF-8'); $this->proc = proc_open($cmd, $descriptors, $this->pipes, null, $env); - if (!is_resource($this->proc)) - { - throw new IDF_Scm_Exception("could not start stdio process"); + if (!is_resource($this->proc)) { + throw new IDF_Scm_Exception('could not start stdio process'); } $this->_checkVersion(); @@ -154,15 +150,13 @@ class IDF_Scm_Monotone_Stdio $read, $write = null, $except = null, 0, 20000 ); - if ($streamsChanged === false) - { + if ($streamsChanged === false) { throw new IDF_Scm_Exception( - "Could not select() on read pipe" + 'Could not select() on read pipe' ); } - if ($streamsChanged == 0) - { + if ($streamsChanged == 0) { return false; } @@ -179,8 +173,7 @@ class IDF_Scm_Monotone_Stdio $this->_waitForReadyRead(); $version = fgets($this->pipes[1]); - if ($version === false) - { + if ($version === false) { throw new IDF_Scm_Exception( "Could not determine stdio version, stderr is:\n". $this->_readStderr() @@ -191,8 +184,8 @@ class IDF_Scm_Monotone_Stdio $m[1] != self::$SUPPORTED_STDIO_VERSION) { throw new IDF_Scm_Exception( - "stdio format version mismatch, expected '". - self::$SUPPORTED_STDIO_VERSION."', got '".@$m[1]."'" + 'stdio format version mismatch, expected "'. + self::$SUPPORTED_STDIO_VERSION.'", got "'.@$m[1].'"' ); } @@ -208,33 +201,28 @@ class IDF_Scm_Monotone_Stdio */ private function _write(array $args, array $options = array()) { - $cmd = ""; - if (count($options) > 0) - { - $cmd = "o"; - foreach ($options as $k => $vals) - { + $cmd = ''; + if (count($options) > 0) { + $cmd = 'o'; + foreach ($options as $k => $vals) { if (!is_array($vals)) $vals = array($vals); - foreach ($vals as $v) - { - $cmd .= strlen((string)$k) . ":" . (string)$k; - $cmd .= strlen((string)$v) . ":" . (string)$v; + foreach ($vals as $v) { + $cmd .= strlen((string)$k) . ':' . (string)$k; + $cmd .= strlen((string)$v) . ':' . (string)$v; } } - $cmd .= "e "; + $cmd .= 'e '; } - $cmd .= "l"; - foreach ($args as $arg) - { - $cmd .= strlen((string)$arg) . ":" . (string)$arg; + $cmd .= 'l'; + foreach ($args as $arg) { + $cmd .= strlen((string)$arg) . ':' . (string)$arg; } $cmd .= "e\n"; - if (!fwrite($this->pipes[0], $cmd)) - { + if (!fwrite($this->pipes[0], $cmd)) { throw new IDF_Scm_Exception("could not write '$cmd' to process"); } @@ -250,11 +238,10 @@ class IDF_Scm_Monotone_Stdio private function _readStderr() { $err = ""; - while (($line = fgets($this->pipes[2])) !== false) - { + while (($line = fgets($this->pipes[2])) !== false) { $err .= $line; } - return empty($err) ? "" : $err; + return empty($err) ? '' : $err; } /** @@ -273,26 +260,22 @@ class IDF_Scm_Monotone_Stdio $output = ""; $errcode = 0; - while (true) - { + while (true) { if (!$this->_waitForReadyRead()) continue; $data = array(0,"",0); $idx = 0; - while (true) - { + while (true) { $c = fgetc($this->pipes[1]); - if ($c === false) - { + if ($c === false) { throw new IDF_Scm_Exception( "No data on stdin, stderr is:\n". $this->_readStderr() ); } - if ($c == ':') - { + if ($c == ':') { if ($idx == 2) break; @@ -307,24 +290,21 @@ class IDF_Scm_Monotone_Stdio } // sanity - if ($this->cmdnum != $data[0]) - { + if ($this->cmdnum != $data[0]) { throw new IDF_Scm_Exception( - "command numbers out of sync; ". - "expected {$this->cmdnum}, got {$data[0]}" + 'command numbers out of sync; expected '. + $this->cmdnum .', got '. $data[0] ); } $toRead = $data[2]; $buffer = ""; - while ($toRead > 0) - { + while ($toRead > 0) { $buffer .= fread($this->pipes[1], $toRead); $toRead = $data[2] - strlen($buffer); } - switch ($data[1]) - { + switch ($data[1]) { case 'w': case 'p': case 't': @@ -340,11 +320,10 @@ class IDF_Scm_Monotone_Stdio } } - if ($errcode != 0) - { + if ($errcode != 0) { throw new IDF_Scm_Exception( "command '{$this->lastcmd}' returned error code $errcode: ". - implode(" ", $this->oob['e']) + implode(' ', $this->oob['e']) ); } diff --git a/src/IDF/Scm/Monotone/Usher.php b/src/IDF/Scm/Monotone/Usher.php index 7c86e0a..9891555 100644 --- a/src/IDF/Scm/Monotone/Usher.php +++ b/src/IDF/Scm/Monotone/Usher.php @@ -42,11 +42,11 @@ class IDF_Scm_Monotone_Usher */ public static function getServerList($state = null) { - $conn = self::_triggerCommand("LIST $state"); - if ($conn == "none") + $conn = self::_triggerCommand('LIST '.$state); + if ($conn == 'none') return array(); - return preg_split("/[ ]/", $conn); + return preg_split('/[ ]/', $conn); } /** @@ -67,19 +67,18 @@ class IDF_Scm_Monotone_Usher */ public static function getConnectionList($server = null) { - $conn = self::_triggerCommand("LISTCONNECTIONS $server"); - if ($conn == "none") + $conn = self::_triggerCommand('LISTCONNECTIONS '.$server); + if ($conn == 'none') return array(); - $single_conns = preg_split("/[ ]/", $conn); + $single_conns = preg_split('/[ ]/', $conn); $ret = array(); - foreach ($single_conns as $conn) - { - preg_match("/\(\w+\)([^:]):(\d+)/", $conn, $matches); + foreach ($single_conns as $conn) { + preg_match('/\(\w+\)([^:]):(\d+)/', $conn, $matches); $ret[$matches[1]][] = (object)array( - "server" => $matches[1], - "address" => $matches[2], - "port" => $matches[3], + 'server' => $matches[1], + 'address' => $matches[2], + 'port' => $matches[3], ); } @@ -96,7 +95,7 @@ class IDF_Scm_Monotone_Usher */ public static function getStatus($server = null) { - return self::_triggerCommand("STATUS $server"); + return self::_triggerCommand('STATUS '.$server); } /** @@ -110,11 +109,11 @@ class IDF_Scm_Monotone_Usher */ public static function matchServer($host, $pattern) { - $ret = self::_triggerCommand("MATCH $host $pattern"); - if (preg_match("/^OK: (.+)/", $ret, $m)) + $ret = self::_triggerCommand('MATCH '.$host.' '.$pattern); + if (preg_match('/^OK: (.+)/', $ret, $m)) return $m[1]; - preg_match("/^ERROR: (.+)/", $ret, $m); - throw new IDF_Scm_Exception("could not match server: ".$m[1]); + preg_match('/^ERROR: (.+)/', $ret, $m); + throw new IDF_Scm_Exception('could not match server: '.$m[1]); } /** @@ -143,7 +142,7 @@ class IDF_Scm_Monotone_Usher */ public static function startServer($server) { - return self::_triggerCommand("START $server"); + return self::_triggerCommand('START '.$server); } /** @@ -156,7 +155,7 @@ class IDF_Scm_Monotone_Usher */ public static function killServer($server) { - return self::_triggerCommand("KILL_NOW $server") == "ok"; + return self::_triggerCommand('KILL_NOW '.$server) == 'ok'; } /** @@ -166,7 +165,7 @@ class IDF_Scm_Monotone_Usher */ public static function shutDown() { - return self::_triggerCommand("SHUTDOWN") == "ok"; + return self::_triggerCommand('SHUTDOWN') == 'ok'; } /** @@ -176,7 +175,7 @@ class IDF_Scm_Monotone_Usher */ public static function startUp() { - return self::_triggerCommand("STARTUP") == "ok"; + return self::_triggerCommand('STARTUP') == 'ok'; } /** @@ -186,60 +185,53 @@ class IDF_Scm_Monotone_Usher */ public static function reload() { - return self::_triggerCommand("RELOAD") == "ok"; + return self::_triggerCommand('RELOAD') == 'ok'; } private static function _triggerCommand($cmd) { $uc = Pluf::f('mtn_usher'); - if (empty($uc['host'])) - { - throw new IDF_Scm_Exception("usher host is empty"); + if (empty($uc['host'])) { + throw new IDF_Scm_Exception('usher host is empty'); } if (!preg_match('/^\d+$/', $uc['port']) || $uc['port'] == 0) { - throw new IDF_Scm_Exception("usher port is invalid"); + throw new IDF_Scm_Exception('usher port is invalid'); } - if (empty($uc['user'])) - { - throw new IDF_Scm_Exception("usher user is empty"); + if (empty($uc['user'])) { + throw new IDF_Scm_Exception('usher user is empty'); } - if (empty($uc['pass'])) - { - throw new IDF_Scm_Exception("usher pass is empty"); + if (empty($uc['pass'])) { + throw new IDF_Scm_Exception('usher pass is empty'); } $sock = @fsockopen($uc['host'], $uc['port'], $errno, $errstr); - if (!$sock) - { + if (!$sock) { throw new IDF_Scm_Exception( "could not connect to usher: $errstr ($errno)" ); } - fwrite($sock, "USERPASS {$uc['user']} {$uc['pass']}\n"); - if (feof($sock)) - { + fwrite($sock, 'USERPASS '.$uc['user'].' '.$uc['pass'].'\n'); + if (feof($sock)) { throw new IDF_Scm_Exception( - "usher closed the connection - probably wrong admin ". - "username or password" + 'usher closed the connection - probably wrong admin '. + 'username or password' ); } - fwrite($sock, "$cmd\n"); - $out = ""; - while (!feof($sock)) - { + fwrite($sock, $cmd.'\n'); + $out = ''; + while (!feof($sock)) { $out .= fgets($sock); } fclose($sock); $out = rtrim($out); - if ($out == "unknown command") - { + if ($out == 'unknown command') { throw new IDF_Scm_Exception("unknown command: $cmd"); } diff --git a/src/IDF/Tests/TestMonotone.php b/src/IDF/Tests/TestMonotone.php index ff01e79..f151122 100644 --- a/src/IDF/Tests/TestMonotone.php +++ b/src/IDF/Tests/TestMonotone.php @@ -55,13 +55,11 @@ class IDF_Tests_TestMonotone extends UnitTestCase $pipes, $dir); - if (!is_resource($process)) - { + if (!is_resource($process)) { throw new Exception("could not create process"); } - if (!empty($stdin)) - { + if (!empty($stdin)) { fwrite($pipes[0], $stdin); fclose($pipes[0]); } @@ -70,8 +68,7 @@ class IDF_Tests_TestMonotone extends UnitTestCase fclose($pipes[1]); $ret = proc_close($process); - if ($ret != 0) - { + if ($ret != 0) { throw new Exception( "call ended with a non-zero error code (complete cmdline was: ". implode(" ", $cmdline).")" @@ -102,12 +99,9 @@ class IDF_Tests_TestMonotone extends UnitTestCase if (is_dir($dirname)) $dir_handle=opendir($dirname); - while ($file = readdir($dir_handle)) - { - if ($file!="." && $file!="..") - { - if (!is_dir($dirname."/".$file)) - { + while ($file = readdir($dir_handle)) { + if ($file!="." && $file!="..") { + if (!is_dir($dirname."/".$file)) { unlink ($dirname."/".$file); continue; } @@ -123,8 +117,7 @@ class IDF_Tests_TestMonotone extends UnitTestCase public function setUp() { - if (is_dir($this->tmpdir)) - { + if (is_dir($this->tmpdir)) { self::deleteRecursive($this->tmpdir); } diff --git a/src/IDF/Views/Admin.php b/src/IDF/Views/Admin.php index b69f851..42cb821 100644 --- a/src/IDF/Views/Admin.php +++ b/src/IDF/Views/Admin.php @@ -324,8 +324,7 @@ class IDF_Views_Admin { $title = __('Usher management'); $servers = array(); - foreach (IDF_Scm_Monotone_Usher::getServerList() as $server) - { + foreach (IDF_Scm_Monotone_Usher::getServerList() as $server) { $servers[] = (object)array( "name" => $server, "status" => IDF_Scm_Monotone_Usher::getStatus($server), @@ -352,21 +351,17 @@ class IDF_Views_Admin $title = __('Usher control'); $action = $match[1]; - if (!empty($action)) - { - if (!in_array($action, array("reload", "shutdown", "startup"))) - { + if (!empty($action)) { + if (!in_array($action, array('reload', 'shutdown', 'startup'))) { throw new Pluf_HTTP_Error404(); } $msg = null; - if ($action == "reload") - { + if ($action == 'reload') { IDF_Scm_Monotone_Usher::reload(); $msg = __('Usher configuration has been reloaded'); } - else if ($action == "shutdown") - { + else if ($action == 'shutdown') { IDF_Scm_Monotone_Usher::shutDown(); $msg = __('Usher has been shut down'); } @@ -399,25 +394,21 @@ class IDF_Views_Admin public function usherServerControl($request, $match) { $server = $match[1]; - if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) - { + if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) { throw new Pluf_HTTP_Error404(); } $action = $match[2]; - if (!in_array($action, array("start", "stop", "kill"))) - { + if (!in_array($action, array('start', 'stop', 'kill'))) { throw new Pluf_HTTP_Error404(); } $msg = null; - if ($action == "start") - { + if ($action == 'start') { IDF_Scm_Monotone_Usher::startServer($server); $msg = sprintf(__('The server "%s" has been started'), $server); } - else if ($action == "stop") - { + else if ($action == 'stop') { IDF_Scm_Monotone_Usher::stopServer($server); $msg = sprintf(__('The server "%s" has been stopped'), $server); } @@ -440,16 +431,14 @@ class IDF_Views_Admin public function usherServerConnections($request, $match) { $server = $match[1]; - if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) - { + if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) { throw new Pluf_HTTP_Error404(); } $title = sprintf(__('Open connections for "%s"'), $server); $connections = IDF_Scm_Monotone_Usher::getConnectionList($server); - if (count($connections) == 0) - { + if (count($connections) == 0) { $request->user->setMessage(sprintf( __('no connections for server "%s"'), $server )); From 0c4846c98608762d123b35cabeef2a0b5544a65d Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Fri, 13 Aug 2010 11:42:14 +0200 Subject: [PATCH 2/3] Adapted monotone's README file and moved it under doc/ --- README | 128 ------------------------------------- doc/readme-monotone.mdtext | 63 ++++++++++++++++++ 2 files changed, 63 insertions(+), 128 deletions(-) delete mode 100644 README create mode 100644 doc/readme-monotone.mdtext diff --git a/README b/README deleted file mode 100644 index 1410f44..0000000 --- a/README +++ /dev/null @@ -1,128 +0,0 @@ -monotone implementation notes ------------------------------ - -1. general - - This branch contains an implementation of the monotone automation interface. - It needs at least monotone version 0.47 (interface version 12.0) or - newer. To set up a new project with monotone, all you need to do is - to create a new monotone database with - - $ mtn db init -d project.mtn - - in the configured repository path ('mtn_repositories'). To have a really - workable setup, this database needs an initial commit on the configured - master branch of the project. This can be done easily with - - $ mkdir tmp && touch tmp/remove_me - $ mtn import -d project.mtn -b master.branch.name \ - -m "initial commit" tmp - $ rm -rf tmp - - -2. current state / internals - - The implementation should be fairly stable and fast, though some - information, such as individual file sizes or last change information, - won't scale well with the tree size. Its expected that the mtn - automation interface improves in this area in the future and that - these parts can then be rewritten with speed in mind. - - Another area of improvement is the access pattern to the monotone - database. While only one process is started per request, the time - (and server resource) penalty for this could still be dramatic once - many clients try to access the service. Luckily, monotone has an - easy way to deliver its stdio protocol for automation usage over the - network (mtn au remote_stdio), so the following scenarios are possible: - - a) setup a single mtn server serving one database on a different - (faster) server and let the stdio client connect to that - - b) setup usher (available from branch net.venge.monotone.contrib.usher - from the official mtn repository on monotone.ca) as proxy in - front of several local monotone databases mirroring themselves - - c) like b), but use usher as proxy in front of several other remote - monotone databases (forwarding) - - The scenario in a) might be needed anyways for a shared hosting - environment, because a database which gets served via netsync cannot - be accessed by another local process at the same time (its locked then), - so ideally both, the network functionality as well as the indefero - browsing functionality should be delivered from one single database - per project via netsync. - - The only alternative for this setup is a two-database approach, where one - database acts as network node and the other as backend for indefero. - The synchronization between these two would then have to happen via - standard tools (cron...) or a sync request from one database to the other. - - While the current implementation is ready for the two database approach, - some code parts and configuration changes have to happen for the remote - stdio usage. Bascially this is replacing the initial call to - - mtn -d project.mtn au stdio (Monotone.php, around line 74) - - with - - mtn au remote_stdio HOSTNAME - - which could be made configurable in conf/idf.php. But again, this heavily - depends on the exact anticipated server setup. - - To scale things up a bit, multiple projects should of course use - separated databases. The main reason for that is that while read access - can be granted on a branch level, write access gives total write - possibilities on the whole database. One approach would be to start - one serve process for each database, but the obvious downside here is - that each of those processes would need to get bound to another - (non-standard) port making it hard for users to "just clone" the - project sources without knowing the exact port. - - Usher comes to the rescue here as well. It has three ways - to recognize the request for a particular database: - - a) by looking at the requested host name (similar to SNI for Apache) - - b) by evaluating the requested branch pattern - - c) by evaluating the path part from an mtn:// uri (new in mtn 0.48) - - The best way is probably to configure it with c) - instead of pulling - a project like this - - $ mtn pull hostname branchname - - a user uses the URI syntax (which will, btw. be the default from - mtn 0.99 onwards): - - $ mtn pull mtn://hostname/database?branchname - - Here, the "/database" part is used by usher to determine which backend - database should be used for the network action. The "clone" command - will also support this mtn:// uri syntax, but this didn't made it into - 0.48, but will be available from 0.99 and later. - - -3. indefero critique: - - It was not always 100% clear what some of the abstract SCM API method - wanted in return. While it helped a lot to have prior art in form of the - SVN and git implementation, the documentation of the abstract IDF_Scm - should probably still be improved. - - Since branch and tag names can be of arbitrary size, it was not possible - to display them completely in the default layout. This might be a problem - in other SCMs as well, in particular for the monotone implementation I - introduced a special filter, called "IDF_Views_Source_ShortenString". - - The API methods getPathInfo() and getTree() return similar VCS "objects" - which unfortunately do not have a well-defined structure - this should - probably addressed in future indefero releases. - - While the returned objects from getTree() contain all the needed - information, indefero doesn't seem to use them to sort the output - f.e. alphabetically or in such a way that directories are outputted - before files. It was unclear if the SCM implementor should do this - task or not and what the admired default sorting should be. - diff --git a/doc/readme-monotone.mdtext b/doc/readme-monotone.mdtext new file mode 100644 index 0000000..2e54367 --- /dev/null +++ b/doc/readme-monotone.mdtext @@ -0,0 +1,63 @@ +# monotone implementation notes + +## general + + This version of indefero contains an implementation of the monotone + automation interface. It needs at least monotone version 0.47 + (interface version 12.0) or newer, but as development continues, its + likely that this dependency has to be raised. + + To set up a new IDF project with monotone quickly, all you need to do + is to create a new monotone database with + + $ mtn db init -d project.mtn + + in the configured repository path `$cfg['mtn_repositories']` and + configure `$cfg['mtn_db_access']` to "local". + + To have a really workable setup, this database needs an initial commit + on the configured master branch of the project. This can be done easily + with + + $ mkdir tmp && touch tmp/remove_me + $ mtn import -d project.mtn -b master.branch.name \ + -m "initial commit" tmp + $ rm -rf tmp + + Its expected that more scripts arrive soon to automate this and other + tasks in the future for (multi)forge setups. + +## current state / internals + + The implementation should be fairly stable and fast, though some + information, such as individual file sizes or last change information, + won't scale well with the tree size. Its expected that the mtn + automation interface improves in this area in the future and that + these parts can then be rewritten with speed in mind. + + As the idf.conf-dist explains more in detail, different access patterns + are possible to retrieve changeset data from monotone. Please refer + to the documentation there for more information. + +## indefero critique: + + It was not always 100% clear what some of the abstract SCM API method + wanted in return. While it helped a lot to have prior art in form of the + SVN and git implementation, the documentation of the abstract IDF_Scm + should probably still be improved. + + Since branch and tag names can be of arbitrary size, it was not possible + to display them completely in the default layout. This might be a problem + in other SCMs as well, in particular for the monotone implementation I + introduced a special filter, called "IDF_Views_Source_ShortenString". + + The API methods getPathInfo() and getTree() return similar VCS "objects" + which unfortunately do not have a well-defined structure - this should + probably addressed in future indefero releases. + + While the returned objects from getTree() contain all the needed + information, indefero doesn't seem to use them to sort the output + f.e. alphabetically or in such a way that directories are outputted + before files. It was unclear if the SCM implementor should do this + task or not and what the admired default sorting should be. + From f0a606e5cfdd12d7630d665d7a7f082f61c00179 Mon Sep 17 00:00:00 2001 From: Thomas Keller Date: Mon, 23 Aug 2010 09:45:04 +0200 Subject: [PATCH 3/3] * its IDF_Key, not IDF_Keys --- src/IDF/Migrations/16KeyType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IDF/Migrations/16KeyType.php b/src/IDF/Migrations/16KeyType.php index aa2716f..521571b 100644 --- a/src/IDF/Migrations/16KeyType.php +++ b/src/IDF/Migrations/16KeyType.php @@ -27,7 +27,7 @@ function IDF_Migrations_16KeyType_up($params=null) { - $table = Pluf::factory('IDF_Keys')->getSqlTable(); + $table = Pluf::factory('IDF_Key')->getSqlTable(); $sql = array(); $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "type" VARCHAR(3) DEFAULT \'ssh\''; $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `type` VARCHAR(3) DEFAULT \'ssh\''; @@ -41,7 +41,7 @@ function IDF_Migrations_16KeyType_up($params=null) function IDF_Migrations_16KeyType_down($params=null) { - $table = Pluf::factory('IDF_Keys')->getSqlTable(); + $table = Pluf::factory('IDF_Key')->getSqlTable(); $sql = array(); $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "type"'; $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `type`';