Merge branch 'develop' of projects.ceondo.com:indefero into develop

This commit is contained in:
William MARTIN 2011-05-31 15:40:14 +02:00
commit de09c8af56
11 changed files with 138 additions and 67 deletions

View File

@ -4,12 +4,15 @@
- Mercurial source views now show parent revisions (if any) and detailed change information
- File download URLs now contain the file name rather than the upload id; old links still work though (issue 686)
- Display monotone file and directory attributes in the tree and file view
(needs a monotone with an interface version of 13.1 or newer)
## Bugfixes
## Bugfixes
- The SVN interface acts more robust if an underlying repository has been restructured (issue 364)
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
- Timeline only displays filter options for items a user has actually access to (issue 655)
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
- Fix SSH public key parsing issues and improve the check for existing, uploaded keys (issue 679)
- Let the SVN command line client not store the login credentials we give him as arguments

View File

@ -31,10 +31,10 @@ class IDF_Scm_Monotone extends IDF_Scm
/** the minimum supported interface version */
public static $MIN_INTERFACE_VERSION = 13.0;
private $stdio;
private static $instances = array();
private $stdio;
/**
* Constructor
*/
@ -698,6 +698,29 @@ class IDF_Scm_Monotone extends IDF_Scm
return (object) $res;
}
/**
* @see IDF_Scm::getProperties()
*/
public function getProperties($rev, $path='')
{
$out = $this->stdio->exec(array('interface_version'));
// support for querying file attributes of committed revisions
// was added for mtn 1.1 (interface version 13.1)
if (floatval($out) < 13.1)
return array();
$out = $this->stdio->exec(array('get_attributes', $path), array('r' => $rev));
$stanzas = IDF_Scm_Monotone_BasicIO::parse($out);
$res = array();
foreach ($stanzas as $stanza) {
$line = $stanza[0];
$res[$line['values'][0]] = $line['values'][1];
}
return $res;
}
/**
* @see IDF_Scm::getExtraProperties
*/

View File

@ -163,11 +163,11 @@ class IDF_Scm_Svn extends IDF_Scm
return IDF_Scm::REVISION_VALID;
}
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
self::exec('IDF_Scm_Svn::validateRevision', $cmd, $out, $ret);
@ -176,7 +176,6 @@ class IDF_Scm_Svn extends IDF_Scm
return IDF_Scm::REVISION_INVALID;
}
/**
* Test a given object hash.
*
@ -191,11 +190,11 @@ class IDF_Scm_Svn extends IDF_Scm
}
// Else, test the path on revision
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlInfo = self::shell_exec('IDF_Scm_Svn::testHash', $cmd);
@ -218,11 +217,11 @@ class IDF_Scm_Svn extends IDF_Scm
public function getTree($commit, $folder='/', $branch=null)
{
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --xml --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($folder)),
escapeshellarg($commit));
escapeshellarg($commit),
escapeshellarg($this->repo.'/'.self::smartEncode($folder)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getTree', $cmd));
$res = array();
@ -248,7 +247,6 @@ class IDF_Scm_Svn extends IDF_Scm
return $res;
}
/**
* Get the commit message of a revision revision.
*
@ -260,11 +258,11 @@ class IDF_Scm_Svn extends IDF_Scm
if (isset($this->cache['commitmess'][$rev])) {
return $this->cache['commitmess'][$rev];
}
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
try {
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getCommitMessage', $cmd));
@ -281,11 +279,11 @@ class IDF_Scm_Svn extends IDF_Scm
if ($rev == null) {
$rev = 'HEAD';
}
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($filename)),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo.'/'.self::smartEncode($filename)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getPathInfo', $cmd));
if (!isset($xml->entry)) {
@ -308,11 +306,11 @@ class IDF_Scm_Svn extends IDF_Scm
public function getFile($def, $cmd_only=false)
{
$cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --no-auth-cache --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --no-auth-cache --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($def->fullpath)),
escapeshellarg($def->rev));
escapeshellarg($def->rev),
escapeshellarg($this->repo.'/'.self::smartEncode($def->fullpath)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
return ($cmd_only) ?
$cmd : self::shell_exec('IDF_Scm_Svn::getFile', $cmd);
@ -329,7 +327,7 @@ class IDF_Scm_Svn extends IDF_Scm
return $this->cache['branches'];
}
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s %s@HEAD',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/branches'));
@ -344,7 +342,7 @@ class IDF_Scm_Svn extends IDF_Scm
}
}
ksort($res);
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s %s@HEAD',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/trunk'));
@ -368,7 +366,7 @@ class IDF_Scm_Svn extends IDF_Scm
return $this->cache['tags'];
}
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s %s@HEAD',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/tags'));
@ -412,7 +410,6 @@ class IDF_Scm_Svn extends IDF_Scm
return array();
}
/**
* Get commit details.
*
@ -426,11 +423,11 @@ class IDF_Scm_Svn extends IDF_Scm
return false;
}
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 -v --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 -v --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($commit));
escapeshellarg($commit),
escapeshellarg($this->repo));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlRes = self::shell_exec('IDF_Scm_Svn::getCommit', $cmd);
$xml = simplexml_load_string($xmlRes);
@ -498,12 +495,12 @@ class IDF_Scm_Svn extends IDF_Scm
$branch = 'HEAD';
}
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml -v --limit %s --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml -v --limit %s --username=%s --password=%s --revision=%s %s',
escapeshellarg($n),
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($branch));
escapeshellarg($branch),
escapeshellarg($this->repo));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlRes = self::shell_exec('IDF_Scm_Svn::getChangeLog', $cmd);
$xml = simplexml_load_string($xmlRes);
@ -520,7 +517,6 @@ class IDF_Scm_Svn extends IDF_Scm
return $res;
}
/**
* Get additionnals properties on path and revision
*
@ -531,11 +527,11 @@ class IDF_Scm_Svn extends IDF_Scm
public function getProperties($rev, $path='')
{
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' proplist --no-auth-cache --xml --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' proplist --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlProps = self::shell_exec('IDF_Scm_Svn::getProperties', $cmd);
$props = simplexml_load_string($xmlProps);
@ -554,7 +550,6 @@ class IDF_Scm_Svn extends IDF_Scm
return $res;
}
/**
* Get a specific additionnal property on path and revision
*
@ -566,12 +561,12 @@ class IDF_Scm_Svn extends IDF_Scm
private function getProperty($property, $rev, $path='')
{
$res = array();
$cmd = sprintf(Pluf::f('svn_path', 'svn').' propget --no-auth-cache --xml %s --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' propget --no-auth-cache --xml %s --username=%s --password=%s --revision=%s %s',
escapeshellarg($property),
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlProp = self::shell_exec('IDF_Scm_Svn::getProperty', $cmd);
$prop = simplexml_load_string($xmlProp);
@ -579,7 +574,6 @@ class IDF_Scm_Svn extends IDF_Scm
return (string) $prop->target->property;
}
/**
* Get the number of the last commit in the repository.
*
@ -590,11 +584,11 @@ class IDF_Scm_Svn extends IDF_Scm
public function getLastCommit($rev='HEAD')
{
$xmlInfo = '';
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s %s@%s',
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
escapeshellarg($this->username),
escapeshellarg($this->password),
escapeshellarg($this->repo),
escapeshellarg($rev));
escapeshellarg($rev),
escapeshellarg($this->repo));
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
$xmlInfo = self::shell_exec('IDF_Scm_Svn::getLastCommit', $cmd);

View File

@ -3231,7 +3231,7 @@ msgid ""
"%%cobject.date%%."
msgstr ""
"Quellcode bei Revision <a class=\"mono\" href=\"%%url%%\">%%commit%%</a> "
"erzeugt am %%cobject.date%%."
"erzeugt %%cobject.date%%."
#: IDF/gettexttemplates/idf/source/git/file.html.php:4
#: IDF/gettexttemplates/idf/source/git/tree.html.php:4
@ -3409,8 +3409,8 @@ msgstr "Revision:"
#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4
#: IDF/gettexttemplates/idf/source/svn/file.html.php:11
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16
msgid "Go to revision"
msgstr "Zu Revision gehen:"
msgid "Switch"
msgstr "Wechseln"
#: IDF/gettexttemplates/idf/source/svn/file.html.php:6
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11

View File

@ -5,12 +5,25 @@
<h2 class="top"><a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $commit)}">{trans 'Root'}</a><span class="sep">/</span>{if $breadcrumb}{$breadcrumb|safe}{/if}</h2>
<table class="code" summary=" ">
{if !$tree_in and !$tags_in}
{if (!$tree_in and !$tags_in) or $props}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
<tfoot>
<tr><th colspan="2">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
</th></tr>
{if $props}
<tr><th colspan="2">
<ul>
{foreach $props as $prop => $val}
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
{/foreach}
</ul>
</th></tr>
{/if}
{if !$tree_in and !$tags_in}
<tr>
<th colspan="2">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
</th>
</tr>
{/if}
</tfoot>
{/if}
<tbody>

View File

@ -11,14 +11,27 @@
<th>{trans 'Message'}</th>
<th>{trans 'Size'}</th>
</tr>
</thead>{if !$tree_in and !$tags_in}
</thead>
{if (!$tree_in and !$tags_in) or $props}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
<tfoot>
<tr><th colspan="5">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
</th></tr>
{if $props}
<tr><th colspan="5">
<ul>
{foreach $props as $prop => $val}
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
{/foreach}
</ul>
</th></tr>
{/if}
{if !$tree_in and !$tags_in}
<tr><th colspan="5">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
</th></tr>
{/if}
{/if}
</tfoot>
{/if}<tbody>
<tbody>
{if $base}
<tr>
<td>&nbsp;</td>

View File

@ -4,7 +4,7 @@
<p><strong>{trans 'Revision:'}</strong> {$commit}</p>
<p>
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
<input type="submit" name="s" value="{trans 'Go to revision'}" />
<input type="submit" name="s" value="{trans 'Switch'}" />
</p>
</form>
{/block}

View File

@ -4,7 +4,7 @@
<p><strong>{trans 'Revision:'}</strong> {$commit}</p>
<p>
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5"/>
<input type="submit" name="s" value="{trans 'Go to revision'}"/>
<input type="submit" name="s" value="{trans 'Switch'}"/>
</p>
</form>
{/block}

View File

@ -6,13 +6,13 @@
<table class="code" summary=" ">
{if !$tree_in || $props}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
<tfoot>
{if $props}
<tr><th colspan="2">
<ul>
{foreach $props as $prop => $val}
<li>{trans 'Property'} <strong>{$prop}</strong> {trans 'set to:'} <em>{$val}</em></li>
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
{/foreach}
</ul>
</th></tr>
@ -38,7 +38,7 @@
<p>
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
<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 'Switch'}" /></p>
</form>
{/block}

View File

@ -13,13 +13,13 @@
<th>{trans 'Size'}</th>
</tr>
</thead>{if (!$tree_in and !$tags_in and $commit != 'HEAD') || $props}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
<tfoot>
{if $props}
<tr><th colspan="6">
<ul>
{foreach $props as $prop => $val}
<li>{trans 'Property'} <strong>{$prop}</strong> {trans 'set to:'} <em>{$val}</em></li>
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
{/foreach}
</ul>
</th></tr>
@ -45,7 +45,7 @@
<td class="fileicon"><img src="{media '/idf/img/'~$file.type~'.png'}" alt="{$file.type}" /></td>
<td><a href="{$url}">{$file.file}</a></td>
<td><span class="smaller">{$file.date|dateago:"without"}</span></td>
<td><span class="smaller">{$file.date|dateago:"without"}</span></td>
<td>{$file.rev}</td>
<td{if $file.type != 'blob'} colspan="2"{/if}><span class="smaller">{$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false}</span></td>
{if $file.type == 'blob'}
@ -66,7 +66,7 @@
<p>
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
<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 'Switch'}" /></p>
</form>
<p><strong>{trans 'Branches:'}</strong><br />
{foreach $branches as $branch => $path}

View File

@ -714,6 +714,31 @@ END;
$this->assertEquals('', $commit->diff);
}
public function testGetProperties()
{
$rev = "2345678901234567890123456789012345678901";
$instance = $this->createMock();
$instance->getStdio()->setExpectedOutput(array('interface_version'), array(), '13.1');
$stdio =<<<END
attr "foo" "bar"
state "unchanged"
attr "some new
line" "and more <weird>-
nesses"
END;
$instance->getStdio()->setExpectedOutput(array('get_attributes', 'foo'), array('r' => $rev), $stdio);
$res = $instance->getProperties($rev, 'foo');
$this->assertEquals(2, count($res));
$this->assertEquals(array(
'foo' => 'bar',
"some new\nline" => "and more <weird>-\nnesses"
), $res);
}
public function testGetExtraProperties()
{
$instance = $this->createMock();