diff --git a/src/IDF/Project.php b/src/IDF/Project.php index b1dfb76..7b968b5 100644 --- a/src/IDF/Project.php +++ b/src/IDF/Project.php @@ -381,15 +381,16 @@ class IDF_Project extends Pluf_Model * This will return the right url based on the user. * * @param Pluf_User The user (null) + * @param string A specific commit to access */ - public function getSourceAccessUrl($user=null) + public function getSourceAccessUrl($user=null, $commit=null) { $right = $this->getConf()->getVal('source_access_rights', 'all'); if (($user == null or $user->isAnonymous()) and $right == 'all' and !$this->private) { - return $this->getRemoteAccessUrl(); + return $this->getRemoteAccessUrl($commit); } - return $this->getWriteRemoteAccessUrl($user); + return $this->getWriteRemoteAccessUrl($user, $commit); } @@ -397,15 +398,17 @@ class IDF_Project extends Pluf_Model * Get the remote access url to the repository. * * This will always return the anonymous access url. + * + * @param string A specific commit to access */ - public function getRemoteAccessUrl() + public function getRemoteAccessUrl($commit=null) { $conf = $this->getConf(); $scm = $conf->getVal('scm', 'git'); $scms = Pluf::f('allowed_scm'); Pluf::loadClass($scms[$scm]); return call_user_func(array($scms[$scm], 'getAnonymousAccessUrl'), - $this); + $this, $commit); } /** @@ -414,14 +417,16 @@ class IDF_Project extends Pluf_Model * Some SCM have a remote access URL to write which is not the * same as the one to read. For example, you do a checkout with * git-daemon and push with SSH. + * + * @param string A specific commit to access */ - public function getWriteRemoteAccessUrl($user) + public function getWriteRemoteAccessUrl($user,$commit=null) { $conf = $this->getConf(); $scm = $conf->getVal('scm', 'git'); $scms = Pluf::f('allowed_scm'); return call_user_func(array($scms[$scm], 'getAuthAccessUrl'), - $this, $user); + $this, $user, $commit); } /** diff --git a/src/IDF/Scm/Git.php b/src/IDF/Scm/Git.php index cd7ec0f..9ad3acc 100644 --- a/src/IDF/Scm/Git.php +++ b/src/IDF/Scm/Git.php @@ -28,12 +28,12 @@ class IDF_Scm_Git extends IDF_Scm { public $mediumtree_fmt = 'commit %H%nAuthor: %an <%ae>%nTree: %T%nDate: %ai%n%n%s%n%n%b'; - + /* ============================================== * * * * Common Methods Implemented By All The SCMs * * * - * ============================================== */ + * ============================================== */ public function __construct($repo, $project=null) { @@ -48,7 +48,7 @@ class IDF_Scm_Git extends IDF_Scm } $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' .escapeshellarg($this->repo); - $out = explode(' ', + $out = explode(' ', self::shell_exec('IDF_Scm_Git::getRepositorySize', $cmd), 2); return (int) $out[0]*1024; @@ -70,13 +70,13 @@ class IDF_Scm_Git extends IDF_Scm return $this->cache['branches']; } $cmd = Pluf::f('idf_exec_cmd_prefix', '') - .sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' branch', + .sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' branch', escapeshellarg($this->repo)); - self::exec('IDF_Scm_Git::getBranches', + self::exec('IDF_Scm_Git::getBranches', $cmd, $out, $return); if ($return != 0) { throw new IDF_Scm_Exception(sprintf($this->error_tpl, - $cmd, $return, + $cmd, $return, implode("\n", $out))); } $res = array(); @@ -216,7 +216,7 @@ class IDF_Scm_Git extends IDF_Scm if ($folder) { // As we are limiting to a given folder, we need to find // the tree corresponding to this folder. - $tinfo = $this->getTreeInfo($commit, $folder); + $tinfo = $this->getTreeInfo($commit, $folder); if (isset($tinfo[0]) and $tinfo[0]->type == 'tree') { $tree = $tinfo[0]->hash; } else { @@ -231,7 +231,7 @@ class IDF_Scm_Git extends IDF_Scm // information as possible. if ($file->type == 'blob') { $file->date = $co->date; - $file->log = '----'; + $file->log = '----'; $file->author = 'Unknown'; } $file->fullpath = ($folder) ? $folder.'/'.$file->file : $file->file; @@ -270,12 +270,12 @@ class IDF_Scm_Git extends IDF_Scm return null; } - public static function getAnonymousAccessUrl($project) + public static function getAnonymousAccessUrl($project, $commit=null) { return sprintf(Pluf::f('git_remote_url'), $project->shortname); } - public static function getAuthAccessUrl($project, $user) + public static function getAuthAccessUrl($project, $user, $commit=null) { return sprintf(Pluf::f('git_write_remote_url'), $project->shortname); } @@ -320,7 +320,7 @@ class IDF_Scm_Git extends IDF_Scm /** * Get the tree info. * - * @param string Tree hash + * @param string Tree hash * @param bool Do we recurse in subtrees (true) * @param string Folder in which we want to get the info ('') * @return array Array of file information. @@ -332,15 +332,15 @@ class IDF_Scm_Git extends IDF_Scm } $cmd_tmpl = 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' ls-tree -l %s %s'; $cmd = Pluf::f('idf_exec_cmd_prefix', '') - .sprintf($cmd_tmpl, escapeshellarg($this->repo), + .sprintf($cmd_tmpl, escapeshellarg($this->repo), escapeshellarg($tree), escapeshellarg($folder)); $out = array(); $res = array(); self::exec('IDF_Scm_Git::getTreeInfo', $cmd, $out); foreach ($out as $line) { list($perm, $type, $hash, $size, $file) = preg_split('/ |\t/', $line, 5, PREG_SPLIT_NO_EMPTY); - $res[] = (object) array('perm' => $perm, 'type' => $type, - 'size' => $size, 'hash' => $hash, + $res[] = (object) array('perm' => $perm, 'type' => $type, + 'size' => $size, 'hash' => $hash, 'file' => $file); } return $res; @@ -356,8 +356,8 @@ class IDF_Scm_Git extends IDF_Scm public function getPathInfo($totest, $commit='HEAD') { $cmd_tmpl = 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' ls-tree -r -t -l %s'; - $cmd = sprintf($cmd_tmpl, - escapeshellarg($this->repo), + $cmd = sprintf($cmd_tmpl, + escapeshellarg($this->repo), escapeshellarg($commit)); $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; @@ -366,8 +366,8 @@ class IDF_Scm_Git extends IDF_Scm list($perm, $type, $hash, $size, $file) = preg_split('/ |\t/', $line, 5, PREG_SPLIT_NO_EMPTY); if ($totest == $file) { $pathinfo = pathinfo($file); - return (object) array('perm' => $perm, 'type' => $type, - 'size' => $size, 'hash' => $hash, + return (object) array('perm' => $perm, 'type' => $type, + 'size' => $size, 'hash' => $hash, 'fullpath' => $file, 'file' => $pathinfo['basename']); } @@ -379,9 +379,9 @@ class IDF_Scm_Git extends IDF_Scm { $cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', ''). 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' cat-file blob %s', - escapeshellarg($this->repo), + escapeshellarg($this->repo), escapeshellarg($def->hash)); - return ($cmd_only) + return ($cmd_only) ? $cmd : self::shell_exec('IDF_Scm_Git::getFile', $cmd); } @@ -396,13 +396,13 @@ class IDF_Scm_Git extends IDF_Scm { if ($getdiff) { $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' show --date=iso --pretty=format:%s %s', - escapeshellarg($this->repo), - "'".$this->mediumtree_fmt."'", + escapeshellarg($this->repo), + "'".$this->mediumtree_fmt."'", escapeshellarg($commit)); } else { $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log -1 --date=iso --pretty=format:%s %s', - escapeshellarg($this->repo), - "'".$this->mediumtree_fmt."'", + escapeshellarg($this->repo), + "'".$this->mediumtree_fmt."'", escapeshellarg($commit)); } $out = array(); @@ -443,8 +443,8 @@ class IDF_Scm_Git extends IDF_Scm public function isCommitLarge($commit='HEAD') { $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --numstat -1 --pretty=format:%s %s', - escapeshellarg($this->repo), - "'commit %H%n'", + escapeshellarg($this->repo), + "'commit %H%n'", escapeshellarg($commit)); $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; @@ -477,7 +477,7 @@ class IDF_Scm_Git extends IDF_Scm if ($n === null) $n = ''; else $n = ' -'.$n; $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log%s --date=iso --pretty=format:\'%s\' %s', - escapeshellarg($this->repo), $n, $this->mediumtree_fmt, + escapeshellarg($this->repo), $n, $this->mediumtree_fmt, escapeshellarg($commit)); $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; @@ -683,7 +683,7 @@ class IDF_Scm_Git extends IDF_Scm /** * Build the blob info cache. * - * We build the blob info cache 500 commits at a time. + * We build the blob info cache 500 commits at a time. */ public function buildBlobInfoCache() { @@ -737,7 +737,7 @@ class IDF_Scm_Git extends IDF_Scm /** * Cache blob info. - * + * * Given a series of blob info, cache them. * * @param array Blob info @@ -765,7 +765,7 @@ class IDF_Scm_Git extends IDF_Scm foreach ($data as $rec) { if (isset($hashes[substr($rec, 0, 40)])) { $tmp = explode(chr(31), substr($rec, 40), 3); - $res[substr($rec, 0, 40)] = + $res[substr($rec, 0, 40)] = (object) array('hash' => substr($rec, 0, 40), 'date' => $tmp[0], 'title' => $tmp[2], @@ -777,7 +777,7 @@ class IDF_Scm_Git extends IDF_Scm /** * File cache blob info. - * + * * Given a series of blob info, cache them. * * @param array Blob info @@ -792,9 +792,9 @@ class IDF_Scm_Git extends IDF_Scm } $data = implode(chr(30), $data).chr(30); $cache = Pluf::f('tmp_folder').'/IDF_Scm_Git-'.md5($this->repo).'.cache.db'; - $fp = fopen($cache, 'ab'); + $fp = fopen($cache, 'ab'); if ($fp) { - flock($fp, LOCK_EX); + flock($fp, LOCK_EX); fwrite($fp, $data, strlen($data)); fclose($fp); // releases the lock too return true; diff --git a/src/IDF/Scm/Mercurial.php b/src/IDF/Scm/Mercurial.php index f0ef715..9f34ab7 100644 --- a/src/IDF/Scm/Mercurial.php +++ b/src/IDF/Scm/Mercurial.php @@ -37,9 +37,9 @@ class IDF_Scm_Mercurial extends IDF_Scm { $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' .escapeshellarg($this->repo); - $out = explode(' ', + $out = explode(' ', self::shell_exec('IDF_Scm_Mercurial::getRepositorySize', - $cmd), + $cmd), 2); return (int) $out[0]*1024; } @@ -77,12 +77,12 @@ class IDF_Scm_Mercurial extends IDF_Scm return 'tip'; } - public static function getAnonymousAccessUrl($project) + public static function getAnonymousAccessUrl($project, $commit=null) { return sprintf(Pluf::f('mercurial_remote_url'), $project->shortname); } - public static function getAuthAccessUrl($project, $user) + public static function getAuthAccessUrl($project, $user, $commit=null) { return sprintf(Pluf::f('mercurial_remote_url'), $project->shortname); } @@ -109,11 +109,11 @@ class IDF_Scm_Mercurial extends IDF_Scm $cmd = sprintf(Pluf::f('hg_path', 'hg').' log -R %s -r %s', escapeshellarg($this->repo), escapeshellarg($hash)); - $ret = 0; + $ret = 0; $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; self::exec('IDF_Scm_Mercurial::testHash', $cmd, $out, $ret); - return ($ret != 0) ? false : 'commit'; + return ($ret != 0) ? false : 'commit'; } public function getTree($commit, $folder='/', $branch=null) @@ -130,7 +130,7 @@ class IDF_Scm_Mercurial extends IDF_Scm $found = true; break; } - } + } if (!$found) { throw new Exception(sprintf(__('Folder %1$s not found in commit %2$s.'), $folder, $commit)); } @@ -142,7 +142,7 @@ class IDF_Scm_Mercurial extends IDF_Scm /** * Get the tree info. * - * @param string Tree hash + * @param string Tree hash * @param bool Do we recurse in subtrees (true) * @return array Array of file information. */ @@ -152,7 +152,7 @@ class IDF_Scm_Mercurial extends IDF_Scm throw new Exception(sprintf(__('Not a valid tree: %s.'), $tree)); } $cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s'; - $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $tree, ($recurse) ? '' : ''); + $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $tree, ($recurse) ? '' : ''); $out = array(); $res = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; @@ -192,7 +192,7 @@ class IDF_Scm_Mercurial extends IDF_Scm } $fullpath = ($folder) ? $folder.'/'.$file : $file; $efullpath = self::smartEncode($fullpath); - $res[] = (object) array('perm' => $perm, 'type' => $type, + $res[] = (object) array('perm' => $perm, 'type' => $type, 'hash' => $hash, 'fullpath' => $fullpath, 'efullpath' => $efullpath, 'file' => $file); } @@ -202,7 +202,7 @@ class IDF_Scm_Mercurial extends IDF_Scm public function getPathInfo($totest, $commit='tip') { $cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s'; - $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $commit); + $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $commit); $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; self::exec('IDF_Scm_Mercurial::getPathInfo', $cmd, $out); @@ -219,8 +219,8 @@ class IDF_Scm_Mercurial extends IDF_Scm $tmp .= $dir[$i]; if ($tmp == $totest) { $pathinfo = pathinfo($totest); - return (object) array('perm' => '000', 'type' => 'tree', - 'hash' => $hash, + return (object) array('perm' => '000', 'type' => 'tree', + 'hash' => $hash, 'fullpath' => $totest, 'file' => $pathinfo['basename'], 'commit' => $commit @@ -239,8 +239,8 @@ class IDF_Scm_Mercurial extends IDF_Scm } if ($totest == $file) { $pathinfo = pathinfo($totest); - return (object) array('perm' => $perm, 'type' => $type, - 'hash' => $hash, + return (object) array('perm' => $perm, 'type' => $type, + 'hash' => $hash, 'fullpath' => $totest, 'file' => $pathinfo['basename'], 'commit' => $commit @@ -249,15 +249,15 @@ class IDF_Scm_Mercurial extends IDF_Scm } return false; } - + public function getFile($def, $cmd_only=false) { $cmd = sprintf(Pluf::f('hg_path', 'hg').' cat -R %s -r %s %s', - escapeshellarg($this->repo), - escapeshellarg($def->commit), + escapeshellarg($this->repo), + escapeshellarg($def->commit), escapeshellarg($this->repo.'/'.$def->fullpath)); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; - return ($cmd_only) ? + return ($cmd_only) ? $cmd : self::shell_exec('IDF_Scm_Mercurial::getFile', $cmd); } @@ -272,7 +272,7 @@ class IDF_Scm_Mercurial extends IDF_Scm return $this->cache['branches']; } $out = array(); - $cmd = sprintf(Pluf::f('hg_path', 'hg').' branches -R %s', + $cmd = sprintf(Pluf::f('hg_path', 'hg').' branches -R %s', escapeshellarg($this->repo)); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; self::exec('IDF_Scm_Mercurial::getBranches', $cmd, $out); @@ -296,7 +296,7 @@ class IDF_Scm_Mercurial extends IDF_Scm return $this->cache['tags']; } $out = array(); - $cmd = sprintf(Pluf::f('hg_path', 'hg').' tags -R %s', + $cmd = sprintf(Pluf::f('hg_path', 'hg').' tags -R %s', escapeshellarg($this->repo)); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; self::exec('IDF_Scm_Mercurial::getTags', $cmd, $out); @@ -311,13 +311,13 @@ class IDF_Scm_Mercurial extends IDF_Scm public function inBranches($commit, $path) { - return (in_array($commit, array_keys($this->getBranches()))) + return (in_array($commit, array_keys($this->getBranches()))) ? array($commit) : array(); } public function inTags($commit, $path) { - return (in_array($commit, array_keys($this->getTags()))) + return (in_array($commit, array_keys($this->getTags()))) ? array($commit) : array(); } @@ -333,9 +333,9 @@ class IDF_Scm_Mercurial extends IDF_Scm if (!$this->isValidRevision($commit)) { return false; } - $tmpl = ($getdiff) ? + $tmpl = ($getdiff) ? Pluf::f('hg_path', 'hg').' log -p -r %s -R %s' : Pluf::f('hg_path', 'hg').' log -r %s -R %s'; - $cmd = sprintf($tmpl, + $cmd = sprintf($tmpl, escapeshellarg($commit), escapeshellarg($this->repo)); $out = array(); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; @@ -411,7 +411,7 @@ class IDF_Scm_Mercurial extends IDF_Scm $c['full_message'] = ''; $i=1; continue; - + } if ($i == $hdrs) { $c['title'] = trim($line); diff --git a/src/IDF/Scm/Monotone.php b/src/IDF/Scm/Monotone.php index b35c6b4..0a3a4d9 100644 --- a/src/IDF/Scm/Monotone.php +++ b/src/IDF/Scm/Monotone.php @@ -61,7 +61,6 @@ class IDF_Scm_Monotone_Stdio $descriptors = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), - 2 => array("pipe", "r") ); $this->proc = proc_open($cmd, $descriptors, $this->pipes); @@ -83,14 +82,43 @@ class IDF_Scm_Monotone_Stdio fclose($this->pipes[0]); fclose($this->pipes[1]); - fclose($this->pipes[2]); proc_close($this->proc); $this->proc = null; } + private function _waitForReadyRead() + { + if (!is_resource($this->pipes[1])) + return false; + + $read = array($this->pipes[1]); + $write = null; + $except = null; + + $streamsChanged = stream_select( + $read, $write, $except, 0, 20000 + ); + + if ($streamsChanged === false) + { + throw new IDF_Scm_Exception( + "Could not select() on read pipe" + ); + } + + if ($streamsChanged == 0) + { + return false; + } + + return true; + } + private function _checkVersion() { + $this->_waitForReadyRead(); + $version = fgets($this->pipes[1]); if (!preg_match('/^format-version: (\d+)$/', $version, $m) || $m[1] != self::$SUPPORTED_STDIO_VERSION) @@ -100,6 +128,7 @@ class IDF_Scm_Monotone_Stdio self::$SUPPORTED_STDIO_VERSION."', got '".@$m[1]."'" ); } + fgets($this->pipes[1]); } @@ -151,25 +180,8 @@ class IDF_Scm_Monotone_Stdio while (true) { - $read = array($this->pipes[1]); - $write = null; - $except = null; - - $streamsChanged = stream_select( - $read, $write, $except, 0, 20000 - ); - - if ($streamsChanged === false) - { - throw new IDF_Scm_Exception( - "Could not select() on read pipe" - ); - } - - if ($streamsChanged == 0) - { + if (!$this->_waitForReadyRead()) continue; - } $data = array(0,"",0); $idx = 0; @@ -669,18 +681,50 @@ class IDF_Scm_Monotone extends IDF_Scm return $branch; } - public static function getAnonymousAccessUrl($project) + public static function getAnonymousAccessUrl($project, $commit = null) { + $branch = self::_getMasterBranch($project); + if (!empty($commit)) + { + $scm = IDF_Scm::get($project); + $revs = $scm->_resolveSelector($commit); + 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 = "*"; + } + else + { + $branch = $certs['branch'][0]; + } + } + } + + $protocol = Pluf::f('mtn_remote_protocol', 'netsync'); + + if ($protocol == "ssh") + { + // ssh is protocol + host + db-path + branch + return "ssh://" . + sprintf(Pluf::f('mtn_remote_host'), $project->shortname) . + sprintf(Pluf::f('mtn_repositories'), $project->shortname) . + " " . $branch; + } + + // netsync is the default return sprintf( - Pluf::f('mtn_remote_url'), - $project->shortname, - self::_getMasterBranch($project) - ); + Pluf::f('mtn_remote_host'), + $project->shortname + )." ".$branch; } - public static function getAuthAccessUrl($project, $user) + public static function getAuthAccessUrl($project, $user, $commit = null) { - return self::getAnonymousAccessUrl($project); + return self::getAnonymousAccessUrl($project, $commit); } /** diff --git a/src/IDF/Scm/Svn.php b/src/IDF/Scm/Svn.php index fbdcb4b..6527bbf 100644 --- a/src/IDF/Scm/Svn.php +++ b/src/IDF/Scm/Svn.php @@ -24,7 +24,7 @@ /** * Subversion backend. * When a branch is not a branch. - * + * * Contrary to most other SCMs, Subversion is using folders to manage * the branches and so what is either the commit or the branch in * other SCMs is the revision number with Subversion. So, do not be @@ -80,12 +80,13 @@ class IDF_Scm_Svn extends IDF_Scm * Returns the URL of the subversion repository. * * @param IDF_Project + * @param string * @return string URL */ - public static function getAnonymousAccessUrl($project) + public static function getAnonymousAccessUrl($project,$commit=null) { $conf = $project->getConf(); - if (false !== ($url=$conf->getVal('svn_remote_url', false)) + if (false !== ($url=$conf->getVal('svn_remote_url', false)) && !empty($url)) { // Remote repository return $url; @@ -97,12 +98,13 @@ class IDF_Scm_Svn extends IDF_Scm * Returns the URL of the subversion repository. * * @param IDF_Project + * @param string * @return string URL */ - public static function getAuthAccessUrl($project, $user) + public static function getAuthAccessUrl($project, $user, $commit=null) { $conf = $project->getConf(); - if (false !== ($url=$conf->getVal('svn_remote_url', false)) + if (false !== ($url=$conf->getVal('svn_remote_url', false)) && !empty($url)) { // Remote repository return $url; @@ -120,7 +122,7 @@ class IDF_Scm_Svn extends IDF_Scm { $conf = $project->getConf(); // Find the repository - if (false !== ($rep=$conf->getVal('svn_remote_url', false)) + if (false !== ($rep=$conf->getVal('svn_remote_url', false)) && !empty($rep)) { // Remote repository $scm = new IDF_Scm_Svn($rep, $project); @@ -268,7 +270,7 @@ class IDF_Scm_Svn extends IDF_Scm $file['type'] = $this->assoc[(string) $entry['kind']]; $pathinfo = pathinfo($filename); $file['file'] = $pathinfo['basename']; - $file['rev'] = $rev; + $file['rev'] = $rev; $file['author'] = (string) $entry->author; $file['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $entry->commit->date)); $file['size'] = (string) $entry->size; @@ -284,12 +286,12 @@ class IDF_Scm_Svn extends IDF_Scm escapeshellarg($this->repo.'/'.self::smartEncode($def->fullpath)), escapeshellarg($def->rev)); $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; - return ($cmd_only) ? + return ($cmd_only) ? $cmd : self::shell_exec('IDF_Scm_Svn::getFile', $cmd); } /** - * Subversion branches are folder based. + * Subversion branches are folder based. * * One need to list the folder to know them. */ @@ -328,7 +330,7 @@ class IDF_Scm_Svn extends IDF_Scm } /** - * Subversion tags are folder based. + * Subversion tags are folder based. * * One need to list the folder to know them. */ diff --git a/src/IDF/conf/idf.php-dist b/src/IDF/conf/idf.php-dist index 49f7e2d..edfd0e4 100644 --- a/src/IDF/conf/idf.php-dist +++ b/src/IDF/conf/idf.php-dist @@ -73,11 +73,29 @@ $cfg['git_write_remote_url'] = 'git@localhost:%s.git'; $cfg['svn_repositories'] = 'file:///home/svn/repositories/%s'; $cfg['svn_remote_url'] = 'http://localhost/svn/%s'; -# Same as for git, you can have multiple repositories, one for each -# project or a single one for all the projects. +# Path to the monotone binary $cfg['mtn_path'] = 'mtn'; +# Same as for git, you can have multiple repositories, one for each +# project or a single one for all the projects. Beware though that +# if you want to setup separate write access for the projects, you +# you have to setup different databases for each one. +# +# To access an mtn repository remotely you have two possibilities, +# via ssh and monotone's own netsync protocol. Usually each repository +# has to serve its contents in a separate process, but there exists a tool, +# called "usher", which acts as single entry point and distributes incoming +# requests further, based either on a particular branch pattern or configured +# host name (similar to SNI, the Server Name Indication, of TLS). +# +# A full HOWTO set this up is beyond this scope, please refer to the +# documentation of monotone and / or ask on their mailing list / IRC channel +# (irc.oftc.net/#monotone) $cfg['mtn_repositories'] = '/home/mtn/repositories/%s.mtn'; -$cfg['mtn_remote_url'] = 'mtn://localhost/~%s/%s'; +# The preferred URL with which people can access this service. The placeholder +# denotes the unique project name which could be used as distinguishable SNI. +$cfg['mtn_remote_host'] = '%s.my.host.com'; +# Possible values 'ssh' and 'netsync' +$cfg['mtn_remote_protocol'] = 'netsync'; # Mercurial repositories path #$cfg['mercurial_repositories'] = '/home/mercurial/repositories/%s'; diff --git a/src/IDF/templates/idf/source/mtn/tree.html b/src/IDF/templates/idf/source/mtn/tree.html index 0250b01..51cf8d3 100644 --- a/src/IDF/templates/idf/source/mtn/tree.html +++ b/src/IDF/templates/idf/source/mtn/tree.html @@ -49,7 +49,7 @@ {aurl 'url', 'IDF_Views_Source::download', array($project.shortname, $commit)}

{* {trans 'Archive'} {trans 'Download this version'} {trans 'or'} *} -mtn clone {$project.getSourceAccessUrl($user)} {trans 'Help'} +mtn clone {$project.getSourceAccessUrl($user, $commit)} {trans 'Help'}