예제 #1
0
 public function willLintPaths(array $paths)
 {
     // Load all file path data into $this->data.
     array_map(array($this, 'getData'), $paths);
     $conduit = new ConduitClient($this->conduitURI);
     $this->lintByPath = $conduit->callMethodSynchronous(self::CONDUIT_METHOD, array('file_contents' => $this->data));
 }
예제 #2
0
 public function run()
 {
     $argv = $this->getArgv();
     if (count($argv) !== 1) {
         throw new Exception("usage: PhabricatorIRCBot <json_config_file>");
     }
     $json_raw = Filesystem::readFile($argv[0]);
     $config = json_decode($json_raw, true);
     if (!is_array($config)) {
         throw new Exception("File '{$argv[0]}' is not valid JSON!");
     }
     $server = idx($config, 'server');
     $port = idx($config, 'port', 6667);
     $handlers = idx($config, 'handlers', array());
     $pass = idx($config, 'pass');
     $nick = idx($config, 'nick', 'phabot');
     $user = idx($config, 'user', $nick);
     $ssl = idx($config, 'ssl', false);
     $nickpass = idx($config, 'nickpass');
     $this->config = $config;
     if (!preg_match('/^[A-Za-z0-9_`[{}^|\\]\\-]+$/', $nick)) {
         throw new Exception("Nickname '{$nick}' is invalid!");
     }
     foreach ($handlers as $handler) {
         $obj = newv($handler, array($this));
         $this->handlers[] = $obj;
     }
     $conduit_uri = idx($config, 'conduit.uri');
     if ($conduit_uri) {
         $conduit_user = idx($config, 'conduit.user');
         $conduit_cert = idx($config, 'conduit.cert');
         $conduit = new ConduitClient($conduit_uri);
         $response = $conduit->callMethodSynchronous('conduit.connect', array('client' => 'PhabricatorIRCBot', 'clientVersion' => '1.0', 'clientDescription' => php_uname('n') . ':' . $nick, 'user' => $conduit_user, 'certificate' => $conduit_cert));
         $this->conduit = $conduit;
     }
     $errno = null;
     $error = null;
     if (!$ssl) {
         $socket = fsockopen($server, $port, $errno, $error);
     } else {
         $socket = fsockopen('ssl://' . $server, $port, $errno, $error);
     }
     if (!$socket) {
         throw new Exception("Failed to connect, #{$errno}: {$error}");
     }
     $ok = stream_set_blocking($socket, false);
     if (!$ok) {
         throw new Exception("Failed to set stream nonblocking.");
     }
     $this->socket = $socket;
     $this->writeCommand('USER', "{$user} 0 * :{$user}");
     if ($pass) {
         $this->writeCommand('PASS', "{$pass}");
     }
     if ($nickpass) {
         $this->writeCommand("NickServ IDENTIFY ", "{$nickpass}");
     }
     $this->writeCommand('NICK', "{$nick}");
     $this->runSelectLoop();
 }
 public function pullDataFromConduit(ConduitClient $conduit, $partial = false)
 {
     $result = $conduit->callMethodSynchronous('differential.parsecommitmessage', array('corpus' => $this->rawCorpus, 'partial' => $partial));
     $this->fields = $result['fields'];
     if (!empty($result['errors'])) {
         throw new ArcanistDifferentialCommitMessageParserException($result['errors']);
     }
     return $this;
 }
예제 #4
0
 protected function run()
 {
     $argv = $this->getArgv();
     if (count($argv) !== 1) {
         throw new Exception(pht('Usage: %s %s', __CLASS__, '<json_config_file>'));
     }
     $json_raw = Filesystem::readFile($argv[0]);
     try {
         $config = phutil_json_decode($json_raw);
     } catch (PhutilJSONParserException $ex) {
         throw new PhutilProxyException(pht("File '%s' is not valid JSON!", $argv[0]), $ex);
     }
     $nick = idx($config, 'nick', 'phabot');
     $handlers = idx($config, 'handlers', array());
     $protocol_adapter_class = idx($config, 'protocol-adapter', 'PhabricatorIRCProtocolAdapter');
     $this->pollFrequency = idx($config, 'poll-frequency', 1);
     $this->config = $config;
     foreach ($handlers as $handler) {
         $obj = newv($handler, array($this));
         $this->handlers[] = $obj;
     }
     $ca_bundle = idx($config, 'https.cabundle');
     if ($ca_bundle) {
         HTTPSFuture::setGlobalCABundleFromPath($ca_bundle);
     }
     $conduit_uri = idx($config, 'conduit.uri');
     if ($conduit_uri) {
         $conduit_token = idx($config, 'conduit.token');
         // Normalize the path component of the URI so users can enter the
         // domain without the "/api/" part.
         $conduit_uri = new PhutilURI($conduit_uri);
         $conduit_host = (string) $conduit_uri->setPath('/');
         $conduit_uri = (string) $conduit_uri->setPath('/api/');
         $conduit = new ConduitClient($conduit_uri);
         if ($conduit_token) {
             $conduit->setConduitToken($conduit_token);
         } else {
             $conduit_user = idx($config, 'conduit.user');
             $conduit_cert = idx($config, 'conduit.cert');
             $response = $conduit->callMethodSynchronous('conduit.connect', array('client' => __CLASS__, 'clientVersion' => '1.0', 'clientDescription' => php_uname('n') . ':' . $nick, 'host' => $conduit_host, 'user' => $conduit_user, 'certificate' => $conduit_cert));
         }
         $this->conduit = $conduit;
     }
     // Instantiate Protocol Adapter, for now follow same technique as
     // handler instantiation
     $this->protocolAdapter = newv($protocol_adapter_class, array());
     $this->protocolAdapter->setConfig($this->config)->connect();
     $this->runLoop();
     $this->protocolAdapter->disconnect();
 }
 public function run()
 {
     $uri = $this->determineConduitURI();
     echo "Installing certificate for '{$uri}'...\n";
     $config = self::readUserConfigurationFile();
     echo "Trying to connect to server...\n";
     $conduit = new ConduitClient($uri);
     try {
         $conduit->callMethodSynchronous('conduit.ping', array());
     } catch (Exception $ex) {
         throw new ArcanistUsageException("Failed to connect to server: " . $ex->getMessage());
     }
     echo "Connection OK!\n";
     $token_uri = new PhutilURI($uri);
     $token_uri->setPath('/conduit/token/');
     echo "\n";
     echo phutil_console_format("**LOGIN TO PHABRICATOR**\n");
     echo "Open this page in your browser and login to Phabricator if " . "necessary:\n";
     echo "\n";
     echo "    {$token_uri}\n";
     echo "\n";
     echo "Then paste the token on that page below.";
     do {
         $token = phutil_console_prompt('Paste token from that page:');
         $token = trim($token);
         if (strlen($token)) {
             break;
         }
     } while (true);
     echo "\n";
     echo "Downloading authentication certificate...\n";
     $info = $conduit->callMethodSynchronous('conduit.getcertificate', array('token' => $token, 'host' => $uri));
     $user = $info['username'];
     echo "Installing certificate for '{$user}'...\n";
     $config['hosts'][$uri] = array('user' => $user, 'cert' => $info['certificate']);
     echo "Writing ~/.arcrc...\n";
     self::writeUserConfigurationFile($config);
     echo phutil_console_format("<bg:green>** SUCCESS! **</bg> Certificate installed.\n");
     return 0;
 }
 private function loadBundleFromConduit(ConduitClient $conduit, $params)
 {
     $future = $conduit->callMethod('differential.getdiff', $params);
     $diff = $future->resolve();
     $changes = array();
     foreach ($diff['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setConduit($conduit);
     // since the conduit method has changes, assume that these fields
     // could be unset
     $bundle->setProjectID(idx($diff, 'projectName'));
     $bundle->setBaseRevision(idx($diff, 'sourceControlBaseRevision'));
     $bundle->setRevisionID(idx($diff, 'revisionID'));
     $bundle->setAuthorName(idx($diff, 'authorName'));
     $bundle->setAuthorEmail(idx($diff, 'authorEmail'));
     return $bundle;
 }
예제 #7
0
 private function loadBundleFromConduit(ConduitClient $conduit, $params)
 {
     $future = $conduit->callMethod('differential.getdiff', $params);
     $diff = $future->resolve();
     $changes = array();
     foreach ($diff['changes'] as $changedict) {
         $changes[] = ArcanistDiffChange::newFromDictionary($changedict);
     }
     $bundle = ArcanistBundle::newFromChanges($changes);
     $bundle->setConduit($conduit);
     $bundle->setProjectID($diff['projectName']);
     $bundle->setBaseRevision($diff['sourceControlBaseRevision']);
     $bundle->setRevisionID($diff['revisionID']);
     return $bundle;
 }
예제 #8
0
 private function executeMethod()
 {
     $user = $this->getUser();
     if (!$user) {
         $user = new PhabricatorUser();
     }
     $this->request->setUser($user);
     if (!$this->shouldRequireAuthentication()) {
         // No auth requirement here.
     } else {
         $allow_public = $this->handler->shouldAllowPublic() && PhabricatorEnv::getEnvConfig('policy.allow-public');
         if (!$allow_public) {
             if (!$user->isLoggedIn() && !$user->isOmnipotent()) {
                 // TODO: As per below, this should get centralized and cleaned up.
                 throw new ConduitException('ERR-INVALID-AUTH');
             }
         }
         // TODO: This would be slightly cleaner by just using a Query, but the
         // Conduit auth workflow requires the Call and User be built separately.
         // Just do it this way for the moment.
         $application = $this->handler->getApplication();
         if ($application) {
             $can_view = PhabricatorPolicyFilter::hasCapability($user, $application, PhabricatorPolicyCapability::CAN_VIEW);
             if (!$can_view) {
                 throw new ConduitException(pht('You do not have access to the application which provides this ' . 'API method.'));
             }
         }
     }
     if (!$this->shouldForceLocal() && $this->servers) {
         $server = $this->pickRandomServer($this->servers);
         $client = new ConduitClient($server);
         $params = $this->request->getAllParameters();
         $params['__conduit__']['isProxied'] = true;
         if ($this->handler->shouldRequireAuthentication()) {
             $client->callMethodSynchronous('conduit.connect', array('client' => 'PhabricatorConduit', 'clientVersion' => '1.0', 'user' => $this->getUser()->getUserName(), 'certificate' => $this->getUser()->getConduitCertificate(), '__conduit__' => $params['__conduit__']));
         }
         return $client->callMethodSynchronous($this->method, $params);
     } else {
         return $this->handler->executeMethod($this->request);
     }
 }
 /**
  * Authenticate the client making the request to a Phabricator user account.
  *
  * @param   ConduitAPIRequest Request being executed.
  * @param   dict              Request metadata.
  * @return  null|pair         Null to indicate successful authentication, or
  *                            an error code and error message pair.
  */
 private function authenticateUser(ConduitAPIRequest $api_request, array $metadata)
 {
     $request = $this->getRequest();
     if ($request->getUser()->getPHID()) {
         $request->validateCSRF();
         return $this->validateAuthenticatedUser($api_request, $request->getUser());
     }
     $auth_type = idx($metadata, 'auth.type');
     if ($auth_type === ConduitClient::AUTH_ASYMMETRIC) {
         $host = idx($metadata, 'auth.host');
         if (!$host) {
             return array('ERR-INVALID-AUTH', pht('Request is missing required "%s" parameter.', 'auth.host'));
         }
         // TODO: Validate that we are the host!
         $raw_key = idx($metadata, 'auth.key');
         $public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($raw_key);
         $ssl_public_key = $public_key->toPKCS8();
         // First, verify the signature.
         try {
             $protocol_data = $metadata;
             // TODO: We should stop writing this into the protocol data when
             // processing a request.
             unset($protocol_data['scope']);
             ConduitClient::verifySignature($this->method, $api_request->getAllParameters(), $protocol_data, $ssl_public_key);
         } catch (Exception $ex) {
             return array('ERR-INVALID-AUTH', pht('Signature verification failure. %s', $ex->getMessage()));
         }
         // If the signature is valid, find the user or device which is
         // associated with this public key.
         $stored_key = id(new PhabricatorAuthSSHKeyQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withKeys(array($public_key))->executeOne();
         if (!$stored_key) {
             return array('ERR-INVALID-AUTH', pht('No user or device is associated with that public key.'));
         }
         $object = $stored_key->getObject();
         if ($object instanceof PhabricatorUser) {
             $user = $object;
         } else {
             if (!$stored_key->getIsTrusted()) {
                 return array('ERR-INVALID-AUTH', pht('The key which signed this request is not trusted. Only ' . 'trusted keys can be used to sign API calls.'));
             }
             if (!PhabricatorEnv::isClusterRemoteAddress()) {
                 return array('ERR-INVALID-AUTH', pht('This request originates from outside of the Phabricator ' . 'cluster address range. Requests signed with trusted ' . 'device keys must originate from within the cluster.'));
             }
             $user = PhabricatorUser::getOmnipotentUser();
             // Flag this as an intracluster request.
             $api_request->setIsClusterRequest(true);
         }
         return $this->validateAuthenticatedUser($api_request, $user);
     } else {
         if ($auth_type === null) {
             // No specified authentication type, continue with other authentication
             // methods below.
         } else {
             return array('ERR-INVALID-AUTH', pht('Provided "%s" ("%s") is not recognized.', 'auth.type', $auth_type));
         }
     }
     $token_string = idx($metadata, 'token');
     if (strlen($token_string)) {
         if (strlen($token_string) != 32) {
             return array('ERR-INVALID-AUTH', pht('API token "%s" has the wrong length. API tokens should be ' . '32 characters long.', $token_string));
         }
         $type = head(explode('-', $token_string));
         $valid_types = PhabricatorConduitToken::getAllTokenTypes();
         $valid_types = array_fuse($valid_types);
         if (empty($valid_types[$type])) {
             return array('ERR-INVALID-AUTH', pht('API token "%s" has the wrong format. API tokens should be ' . '32 characters long and begin with one of these prefixes: %s.', $token_string, implode(', ', $valid_types)));
         }
         $token = id(new PhabricatorConduitTokenQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withTokens(array($token_string))->withExpired(false)->executeOne();
         if (!$token) {
             $token = id(new PhabricatorConduitTokenQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withTokens(array($token_string))->withExpired(true)->executeOne();
             if ($token) {
                 return array('ERR-INVALID-AUTH', pht('API token "%s" was previously valid, but has expired.', $token_string));
             } else {
                 return array('ERR-INVALID-AUTH', pht('API token "%s" is not valid.', $token_string));
             }
         }
         // If this is a "cli-" token, it expires shortly after it is generated
         // by default. Once it is actually used, we extend its lifetime and make
         // it permanent. This allows stray tokens to get cleaned up automatically
         // if they aren't being used.
         if ($token->getTokenType() == PhabricatorConduitToken::TYPE_COMMANDLINE) {
             if ($token->getExpires()) {
                 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
                 $token->setExpires(null);
                 $token->save();
                 unset($unguarded);
             }
         }
         // If this is a "clr-" token, Phabricator must be configured in cluster
         // mode and the remote address must be a cluster node.
         if ($token->getTokenType() == PhabricatorConduitToken::TYPE_CLUSTER) {
             if (!PhabricatorEnv::isClusterRemoteAddress()) {
                 return array('ERR-INVALID-AUTH', pht('This request originates from outside of the Phabricator ' . 'cluster address range. Requests signed with cluster API ' . 'tokens must originate from within the cluster.'));
             }
             // Flag this as an intracluster request.
             $api_request->setIsClusterRequest(true);
         }
         $user = $token->getObject();
         if (!$user instanceof PhabricatorUser) {
             return array('ERR-INVALID-AUTH', pht('API token is not associated with a valid user.'));
         }
         return $this->validateAuthenticatedUser($api_request, $user);
     }
     // handle oauth
     $access_token = idx($metadata, 'access_token');
     $method_scope = idx($metadata, 'scope');
     if ($access_token && $method_scope != PhabricatorOAuthServerScope::SCOPE_NOT_ACCESSIBLE) {
         $token = id(new PhabricatorOAuthServerAccessToken())->loadOneWhere('token = %s', $access_token);
         if (!$token) {
             return array('ERR-INVALID-AUTH', pht('Access token does not exist.'));
         }
         $oauth_server = new PhabricatorOAuthServer();
         $valid = $oauth_server->validateAccessToken($token, $method_scope);
         if (!$valid) {
             return array('ERR-INVALID-AUTH', pht('Access token is invalid.'));
         }
         // valid token, so let's log in the user!
         $user_phid = $token->getUserPHID();
         $user = id(new PhabricatorUser())->loadOneWhere('phid = %s', $user_phid);
         if (!$user) {
             return array('ERR-INVALID-AUTH', pht('Access token is for invalid user.'));
         }
         return $this->validateAuthenticatedUser($api_request, $user);
     }
     // Handle sessionless auth.
     // TODO: This is super messy.
     // TODO: Remove this in favor of token-based auth.
     if (isset($metadata['authUser'])) {
         $user = id(new PhabricatorUser())->loadOneWhere('userName = %s', $metadata['authUser']);
         if (!$user) {
             return array('ERR-INVALID-AUTH', pht('Authentication is invalid.'));
         }
         $token = idx($metadata, 'authToken');
         $signature = idx($metadata, 'authSignature');
         $certificate = $user->getConduitCertificate();
         $hash = sha1($token . $certificate);
         if (!phutil_hashes_are_identical($hash, $signature)) {
             return array('ERR-INVALID-AUTH', pht('Authentication is invalid.'));
         }
         return $this->validateAuthenticatedUser($api_request, $user);
     }
     // Handle session-based auth.
     // TODO: Remove this in favor of token-based auth.
     $session_key = idx($metadata, 'sessionKey');
     if (!$session_key) {
         return array('ERR-INVALID-SESSION', pht('Session key is not present.'));
     }
     $user = id(new PhabricatorAuthSessionEngine())->loadUserForSession(PhabricatorAuthSession::TYPE_CONDUIT, $session_key);
     if (!$user) {
         return array('ERR-INVALID-SESSION', pht('Session key is invalid.'));
     }
     return $this->validateAuthenticatedUser($api_request, $user);
 }
 public function pingConduit()
 {
     // It's fairly common to have issues here, e.g. because Phabricator isn't
     // running, isn't accessible, you put the domain in your hostsfile but it
     // isn't available on the production host, etc. If any of this doesn't work,
     // conduit will throw.
     // We do this here rather than in the daemon since there's an HTTPS + curl
     // + fork issue of some kind that makes
     $conduit = new ConduitClient(PhabricatorEnv::getURI('/api/'));
     $conduit->setTimeout(5);
     $conduit->callMethodSynchronous('conduit.ping', array());
 }
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     // We don't have much to go on in SVN, look for revisions that came from
     // this directory and belong to the same project.
     $project = $this->getWorkingCopyIdentity()->getProjectID();
     if (!$project) {
         return array();
     }
     $results = $conduit->callMethodSynchronous('differential.query', $query + array('arcanistProjects' => array($project)));
     foreach ($results as $key => $result) {
         if ($result['sourcePath'] != $this->getPath()) {
             unset($results[$key]);
         }
     }
     foreach ($results as $key => $result) {
         $results[$key]['why'] = "Matching arcanist project name and working copy directory path.";
     }
     return $results;
 }
 public function testConduitRequestEncoding()
 {
     $input = array('z' => array('nothing' => null, 'emptystring' => ''), 'empty' => array(), 'list' => array(15, 'quack', true, false), 'a' => array('key' => 'value', 'key2' => 'value2'));
     $expect = 'O4:S1:aO2:S3:keyS5:valueS4:key2S6:value2S5:emptyA0:S4:listA4:I2:15' . 'S5:quackB1:B0:S1:zO2:S11:emptystringS0:S7:nothingN:';
     $this->assertEqual($expect, ConduitClient::encodeRawDataForSignature($input));
 }
<?php

require_once __DIR__ . '/vendor/libphutil/src/__phutil_library_init__.php';
require_once __DIR__ . '/vendor/autoload.php';
if (count($argv) < 3) {
    echo "Usage: php maniphest_bulk_add.php project_id /path/to/tasks_file\n";
    exit(1);
}
$project = $argv[1];
$tasksFile = $argv[2];
$config = Symfony\Component\Yaml\Yaml::parse(file_get_contents(__DIR__ . '/config.yml'));
$conduit = new ConduitClient($config['PHABRICATOR_URL']);
$conduit->callMethodSynchronous('conduit.connect', ['client' => 'Maniphest Bulk Add', 'clientVersion' => 1, 'user' => $config['USER'], 'certificate' => $config['CONDUIT_CERTIFICATE']]);
$projectQuery = $conduit->callMethodSynchronous('project.query', ['ids' => [$project]]);
if (empty($projectQuery['data'])) {
    echo "Could not find project {$project}";
    exit(1);
}
$targetProject = reset($projectQuery['data']);
$taskIDs = array_filter(array_map(function ($line) {
    preg_match("/\\d+\$/", $line, $matches);
    if (!empty($matches)) {
        return $matches[0];
    }
}, explode("\n", file_get_contents($tasksFile))));
$tasks = $conduit->callMethodSynchronous('maniphest.query', ['ids' => $taskIDs]);
if (count($tasks) !== count($taskIDs)) {
    echo "Couldn't find all the tasks. Aborting :(\n";
    exit(1);
}
foreach ($tasks as $task) {
예제 #14
0
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     $results = $conduit->callMethodSynchronous('differential.query', $query);
     foreach ($results as $key => $result) {
         if ($result['sourcePath'] != $this->getPath()) {
             unset($results[$key]);
         }
     }
     foreach ($results as $key => $result) {
         $results[$key]['why'] = pht('Matching working copy directory path.');
     }
     return $results;
 }
예제 #15
0
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     $messages = $this->getGitCommitLog();
     if (!strlen($messages)) {
         return array();
     }
     $parser = new ArcanistDiffParser();
     $messages = $parser->parseDiff($messages);
     // First, try to find revisions by explicit revision IDs in commit messages.
     $revision_ids = array();
     foreach ($messages as $message) {
         $object = ArcanistDifferentialCommitMessage::newFromRawCorpus($message->getMetadata('message'));
         if ($object->getRevisionID()) {
             $revision_ids[] = $object->getRevisionID();
         }
     }
     if ($revision_ids) {
         $results = $conduit->callMethodSynchronous('differential.query', $query + array('ids' => $revision_ids));
         return $results;
     }
     // If we didn't succeed, try to find revisions by hash.
     $hashes = array();
     foreach ($this->getLocalCommitInformation() as $commit) {
         $hashes[] = array('gtcm', $commit['commit']);
         $hashes[] = array('gttr', $commit['tree']);
     }
     $results = $conduit->callMethodSynchronous('differential.query', $query + array('commitHashes' => $hashes));
     return $results;
 }
 public function pingConduit()
 {
     // It's fairly common to have issues here, e.g. because Phabricator isn't
     // running, isn't accessible, you put the domain in your hostsfile but it
     // isn't available on the production host, etc. If any of this doesn't work,
     // conduit will throw.
     $conduit = new ConduitClient(PhabricatorEnv::getURI('/api/'));
     $conduit->callMethodSynchronous('conduit.ping', array());
 }
예제 #17
0
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     // Try to find revisions by hash.
     $hashes = array();
     foreach ($this->getLocalCommitInformation() as $commit) {
         $hashes[] = array('hgcm', $commit['rev']);
     }
     $results = $conduit->callMethodSynchronous('differential.query', $query + array('commitHashes' => $hashes));
     return $results;
 }
예제 #18
0
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     $messages = $this->getCommitMessageLog();
     $parser = new ArcanistDiffParser();
     // First, try to find revisions by explicit revision IDs in commit messages.
     $reason_map = array();
     $revision_ids = array();
     foreach ($messages as $node_id => $message) {
         $object = ArcanistDifferentialCommitMessage::newFromRawCorpus($message);
         if ($object->getRevisionID()) {
             $revision_ids[] = $object->getRevisionID();
             $reason_map[$object->getRevisionID()] = $node_id;
         }
     }
     if ($revision_ids) {
         $results = $conduit->callMethodSynchronous('differential.query', $query + array('ids' => $revision_ids));
         foreach ($results as $key => $result) {
             $hash = substr($reason_map[$result['id']], 0, 16);
             $results[$key]['why'] = pht("Commit message for '%s' has explicit 'Differential Revision'.", $hash);
         }
         return $results;
     }
     // Try to find revisions by hash.
     $hashes = array();
     foreach ($this->getLocalCommitInformation() as $commit) {
         $hashes[] = array('hgcm', $commit['commit']);
     }
     if ($hashes) {
         // NOTE: In the case of "arc diff . --uncommitted" in a Mercurial working
         // copy with dirty changes, there may be no local commits.
         $results = $conduit->callMethodSynchronous('differential.query', $query + array('commitHashes' => $hashes));
         foreach ($results as $key => $hash) {
             $results[$key]['why'] = pht('A mercurial commit hash in the commit range is already attached ' . 'to the Differential revision.');
         }
         return $results;
     }
     return array();
 }
예제 #19
0
 public function loadWorkingCopyDifferentialRevisions(ConduitClient $conduit, array $query)
 {
     $messages = $this->getGitCommitLog();
     if (!strlen($messages)) {
         return array();
     }
     $parser = new ArcanistDiffParser();
     $messages = $parser->parseDiff($messages);
     // First, try to find revisions by explicit revision IDs in commit messages.
     $reason_map = array();
     $revision_ids = array();
     foreach ($messages as $message) {
         $object = ArcanistDifferentialCommitMessage::newFromRawCorpus($message->getMetadata('message'));
         if ($object->getRevisionID()) {
             $revision_ids[] = $object->getRevisionID();
             $reason_map[$object->getRevisionID()] = $message->getCommitHash();
         }
     }
     if ($revision_ids) {
         $results = $conduit->callMethodSynchronous('differential.query', $query + array('ids' => $revision_ids));
         foreach ($results as $key => $result) {
             $hash = substr($reason_map[$result['id']], 0, 16);
             $results[$key]['why'] = "Commit message for '{$hash}' has explicit 'Differential Revision'.";
         }
         return $results;
     }
     // If we didn't succeed, try to find revisions by hash.
     $hashes = array();
     foreach ($this->getLocalCommitInformation() as $commit) {
         $hashes[] = array('gtcm', $commit['commit']);
         $hashes[] = array('gttr', $commit['tree']);
     }
     $results = $conduit->callMethodSynchronous('differential.query', $query + array('commitHashes' => $hashes));
     foreach ($results as $key => $result) {
         $results[$key]['why'] = 'A git commit or tree hash in the commit range is already attached ' . 'to the Differential revision.';
     }
     return $results;
 }
예제 #20
0
파일: index.php 프로젝트: egig/rephort
<?php

use Rych\Silex\Provider\PlatesServiceProvider;
require_once __DIR__ . '/vendor/autoload.php';
$app = new Silex\Application(require_once __DIR__ . '/config.php');
require_once $app['libphutil_path'] . '/libphutil/src/__phutil_library_init__.php';
$_client = new ConduitClient($app['phabricator_url']);
$_client->setConduitToken($app['api_token']);
$_escaper = new Escaper();
$_template = new Template(__DIR__ . '/_tpl', $_escaper);
/* HOME redirect to /{year}/{date} */
$app->get('/', function () use($app) {
    $url = $app['request']->getBaseUrl() . '/' . date('Y') . '/' . date('n');
    return $app->redirect($url);
});
/* MAIN */
$app->get('/{year}/{month}', function ($year, $month) use($app, $_client, $_template) {
    $data['base_path'] = $app['request']->getBaseUrl();
    $data['year'] = $year;
    $data['month'] = $month;
    $data['users'] = $_client->callMethodSynchronous('user.query', []);
    $data['days'] = cal_days_in_month(CAL_GREGORIAN, $month, $year);
    return $_template->render('index', $data);
});
/* API to get json data */
$app->get('/api', function () use($app, $_client) {
    $users = $_client->callMethodSynchronous('user.query', []);
    $colors = ['#80E680', '#4D4DFF', '#E066A3', '#DB4D4D', '#FF944D', '#A38566', '#FFFF66'];
    $projectColors = [];
    foreach ($users as &$user) {
        $open_tasks = $_client->callMethodSynchronous('maniphest.query', ['status' => 'status-open', 'ownerPHIDs' => [$user['phid']]]);