mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-02 18:08:26 +01:00
Add a "{src ...}" Remarkup rule to provide a more flexible way to reference source files in Diffusion
Summary: Depends on D20538. Ref T13291. We now recognize full source URIs, but encoding full URIs isn't super human-friendly and we can't do stuff like relative links with them. Add `{src ...}` as a way to get to this behavior that supports options and more flexible syntax. Test Plan: {F6463607} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13291 Differential Revision: https://secure.phabricator.com/D20539
This commit is contained in:
parent
56e7bde68d
commit
4180b337cf
3 changed files with 224 additions and 0 deletions
|
@ -1000,6 +1000,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionSetPasswordSettingsPanel' => 'applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php',
|
||||
'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php',
|
||||
'DiffusionSourceHyperlinkEngineExtension' => 'applications/diffusion/engineextension/DiffusionSourceHyperlinkEngineExtension.php',
|
||||
'DiffusionSourceLinkRemarkupRule' => 'applications/diffusion/remarkup/DiffusionSourceLinkRemarkupRule.php',
|
||||
'DiffusionSourceLinkView' => 'applications/diffusion/view/DiffusionSourceLinkView.php',
|
||||
'DiffusionSubversionCommandEngine' => 'applications/diffusion/protocol/DiffusionSubversionCommandEngine.php',
|
||||
'DiffusionSubversionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSubversionSSHWorkflow.php',
|
||||
|
@ -6685,6 +6686,7 @@ phutil_register_library_map(array(
|
|||
'DiffusionSetPasswordSettingsPanel' => 'PhabricatorSettingsPanel',
|
||||
'DiffusionSetupException' => 'Exception',
|
||||
'DiffusionSourceHyperlinkEngineExtension' => 'PhabricatorRemarkupHyperlinkEngineExtension',
|
||||
'DiffusionSourceLinkRemarkupRule' => 'PhutilRemarkupRule',
|
||||
'DiffusionSourceLinkView' => 'AphrontView',
|
||||
'DiffusionSubversionCommandEngine' => 'DiffusionCommandEngine',
|
||||
'DiffusionSubversionSSHWorkflow' => 'DiffusionSSHWorkflow',
|
||||
|
|
|
@ -40,6 +40,7 @@ final class PhabricatorDiffusionApplication extends PhabricatorApplication {
|
|||
new DiffusionCommitRemarkupRule(),
|
||||
new DiffusionRepositoryRemarkupRule(),
|
||||
new DiffusionRepositoryByIDRemarkupRule(),
|
||||
new DiffusionSourceLinkRemarkupRule(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
|
||||
final class DiffusionSourceLinkRemarkupRule
|
||||
extends PhutilRemarkupRule {
|
||||
|
||||
const KEY_SOURCELINKS = 'diffusion.links';
|
||||
|
||||
public function getPriority() {
|
||||
return 200.0;
|
||||
}
|
||||
|
||||
public function apply($text) {
|
||||
return preg_replace_callback(
|
||||
'@{(?:src|source)\b((?:[^}\\\\]+|\\\\.)*)}@m',
|
||||
array($this, 'markupSourceLink'),
|
||||
$text);
|
||||
}
|
||||
|
||||
public function markupSourceLink(array $matches) {
|
||||
$engine = $this->getEngine();
|
||||
$text_mode = $engine->isTextMode();
|
||||
$mail_mode = $engine->isHTMLMailMode();
|
||||
|
||||
if (!$this->isFlatText($matches[0]) || $text_mode || $mail_mode) {
|
||||
// We could do better than this in text mode and mail mode, but focus
|
||||
// on web mode first.
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$metadata_key = self::KEY_SOURCELINKS;
|
||||
$metadata = $engine->getTextMetadata($metadata_key, array());
|
||||
|
||||
$token = $engine->storeText($matches[0]);
|
||||
|
||||
$metadata[] = array(
|
||||
'token' => $token,
|
||||
'raw' => $matches[0],
|
||||
'input' => $matches[1],
|
||||
);
|
||||
|
||||
$engine->setTextMetadata($metadata_key, $metadata);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function didMarkupText() {
|
||||
$engine = $this->getEngine();
|
||||
$metadata_key = self::KEY_SOURCELINKS;
|
||||
$metadata = $engine->getTextMetadata($metadata_key, array());
|
||||
|
||||
if (!$metadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
$viewer = $engine->getConfig('viewer');
|
||||
if (!$viewer) {
|
||||
return;
|
||||
}
|
||||
|
||||
$defaults = array(
|
||||
'repository' => null,
|
||||
'line' => null,
|
||||
'commit' => null,
|
||||
'ref' => null,
|
||||
);
|
||||
|
||||
$tags = array();
|
||||
foreach ($metadata as $ref) {
|
||||
$token = $ref['token'];
|
||||
$raw = $ref['raw'];
|
||||
$input = $ref['input'];
|
||||
|
||||
$pattern =
|
||||
'(^'.
|
||||
'[\s,]*'.
|
||||
'(?:"(?P<quotedpath>(?:[^\\\\"]+|\\.)+)"|(?P<rawpath>[^\s,]+))'.
|
||||
'[\s,]*'.
|
||||
'(?P<options>.*)'.
|
||||
'\z)';
|
||||
$matches = null;
|
||||
if (!preg_match($pattern, $input, $matches)) {
|
||||
$hint_text = pht(
|
||||
'Missing path, expected "{src path ...}" in: %s',
|
||||
$raw);
|
||||
$hint = $this->newSyntaxHint($hint_text);
|
||||
|
||||
$engine->overwriteStoredText($token, $hint);
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = idx($matches, 'rawpath');
|
||||
if (!strlen($path)) {
|
||||
$path = idx($matches, 'quotedpath');
|
||||
$path = stripcslashes($path);
|
||||
}
|
||||
|
||||
$parts = explode(':', $path, 2);
|
||||
if (count($parts) == 2) {
|
||||
$repository = nonempty($parts[0], null);
|
||||
$path = $parts[1];
|
||||
} else {
|
||||
$repository = null;
|
||||
$path = $parts[0];
|
||||
}
|
||||
|
||||
$options = $matches['options'];
|
||||
|
||||
$parser = new PhutilSimpleOptions();
|
||||
$options = $parser->parse($options) + $defaults;
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if (!array_key_exists($key, $defaults)) {
|
||||
$hint_text = pht(
|
||||
'Unknown option "%s" in: %s',
|
||||
$key,
|
||||
$raw);
|
||||
$hint = $this->newSyntaxHint($hint_text);
|
||||
|
||||
$engine->overwriteStoredText($token, $hint);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
if ($options['repository'] !== null) {
|
||||
$repository = $options['repository'];
|
||||
}
|
||||
|
||||
if ($repository === null) {
|
||||
$hint_text = pht(
|
||||
'Missing repository, expected "{src repository:path ...}" '.
|
||||
'or "{src path repository=...}" in: %s',
|
||||
$raw);
|
||||
$hint = $this->newSyntaxHint($hint_text);
|
||||
|
||||
$engine->overwriteStoredText($token, $hint);
|
||||
continue;
|
||||
}
|
||||
|
||||
$tags[] = array(
|
||||
'token' => $token,
|
||||
'raw' => $raw,
|
||||
'identifier' => $repository,
|
||||
'path' => $path,
|
||||
'options' => $options,
|
||||
);
|
||||
}
|
||||
|
||||
if (!$tags) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query = id(new PhabricatorRepositoryQuery())
|
||||
->setViewer($viewer)
|
||||
->withIdentifiers(ipull($tags, 'identifier'));
|
||||
|
||||
$query->execute();
|
||||
|
||||
$repository_map = $query->getIdentifierMap();
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$token = $tag['token'];
|
||||
|
||||
$identifier = $tag['identifier'];
|
||||
$repository = idx($repository_map, $identifier);
|
||||
if (!$repository) {
|
||||
// For now, just bail out here. Ideally, we should distingiush between
|
||||
// restricted and invalid repositories.
|
||||
continue;
|
||||
}
|
||||
|
||||
$drequest = DiffusionRequest::newFromDictionary(
|
||||
array(
|
||||
'user' => $viewer,
|
||||
'repository' => $repository,
|
||||
));
|
||||
|
||||
$options = $tag['options'];
|
||||
|
||||
$line = $options['line'];
|
||||
$commit = $options['commit'];
|
||||
$ref_name = $options['ref'];
|
||||
|
||||
$link_uri = $drequest->generateURI(
|
||||
array(
|
||||
'action' => 'browse',
|
||||
'path' => $tag['path'],
|
||||
'commit' => $commit,
|
||||
'line' => $line,
|
||||
'branch' => $ref_name,
|
||||
));
|
||||
|
||||
$view = id(new DiffusionSourceLinkView())
|
||||
->setRepository($repository)
|
||||
->setPath($tag['path'])
|
||||
->setURI($link_uri);
|
||||
|
||||
if ($line !== null) {
|
||||
$view->setLine($line);
|
||||
}
|
||||
|
||||
if ($commit !== null) {
|
||||
$view->setCommit($commit);
|
||||
}
|
||||
|
||||
if ($ref_name !== null) {
|
||||
$view->setRefName($ref_name);
|
||||
}
|
||||
|
||||
$engine->overwriteStoredText($token, $view);
|
||||
}
|
||||
}
|
||||
|
||||
private function newSyntaxHint($text) {
|
||||
return id(new PHUITagView())
|
||||
->setType(PHUITagView::TYPE_SHADE)
|
||||
->setColor('red')
|
||||
->setIcon('fa-exclamation-triangle')
|
||||
->setName($text);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue