Page MenuHomePhorge

No OneTemporary

diff --git a/src/lint/linter/spelling/ArcanistSpellingDefaultData.php b/src/lint/linter/spelling/ArcanistSpellingDefaultData.php
index 6bd9091d..5c69a9f7 100644
--- a/src/lint/linter/spelling/ArcanistSpellingDefaultData.php
+++ b/src/lint/linter/spelling/ArcanistSpellingDefaultData.php
@@ -1,536 +1,540 @@
<?php
/**
* Contains default spelling correction rules for ArcanistSpellingLinter.
* Inside its own file to keep logic of ArcanistSpellingLinter clean
*
* @nolint
* @group linter
*/
class ArcanistSpellingDefaultData {
// From http://cpansearch.perl.org/src/APOCAL/Pod-Spell-CommonMistakes-1.000/lib/Pod/Spell/CommonMistakes/WordList.pm
// Pruned by hand. If you modify this list, remember to remove case only
// spelling suggestions and any with special characters like - or '
public static function getFullWordRules() {
return array(
array(
// Variable common
"abandonning" => "abandoning",
"abigious" => "ambiguous",
"abitrate" => "arbitrate",
"absense" => "absence",
"absolut" => "absolute",
"absoulte" => "absolute",
"acceleratoin" => "acceleration",
"accelleration" => "acceleration",
"accesing" => "accessing",
"accesnt" => "accent",
"accessable" => "accessible",
"accidentaly" => "accidentally",
"accidentually" => "accidentally",
"accomodate" => "accommodate",
"accomodates" => "accommodates",
"accout" => "account",
"acessable" => "accessible",
"ackowledge" => "acknowledge",
"ackowledged" => "acknowledged",
"acknowldegement" => "acknowldegement",
"acording" => "according",
"activete" => "activate",
"acumulating" => "accumulating",
"addional" => "additional",
"additionaly" => "additionally",
"addreses" => "addresses",
"aditional" => "additional",
"aditionally" => "additionally",
"aditionaly" => "additionally",
"adress" => "address",
"adresses" => "addresses",
"adviced" => "advised",
"afecting" => "affecting",
"albumns" => "albums",
"alegorical" => "allegorical",
"algorith" => "algorithm",
"algorithmical" => "algorithmically",
"algoritm" => "algorithm",
"algoritms" => "algorithms",
"algorrithm" => "algorithm",
"algorritm" => "algorithm",
"allpication" => "application",
"altough" => "although",
"ambigious" => "ambiguous",
"amoung" => "among",
"amout" => "amount",
"analysator" => "analyzer",
"anniversery" => "anniversary",
"annoucement" => "announcement",
"anomolies" => "anomalies",
"anomoly" => "anomaly",
"aplication" => "application",
"appearence" => "appearance",
"appropiate" => "appropriate",
"appropriatly" => "appropriately",
"aquired" => "acquired",
"arbitary" => "arbitrary",
"architechture" => "architecture",
"arguement" => "argument",
"arguements" => "arguments",
"aritmetic" => "arithmetic",
"arraival" => "arrival",
"artifical" => "artificial",
"artillary" => "artillery",
"assigment" => "assignment",
"assigments" => "assignments",
"assistent" => "assistant",
"asuming" => "assuming",
"atomatically" => "automatically",
"attemps" => "attempts",
"attruibutes" => "attributes",
"authentification" => "authentication",
"automaticaly" => "automatically",
"automaticly" => "automatically",
"automatize" => "automate",
"automatized" => "automated",
"automatizes" => "automates",
"autonymous" => "autonomous",
"auxilliary" => "auxiliary",
"avaiable" => "available",
"availabled" => "available",
"availablity" => "availability",
"availale" => "available",
"availavility" => "availability",
"availble" => "available",
"availiable" => "available",
"avaliable" => "available",
"backgroud" => "background",
"bahavior" => "behavior",
"baloon" => "balloon",
"baloons" => "balloons",
"batery" => "battery",
"becomming" => "becoming",
"becuase" => "because",
"begining" => "beginning",
"calender" => "calendar",
"cancelation" => "cancellation",
"capabilites" => "capabilities",
"capatibilities" => "capabilities",
"cariage" => "carriage",
"challange" => "challenge",
"challanges" => "challenges",
"changable" => "changeable",
"charachter" => "character",
"charachters" => "characters",
"charcter" => "character",
"childs" => "children",
"chnage" => "change",
"chnages" => "changes",
"choosen" => "chosen",
"collapsable" => "collapsible",
"colorfull" => "colorful",
"comand" => "command",
"comit" => "commit",
"commerical" => "commercial",
"comminucation" => "communication",
"commited" => "committed",
"commiting" => "committing",
"committ" => "commit",
"commoditiy" => "commodity",
"compability" => "compatibility",
"compatability" => "compatibility",
"compatable" => "compatible",
"compatibiliy" => "compatibility",
"compatibilty" => "compatibility",
"compleatly" => "completely",
"completly" => "completely",
"complient" => "compliant",
"compres" => "compress",
"compresion" => "compression",
"configuratoin" => "configuration",
"conjuction" => "conjunction",
"connectinos" => "connections",
"connnection" => "connection",
"connnections" => "connections",
"consistancy" => "consistency",
"containes" => "contains",
"containts" => "contains",
"contence" => "contents",
"continous" => "continuous",
"continueing" => "continuing",
"contraints" => "constraints",
"convertor" => "converter",
"convinient" => "convenient",
"corected" => "corrected",
"correponding" => "corresponding",
"correponds" => "corresponds",
"correspoding" => "corresponding",
"cryptocraphic" => "cryptographic",
"curently" => "currently",
"dafault" => "default",
"deafult" => "default",
"deamon" => "daemon",
"decompres" => "decompress",
"definate" => "definite",
"definately" => "definitely",
"delemiter" => "delimiter",
"dependancies" => "dependencies",
"dependancy" => "dependency",
"dependant" => "dependent",
"desactivate" => "deactivate",
"detabase" => "database",
"developement" => "development",
"developped" => "developed",
"developpement" => "development",
"developper" => "developer",
"deveolpment" => "development",
"devided" => "divided",
"dictionnary" => "dictionary",
"diplay" => "display",
"disapeared" => "disappeared",
"discontiguous" => "noncontiguous",
"dispertion" => "dispersion",
"dissapears" => "disappears",
"docuentation" => "documentation",
"documantation" => "documentation",
"documentaion" => "documentation",
"downlad" => "download",
"downlads" => "downloads",
"easilly" => "easily",
"ecspecially" => "especially",
"edditable" => "editable",
"editting" => "editing",
"eletronic" => "electronic",
"enchanced" => "enhanced",
"encorporating" => "incorporating",
"endianess" => "endianness",
"enhaced" => "enhanced",
"enlightnment" => "enlightenment",
"enocded" => "encoded",
"enterily" => "entirely",
"enviroiment" => "environment",
"enviroment" => "environment",
"environement" => "environment",
"environent" => "environment",
"equivelant" => "equivalent",
"equivilant" => "equivalent",
"excecutable" => "executable",
"exceded" => "exceeded",
"excellant" => "excellent",
"exlcude" => "exclude",
"exlcusive" => "exclusive",
"expecially" => "especially",
"explicitely" => "explicitly",
"expresion" => "expression",
"exprimental" => "experimental",
"extention" => "extension",
"failuer" => "failure",
"familar" => "familiar",
"fatser" => "faster",
"feauture" => "feature",
"feautures" => "features",
"fetaure" => "feature",
"fetaures" => "features",
"forse" => "force",
"fortan" => "fortran",
"forwardig" => "forwarding",
"framwork" => "framework",
"fuction" => "function",
"fuctions" => "functions",
"functionaly" => "functionally",
"functionnality" => "functionality",
"functonality" => "functionality",
"futhermore" => "furthermore",
"generiously" => "generously",
"grahical" => "graphical",
"grahpical" => "graphical",
"grapic" => "graphic",
"guage" => "gauge",
"halfs" => "halves",
"heirarchically" => "hierarchically",
"helpfull" => "helpful",
"hierachy" => "hierarchy",
"heirachy" => "hierarchy",
"heirarchy" => "hierarchy",
"hierarchie" => "hierarchy",
"heirarchie" => "hierarchy",
"howver" => "however",
"immeadiately" => "immediately",
"implemantation" => "implementation",
"implemention" => "implementation",
"incomming" => "incoming",
"incompatabilities" => "incompatibilities",
"incompatable" => "incompatible",
"inconsistant" => "inconsistent",
"indendation" => "indentation",
"indended" => "intended",
"independant" => "independent",
"informatiom" => "information",
"informations" => "information",
"infromation" => "information",
"initalize" => "initialize",
"initators" => "initiators",
"initializiation" => "initialization",
"inofficial" => "unofficial",
"integreated" => "integrated",
"integrety" => "integrity",
"integrey" => "integrity",
"intendet" => "intended",
"interchangable" => "interchangeable",
"intermittant" => "intermittent",
"interupted" => "interrupted",
"jave" => "java",
"langage" => "language",
"langauage" => "language",
"langugage" => "language",
"lauch" => "launch",
"lesstiff" => "lesstif",
"libaries" => "libraries",
"libary" => "library",
"libraris" => "libraries",
"licenceing" => "licencing",
"loggging" => "logging",
"loggin" => "login",
"logile" => "logfile",
"machinary" => "machinery",
"maintainance" => "maintenance",
"maintainence" => "maintenance",
"makeing" => "making",
"malplace" => "misplace",
"malplaced" => "misplaced",
"managable" => "manageable",
"manoeuvering" => "maneuvering",
"mathimatical" => "mathematical",
"mathimatic" => "mathematic",
"mathimatics" => "mathematics",
"ment" => "meant",
"messsage" => "message",
"messsages" => "messages",
"microprocesspr" => "microprocessor",
"milliseonds" => "milliseconds",
"miscelleneous" => "miscellaneous",
"misformed" => "malformed",
"mispelled" => "misspelled",
"mmnemonic" => "mnemonic",
"modulues" => "modules",
"monochorome" => "monochrome",
"monochromo" => "monochrome",
"monocrome" => "monochrome",
"mroe" => "more",
"multidimensionnal" => "multidimensional",
"mulitplied" => "multiplied",
"mutiple" => "multiple",
"nam" => "name",
"nams" => "names",
"navagating" => "navigating",
"nead" => "need",
"neccesary" => "necessary",
"neccessary" => "necessary",
"necesary" => "necessary",
"negotation" => "negotiation",
"nescessary" => "necessary",
"nessessary" => "necessary",
"noticable" => "noticeable",
"notications" => "notifications",
"omitt" => "omit",
"ommitted" => "omitted",
"onself" => "oneself",
"optionnal" => "optional",
"optmizations" => "optimizations",
"orientatied" => "orientated",
"orientied" => "oriented",
"ouput" => "output",
"overaall" => "overall",
"overriden" => "overridden",
"pacakge" => "package",
"pachage" => "package",
"packacge" => "package",
"packege" => "package",
"packge" => "package",
"pakage" => "package",
"pallette" => "palette",
"paramameters" => "parameters",
"paramater" => "parameter",
"parametes" => "parameters",
"paramter" => "parameter",
"paramters" => "parameters",
"particularily" => "particularly",
"pased" => "passed",
"peprocessor" => "preprocessor",
"perfoming" => "performing",
"permissons" => "permissions",
"persistant" => "persistent",
"plattform" => "platform",
"pleaes" => "please",
"ploting" => "plotting",
"posible" => "possible",
"powerfull" => "powerful",
+ "preceed" => "precede",
"preceeded" => "preceded",
"preceeding" => "preceding",
"precendence" => "precedence",
"precission" => "precision",
"prefered" => "preferred",
"prefferably" => "preferably",
"prepaired" => "prepared",
"primative" => "primitive",
"princliple" => "principle",
"priorty" => "priority",
"procceed" => "proceed",
"proccesors" => "processors",
"proces" => "process",
"processessing" => "processing",
"processpr" => "processor",
"processsing" => "processing",
"progams" => "programs",
"programers" => "programmers",
"programm" => "program",
"programms" => "programs",
"promps" => "prompts",
"pronnounced" => "pronounced",
"prononciation" => "pronunciation",
"pronouce" => "pronounce",
"pronunce" => "pronounce",
"propery" => "property",
"prosess" => "process",
"protable" => "portable",
"protcol" => "protocol",
"protecion" => "protection",
"protocoll" => "protocol",
"psychadelic" => "psychedelic",
"quering" => "querying",
"reasearch" => "research",
"reasearcher" => "researcher",
"reasearchers" => "researchers",
"recogniced" => "recognised",
"recognizeable" => "recognizable",
"recommanded" => "recommended",
"redircet" => "redirect",
"redirectrion" => "redirection",
"refence" => "reference",
"registerd" => "registered",
"registraration" => "registration",
"regulamentations" => "regulations",
"remoote" => "remote",
"removeable" => "removable",
"repectively" => "respectively",
"replacments" => "replacements",
"replys" => "replies",
"requiere" => "require",
"requred" => "required",
"resizeable" => "resizable",
"ressize" => "resize",
"ressource" => "resource",
"retransmited" => "retransmitted",
"runned" => "ran",
"runnning" => "running",
"safly" => "safely",
"savable" => "saveable",
"searchs" => "searches",
"secund" => "second",
"separatly" => "separately",
"sepcify" => "specify",
"seperated" => "separated",
"seperately" => "separately",
"seperate" => "separate",
"seperatly" => "separately",
"seperator" => "separator",
"sequencial" => "sequential",
"serveral" => "several",
"setts" => "sets",
"similiar" => "similar",
"simliar" => "similar",
"speach" => "speech",
"speciefied" => "specified",
"specifed" => "specified",
"specificaton" => "specification",
"specifing" => "specifying",
"speficied" => "specified",
"speling" => "spelling",
"splitted" => "split",
"staically" => "statically",
"standardss" => "standards",
"standart" => "standard",
"staticly" => "statically",
"subdirectoires" => "subdirectories",
"suble" => "subtle",
"succesfully" => "successfully",
"succesful" => "successful",
"sucessfully" => "successfully",
"superflous" => "superfluous",
"superseeded" => "superseded",
"suplied" => "supplied",
"suport" => "support",
"suppored" => "supported",
"supportin" => "supporting",
"suppoted" => "supported",
"suppported" => "supported",
"suppport" => "support",
+ "supress" => "suppress",
+ "surpress" => "suppress",
"surpresses" => "suppresses",
+ "surpesses" => "suppresses",
"suspicously" => "suspiciously",
"synax" => "syntax",
"synchonized" => "synchronized",
"syncronize" => "synchronize",
"syncronizing" => "synchronizing",
"syncronus" => "synchronous",
"syste" => "system",
"sythesis" => "synthesis",
"taht" => "that",
"throught" => "through",
"transfering" => "transferring",
"trasmission" => "transmission",
"treshold" => "threshold",
"trigerring" => "triggering",
"unecessary" => "unnecessary",
"unexecpted" => "unexpected",
"unfortunatelly" => "unfortunately",
"unknonw" => "unknown",
"unkown" => "unknown",
"unuseful" => "useless",
"usefull" => "useful",
"usualy" => "usually",
"utilites" => "utilities",
"utillities" => "utilities",
"utilties" => "utilities",
"utiltity" => "utility",
"utitlty" => "utility",
"variantions" => "variations",
"varient" => "variant",
"verbse" => "verbose",
"verisons" => "versions",
"verison" => "version",
"verson" => "version",
"visiters" => "visitors",
"vitual" => "virtual",
"whataver" => "whatever",
"wheter" => "whether",
"wierd" => "weird",
"yur" => "your",
// Variable common_cpan
"refering" => "referring",
"writeable" => "writable",
"nineth" => "ninth",
"ommited" => "omitted",
"omited" => "omitted",
"requrie" => "require",
"existant" => "existent",
"explict" => "explicit",
"agument" => "augument",
"destionation" => "destination",
), array(
'teh' => 'the'
)
);
}
public static function getPartialWordRules() {
return array(
array(),
array(
'recieve' => 'receive',
'uft8' => 'utf8',
'lenght' => 'length',
'heigth' => 'height',
'fuction' => 'function',
)
);
}
}
diff --git a/src/workflow/ArcanistCommitWorkflow.php b/src/workflow/ArcanistCommitWorkflow.php
index 9570c94d..45243ac9 100644
--- a/src/workflow/ArcanistCommitWorkflow.php
+++ b/src/workflow/ArcanistCommitWorkflow.php
@@ -1,340 +1,340 @@
<?php
/**
* Executes "svn commit" once a revision has been "Accepted".
*
* @group workflow
*/
final class ArcanistCommitWorkflow extends ArcanistBaseWorkflow {
private $revisionID;
public function getWorkflowName() {
return 'commit';
}
public function getCommandSynopses() {
return phutil_console_format(<<<EOTEXT
**commit** [--revision __revision_id__] [--show]
EOTEXT
);
}
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
Supports: svn
Commit a revision which has been accepted by a reviewer.
EOTEXT
);
}
public function requiresWorkingCopy() {
return true;
}
public function requiresConduit() {
return true;
}
public function requiresAuthentication() {
return true;
}
public function requiresRepositoryAPI() {
return true;
}
public function getRevisionID() {
return $this->revisionID;
}
public function getArguments() {
return array(
'show' => array(
'help' =>
"Show the command which would be issued, but do not actually ".
"commit anything."
),
'revision' => array(
'param' => 'revision_id',
'help' =>
"Commit a specific revision. If you do not specify a revision, ".
"arc will look for committable revisions.",
)
);
}
public function run() {
$repository_api = $this->getRepositoryAPI();
if (!($repository_api instanceof ArcanistSubversionAPI)) {
throw new ArcanistUsageException(
"'arc commit' is only supported under svn.");
}
$revision_id = $this->normalizeRevisionID($this->getArgument('revision'));
if (!$revision_id) {
$revisions = $repository_api->loadWorkingCopyDifferentialRevisions(
$this->getConduit(),
array(
'authors' => array($this->getUserPHID()),
'status' => 'status-accepted',
));
if (count($revisions) == 0) {
throw new ArcanistUsageException(
"Unable to identify the revision in the working copy. Use ".
"'--revision <revision_id>' to select a revision.");
} else if (count($revisions) > 1) {
throw new ArcanistUsageException(
"More than one revision exists in the working copy:\n\n".
$this->renderRevisionList($revisions)."\n".
"Use '--revision <revision_id>' to select a revision.");
}
} else {
$revisions = $this->getConduit()->callMethodSynchronous(
'differential.query',
array(
'ids' => array($revision_id),
));
if (count($revisions) == 0) {
throw new ArcanistUsageException(
"Revision 'D{$revision_id}' does not exist.");
}
}
$revision = head($revisions);
$this->revisionID = $revision['id'];
$revision_id = $revision['id'];
$is_show = $this->getArgument('show');
if (!$is_show) {
$this->runSanityChecks($revision);
}
$message = $this->getConduit()->callMethodSynchronous(
'differential.getcommitmessage',
array(
'revision_id' => $revision_id,
'edit' => false,
));
$event = $this->dispatchEvent(
ArcanistEventType::TYPE_COMMIT_WILLCOMMITSVN,
array(
'message' => $message,
));
$message = $event->getValue('message');
if ($is_show) {
echo $message."\n";
return 0;
}
$revision_title = $revision['title'];
echo "Committing 'D{$revision_id}: {$revision_title}'...\n";
$files = $this->getCommitFileList($revision);
$tmp_file = new TempFile();
Filesystem::writeFile($tmp_file, $message);
$command = csprintf(
'svn commit %Ls --encoding utf-8 -F %s',
$files,
$tmp_file);
- // make sure to specify LANG on non-windows systems to surpress any fancy
+ // make sure to specify LANG on non-windows systems to suppress any fancy
// warnings; see @{method:getSVNLangEnvVar}.
if (!phutil_is_windows()) {
$command = csprintf('LANG=%C %C', $this->getSVNLangEnvVar(), $command);
}
chdir($repository_api->getPath());
$err = phutil_passthru('%C', $command);
if ($err) {
throw new Exception("Executing 'svn commit' failed!");
}
$mark_workflow = $this->buildChildWorkflow(
'close-revision',
array(
'--finalize',
$revision_id,
));
$mark_workflow->run();
return $err;
}
protected function getCommitFileList(array $revision) {
$repository_api = $this->getRepositoryAPI();
$revision_id = $revision['id'];
$commit_paths = $this->getConduit()->callMethodSynchronous(
'differential.getcommitpaths',
array(
'revision_id' => $revision_id,
));
$dir_paths = array();
foreach ($commit_paths as $path) {
$path = dirname($path);
while ($path != '.') {
$dir_paths[$path] = true;
$path = dirname($path);
}
}
$commit_paths = array_fill_keys($commit_paths, true);
$status = $repository_api->getSVNStatus();
$modified_but_not_included = array();
foreach ($status as $path => $mask) {
if (!empty($dir_paths[$path])) {
$commit_paths[$path] = true;
}
if (!empty($commit_paths[$path])) {
continue;
}
foreach ($commit_paths as $will_commit => $ignored) {
if (Filesystem::isDescendant($path, $will_commit)) {
throw new ArcanistUsageException(
"This commit includes the directory '{$will_commit}', but ".
"it contains a modified path ('{$path}') which is NOT included ".
"in the commit. Subversion can not handle this operation and ".
"will commit the path anyway. You need to sort out the working ".
"copy changes to '{$path}' before you may proceed with the ".
"commit.");
}
}
$modified_but_not_included[] = $path;
}
if ($modified_but_not_included) {
$prefix = pht(
'Locally modified path(s) are not included in this revision:',
count($modified_but_not_included));
$prompt = pht(
'They will NOT be committed. Commit this revision anyway?',
count($modified_but_not_included));
$this->promptFileWarning($prefix, $prompt, $modified_but_not_included);
}
$do_not_exist = array();
foreach ($commit_paths as $path => $ignored) {
$disk_path = $repository_api->getPath($path);
if (file_exists($disk_path)) {
continue;
}
if (is_link($disk_path)) {
continue;
}
if (idx($status, $path) & ArcanistRepositoryAPI::FLAG_DELETED) {
continue;
}
$do_not_exist[] = $path;
unset($commit_paths[$path]);
}
if ($do_not_exist) {
$prefix = pht(
'Revision includes changes to path(s) that do not exist:',
count($do_not_exist));
$prompt = "Commit this revision anyway?";
$this->promptFileWarning($prefix, $prompt, $do_not_exist);
}
$files = array_keys($commit_paths);
$files = ArcanistSubversionAPI::escapeFileNamesForSVN($files);
if (empty($files)) {
throw new ArcanistUsageException(
"There is nothing left to commit. None of the modified paths exist.");
}
return $files;
}
protected function promptFileWarning($prefix, $prompt, array $paths) {
echo $prefix."\n\n";
foreach ($paths as $path) {
echo " ".$path."\n";
}
if (!phutil_console_confirm($prompt)) {
throw new ArcanistUserAbortException();
}
}
protected function getSupportedRevisionControlSystems() {
return array('svn');
}
/**
* On some systems, we need to specify "en_US.UTF-8" instead of "en_US.utf8",
* and SVN spews some bewildering warnings if we don't:
*
* svn: warning: cannot set LC_CTYPE locale
* svn: warning: environment variable LANG is en_US.utf8
* svn: warning: please check that your locale name is correct
*
* For example, it happens on epriestley's Mac (10.6.7) with
* Subversion 1.6.15.
*/
private function getSVNLangEnvVar() {
$locale = 'en_US.utf8';
try {
list($locales) = execx('locale -a');
$locales = explode("\n", trim($locales));
$locales = array_fill_keys($locales, true);
if (isset($locales['en_US.UTF-8'])) {
$locale = 'en_US.UTF-8';
}
} catch (Exception $ex) {
// Ignore.
}
return $locale;
}
private function runSanityChecks(array $revision) {
$repository_api = $this->getRepositoryAPI();
$revision_id = $revision['id'];
$revision_title = $revision['title'];
$confirm = array();
if ($revision['status'] != ArcanistDifferentialRevisionStatus::ACCEPTED) {
$confirm[] =
"Revision 'D{$revision_id}: {$revision_title}' has not been accepted. ".
"Commit this revision anyway?";
}
if ($revision['authorPHID'] != $this->getUserPHID()) {
$confirm[] =
"You are not the author of 'D{$revision_id}: {$revision_title}'. ".
"Commit this revision anyway?";
}
$revision_source = idx($revision, 'sourcePath');
$current_source = $repository_api->getPath();
if ($revision_source != $current_source) {
$confirm[] =
"Revision 'D{$revision_id}: {$revision_title}' was generated from ".
"'{$revision_source}', but current working copy root is ".
"'{$current_source}'. Commit this revision anyway?";
}
foreach ($confirm as $thing) {
if (!phutil_console_confirm($thing)) {
throw new ArcanistUserAbortException();
}
}
}
}
diff --git a/src/workflow/ArcanistFeatureWorkflow.php b/src/workflow/ArcanistFeatureWorkflow.php
index e1601d08..bc216ca3 100644
--- a/src/workflow/ArcanistFeatureWorkflow.php
+++ b/src/workflow/ArcanistFeatureWorkflow.php
@@ -1,354 +1,354 @@
<?php
/**
* Displays user's Git branches or Mercurial bookmarks
*
* @group workflow
* @concrete-extensible
*/
class ArcanistFeatureWorkflow extends ArcanistBaseWorkflow {
private $branches;
public function getWorkflowName() {
return 'feature';
}
public function getCommandSynopses() {
return phutil_console_format(<<<EOTEXT
**feature** [__options__]
**feature** __name__ [__start__]
EOTEXT
);
}
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
Supports: git, hg
A wrapper on 'git branch' or 'hg bookmark'.
Without __name__, it lists the available branches and their revision
status.
With __name__, it creates or checks out a branch. If the branch
__name__ doesn't exist and is in format D123 then the branch of
revision D123 is checked out. Use __start__ to specify where the new
branch will start. Use 'arc.feature.start.default' to set the default
feature start location.
EOTEXT
);
}
public function requiresConduit() {
return true;
}
public function requiresRepositoryAPI() {
return true;
}
public function requiresAuthentication() {
return !$this->getArgument('names');
}
public function getArguments() {
return array(
'view-all' => array(
'help' => 'Include closed and abandoned revisions.',
),
'by-status' => array(
'help' => 'Sort branches by status instead of time.',
),
'*' => 'names',
);
}
public function run() {
$repository_api = $this->getRepositoryAPI();
if (!($repository_api instanceof ArcanistGitAPI) &&
!($repository_api instanceof ArcanistMercurialAPI)) {
throw new ArcanistUsageException(
'arc feature is only supported under Git and Mercurial.');
}
$names = $this->getArgument('names');
if ($names) {
if (count($names) > 2) {
throw new ArcanistUsageException("Specify only one branch.");
}
return $this->checkoutBranch($names);
}
$branches = $repository_api->getAllBranches();
if (!$branches) {
throw new ArcanistUsageException('No branches in this working copy.');
}
$branches = $this->loadCommitInfo($branches);
$revisions = $this->loadRevisions($branches);
$this->printBranches($branches, $revisions);
return 0;
}
private function checkoutBranch(array $names) {
$api = $this->getRepositoryAPI();
if ($api instanceof ArcanistMercurialAPI) {
$command = 'update %s';
} else {
$command = 'checkout %s';
}
$err = 1;
$name = $names[0];
if (isset($names[1])) {
$start = $names[1];
} else {
$start = $this->getWorkingCopy()->getConfigFromAnySource(
'arc.feature.start.default');
}
$branches = $api->getAllBranches();
if (in_array($name, ipull($branches, 'name'))) {
list($err, $stdout, $stderr) = $api->execManualLocal(
$command,
$name);
}
if ($err) {
$match = null;
if (preg_match('/^D(\d+)$/', $name, $match)) {
try {
$diff = $this->getConduit()->callMethodSynchronous(
'differential.getdiff',
array(
'revision_id' => $match[1],
));
if ($diff['branch'] != '') {
$name = $diff['branch'];
list($err, $stdout, $stderr) = $api->execManualLocal(
$command,
$name);
}
} catch (ConduitException $ex) {
}
}
}
if ($err) {
if ($api instanceof ArcanistMercurialAPI) {
$rev = '';
if ($start) {
$rev = csprintf('-r %s', $start);
}
$exec = $api->execManualLocal(
'bookmark %C %s',
$rev,
$name);
if (!$exec[0] && $start) {
$api->execxLocal('update %s', $name);
}
} else {
$startarg = $start ? csprintf('%s', $start) : '';
$exec = $api->execManualLocal(
'checkout --track -b %s %C',
$name,
$startarg);
}
list($err, $stdout, $stderr) = $exec;
}
echo $stdout;
fprintf(STDERR, $stderr);
return $err;
}
private function loadCommitInfo(array $branches) {
$repository_api = $this->getRepositoryAPI();
$futures = array();
foreach ($branches as $branch) {
if ($repository_api instanceof ArcanistMercurialAPI) {
$futures[$branch['name']] = $repository_api->execFutureLocal(
"log -l 1 --template '%C' -r %s",
"{node}\1{date|hgdate}\1{p1node}\1{desc|firstline}\1{desc}",
- hgsprintf($branch['name']));
+ hgsprintf('%s', $branch['name']));
} else {
// NOTE: "-s" is an option deep in git's diff argument parser that
// doesn't seem to have much documentation and has no long form. It
// suppresses any diff output.
$futures[$branch['name']] = $repository_api->execFutureLocal(
'show -s --format=%C %s --',
'%H%x01%ct%x01%T%x01%s%x01%s%n%n%b',
$branch['name']);
}
}
$branches = ipull($branches, null, 'name');
foreach (Futures($futures)->limit(16) as $name => $future) {
list($info) = $future->resolvex();
list($hash, $epoch, $tree, $desc, $text) = explode("\1", trim($info), 5);
$branch = $branches[$name];
$branch['hash'] = $hash;
$branch['desc'] = $desc;
try {
$message = ArcanistDifferentialCommitMessage::newFromRawCorpus($text);
$id = $message->getRevisionID();
$branch += array(
'epoch' => (int)$epoch,
'tree' => $tree,
'revisionID' => $id,
);
} catch (ArcanistUsageException $ex) {
// In case of invalid commit message which fails the parsing,
// do nothing.
}
$branches[$name] = $branch;
}
return $branches;
}
private function loadRevisions(array $branches) {
$ids = array();
$hashes = array();
foreach ($branches as $branch) {
if ($branch['revisionID']) {
$ids[] = $branch['revisionID'];
}
$hashes[] = array('gtcm', $branch['hash']);
$hashes[] = array('gttr', $branch['tree']);
}
$calls = array();
if ($ids) {
$calls[] = $this->getConduit()->callMethod(
'differential.query',
array(
'ids' => $ids,
));
}
if ($hashes) {
$calls[] = $this->getConduit()->callMethod(
'differential.query',
array(
'commitHashes' => $hashes,
));
}
$results = array();
foreach (Futures($calls) as $call) {
$results[] = $call->resolve();
}
return array_mergev($results);
}
private function printBranches(array $branches, array $revisions) {
$revisions = ipull($revisions, null, 'id');
static $color_map = array(
'Closed' => 'cyan',
'Needs Review' => 'magenta',
'Needs Revision' => 'red',
'Accepted' => 'green',
'No Revision' => 'blue',
'Abandoned' => 'default',
);
static $ssort_map = array(
'Closed' => 1,
'No Revision' => 2,
'Needs Review' => 3,
'Needs Revision' => 4,
'Accepted' => 5,
);
$out = array();
foreach ($branches as $branch) {
$revision = idx($revisions, idx($branch, 'revisionID'));
// If we haven't identified a revision by ID, try to identify it by hash.
if (!$revision) {
foreach ($revisions as $rev) {
$hashes = idx($rev, 'hashes', array());
foreach ($hashes as $hash) {
if (($hash[0] == 'gtcm' && $hash[1] == $branch['hash']) ||
($hash[0] == 'gttr' && $hash[1] == $branch['tree'])) {
$revision = $rev;
break;
}
}
}
}
if ($revision) {
$desc = 'D'.$revision['id'].': '.$revision['title'];
$status = $revision['statusName'];
} else {
$desc = $branch['desc'];
$status = 'No Revision';
}
if (!$this->getArgument('view-all') && !$branch['current']) {
if ($status == 'Closed' || $status == 'Abandoned') {
continue;
}
}
$epoch = $branch['epoch'];
$color = idx($color_map, $status, 'default');
$ssort = sprintf('%d%012d', idx($ssort_map, $status, 0), $epoch);
$out[] = array(
'name' => $branch['name'],
'current' => $branch['current'],
'status' => $status,
'desc' => $desc,
'color' => $color,
'esort' => $epoch,
'ssort' => $ssort,
);
}
$len_name = max(array_map('strlen', ipull($out, 'name'))) + 2;
$len_status = max(array_map('strlen', ipull($out, 'status'))) + 2;
if ($this->getArgument('by-status')) {
$out = isort($out, 'ssort');
} else {
$out = isort($out, 'esort');
}
$console = PhutilConsole::getConsole();
foreach ($out as $line) {
$color = $line['color'];
$console->writeOut(
"%s **%s** <fg:{$color}>%s</fg> %s\n",
$line['current'] ? '* ' : ' ',
str_pad($line['name'], $len_name),
str_pad($line['status'], $len_status),
$line['desc']);
}
}
}
diff --git a/src/workflow/ArcanistTasksWorkflow.php b/src/workflow/ArcanistTasksWorkflow.php
index 1e08a0d6..5aadd2cf 100644
--- a/src/workflow/ArcanistTasksWorkflow.php
+++ b/src/workflow/ArcanistTasksWorkflow.php
@@ -1,257 +1,262 @@
<?php
/**
* Displays User Tasks
*
* @group workflow
*/
final class ArcanistTasksWorkflow extends ArcanistBaseWorkflow {
private $tasks;
public function getWorkflowName() {
return 'tasks';
}
public function getCommandSynopses() {
return phutil_console_format(<<<EOTEXT
**tasks** [__options__]
EOTEXT
);
}
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
View all assigned tasks.
EOTEXT
);
}
public function requiresConduit() {
return true;
}
public function requiresRepositoryAPI() {
return false;
}
public function requiresAuthentication() {
return true;
}
public function getArguments() {
return array(
'status' => array(
'param' => 'task_status',
'help' => "Show tasks that or open or closed, default is open.",
),
'owner' => array(
'param' => 'username',
'paramtype' => 'username',
'help' =>
"Only show tasks assigned to the given username, ".
"also accepts @all to show all, default is you.",
'conflict' => array(
- "unassigned" => "--owner supresses unassigned",
+ "unassigned" => "--owner suppresses unassigned",
),
),
'order' => array(
'param' => 'task_order',
'help' =>
"Arrange tasks based on priority, created, or modified, ".
"default is priority.",
),
'limit' => array(
'param' => 'n',
'paramtype' => 'int',
'help' => "Limit the amount of tasks outputted, default is all.",
),
'unassigned' => array(
'help' => "Only show tasks that are not assigned (upforgrabs).",
)
);
}
public function run() {
$output = array();
$status = $this->getArgument('status');
$owner = $this->getArgument('owner');
$order = $this->getArgument('order');
$limit = $this->getArgument('limit');
$unassigned = $this->getArgument('unassigned');
if ($owner) {
- $ownerPHID = $this->findOwnerPhid($owner);
+ $owner_phid = $this->findOwnerPhid($owner);
} elseif ($unassigned) {
- $ownerPHID = null;
+ $owner_phid = null;
} else {
- $ownerPHID = $this->getUserPHID();
+ $owner_phid = $this->getUserPHID();
}
$this->tasks = $this->loadManiphestTasks(
($status == 'all' ? 'any' : $status),
- $ownerPHID,
+ $owner_phid,
$order,
$limit);
if (!$this->tasks) {
echo "No tasks found.\n";
return 0;
}
$task_rows = array();
foreach ($this->tasks as $task) {
$output = array();
// Render the "T123" column.
$task_id = "T".$task['id'];
$formatted_task_id = phutil_console_format(
'**%s**',
$task_id);
$output['id'] = array(
'text' => $formatted_task_id,
'len' => phutil_utf8_console_strlen($task_id),
);
// Render the "Title" column.
$formatted_title = rtrim($task['title']);
$output['title'] = array(
'text' => $formatted_title,
'len' => phutil_utf8_console_strlen($formatted_title),
);
// Render the "Priority" column.
switch ($task['priority']) {
case 'Needs Triage':
$color = 'magenta';
break;
case 'Unbreak Now!':
$color = 'red';
break;
case 'High':
$color = 'yellow';
break;
case 'Normal':
$color = 'green';
break;
case 'Low':
$color = 'blue';
break;
case 'Wishlist':
$color = 'cyan';
break;
default:
$color = 'white';
break;
}
$formatted_priority = phutil_console_format(
"<bg:{$color}> </bg> %s",
$task['priority']);
$output['priority'] = array(
'text' => $formatted_priority,
'len' => phutil_utf8_console_strlen($task['priority']) + 2,
);
// Render the "Status" column.
if ($task['status']) {
$status_text = 'Closed';
$status_color = 'red';
} else {
$status_text = 'Open';
$status_color = 'green';
}
$formatted_status = phutil_console_format(
"<bg:{$status_color}> </bg> %s",
$status_text);
$output['status'] = array(
'text' => $formatted_status,
'len' => phutil_utf8_console_strlen('status') + 2,
);
$task_rows[] = $output;
}
// Find the longest string in each column.
$col_size = array();
foreach ($task_rows as $row) {
foreach ($row as $key => $col) {
if (empty($col_size[$key])) {
$col_size[$key] = 0;
}
$col_size[$key] = max($col_size[$key], $col['len']);
}
}
// Determine the terminal width. If we can't figure it out, assume 80.
$width = nonempty(phutil_console_get_terminal_width(), 80);
// We're going to clip the titles so they'll all fit in one line on the
// terminal. Figure out where to clip them.
$padding_between_columns = 4;
$clip_title_at = max(
// Always show at least a little bit of text even if it will make the
// UI wrap, since it's useless if we don't show anything.
16,
$width -
($col_size['id'] + $col_size['priority'] + $col_size['status'] +
($padding_between_columns * 3)));
$col_size['title'] = min($col_size['title'], $clip_title_at);
foreach ($task_rows as $key => $cols) {
$new_title = phutil_utf8_shorten($cols['title']['text'], $clip_title_at);
$task_rows[$key]['title']['len'] = phutil_utf8_console_strlen($new_title);
$task_rows[$key]['title']['text'] = $new_title;
}
$table = array();
foreach ($task_rows as $row) {
$trow = array();
foreach ($row as $col => $cell) {
$text = $cell['text'];
$pad_len = $col_size[$col] - $cell['len'];
if ($pad_len) {
$text .= str_repeat(' ', $pad_len);
}
$trow[] = $text;
}
$table[] = implode(str_repeat(' ', $padding_between_columns), $trow);
}
$table = implode("\n", $table)."\n";
echo $table;
}
- private function findOwnerPhid($owner) {
+ private function findOwnerPHID($owner) {
$conduit = $this->getConduit();
+
$owner_phid = $conduit->callMethodSynchronous(
'user.find',
array(
'aliases' => array($owner),
));
- return (isset($owner_phid[$owner])?$owner_phid[$owner]:false);
+
+ return idx($owner_phid, $owner);
}
private function loadManiphestTasks($status, $owner_phid, $order, $limit) {
$conduit = $this->getConduit();
$find_params = array();
- if ($owner_phid !== false) {
+ if ($owner_phid !== null) {
$find_params['ownerPHIDs'] = array($owner_phid);
}
+
if ($limit !== false) {
$find_params['limit'] = $limit;
}
- $find_params['order'] = ($order?"order-".$order:"order-priority");
- $find_params['status'] = ($status?"status-".$status:"status-open");
+
+ $find_params['order'] = ($order ? "order-".$order : "order-priority");
+ $find_params['status'] = ($status ? "status-".$status : "status-open");
$tasks = $conduit->callMethodSynchronous(
'maniphest.find',
$find_params);
+
return $tasks;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 16:42 (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126584
Default Alt Text
(46 KB)

Event Timeline