Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F3281478
ArcanistAliasEngine.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
7 KB
Referenced Files
None
Subscribers
None
ArcanistAliasEngine.php
View Options
<?php
final
class
ArcanistAliasEngine
extends
Phobject
{
private
$runtime
;
private
$toolset
;
private
$workflows
;
private
$configurationSourceList
;
public
function
setRuntime
(
ArcanistRuntime
$runtime
)
{
$this
->
runtime
=
$runtime
;
return
$this
;
}
public
function
getRuntime
(
)
{
return
$this
->
runtime
;
}
public
function
setToolset
(
ArcanistToolset
$toolset
)
{
$this
->
toolset
=
$toolset
;
return
$this
;
}
public
function
getToolset
(
)
{
return
$this
->
toolset
;
}
public
function
setWorkflows
(
array
$workflows
)
{
assert_instances_of
(
$workflows
,
'ArcanistWorkflow'
)
;
$this
->
workflows
=
$workflows
;
return
$this
;
}
public
function
getWorkflows
(
)
{
return
$this
->
workflows
;
}
public
function
setConfigurationSourceList
(
ArcanistConfigurationSourceList
$config
)
{
$this
->
configurationSourceList
=
$config
;
return
$this
;
}
public
function
getConfigurationSourceList
(
)
{
return
$this
->
configurationSourceList
;
}
public
function
resolveAliases
(
array
$argv
)
{
$aliases_key
=
ArcanistArcConfigurationEngineExtension
::
KEY_ALIASES
;
$source_list
=
$this
->
getConfigurationSourceList
(
)
;
$aliases
=
$source_list
->
getConfig
(
$aliases_key
)
;
$results
=
array
(
)
;
// Identify aliases which had some kind of format or specification issue
// when loading config. We could possibly do this earlier, but it's nice
// to handle all the alias stuff in one place.
foreach
(
$aliases
as
$key
=>
$alias
)
{
$exception
=
$alias
->
getException
(
)
;
if
(
!
$exception
)
{
continue
;
}
// This alias is not defined properly, so we're going to ignore it.
unset
(
$aliases
[
$key
]
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_MISCONFIGURATION
)
->
setMessage
(
pht
(
'Configuration source ("%s") defines an invalid alias, which '
.
'will be ignored: %s'
,
$alias
->
getConfigurationSource
(
)
->
getSourceDisplayName
(
)
,
$exception
->
getMessage
(
)
)
)
;
}
$command
=
array_shift
(
$argv
)
;
$stack
=
array
(
)
;
return
$this
->
resolveAliasesForCommand
(
$aliases
,
$command
,
$argv
,
$results
,
$stack
)
;
}
private
function
resolveAliasesForCommand
(
array
$aliases
,
$command
,
array
$argv
,
array
$results
,
array
$stack
)
{
$toolset
=
$this
->
getToolset
(
)
;
$toolset_key
=
$toolset
->
getToolsetKey
(
)
;
// If we have a command which resolves to a real workflow, match it and
// finish resolution. You can not overwrite a real workflow with an alias.
$workflows
=
$this
->
getWorkflows
(
)
;
if
(
isset
(
$workflows
[
$command
]
)
)
{
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_RESOLUTION
)
->
setCommand
(
$command
)
->
setArguments
(
$argv
)
;
return
$results
;
}
// Find all the aliases which match whatever the user typed, like "draft".
// We look for aliases in other toolsets, too, so we can provide the user
// a hint when they type "phage draft" and mean "arc draft".
$matches
=
array
(
)
;
$toolset_matches
=
array
(
)
;
foreach
(
$aliases
as
$alias
)
{
if
(
$alias
->
getTrigger
(
)
===
$command
)
{
$matches
[
]
=
$alias
;
if
(
$alias
->
getToolset
(
)
==
$toolset_key
)
{
$toolset_matches
[
]
=
$alias
;
}
}
}
if
(
!
$toolset_matches
)
{
// If the user typed "phage draft" and meant "arc draft", give them a
// hint that the alias exists somewhere else and they may have specified
// the wrong toolset.
foreach
(
$matches
as
$match
)
{
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_SUGGEST
)
->
setMessage
(
pht
(
'No "%s %s" alias is defined, did you mean "%s %s"?'
,
$toolset_key
,
$command
,
$match
->
getToolset
(
)
,
$command
)
)
;
}
// If the user misspells a command (like "arc hlep") and it doesn't match
// anything (no alias or workflow), we want to pass it through unmodified
// and let the parser try to correct the spelling into a real workflow
// later on.
// However, if the user correctly types a command (like "arc draft") that
// resolves at least once (so it hits a valid alias) but does not
// ultimately resolve into a valid workflow, we want to treat this as a
// hard failure.
// This could happen if you manually defined a bad alias, or a workflow
// you'd previously aliased to was removed, or you stacked aliases and
// then deleted one.
if
(
$stack
)
{
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_NOTFOUND
)
->
setMessage
(
pht
(
'Alias resolved to "%s", but this is not a valid workflow or '
.
'alias name. This alias or workflow might have previously '
.
'existed and been removed.'
,
$command
)
)
;
}
else
{
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_RESOLUTION
)
->
setCommand
(
$command
)
->
setArguments
(
$argv
)
;
}
return
$results
;
}
$alias
=
array_pop
(
$toolset_matches
)
;
if
(
$toolset_matches
)
{
$source
=
$alias
->
getConfigurationSource
(
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_IGNORED
)
->
setMessage
(
pht
(
'Multiple configuration sources define an alias for "%s %s". '
.
'The last definition in the most specific source ("%s") will '
.
'be used.'
,
$toolset_key
,
$command
,
$source
->
getSourceDisplayName
(
)
)
)
;
foreach
(
$toolset_matches
as
$ignored_match
)
{
$source
=
$ignored_match
->
getConfigurationSource
(
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_IGNORED
)
->
setMessage
(
pht
(
'A definition of "%s %s" in "%s" will be ignored.'
,
$toolset_key
,
$command
,
$source
->
getSourceDisplayName
(
)
)
)
;
}
}
$alias_argv
=
$alias
->
getCommand
(
)
;
$alias_command
=
array_shift
(
$alias_argv
)
;
if
(
$alias
->
isShellCommandAlias
(
)
)
{
$shell_command
=
substr
(
$alias_command
,
1
)
;
$shell_argv
=
array_merge
(
array
(
$shell_command
)
,
$alias_argv
,
$argv
)
;
$shell_display
=
csprintf
(
'%Ls'
,
$shell_argv
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_SHELL
)
->
setMessage
(
pht
(
'%s %s -> $ %s'
,
$toolset_key
,
$command
,
$shell_display
)
)
->
setArguments
(
$shell_argv
)
;
return
$results
;
}
if
(
isset
(
$stack
[
$alias_command
]
)
)
{
$cycle
=
array_keys
(
$stack
)
;
$cycle
[
]
=
$alias_command
;
$cycle
=
implode
(
' -> '
,
$cycle
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_CYCLE
)
->
setMessage
(
pht
(
'Alias definitions form a cycle which can not be resolved: %s.'
,
$cycle
)
)
;
return
$results
;
}
$stack
[
$alias_command
]
=
true
;
$stack_limit
=
16
;
if
(
count
(
$stack
)
>=
$stack_limit
)
{
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_STACK
)
->
setMessage
(
pht
(
'Alias definitions form an unreasonably deep stack. A chain of '
.
'aliases may not resolve more than %s times.'
,
new
PhutilNumber
(
$stack_limit
)
)
)
;
return
$results
;
}
$display_argv
=
(string)
csprintf
(
'%LR'
,
$alias_argv
)
;
$results
[
]
=
$this
->
newEffect
(
ArcanistAliasEffect
::
EFFECT_ALIAS
)
->
setMessage
(
pht
(
'%s %s -> %s %s %s'
,
$toolset_key
,
$command
,
$toolset_key
,
$alias_command
,
$display_argv
)
)
;
$argv
=
array_merge
(
$alias_argv
,
$argv
)
;
return
$this
->
resolveAliasesForCommand
(
$aliases
,
$alias_command
,
$argv
,
$results
,
$stack
)
;
}
protected
function
newEffect
(
$effect_type
)
{
return
id
(
new
ArcanistAliasEffect
(
)
)
->
setType
(
$effect_type
)
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sun, Mar 23, 22:34 (4 d, 1 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1115302
Default Alt Text
ArcanistAliasEngine.php (7 KB)
Attached To
Mode
rARC Arcanist
Attached
Detach File
Event Timeline
Log In to Comment