Base refactor of the Subversion backend.

This commit is contained in:
Loic d'Anterroches 2009-04-26 11:57:21 +02:00
parent 7c502b1745
commit cf5acfb669
3 changed files with 93 additions and 65 deletions

View File

@ -25,7 +25,7 @@
* SVN utils. * SVN utils.
* *
*/ */
class IDF_Scm_Svn class IDF_Scm_Svn extends IDF_Scm
{ {
public $repo = ''; public $repo = '';
public $username = ''; public $username = '';
@ -42,6 +42,11 @@ class IDF_Scm_Svn
$this->password = $password; $this->password = $password;
} }
public function isAvailable()
{
return true;
}
/** /**
* Given the string describing the author from the log find the * Given the string describing the author from the log find the
* author in the database. * author in the database.
@ -62,7 +67,7 @@ class IDF_Scm_Svn
* @param IDF_Project * @param IDF_Project
* @return string URL * @return string URL
*/ */
public static function getRemoteAccessUrl($project) public static function getAnonymousAccessUrl($project)
{ {
$conf = $project->getConf(); $conf = $project->getConf();
if (false !== ($url=$conf->getVal('svn_remote_url', false)) if (false !== ($url=$conf->getVal('svn_remote_url', false))
@ -95,6 +100,24 @@ class IDF_Scm_Svn
} }
} }
/**
* Subversion revisions are either a number or 'HEAD'.
*/
public function isValidRevision($rev)
{
if ($rev == 'HEAD') {
return true;
}
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --username=%s --password=%s %s@%s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($rev));
exec($cmd, $out, $ret);
return (0 == $ret);
}
/** /**
* Test a given object hash. * Test a given object hash.
* *
@ -114,7 +137,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$path), escapeshellarg($this->repo.'/'.$path),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlInfo = IDF_Scm::shell_exec($cmd); $xmlInfo = shell_exec($cmd);
// If exception is thrown, return false // If exception is thrown, return false
try { try {
@ -133,26 +156,14 @@ class IDF_Scm_Svn
return 'commit'; return 'commit';
} }
public function getTree($rev='HEAD', $folder='')
/**
* Given a commit hash returns an array of files in it.
*
* A file is a class with the following properties:
*
* 'perm', 'type', 'size', 'hash', 'file'
*
* @param string Commit ('HEAD')
* @param string Base folder ('')
* @return array
*/
public function filesAtCommit($rev='HEAD', $folder='')
{ {
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --xml --username=%s --password=%s %s@%s', $cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --xml --username=%s --password=%s %s@%s',
escapeshellarg($this->username), escapeshellarg($this->username),
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$folder), escapeshellarg($this->repo.'/'.$folder),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlLs = IDF_Scm::shell_exec($cmd); $xmlLs = shell_exec($cmd);
$xml = simplexml_load_string($xmlLs); $xml = simplexml_load_string($xmlLs);
$res = array(); $res = array();
$folder = (strlen($folder)) ? $folder.'/' : ''; $folder = (strlen($folder)) ? $folder.'/' : '';
@ -176,7 +187,6 @@ class IDF_Scm_Svn
$file['perm'] = ''; $file['perm'] = '';
$res[] = (object) $file; $res[] = (object) $file;
} }
return $res; return $res;
} }
@ -197,31 +207,25 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($file), escapeshellarg($file),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlLog = IDF_Scm::shell_exec($cmd); $xmlLog = shell_exec($cmd);
$xml = simplexml_load_string($xmlLog); $xml = simplexml_load_string($xmlLog);
$commit[$rev]=(string) $xml->logentry->msg; $commit[$rev]=(string) $xml->logentry->msg;
return (string) $xml->logentry->msg; return (string) $xml->logentry->msg;
} }
/** /**
* Get the file info. * FIXME: Need to check the case of an inexisting file.
*
* @param string File
* @param string Commit ('HEAD')
* @return false Information
*/ */
public function getFileInfo($totest, $rev='HEAD') public function getPathInfo($totest, $rev='HEAD')
{ {
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s@%s', $cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s@%s',
escapeshellarg($this->username), escapeshellarg($this->username),
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$totest), escapeshellarg($this->repo.'/'.$totest),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlInfo = IDF_Scm::shell_exec($cmd); $xmlInfo = shell_exec($cmd);
$xml = simplexml_load_string($xmlInfo); $xml = simplexml_load_string($xmlInfo);
$entry = $xml->entry; $entry = $xml->entry;
$file = array(); $file = array();
$file['fullpath'] = $totest; $file['fullpath'] = $totest;
$file['hash'] = (string) $entry->repository->uuid; $file['hash'] = (string) $entry->repository->uuid;
@ -236,35 +240,67 @@ class IDF_Scm_Svn
return (object) $file; return (object) $file;
} }
public function getFile($def)
/**
* Get a blob.
*
* @param string request_file_info
* @return string Raw blob
*/
public function getBlob($request_file_info, $rev)
{ {
$cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --username=%s --password=%s %s@%s', $cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --username=%s --password=%s %s@%s',
escapeshellarg($this->username), escapeshellarg($this->username),
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$request_file_info->fullpath), escapeshellarg($this->repo.'/'.$def->fullpath),
escapeshellarg($rev)); escapeshellarg($def->rev));
return IDF_Scm::shell_exec($cmd); return shell_exec($cmd);
} }
/** /**
* Get the branches. * Subversion branches are repository based.
* *
* @return array Branches. * One need to list the folder to know them.
*/ */
public function getBranches() public function getBranches()
{ {
$res = array('HEAD'); if (isset($this->cache['branches'])) {
return $this->cache['branches'];
}
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --username=%s --password=%s %s@HEAD',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/branches'));
exec($cmd, $out, $ret);
if ($ret == 0) {
foreach ($out as $entry) {
if (substr(trim($entry), -1) == '/') {
$branch = substr(trim($entry), 0, -1);
$res[$branch] = 'branches/'.$branch;
}
}
}
ksort($res);
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --username=%s --password=%s %s@HEAD',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/trunk'));
exec($cmd, $out, $ret);
if ($ret == 0) {
$res = array_merge(array('trunk' => 'trunk'), $res);
}
$this->cache['branches'] = $res;
return $res; return $res;
} }
public function getMainBranch()
{
return 'HEAD';
}
public function inBranches($commit, $path)
{
foreach ($this->getBranches() as $branch => $bpath) {
if ($bpath and 0 === strpos($path, $bpath)) {
return array($branch);
}
}
return array();
}
/** /**
* Get commit details. * Get commit details.
@ -281,7 +317,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo), escapeshellarg($this->repo),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlRes = IDF_Scm::shell_exec($cmd); $xmlRes = shell_exec($cmd);
$xml = simplexml_load_string($xmlRes); $xml = simplexml_load_string($xmlRes);
$res['author'] = (string) $xml->logentry->author; $res['author'] = (string) $xml->logentry->author;
$res['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $xml->logentry->date)); $res['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $xml->logentry->date));
@ -309,7 +345,7 @@ class IDF_Scm_Svn
$cmd = sprintf(Pluf::f('svnlook_path', 'svnlook').' changed -r %s %s', $cmd = sprintf(Pluf::f('svnlook_path', 'svnlook').' changed -r %s %s',
escapeshellarg($commit), escapeshellarg($commit),
escapeshellarg($repo)); escapeshellarg($repo));
$out = IDF_Scm::shell_exec($cmd); $out = shell_exec($cmd);
$lines = preg_split("/\015\012|\015|\012/", $out); $lines = preg_split("/\015\012|\015|\012/", $out);
return (count($lines) > 100); return (count($lines) > 100);
} }
@ -322,7 +358,7 @@ class IDF_Scm_Svn
escapeshellarg($this->username), escapeshellarg($this->username),
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo)); escapeshellarg($this->repo));
return IDF_Scm::shell_exec($cmd); return shell_exec($cmd);
} }
@ -343,7 +379,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo), escapeshellarg($this->repo),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlRes = IDF_Scm::shell_exec($cmd); $xmlRes = shell_exec($cmd);
$xml = simplexml_load_string($xmlRes); $xml = simplexml_load_string($xmlRes);
$res = array(); $res = array();
@ -362,20 +398,6 @@ class IDF_Scm_Svn
} }
/**
* Generate the command to create a zip archive at a given commit.
* Unsupported feature in subversion
*
* @param string dummy
* @param string dummy
* @return Exception
*/
public function getArchiveCommand($commit, $prefix='git-repo-dump/')
{
throw new Exception('Unsupported feature.');
}
/** /**
* Get additionnals properties on path and revision * Get additionnals properties on path and revision
* *
@ -391,7 +413,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$path), escapeshellarg($this->repo.'/'.$path),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlProps = IDF_Scm::shell_exec($cmd); $xmlProps = shell_exec($cmd);
$props = simplexml_load_string($xmlProps); $props = simplexml_load_string($xmlProps);
// No properties, returns an empty array // No properties, returns an empty array
@ -426,7 +448,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.$path), escapeshellarg($this->repo.'/'.$path),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlProp = IDF_Scm::shell_exec($cmd); $xmlProp = shell_exec($cmd);
$prop = simplexml_load_string($xmlProp); $prop = simplexml_load_string($xmlProp);
return (string) $prop->target->property; return (string) $prop->target->property;
@ -448,7 +470,7 @@ class IDF_Scm_Svn
escapeshellarg($this->password), escapeshellarg($this->password),
escapeshellarg($this->repo), escapeshellarg($this->repo),
escapeshellarg($rev)); escapeshellarg($rev));
$xmlInfo = IDF_Scm::shell_exec($cmd); $xmlInfo = shell_exec($cmd);
$xml = simplexml_load_string($xmlInfo); $xml = simplexml_load_string($xmlInfo);
return (string) $xml->entry->commit['revision']; return (string) $xml->entry->commit['revision'];

View File

@ -219,7 +219,6 @@ class IDF_Views_Source
} catch (Exception $e) { } catch (Exception $e) {
throw $e; throw $e;
// return new Pluf_HTTP_Response_Redirect($fburl);
} }
// try to find the previous level if it exists. // try to find the previous level if it exists.
$prev = split('/', $request_file); $prev = split('/', $request_file);

View File

@ -68,5 +68,12 @@
<input type="hidden" name="sourcefile" value="{$base}"/> <input type="hidden" name="sourcefile" value="{$base}"/>
<input type="submit" name="s" value="{trans 'Go to revision'}" /></p> <input type="submit" name="s" value="{trans 'Go to revision'}" /></p>
</form> </form>
<p><strong>{trans 'Branches:'}</strong><br />
{foreach $branches as $branch => $path}
{if $path}{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, 'HEAD', $path)}
{else}{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, 'HEAD')}{/if}
<span class="label{if in_array($branch, $tree_in)} active{/if}"><a href="{$url}" class="label">{$branch}</a></span><br />
{/foreach}
</p>
{/block} {/block}