diff --git a/.arcconfig b/.arcconfig index 2e452e56a..7a3efdff7 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,10 +1,10 @@ { "project_id" : "phabricator", - "conduit_uri" : "http://tools.epriestley-conduit.dev1557.facebook.com/api/", + "conduit_uri" : "http://local.aphront.com/api/", "lint_engine" : "PhutilLintEngine", "unit_engine" : "PhutilUnitTestEngine", "copyright_holder" : "Facebook, Inc.", "phutil_libraries" : { "phabricator" : "src/" } } diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 044b3158f..181cd51b8 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,191 +1,204 @@ array( 'Aphront404Response' => 'aphront/response/404', 'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration', 'AphrontController' => 'aphront/controller', 'AphrontDatabaseConnection' => 'storage/connection/base', 'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration', 'AphrontDefaultApplicationController' => 'aphront/default/controller', 'AphrontDialogResponse' => 'aphront/response/dialog', 'AphrontDialogView' => 'view/dialog', 'AphrontErrorView' => 'view/form/error', 'AphrontFileResponse' => 'aphront/response/file', 'AphrontFormControl' => 'view/form/control/base', 'AphrontFormFileControl' => 'view/form/control/file', 'AphrontFormSelectControl' => 'view/form/control/select', 'AphrontFormStaticControl' => 'view/form/control/static', 'AphrontFormSubmitControl' => 'view/form/control/submit', 'AphrontFormTextAreaControl' => 'view/form/control/textarea', 'AphrontFormTextControl' => 'view/form/control/text', 'AphrontFormView' => 'view/form/base', 'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql', 'AphrontNullView' => 'view/null', 'AphrontPageView' => 'view/page/base', 'AphrontPanelView' => 'view/layout/panel', 'AphrontQueryConnectionException' => 'storage/exception/connection', 'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost', 'AphrontQueryCountException' => 'storage/exception/count', 'AphrontQueryException' => 'storage/exception/base', 'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing', 'AphrontQueryParameterException' => 'storage/exception/parameter', 'AphrontQueryRecoverableException' => 'storage/exception/recoverable', 'AphrontRedirectResponse' => 'aphront/response/redirect', 'AphrontRequest' => 'aphront/request', 'AphrontResponse' => 'aphront/response/base', 'AphrontSideNavView' => 'view/layout/sidenav', 'AphrontTableView' => 'view/control/table', 'AphrontURIMapper' => 'aphront/mapper', 'AphrontView' => 'view/base', 'AphrontWebpageResponse' => 'aphront/response/webpage', 'ConduitAPIMethod' => 'applications/conduit/method/base', 'ConduitAPIRequest' => 'applications/conduit/protocol/request', + 'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff', 'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload', 'ConduitException' => 'applications/conduit/protocol/exception', 'DifferentialAction' => 'applications/differential/constants/action', 'DifferentialChangeType' => 'applications/differential/constants/changetype', + 'DifferentialChangeset' => 'applications/differential/storage/changeset', + 'DifferentialDAO' => 'applications/differential/storage/base', + 'DifferentialDiff' => 'applications/differential/storage/diff', + 'DifferentialHunk' => 'applications/differential/storage/hunk', 'DifferentialLintStatus' => 'applications/differential/constants/lintstatus', + 'DifferentialRevision' => 'applications/differential/storage/revision', + 'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem', 'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'LiskDAO' => 'storage/lisk/dao', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/api', 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console', 'PhabricatorConduitController' => 'applications/conduit/controller/base', 'PhabricatorConduitDAO' => 'applications/conduit/storage/base', 'PhabricatorConduitLogController' => 'applications/conduit/controller/log', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog', 'PhabricatorController' => 'applications/base/controller/base', 'PhabricatorDirectoryCategory' => 'applications/directory/storage/category', 'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete', 'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit', 'PhabricatorDirectoryCategoryListController' => 'applications/directory/controller/categorylist', 'PhabricatorDirectoryController' => 'applications/directory/controller/base', 'PhabricatorDirectoryDAO' => 'applications/directory/storage/base', 'PhabricatorDirectoryItem' => 'applications/directory/storage/item', 'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete', 'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit', 'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist', 'PhabricatorDirectoryMainController' => 'applications/directory/controller/main', 'PhabricatorFile' => 'applications/files/storage/file', 'PhabricatorFileController' => 'applications/files/controller/base', 'PhabricatorFileDAO' => 'applications/files/storage/base', 'PhabricatorFileListController' => 'applications/files/controller/list', 'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob', 'PhabricatorFileUploadController' => 'applications/files/controller/upload', 'PhabricatorFileViewController' => 'applications/files/controller/view', 'PhabricatorLiskDAO' => 'applications/base/storage/lisk', 'PhabricatorPHID' => 'applications/phid/storage/phid', 'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate', 'PhabricatorPHIDController' => 'applications/phid/controller/base', 'PhabricatorPHIDDAO' => 'applications/phid/storage/base', 'PhabricatorPHIDListController' => 'applications/phid/controller/list', 'PhabricatorPHIDType' => 'applications/phid/storage/type', 'PhabricatorPHIDTypeEditController' => 'applications/phid/controller/typeedit', 'PhabricatorPHIDTypeListController' => 'applications/phid/controller/typelist', 'PhabricatorPeopleController' => 'applications/people/controller/base', 'PhabricatorPeopleEditController' => 'applications/people/controller/edit', 'PhabricatorPeopleListController' => 'applications/people/controller/list', 'PhabricatorPeopleProfileController' => 'applications/people/controller/profile', 'PhabricatorStandardPageView' => 'view/page/standard', 'PhabricatorUser' => 'applications/people/storage/user', 'PhabricatorUserDAO' => 'applications/people/storage/base', ), 'function' => array( '_qsprintf_check_scalar_type' => 'storage/qsprintf', '_qsprintf_check_type' => 'storage/qsprintf', 'qsprintf' => 'storage/qsprintf', 'queryfx' => 'storage/queryfx', 'queryfx_all' => 'storage/queryfx', 'queryfx_one' => 'storage/queryfx', 'vqsprintf' => 'storage/qsprintf', 'vqueryfx' => 'storage/queryfx', 'xsprintf_query' => 'storage/qsprintf', ), 'requires_class' => array( 'Aphront404Response' => 'AphrontResponse', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDefaultApplicationController' => 'AphrontController', 'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogView' => 'AphrontView', 'AphrontErrorView' => 'AphrontView', 'AphrontFileResponse' => 'AphrontResponse', 'AphrontFormControl' => 'AphrontView', 'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormSelectControl' => 'AphrontFormControl', 'AphrontFormStaticControl' => 'AphrontFormControl', 'AphrontFormSubmitControl' => 'AphrontFormControl', 'AphrontFormTextAreaControl' => 'AphrontFormControl', 'AphrontFormTextControl' => 'AphrontFormControl', 'AphrontFormView' => 'AphrontView', 'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontNullView' => 'AphrontView', 'AphrontPageView' => 'AphrontView', 'AphrontPanelView' => 'AphrontView', 'AphrontQueryConnectionException' => 'AphrontQueryException', 'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException', 'AphrontQueryCountException' => 'AphrontQueryException', 'AphrontQueryObjectMissingException' => 'AphrontQueryException', 'AphrontQueryParameterException' => 'AphrontQueryException', 'AphrontQueryRecoverableException' => 'AphrontQueryException', 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontSideNavView' => 'AphrontView', 'AphrontTableView' => 'AphrontView', 'AphrontWebpageResponse' => 'AphrontResponse', + 'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod', + 'DifferentialChangeset' => 'DifferentialDAO', + 'DifferentialDAO' => 'PhabricatorLiskDAO', + 'DifferentialDiff' => 'DifferentialDAO', + 'DifferentialHunk' => 'DifferentialDAO', + 'DifferentialRevision' => 'DifferentialDAO', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO', 'PhabricatorController' => 'AphrontController', 'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryController' => 'PhabricatorController', 'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController', 'PhabricatorFile' => 'PhabricatorFileDAO', 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileViewController' => 'PhabricatorFileController', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorPHID' => 'PhabricatorPHIDDAO', 'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController', 'PhabricatorPHIDController' => 'PhabricatorController', 'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO', 'PhabricatorPHIDListController' => 'PhabricatorPHIDController', 'PhabricatorPHIDType' => 'PhabricatorPHIDDAO', 'PhabricatorPHIDTypeEditController' => 'PhabricatorPHIDController', 'PhabricatorPHIDTypeListController' => 'PhabricatorPHIDController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorStandardPageView' => 'AphrontPageView', 'PhabricatorUser' => 'PhabricatorUserDAO', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', ), 'requires_interface' => array( ), )); diff --git a/src/applications/conduit/method/differential/creatediff/ConduitAPI_differential_creatediff_Method.php b/src/applications/conduit/method/differential/creatediff/ConduitAPI_differential_creatediff_Method.php new file mode 100644 index 000000000..63bc4d7ba --- /dev/null +++ b/src/applications/conduit/method/differential/creatediff/ConduitAPI_differential_creatediff_Method.php @@ -0,0 +1,134 @@ + 'required list', + 'sourceMachine' => 'required string', + 'sourcePath' => 'required string', + 'branch' => 'required string', + 'sourceControlSystem' => 'required enum', + 'sourceControlPath' => 'required string', + 'sourceControlBaseRevision' => 'required string', + 'parentRevisionID' => 'optional revisionid', + 'creationMethod' => 'optional string', + 'ownerPHID' => 'optional phid', + 'arcanistProject' => 'optional string', + 'lintStatus' => + 'required enum', + 'unitStatus' => + 'required enum', + ); + } + + public function defineReturnType() { + return 'nonempty dict'; + } + + public function defineErrorTypes() { + return array( + ); + } + + protected function execute(ConduitAPIRequest $request) { + $change_data = $request->getValue('changes'); + + $changes = array(); + foreach ($change_data as $dict) { + $changes[] = ArcanistDiffChange::newFromDictionary($dict); + } + + $diff = DifferentialDiff::newFromRawChanges($changes); + $diff->setSourcePath($request->getValue('sourcePath')); + $diff->setSourceMachine($request->getValue('sourceMachine')); + + $diff->setBranch($request->getValue('branch')); + $diff->setCreationMethod($request->getValue('creationMethod')); + $diff->setOwnerPHID($request->getValue('ownerPHID')); + + $parent_id = $request->getValue('parentRevisionID'); + if ($parent_id) { + $parent_rev = id(new DifferentialRevision())->load($parent_id); + if ($parent_rev) { + if ($parent_rev->getStatus() != DifferentialRevisionStatus::COMMITTED) { + $diff->setParentRevisionID($parent_id); + } + } + } + + $system = $request->getValue('sourceControlSystem'); + $diff->setSourceControlSystem($system); + $diff->setSourceControlPath($request->getValue('sourceControlPath')); + $diff->setSourceControlBaseRevision( + $request->getValue('sourceControlBaseRevision')); + + $diff->setArcanistProject($request->getValue('arcanistProject')); + + switch ($request->getValue('lintStatus')) { + case 'skip': + $diff->setLintStatus(DifferentialLintStatus::LINT_SKIP); + break; + case 'okay': + $diff->setLintStatus(DifferentialLintStatus::LINT_OKAY); + break; + case 'warn': + $diff->setLintStatus(DifferentialLintStatus::LINT_WARN); + break; + case 'fail': + $diff->setLintStatus(DifferentialLintStatus::LINT_FAIL); + break; + case 'none': + default: + $diff->setLintStatus(DifferentialLintStatus::LINT_NONE); + break; + } + + switch ($request->getValue('unitStatus')) { + case 'skip': + $diff->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP); + break; + case 'okay': + $diff->setUnitStatus(DifferentialUnitStatus::UNIT_OKAY); + break; + case 'warn': + $diff->setUnitStatus(DifferentialUnitStatus::UNIT_WARN); + break; + case 'fail': + $diff->setUnitStatus(DifferentialUnitStatus::UNIT_FAIL); + break; + case 'none': + default: + $diff->setUnitStatus(DifferentialUnitStatus::UNIT_NONE); + break; + } + + $diff->save(); + + return array( + 'diffid' => $diff->getID(), + 'uri' => '?'//$diff->getURI(), + ); + } + +} diff --git a/src/applications/conduit/method/differential/creatediff/__init__.php b/src/applications/conduit/method/differential/creatediff/__init__.php new file mode 100644 index 000000000..f43bd3996 --- /dev/null +++ b/src/applications/conduit/method/differential/creatediff/__init__.php @@ -0,0 +1,21 @@ + array( + 'metadata' => self::SERIALIZATION_JSON, + 'oldProperties' => self::SERIALIZATION_JSON, + 'newProperties' => self::SERIALIZATION_JSON, + 'awayPaths' => self::SERIALIZATION_JSON, + )) + parent::getConfiguration(); + } + + public function getAffectedLineCount() { + return $this->getAddLines() + $this->getDelLines(); + } + + public function getFileType() { + return $this->fileType; + } + + public function getChangeType() { + return $this->changeType; + } + + public function getDisplayFilename() { + $name = $this->getFilename(); + if ($this->getFileType() == DifferentialChangeType::FILE_DIRECTORY) { + $name .= '/'; + } + return $name; + } + + public function addHunk(DifferentialHunk $hunk) { + if (!isset($this->_hunks)) { + $this->_hunks = array(); + } + $this->_hunks[] = $hunk; + + return $this; + } + + public function attachHunks(array $hunks) { + $this->_hunks = $hunks; + return $this; + } + + public function getHunks() { + if (!isset($this->_hunks)) { + throw new Exception("You must load hunks before accessing them."); + } + return $this->_hunks; + } + + public function loadHunks() { + if (!$this->getID()) { + return array(); + } + return id(new DifferentialHunk())->loadAllWhere( + 'changesetID = %d', + $this->getID()); + } + + + public function delete() { + $this->openTransaction(); + foreach ($this->loadHunks() as $hunk) { + $hunk->delete(); + } + $this->_hunks = array(); + $ret = parent::delete(); + $this->saveTransaction(); + return $ret; + } + + public function getSortKey() { + $sort_key = $this->getFilename(); + // Sort files with ".h" in them first, so headers (.h, .hpp) come before + // implementations (.c, .cpp, .cs). + $sort_key = str_replace('.h', '.!h', $sort_key); + return $sort_key; + } + + public function makeNewFile() { + $file = array(); + foreach ($this->getHunks() as $hunk) { + $file[] = $hunk->makeNewFile(); + } + return implode("\n", $file); + } + + public function makeOldFile() { + $file = array(); + foreach ($this->getHunks() as $hunk) { + $file[] = $hunk->makeOldFile(); + } + return implode("\n", $file); + } + +} diff --git a/src/applications/differential/storage/changeset/__init__.php b/src/applications/differential/storage/changeset/__init__.php new file mode 100644 index 000000000..3b8085af0 --- /dev/null +++ b/src/applications/differential/storage/changeset/__init__.php @@ -0,0 +1,16 @@ +getID()) { + return array(); + } + return id(new DifferentialChangeset())->loadAllWhere( + 'diffID = %d', + $this->getID()); + } + + public function delete() { + $this->openTransaction(); + foreach ($this->loadChangesets() as $changeset) { + $changeset->delete(); + } + $ret = parent::delete(); + $this->saveTransaction(); + return $ret; + } + + public static function newFromRawChanges(array $changes) { + $diff = new DifferentialDiff(); + + $lines = 0; + foreach ($changes as $change) { + $changeset = new DifferentialChangeset(); + $add_lines = 0; + $del_lines = 0; + foreach ($change->getHunks() as $hunk) { + $dhunk = new Hunk(); + $dhunk->setOldOffset($hunk->getOldOffset()); + $dhunk->setOldLen($hunk->getOldLength()); + $dhunk->setNewOffset($hunk->getNewOffset()); + $dhunk->setNewLen($hunk->getNewLength()); + $dhunk->setChanges($hunk->getCorpus()); + $changeset->addHunk($dhunk); + $add_lines += $hunk->getAddLines(); + $del_lines += $hunk->getDelLines(); + $lines += $add_lines + $del_lines; + } + $changeset->setHunkCount(count($change->getHunks())); + + $changeset->setOldFile($change->getOldPath()); + $changeset->setNewFile($change->getCurrentPath()); + $changeset->setFilename($change->getCurrentPath()); + $changeset->setChangeType($change->getType()); + + $changeset->setFileType($change->getFileType()); + $changeset->setMetadata($change->getAllMetadata()); + $changeset->setOldProperties($change->getOldProperties()); + $changeset->setNewProperties($change->getNewProperties()); + $changeset->setAwayPaths($change->getAwayPaths()); + $changeset->setAddLines($add_lines); + $changeset->setDelLines($del_lines); + + $diff->addChangeset($changeset); + } + $diff->setLineCount($lines); + + return $diff; + } + +} diff --git a/src/applications/differential/storage/diff/__init__.php b/src/applications/differential/storage/diff/__init__.php new file mode 100644 index 000000000..95814ba1f --- /dev/null +++ b/src/applications/differential/storage/diff/__init__.php @@ -0,0 +1,15 @@ +makeContent($exclude = '-'); + } + + public function makeOldFile() { + return $this->makeContent($exclude = '+'); + } + + public function makeChanges() { + return $this->makeContent($exclude = ' '); + } + + final private function makeContent($exclude) { + $results = array(); + $lines = explode("\n", $this->changes); + foreach ($lines as $line) { + if (isset($line[0]) && $line[0] == $exclude) { + continue; + } + $results[] = substr($line, 1); + } + return implode("\n", $results); + } + +} diff --git a/src/applications/differential/storage/hunk/__init__.php b/src/applications/differential/storage/hunk/__init__.php new file mode 100644 index 000000000..6d095cc21 --- /dev/null +++ b/src/applications/differential/storage/hunk/__init__.php @@ -0,0 +1,12 @@ +setHost($host); $application->setPath($path); $request = $application->buildRequest(); $application->setRequest($request); list($controller, $uri_data) = $application->buildController(); $controller->willProcessRequest($uri_data); try { $response = $controller->processRequest(); } catch (Exception $ex) { $response = $application->handleException($ex); } $response = $application->willSendResponse($response); $response->setRequest($request); $response_string = $response->buildResponseString(); $headers = $response->getCacheHeaders(); $headers = array_merge($headers, $response->getHeaders()); foreach ($headers as $header) { list($header, $value) = $header; header("{$header}: {$value}"); } echo $response_string; /** * @group aphront */ function setup_aphront_basics() { $aphront_root = dirname(dirname(__FILE__)); $libraries_root = dirname($aphront_root); ini_set('include_path', ini_get('include_path').':'.$libraries_root.'/'); @include_once 'libphutil/src/__phutil_library_init__.php'; if (!@constant('__LIBPHUTIL__')) { echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ". "include the parent directory of libphutil/.\n"; exit(1); } if (!ini_get('date.timezone')) { date_default_timezone_set('America/Los_Angeles'); } + phutil_load_library($libraries_root.'/arcanist/src'); phutil_load_library($aphront_root.'/src'); } function __autoload($class_name) { PhutilSymbolLoader::loadClass($class_name); }