Page MenuHomestyx hydra

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/bin/ssh-auth-key b/bin/ssh-auth-key
new file mode 120000
index 0000000000..7dff83c316
--- /dev/null
+++ b/bin/ssh-auth-key
@@ -0,0 +1 @@
+../scripts/ssh/ssh-auth-key.php
\ No newline at end of file
diff --git a/conf/default.conf.php b/conf/default.conf.php
index 2a27da97d3..8291677b02 100644
--- a/conf/default.conf.php
+++ b/conf/default.conf.php
@@ -1,1161 +1,1154 @@
<?php
// IMPORTANT: DO NOT EDIT THIS FILE.
// This file is no longer read by default, and your efforts will have no effect.
// Follow the instructions in the documentation to configure Phabricator.
return array(
// The root URI which Phabricator is installed on.
// Example: "http://phabricator.example.com/"
'phabricator.base-uri' => null,
// If you have multiple environments, provide the production environment URI
// here so that emails, etc., generated in development/sandbox environments
// contain the right links.
'phabricator.production-uri' => null,
// -- IMPORTANT! Security! -------------------------------------------------- //
// IMPORTANT: By default, Phabricator serves files from the same domain the
// application lives on. This is convenient but not secure: it creates a large
// class of vulnerabilities which can not be generally mitigated.
//
// To avoid this, you should configure a second domain in the same way you
// have the primary domain configured (e.g., point it at the same machine and
// set up the same vhost rules) and provide it here. For instance, if your
// primary install is on "http://www.phabricator-example.com/", you could
// configure "http://www.phabricator-files.com/" and specify the entire
// domain (with protocol) here. This will enforce that files are
// served only from the alternate domain. Ideally, you should use a
// completely separate domain name rather than just a different subdomain.
//
// It is STRONGLY RECOMMENDED that you configure this. Your install is NOT
// SECURE unless you do so.
'security.alternate-file-domain' => null,
// Default key for HMAC digests where the key is not important (i.e., the
// hash itself is secret). You can change this if you want (to any other
// string), but doing so will break existing sessions and CSRF tokens.
'security.hmac-key' => '[D\t~Y7eNmnQGJ;rnH6aF;m2!vJ8@v8C=Cs:aQS\.Qw',
// If the web server responds to both HTTP and HTTPS requests but you want
// users to connect with only HTTPS, you can set this to true to make
// Phabricator redirect HTTP requests to HTTPS.
//
// Normally, you should just configure your server not to accept HTTP traffic,
// but this setting may be useful if you originally used HTTP and have now
// switched to HTTPS but don't want to break old links, or if your webserver
// sits behind a load balancer which terminates HTTPS connections and you
// can not reasonably configure more granular behavior there.
//
// NOTE: Phabricator determines if a request is HTTPS or not by examining the
// PHP $_SERVER['HTTPS'] variable. If you run Apache/mod_php this will
// probably be set correctly for you automatically, but if you run Phabricator
// as CGI/FCGI (e.g., through nginx or lighttpd), you need to configure your
// web server so that it passes the value correctly based on the connection
// type. Alternatively, you can add a PHP snippet to the top of this
// configuration file to directly set $_SERVER['HTTPS'] to the correct value.
'security.require-https' => false,
// Is Phabricator permitted to make outbound HTTP requests?
'security.allow-outbound-http' => true,
// -- Internationalization -------------------------------------------------- //
// This allows customizing texts used in Phabricator. The class must extend
// PhabricatorTranslation.
'translation.provider' => 'PhabricatorEnglishTranslation',
// You can use 'translation.override' if you don't want to create a full
// translation to give users an option for switching to it and you just want
// to override some strings in the default translation.
'translation.override' => array(),
// -- Access Policies ------------------------------------------------------- //
// Phabricator allows you to set the visibility of objects (like repositories
// and source code) to "Public", which means anyone on the internet can see
// them, even without being logged in. This is great for open source, but
// some installs may never want to make anything public, so this policy is
// disabled by default. You can enable it here, which will let you set the
// policy for objects to "Public". With this option disabled, the most open
// policy is "All Users", which means users must be logged in to view things.
'policy.allow-public' => false,
// -- Logging --------------------------------------------------------------- //
// To enable the Phabricator access log, specify a path here. The Phabricator
// access log can provide more detailed information about Phabricator access
// than normal HTTP access logs (for instance, it can show logged-in users,
// controllers, and other application data). If not set, no log will be
// written.
//
// Make sure the PHP process can write to the log!
'log.access.path' => null,
// Format for the access log. If not set, the default format will be used:
//
// "[%D]\t%h\t%u\t%M\t%C\t%m\t%U\t%c\t%T"
//
// Available variables are:
//
// - %c The HTTP response code.
// - %C The controller which handled the request.
// - %D The request date.
// - %e Epoch timestamp.
// - %h The webserver's host name.
// - %p The PID of the server process.
// - %R The HTTP referrer.
// - %r The remote IP.
// - %T The request duration, in microseconds.
// - %U The request path.
// - %u The logged-in username, if one is logged in.
// - %P The logged-in user PHID, if one is logged in.
// - %M The HTTP method.
// - %m For conduit, the Conduit method which was invoked.
//
// If a variable isn't available (for example, %m appears in the file format
// but the request is not a Conduit request), it will be rendered as "-".
//
// Note that the default format is subject to change in the future, so if you
// rely on the log's format, specify it explicitly.
'log.access.format' => null,
// -- DarkConsole ----------------------------------------------------------- //
// DarkConsole is a administrative debugging/profiling tool built into
// Phabricator. You can leave it disabled unless you're developing against
// Phabricator.
// Determines whether or not DarkConsole is available. DarkConsole exposes
// some data like queries and stack traces, so you should be careful about
// turning it on in production (although users can not normally see it, even
// if the deployment configuration enables it).
'darkconsole.enabled' => false,
// Always enable DarkConsole, even for logged out users. This potentially
// exposes sensitive information to users, so make sure untrusted users can
// not access an install running in this mode. You should definitely leave
// this off in production. It is only really useful for using DarkConsole
// utilities to debug or profile logged-out pages. You must set
// 'darkconsole.enabled' to use this option.
'darkconsole.always-on' => false,
// Map of additional configuration values to lock.
'config.lock' => array(),
// Map of additional configuration values to hide.
'config.hide' => array(),
// Map of additional configuration values to mask.
'config.mask' => array(),
// Ignore setup warnings of the following issues.
'config.ignore-issues' => array(),
// -- MySQL --------------------------------------------------------------- //
// Class providing database configuration. It must implement
// DatabaseConfigurationProvider.
'mysql.configuration-provider' => 'DefaultDatabaseConfigurationProvider',
// The username to use when connecting to MySQL.
'mysql.user' => 'root',
// The password to use when connecting to MySQL.
'mysql.pass' => '',
// The MySQL server to connect to.
'mysql.host' => 'localhost',
// If you want to connect to a different port than the default (which is 3306)
'mysql.port' => null,
// Phabricator supports PHP extensions MySQL and MySQLi. It is possible to
// implement also other access mechanism (e.g. PDO_MySQL). The class must
// extend AphrontMySQLDatabaseConnectionBase.
'mysql.implementation' => (extension_loaded('mysqli')
? 'AphrontMySQLiDatabaseConnection'
: 'AphrontMySQLDatabaseConnection'),
// -- Notifications --------------------------------------------------------- //
// Set this to true to enable real-time notifications. You must also run a
// notification server for this to work. Consult the documentation in
// "Notifications User Guide: Setup and Configuration" for instructions.
'notification.enabled' => false,
// Client port for the realtime server to listen on, and for realtime clients
// to connect to. Use "localhost" if you are running the notification server
// on the same host as the web server.
'notification.client-uri' => 'http://localhost:22280/',
// URI and port for the notification root server.
'notification.server-uri' => 'http://localhost:22281/',
// The server must be started as root so it can bind to privileged ports, but
// if you specify a user here it will drop permissions after binding.
'notification.user' => null,
// Location where the server should log to.
'notification.log' => '/var/log/aphlict.log',
// PID file to use.
'notification.pidfile' => '/var/run/aphlict.pid',
// Enable this option to get additional debug output in the browser.
'notification.debug' => false,
// -- Email ----------------------------------------------------------------- //
// Some Phabricator tools send email notifications, e.g. when Differential
// revisions are updated or Maniphest tasks are changed. These options allow
// you to configure how email is delivered.
// You can test your mail setup by going to "MetaMTA" in the web interface,
// clicking "Send New Message", and then composing a message.
// Default address to send mail "From".
'metamta.default-address' => 'noreply@example.com',
// Domain used to generate Message-IDs.
'metamta.domain' => 'example.com',
// When a message is sent to multiple recipients (for example, several
// reviewers on a code review), Phabricator can either deliver one email to
// everyone (e.g., "To: alincoln, usgrant, htaft") or separate emails to each
// user (e.g., "To: alincoln", "To: usgrant", "To: htaft"). The major
// advantages and disadvantages of each approach are:
//
// - One mail to everyone:
// - Recipients can see To/Cc at a glance.
// - If you use mailing lists, you won't get duplicate mail if you're
// a normal recipient and also Cc'd on a mailing list.
// - Getting threading to work properly is harder, and probably requires
// making mail less useful by turning off options.
// - Sometimes people will "Reply All" and everyone will get two mails,
// one from the user and one from Phabricator turning their mail into
// a comment.
// - Not supported with a private reply-to address.
// - Mails are sent in the server default translation.
// - One mail to each user:
// - Recipients need to look in the mail body to see To/Cc.
// - If you use mailing lists, recipients may sometimes get duplicate
// mail.
// - Getting threading to work properly is easier, and threading settings
// can be customzied by each user.
// - "Reply All" no longer spams all other users.
// - Required if private reply-to addresses are configured.
// - Mails are sent in the language of user preference.
//
// In the code, splitting one outbound email into one-per-recipient is
// sometimes referred to as "multiplexing".
'metamta.one-mail-per-recipient' => true,
// When sending a message that has no To recipient (i.e. all recipients
// are CC'd, for example when multiplexing mail), set the To field to the
// following value. If no value is set, messages with no To will have
// their CCs upgraded to To.
'metamta.placeholder-to-recipient' => null,
// When a user takes an action which generates an email notification (like
// commenting on a Differential revision), Phabricator can either send that
// mail "From" the user's email address (like "alincoln@logcabin.com") or
// "From" the 'metamta.default-address' address. The user experience is
// generally better if Phabricator uses the user's real address as the "From"
// since the messages are easier to organize when they appear in mail clients,
// but this will only work if the server is authorized to send email on behalf
// of the "From" domain. Practically, this means:
// - If you are doing an install for Example Corp and all the users will
// have corporate @corp.example.com addresses and any hosts Phabricator
// is running on are authorized to send email from corp.example.com,
// you can enable this to make the user experience a little better.
// - If you are doing an install for an open source project and your
// users will be registering via Facebook and using personal email
// addresses, you MUST NOT enable this or virtually all of your outgoing
// email will vanish into SFP blackholes.
// - If your install is anything else, you're much safer leaving this
// off since the risk in turning it on is that your outgoing mail will
// mostly never arrive.
'metamta.can-send-as-user' => false,
// Limit the maximum size of the body of an email generated for a diff
// (in bytes).
'metamta.email-body-limit' => 524288,
// Adapter class to use to transmit mail to the MTA. The default uses
// PHPMailerLite, which will invoke "sendmail". This is appropriate
// if sendmail actually works on your host, but if you haven't configured mail
// it may not be so great. A number of other mailers are available (e.g., SES,
// SendGrid, SMTP, custom mailers), consult "Configuring Outbound Email" in
// the documentation for details.
'metamta.mail-adapter' =>
'PhabricatorMailImplementationPHPMailerLiteAdapter',
// When email is sent, try to hand it off to the MTA immediately instead of
// queueing it for delivery by the daemons. If you are running the Phabricator
// daemons with "phd start", you should disable this to provide a (sometimes
// substantial) performance boost. It's on by default to make setup and
// configuration a little easier.
'metamta.send-immediately' => true,
// When email is sent, what format should Phabricator use for user's
// email addresses? Valid values are:
// - 'short' - 'gwashington <gwashington@example.com>'
// - 'real' - 'George Washington <gwashington@example.com>'
// - 'full' - 'gwashington (George Washington) <gwashington@example.com>'
// The default is 'full'.
'metamta.user-address-format' => 'full',
// If you're using PHPMailer to send email, provide the mailer and options
// here. PHPMailer is much more enormous than PHPMailerLite, and provides more
// mailers and greater enormity. You need it when you want to use SMTP
// instead of sendmail as the mailer.
'phpmailer.mailer' => 'smtp',
'phpmailer.smtp-host' => '',
'phpmailer.smtp-port' => 25,
// When using PHPMailer with SMTP, you can set this to one of "tls" or "ssl"
// to use TLS or SSL. Leave it blank for vanilla SMTP. If you're sending
// via Gmail, set it to "ssl".
'phpmailer.smtp-protocol' => '',
// Set following if your smtp server requires authentication.
'phpmailer.smtp-user' => null,
'phpmailer.smtp-password' => null,
// If you're using Amazon SES to send email, provide your AWS access key
// and AWS secret key here. To set up Amazon SES with Phabricator, you need
// to:
// - Make sure 'metamta.mail-adapter' is set to:
// "PhabricatorMailImplementationAmazonSESAdapter"
// - Make sure 'metamta.can-send-as-user' is false.
// - Make sure 'metamta.default-address' is configured to something sensible.
// - Make sure 'metamta.default-address' is a validated SES "From" address.
'amazon-ses.access-key' => null,
'amazon-ses.secret-key' => null,
// If you're using Sendgrid to send email, provide your access credentials
// here. This will use the REST API. You can also use Sendgrid as a normal
// SMTP service.
'sendgrid.api-user' => null,
'sendgrid.api-key' => null,
// You can configure a reply handler domain so that email sent from Maniphest
// will have a special "Reply To" address like "T123+82+af19f@example.com"
// that allows recipients to reply by email and interact with tasks. For
// instructions on configurating reply handlers, see the article
// "Configuring Inbound Email" in the Phabricator documentation. By default,
// this is set to 'null' and Phabricator will use a generic 'noreply@' address
// or the address of the acting user instead of a special reply handler
// address (see 'metamta.default-address'). If you set a domain here,
// Phabricator will begin generating private reply handler addresses. See
// also 'metamta.maniphest.reply-handler' to further configure behavior.
// This key should be set to the domain part after the @, like "example.com".
'metamta.maniphest.reply-handler-domain' => null,
// You can follow the instructions in "Configuring Inbound Email" in the
// Phabricator documentation and set 'metamta.maniphest.reply-handler-domain'
// to support updating Maniphest tasks by email. If you want more advanced
// customization than this provides, you can override the reply handler
// class with an implementation of your own. This will allow you to do things
// like have a single public reply handler or change how private reply
// handlers are generated and validated.
//
// This key should be set to a loadable subclass of
// PhabricatorMailReplyHandler.
'metamta.maniphest.reply-handler' => 'ManiphestReplyHandler',
// If you don't want phabricator to take up an entire domain
// (or subdomain for that matter), you can use this and set a common
// prefix for mail sent by phabricator. It will make use of the fact that
// a mail-address such as phabricator+D123+1hjk213h@example.com will be
// delivered to the phabricator users mailbox.
// Set this to the left part of the email address and it well get
// prepended to all outgoing mail. If you want to use e.g.
// 'phabricator@example.com' this should be set to 'phabricator'.
'metamta.single-reply-handler-prefix' => null,
// Prefix prepended to mail sent by Maniphest. You can change this to
// distinguish between testing and development installs, for example.
'metamta.maniphest.subject-prefix' => '[Maniphest]',
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing, but
// affects Pholio.
'metamta.pholio.reply-handler-domain' => null,
// Prefix prepended to mail sent by Pholio.
'metamta.pholio.subject-prefix' => '[Pholio]',
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing, but
// affects Macro.
'metamta.macro.reply-handler-domain' => null,
// Prefix prepended to mail sent by Macro.
'metamta.macro.subject-prefix' => '[Macro]',
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
// but allows email replies via Differential.
'metamta.differential.reply-handler-domain' => null,
// See 'metamta.maniphest.reply-handler'. This does the same thing, but
// affects Differential.
'metamta.differential.reply-handler' => 'DifferentialReplyHandler',
// Prefix prepended to mail sent by Differential.
'metamta.differential.subject-prefix' => '[Differential]',
// Set this to true if you want patches to be attached to mail from
// Differential. This won't work if you are using SendGrid as your mail
// adapter.
'metamta.differential.attach-patches' => false,
// To include patches in email bodies, set this to a positive integer. Patches
// will be inlined if they are at most that many lines. For instance, a value
// of 100 means "inline patches if they are no longer than 100 lines". By
// default, patches are not inlined.
'metamta.differential.inline-patches' => 0,
// If you enable either of the options above, you can choose what format
// patches are sent in. Valid options are 'unified' (like diff -u) or 'git'.
'metamta.differential.patch-format' => 'unified',
// Enables a different format for comments in differential emails.
// Differential will create unified diffs around the comment, which
// will give enough context for people who are only viewing the
// reviews in email to understand what is going on. The context will
// be created based on the range of the comment.
'metamta.differential.unified-comment-context' => false,
// Prefix prepended to mail sent by Diffusion.
'metamta.diffusion.subject-prefix' => '[Diffusion]',
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
// but allows email replies via Diffusion.
'metamta.diffusion.reply-handler-domain' => null,
// See 'metamta.maniphest.reply-handler'. This does the same thing, but
// affects Diffusion.
'metamta.diffusion.reply-handler' => 'PhabricatorAuditReplyHandler',
// Set this to true if you want patches to be attached to commit notifications
// from Diffusion. This won't work with SendGrid.
'metamta.diffusion.attach-patches' => false,
// To include patches in Diffusion email bodies, set this to a positive
// integer. Patches will be inlined if they are at most that many lines.
// By default, patches are not inlined.
'metamta.diffusion.inline-patches' => 0,
// If you've enabled attached patches or inline patches for commit emails, you
// can establish a hard byte limit on their size. You should generally set
// reasonable byte and time limits (defaults are 1MB and 60 seconds) to avoid
// sending ridiculously enormous email for changes like "importing an external
// library" or "accidentally committed this full-length movie as text".
'metamta.diffusion.byte-limit' => 1024 * 1024,
// If you've enabled attached patches or inline patches for commit emails, you
// can establish a hard time limit on generating them.
'metamta.diffusion.time-limit' => 60,
// Prefix prepended to mail sent by Package.
'metamta.package.subject-prefix' => '[Package]',
// See 'metamta.maniphest.reply-handler'. This does similar thing for package
// except that it only supports sending out mail and doesn't handle incoming
// email.
'metamta.package.reply-handler' => 'OwnersPackageReplyHandler',
// By default, Phabricator generates unique reply-to addresses and sends a
// separate email to each recipient when you enable reply handling. This is
// more secure than using "From" to establish user identity, but can mean
// users may receive multiple emails when they are on mailing lists. Instead,
// you can use a single, non-unique reply to address and authenticate users
// based on the "From" address by setting this to 'true'. This trades away
// a little bit of security for convenience, but it's reasonable in many
// installs. Object interactions are still protected using hashes in the
// single public email address, so objects can not be replied to blindly.
'metamta.public-replies' => false,
// You can configure an email address like "bugs@phabricator.example.com"
// which will automatically create Maniphest tasks when users send email
// to it. This relies on the "From" address to authenticate users, so it is
// is not completely secure. To set this up, enter a complete email
// address like "bugs@phabricator.example.com" and then configure mail to
// that address so it routed to Phabricator (if you've already configured
// reply handlers, you're probably already done). See "Configuring Inbound
// Email" in the documentation for more information.
'metamta.maniphest.public-create-email' => null,
// If you enable 'metamta.public-replies', Phabricator uses "From" to
// authenticate users. You can additionally enable this setting to try to
// authenticate with 'Reply-To'. Note that this is completely spoofable and
// insecure (any user can set any 'Reply-To' address) but depending on the
// nature of your install or other deliverability conditions this might be
// okay. Generally, you can't do much more by spoofing Reply-To than be
// annoying (you can write but not read content). But, you know, this is
// still **COMPLETELY INSECURE**.
'metamta.insecure-auth-with-reply-to' => false,
// If you enable 'metamta.maniphest.public-create-email' and create an
// email address like "bugs@phabricator.example.com", it will default to
// rejecting mail which doesn't come from a known user. However, you might
// want to let anyone send email to this address; to do so, set a default
// author here (a Phabricator username). A typical use of this might be to
// create a "System Agent" user called "bugs" and use that name here. If you
// specify a valid username, mail will always be accepted and used to create
// a task, even if the sender is not a system user. The original email
// address will be stored in an 'From Email' field on the task.
'metamta.maniphest.default-public-author' => null,
'metamta.herald.show-hints' => true,
// You can disable the hints under "REPLY HANDLER ACTIONS" if users prefer
// smaller messages. The actions themselves will still work properly.
'metamta.reply.show-hints' => true,
// You can disable the "To:" and "Cc:" footers in mail if users prefer
// smaller messages.
'metamta.recipients.show-hints' => true,
// If this option is enabled, Phabricator will add a "Precedence: bulk"
// header to transactional mail (e.g., Differential, Maniphest and Herald
// notifications). This may improve the behavior of some auto-responder
// software and prevent it from replying. However, it may also cause
// deliverability issues -- notably, you currently can not send this header
// via Amazon SES, and enabling this option with SES will prevent delivery
// of any affected mail.
'metamta.precedence-bulk' => false,
// Mail.app on OS X Lion won't respect threading headers unless the subject
// is prefixed with "Re:". If you enable this option, Phabricator will add
// "Re:" to the subject line of all mail which is expected to thread. If
// you've set 'metamta.one-mail-per-recipient', users can override this
// setting in their preferences.
'metamta.re-prefix' => false,
// If true, allow MetaMTA to change mail subjects to put text like
// '[Accepted]' and '[Commented]' in them. This makes subjects more useful,
// but might break threading on some clients. If you've set
// 'metamta.one-mail-per-recipient', users can override this setting in their
// preferences.
'metamta.vary-subjects' => true,
// -- Auth ------------------------------------------------------------------ //
// Maximum number of simultaneous web sessions each user is permitted to have.
// Setting this to "1" will prevent a user from logging in on more than one
// browser at the same time.
'auth.sessions.web' => 5,
// Maximum number of simultaneous Conduit sessions each user is permitted
// to have.
'auth.sessions.conduit' => 5,
- // Set this true to enable the Settings -> SSH Public Keys panel, which will
- // allow users to associated SSH public keys with their accounts. This is only
- // really useful if you're setting up services over SSH and want to use
- // Phabricator for authentication; in most situations you can leave this
- // disabled.
- 'auth.sshkeys.enabled' => false,
-
// If true, email addresses must be verified (by clicking a link in an
// email) before a user can login. By default, verification is optional
// unless 'auth.email-domains' is nonempty (see below).
'auth.require-email-verification' => false,
// You can restrict allowed email addresses to certain domains (like
// "yourcompany.com") by setting a list of allowed domains here. Users will
// only be allowed to register using email addresses at one of the domains,
// and will only be able to add new email addresses for these domains. If
// you configure this, it implies 'auth.require-email-verification'.
//
// To configure email domains, set a list of domains like this:
//
// array(
// 'yourcompany.com',
// 'yourcompany.co.uk',
// )
//
// You should omit the "@" from domains. Note that the domain must match
// exactly. If you allow "yourcompany.com", that permits "joe@yourcompany.com"
// but rejects "joe@mail.yourcompany.com".
'auth.email-domains' => array(),
// You can provide an arbitrary block of HTML here, which will appear on the
// login screen. Normally, you'd use this to provide login or registration
// instructions to users.
'auth.login-message' => null,
// -- Accounts -------------------------------------------------------------- //
// Is basic account information (email, real name, profile picture) editable?
// If you set up Phabricator to automatically synchronize account information
// from some other authoritative system, you can disable this to ensure
// information remains consistent across both systems.
'account.editable' => true,
// When users set or reset a password, it must have at least this many
// characters.
'account.minimum-password-length' => 8,
// -- Recaptcha ------------------------------------------------------------- //
// Is Recaptcha enabled? If disabled, captchas will not appear. You should
// enable Recaptcha if your install is public-facing, as it hinders
// brute-force attacks.
'recaptcha.enabled' => false,
// Your Recaptcha public key, obtained from Recaptcha.
'recaptcha.public-key' => null,
// Your Recaptcha private key, obtained from Recaptcha.
'recaptcha.private-key' => null,
// -- Misc ------------------------------------------------------------------ //
// This is hashed with other inputs to generate CSRF tokens. If you want, you
// can change it to some other string which is unique to your install. This
// will make your install more secure in a vague, mostly theoretical way. But
// it will take you like 3 seconds of mashing on your keyboard to set it up so
// you might as well.
'phabricator.csrf-key' => '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3',
// This is hashed with other inputs to generate mail tokens. If you want, you
// can change it to some other string which is unique to your install. In
// particular, you will want to do this if you accidentally send a bunch of
// mail somewhere you shouldn't have, to invalidate all old reply-to
// addresses.
'phabricator.mail-key' => '5ce3e7e8787f6e40dfae861da315a5cdf1018f12',
// PHP requires that you set a timezone in your php.ini before using date
// functions, or it will emit a warning. If this isn't possible (for instance,
// because you are using HPHP) you can set some valid constant for
// date_default_timezone_set() here and Phabricator will set it on your
// behalf, silencing the warning.
'phabricator.timezone' => null,
// Show stack traces when unhandled exceptions occur, force reloading of
// static resources (skipping the cache), show an error callout if a page
// generated PHP errors, warnings, or notices, force disk reads when
// reloading, and generally make development easier. This option should not
// be enabled in production.
'phabricator.developer-mode' => false,
// When users write comments which have URIs, they'll be automatically linked
// if the protocol appears in this set. This whitelist is primarily to prevent
// security issues like javascript:// URIs.
'uri.allowed-protocols' => array(
'http' => true,
'https' => true,
),
// Tokenizers are UI controls which let the user select other users, email
// addresses, project names, etc., by typing the first few letters and having
// the control autocomplete from a list. They can load their data in two ways:
// either in a big chunk up front, or as the user types. By default, the data
// is loaded in a big chunk. This is simpler and performs better for small
// datasets. However, if you have a very large number of users or projects,
// (in the ballpark of more than a thousand), loading all that data may become
// slow enough that it's worthwhile to query on demand instead. This makes
// the typeahead slightly less responsive but overall performance will be much
// better if you have a ton of stuff. You can figure out which setting is
// best for your install by changing this setting and then playing with a
// user tokenizer (like the user selectors in Maniphest or Differential) and
// seeing which setting loads faster and feels better.
'tokenizer.ondemand' => false,
// By default, Phabricator includes some silly nonsense in the UI, such as
// a submit button called "Clowncopterize" in Differential and a call to
// "Leap Into Action". If you'd prefer more traditional UI strings like
// "Submit", you can set this flag to disable most of the jokes and easter
// eggs.
'phabricator.serious-business' => false,
// Should Phabricator show beta applications on the homepage
'phabricator.show-beta-applications' => false,
// Contains a list of uninstalled applications
'phabricator.uninstalled-applications' => array(),
// Allowing non-members to interact with tasks over email.
'phabricator.allow-email-users' => false,
// -- Welcome Screen -------------------------------------------------------- //
// The custom HTML content for the Phabricator welcome screen.
'welcome.html' => null,
// -- Files ----------------------------------------------------------------- //
// Lists which uploaded file types may be viewed in the browser. If a file
// has a mime type which does not appear in this list, it will always be
// downloaded instead of displayed. This is mainly a usability
// consideration, since browsers tend to freak out when viewing enormous
// binary files.
//
// The keys in this array are viewable mime types; the values are the mime
// types they will be delivered as when they are viewed in the browser.
//
// IMPORTANT: Configure 'security.alternate-file-domain' above! Your install
// is NOT safe if it is left unconfigured.
'files.viewable-mime-types' => array(
'image/jpeg' => 'image/jpeg',
'image/jpg' => 'image/jpg',
'image/png' => 'image/png',
'image/gif' => 'image/gif',
'text/plain' => 'text/plain; charset=utf-8',
'text/x-diff' => 'text/plain; charset=utf-8',
// ".ico" favicon files, which have mime type diversity. See:
// http://en.wikipedia.org/wiki/ICO_(file_format)#MIME_type
'image/x-ico' => 'image/x-icon',
'image/x-icon' => 'image/x-icon',
'image/vnd.microsoft.icon' => 'image/x-icon',
),
// List of mime types which can be used as the source for an <img /> tag.
// This should be a subset of 'files.viewable-mime-types' and exclude files
// like text.
'files.image-mime-types' => array(
'image/jpeg' => true,
'image/jpg' => true,
'image/png' => true,
'image/gif' => true,
'image/x-ico' => true,
'image/x-icon' => true,
'image/vnd.microsoft.icon' => true,
),
// Configuration option for enabling imagemagick
// to resize animated profile pictures (gif)
'files.enable-imagemagick' => false,
// -- Storage --------------------------------------------------------------- //
// Phabricator allows users to upload files, and can keep them in various
// storage engines. This section allows you to configure which engines
// Phabricator will use, and how it will use them.
// The largest filesize Phabricator will store in the MySQL BLOB storage
// engine, which just uses a database table to store files. While this isn't a
// best practice, it's really easy to set up. Set this to 0 to disable use of
// the MySQL blob engine.
'storage.mysql-engine.max-size' => 1000000,
// Phabricator provides a local disk storage engine, which just writes files
// to some directory on local disk. The webserver must have read/write
// permissions on this directory. This is straightforward and suitable for
// most installs, but will not scale past one web frontend unless the path
// is actually an NFS mount, since you'll end up with some of the files
// written to each web frontend and no way for them to share. To use the
// local disk storage engine, specify the path to a directory here. To
// disable it, specify null.
'storage.local-disk.path' => null,
// If you want to store files in Amazon S3, specify an AWS access and secret
// key here and a bucket name below.
'amazon-s3.access-key' => null,
'amazon-s3.secret-key' => null,
// To use a custom endpoint, specify it here. Normally, you do not need to
// configure this.
'amazon-s3.endpoint' => null,
// Set this to a valid Amazon S3 bucket to store files there. You must also
// configure S3 access keys above.
'storage.s3.bucket' => null,
// Phabricator uses a storage engine selector to choose which storage engine
// to use when writing file data. If you add new storage engines or want to
// provide very custom rules (e.g., write images to one storage engine and
// other files to a different one), you can provide an alternate
// implementation here. The default engine will use choose MySQL, Local Disk,
// and S3, in that order, if they have valid configurations above and a file
// fits within configured limits.
'storage.engine-selector' => 'PhabricatorDefaultFileStorageEngineSelector',
// Set the size of the largest file a user may upload. This is used to render
// text like "Maximum file size: 10MB" on interfaces where users can upload
// files, and files larger than this size will be rejected.
//
// Specify this limit in bytes, or using a "K", "M", or "G" suffix.
//
// NOTE: Setting this to a large size is NOT sufficient to allow users to
// upload large files. You must also configure a number of other settings. To
// configure file upload limits, consult the article "Configuring File Upload
// Limits" in the documentation. Once you've configured some limit across all
// levels of the server, you can set this limit to an appropriate value and
// the UI will then reflect the actual configured limit.
'storage.upload-size-limit' => null,
// Phabricator puts databases in a namespace, which defualts to "phabricator"
// -- for instance, the Differential database is named
// "phabricator_differential" by default. You can change this namespace if you
// want. Normally, you should not do this unless you are developing
// Phabricator and using namespaces to separate multiple sandbox datasets.
'storage.default-namespace' => 'phabricator',
// -- Search ---------------------------------------------------------------- //
// Phabricator supports Elastic Search; to use it, specify a host like
// 'http://elastic.example.com:9200/' here.
'search.elastic.host' => null,
// Phabricator uses a search engine selector to choose which search engine
// to use when indexing and reconstructing documents, and when executing
// queries. You can override the engine selector to provide a new selector
// class which can select some custom engine you implement, if you want to
// store your documents in some search engine which does not have default
// support.
'search.engine-selector' => 'PhabricatorDefaultSearchEngineSelector',
// -- Differential ---------------------------------------------------------- //
'differential.revision-custom-detail-renderer' => null,
// List of file regexps where whitespace is meaningful and should not
// use 'ignore-all' by default
'differential.whitespace-matters' => array(
'/\.py$/',
'/\.l?hs$/',
),
'differential.field-selector' => 'DifferentialDefaultFieldSelector',
// Differential can show "Host" and "Path" fields on revisions, with
// information about the machine and working directory where the
// change came from. These fields are disabled by default because they may
// occasionally have sensitive information; you can set this to true to
// enable them.
'differential.show-host-field' => false,
// Differential has a required "Test Plan" field by default, which requires
// authors to fill out information about how they verified the correctness of
// their changes when sending code for review. If you'd prefer not to use
// this field, you can disable it here. You can also make it optional
// (instead of required) below.
'differential.show-test-plan-field' => true,
// Differential has a required "Test Plan" field by default. You can make it
// optional by setting this to false. You can also completely remove it above,
// if you prefer.
'differential.require-test-plan-field' => true,
// If you set this to true, users can "!accept" revisions via email (normally,
// they can take other actions but can not "!accept"). This action is disabled
// by default because email authentication can be configured to be very weak,
// and, socially, email "!accept" is kind of sketchy and implies revisions may
// not actually be receiving thorough review.
'differential.enable-email-accept' => false,
// If you set this to true, users won't need to login to view differential
// revisions. Anonymous users will have read-only access and won't be able to
// interact with the revisions.
'differential.anonymous-access' => false,
// List of file regexps that should be treated as if they are generated by
// an automatic process, and thus get hidden by default in differential.
'differential.generated-paths' => array(
// '/config\.h$/',
// '#/autobuilt/#',
),
// If you set this to true, users can accept their own revisions. This action
// is disabled by default because it's most likely not a behavior you want,
// but it proves useful if you are working alone on a project and want to make
// use of all of differential's features.
'differential.allow-self-accept' => false,
// If you set this to true, any user can close any revision so long as it has
// been accepted. This can be useful depending on your development model. For
// example, github-style pull requests where the reviewer is often the
// actual committer can benefit from turning this option to true. If false,
// only the submitter can close a revision.
'differential.always-allow-close' => false,
// If you set this to true, any user can reopen a revision so long as it has
// been closed. This can be useful if a revision is accidentally closed or
// if a developer changes his or her mind after closing a revision. If it is
// false, reopening is not allowed.
'differential.allow-reopen' => false,
// Revisions newer than this number of days are marked as fresh in Action
// Required and Revisions Waiting on You views. Only work days (not weekends
// and holidays) are included. Set to 0 to disable this feature.
'differential.days-fresh' => 1,
// Similar to 'differential.days-fresh' but marks stale revisions. If the
// revision is even older than it is marked as old.
'differential.days-stale' => 3,
// -- Repositories ---------------------------------------------------------- //
// The default location in which to store local copies of repositories.
// Anything stored in this directory will be assumed to be under the
// control of phabricator, which means that Phabricator will try to do some
// maintenance on working copies if there are problems (such as a change
// to the remote origin url). This maintenance may include completely
// removing (and recloning) anything in this directory.
//
// When set to null, this option is ignored (i.e. Phabricator will not fully
// control any working copies).
'repository.default-local-path' => null,
// -- Maniphest ------------------------------------------------------------- //
// What should the default task priority be in create flows?
// See the constants in @{class:ManiphestTaskPriority} for valid values.
// Defaults to "needs triage".
'maniphest.default-priority' => 90,
// -- Phame ----------------------------------------------------------------- //
// Should Phame users have Disqus comment widget, and if so what's the
// website shortname to use? For example, secure.phabricator.org uses
// "phabricator", which we registered with Disqus. If you aren't familiar
// with Disqus, see:
// Disqus quick start guide - http://docs.disqus.com/help/4/
// Information on shortnames - http://docs.disqus.com/help/68/
'disqus.shortname' => null,
// Directories to look for Phame skins inside of.
'phame.skins' => array(
'externals/skins/',
),
// -- Remarkup -------------------------------------------------------------- //
// If you enable this, linked YouTube videos will be embeded inline. This has
// mild security implications (you'll leak referrers to YouTube) and is pretty
// silly (but sort of awesome).
'remarkup.enable-embedded-youtube' => false,
// -- Cache ----------------------------------------------------------------- //
// Set this to false to disable the use of gzdeflate()-based compression in
// some caches. This may give you less performant (but more debuggable)
// caching.
'cache.enable-deflate' => true,
// -- Garbage Collection ---------------------------------------------------- //
// Phabricator generates various logs and caches in the database which can
// be garbage collected after a while to make the total data size more
// manageable. To run garbage collection, launch a
// PhabricatorGarbageCollector daemon.
// These 'ttl' keys configure how much old data the GC daemon keeps around.
// Objects older than the ttl will be collected. Set any value to 0 to store
// data indefinitely.
'gcdaemon.ttl.herald-transcripts' => 30 * (24 * 60 * 60),
'gcdaemon.ttl.daemon-logs' => 7 * (24 * 60 * 60),
'gcdaemon.ttl.differential-parse-cache' => 14 * (24 * 60 * 60),
'gcdaemon.ttl.markup-cache' => 30 * (24 * 60 * 60),
'gcdaemon.ttl.task-archive' => 14 * (24 * 60 * 60),
'gcdaemon.ttl.general-cache' => 30 * (24 * 60 * 60),
// -- Feed ------------------------------------------------------------------ //
// If you set this to true, you can embed Phabricator activity feeds in other
// pages using iframes. These feeds are completely public, and a login is not
// required to view them! This is intended for things like open source
// projects that want to expose an activity feed on the project homepage.
//
// NOTE: You must also set `policy.allow-public` to true for this setting
// to work properly.
'feed.public' => false,
// If you set this to a list of http URIs, when a feed story is published a
// task will be created for each uri that posts the story data to the uri.
// Daemons automagically retry failures 100 times, waiting $fail_count * 60s
// between each subsequent failure. Be sure to keep the daemon console
// (/daemon/) open while developing and testing your end points.
//
// NOTE: URIs are not validated, the URI must return http status 200 within
// 30 seconds, and no permission checks are performed.
'feed.http-hooks' => array(),
// -- Drydock --------------------------------------------------------------- //
// If you want to use Drydock's builtin EC2 Blueprints, configure your AWS
// EC2 credentials here.
'amazon-ec2.access-key' => null,
'amazon-ec2.secret-key' => null,
// -- Customization --------------------------------------------------------- //
// Paths to additional phutil libraries to load.
'load-libraries' => array(),
'aphront.default-application-configuration-class' =>
'AphrontDefaultApplicationConfiguration',
// Directory that phd (the Phabricator daemon control script) should use to
// track running daemons.
'phd.pid-directory' => '/var/tmp/phd/pid',
// Directory that the Phabricator daemons should use to store the log file
'phd.log-directory' => '/var/tmp/phd/log',
// Number of "TaskMaster" daemons that "phd start" should start. You can
// raise this if you have a task backlog, or explicitly launch more with
// "phd launch <N> taskmaster".
'phd.start-taskmasters' => 4,
// Launch daemons in "verbose" mode by default. This creates a lot of output,
// but can help debug issues. Daemons launched in debug mode with "phd debug"
// are always launched in verbose mode. See also 'phd.trace'.
'phd.verbose' => false,
// Launch daemons in "trace" mode by default. This creates an ENORMOUS amount
// of output, but can help debug issues. Daemons launched in debug mode with
// "phd debug" are always launched in trace mdoe. See also 'phd.verbose'.
'phd.trace' => false,
// Path to custom celerity resource map relative to 'phabricator/src'.
// See also `scripts/celerity_mapper.php`.
'celerity.resource-path' => '__celerity_resource_map__.php',
// This value is an input to the hash function when building resource hashes.
// It has no security value, but if you accidentally poison user caches (by
// pushing a bad patch or having something go wrong with a CDN, e.g.) you can
// change this to something else and rebuild the Celerity map to break user
// caches. Unless you are doing Celerity development, it is exceptionally
// unlikely that you need to modify this.
'celerity.resource-hash' => 'd9455ea150622ee044f7931dabfa52aa',
// Minify static resources by removing whitespace and comments. You should
// enable this in production, but disable it in development.
'celerity.minify' => false,
// You can respond to various application events by installing listeners,
// which will receive callbacks when interesting things occur. Specify a list
// of classes which extend PhabricatorEventListener here.
'events.listeners' => array(),
// -- Syntax Highlighting --------------------------------------------------- //
// Phabricator can highlight PHP by default and use Pygments for other
// languages if enabled. You can provide a custom highlighter engine by
// extending class PhutilSyntaxHighlighterEngine.
'syntax-highlighter.engine' => 'PhutilDefaultSyntaxHighlighterEngine',
// If you want syntax highlighting for other languages than PHP then you can
// install the python package 'Pygments', make sure the 'pygmentize' script is
// available in the $PATH of the webserver, and then enable this.
'pygments.enabled' => false,
// In places that we display a dropdown to syntax-highlight code,
// this is where that list is defined.
// Syntax is 'lexer-name' => 'Display Name',
'pygments.dropdown-choices' => array(
'apacheconf' => 'Apache Configuration',
'bash' => 'Bash Scripting',
'brainfuck' => 'Brainf*ck',
'c' => 'C',
'cpp' => 'C++',
'css' => 'CSS',
'd' => 'D',
'diff' => 'Diff',
'django' => 'Django Templating',
'erb' => 'Embedded Ruby/ERB',
'erlang' => 'Erlang',
'haskell' => 'Haskell',
'html' => 'HTML',
'java' => 'Java',
'js' => 'Javascript',
'mysql' => 'MySQL',
'objc' => 'Objective-C',
'perl' => 'Perl',
'php' => 'PHP',
'rest' => 'reStructuredText',
'text' => 'Plain Text',
'python' => 'Python',
'rainbow' => 'Rainbow',
'remarkup' => 'Remarkup',
'ruby' => 'Ruby',
'xml' => 'XML',
),
// This is an override list of regular expressions which allows you to choose
// what language files are highlighted as. If your projects have certain rules
// about filenames or use unusual or ambiguous language extensions, you can
// create a mapping here. This is an ordered dictionary of regular expressions
// which will be tested against the filename. They should map to either an
// explicit language as a string value, or a numeric index into the captured
// groups as an integer.
'syntax.filemap' => array(
// Example: Treat all '*.xyz' files as PHP.
// '@\\.xyz$@' => 'php',
// Example: Treat 'httpd.conf' as 'apacheconf'.
// '@/httpd\\.conf$@' => 'apacheconf',
// Example: Treat all '*.x.bak' file as '.x'. NOTE: we map to capturing
// group 1 by specifying the mapping as "1".
// '@\\.([^.]+)\\.bak$@' => 1,
'@\.arcconfig$@' => 'js',
'@\.divinerconfig$@' => 'js',
),
// Set the default monospaced font style for users who haven't set a custom
// style.
'style.monospace' => '10px "Menlo", "Consolas", "Monaco", monospace',
'style.monospace.windows' => '11px "Menlo", "Consolas", "Monaco", monospace',
// -- Debugging ------------------------------------------------------------- //
// Enable this to change HTTP redirects into normal pages with a link to the
// redirection target. For example, after you submit a form you'll get a page
// saying "normally, you'd be redirected...". This is useful to examine
// service or profiler information on write pathways, or debug redirects. It
// also makes the UX horrible for normal use, so you should enable it only
// when debugging.
//
// NOTE: This does not currently work for forms with Javascript "workflow",
// since the redirect happens in Javascript.
'debug.stop-on-redirect' => false,
// Set the rate for how often to do sampled profiling. On average, one
// request for every number of requests specified here will be sampled.
// Set this value to 0 to completely disable profiling. In a production
// environment, this value should either be set to 0 (to disable) or to
// a large number (to sample only a few requests).
'debug.profile-rate' => 0,
// -- Environment ---------------------------------------------------------- //
// Phabricator occasionally shells out to other binaries on the server.
// An example of this is the "pygmentize" command, used to syntax-highlight
// code written in languages other than PHP. By default, it is assumed that
// these binaries are in the $PATH of the user running Phabricator (normally
// 'apache', 'httpd', or 'nobody'). Here you can add extra directories to
// the $PATH environment variable, for when these binaries are in non-standard
// locations.
'environment.append-paths' => array(),
// -- Audit ---------------------------------------------------------- //
// Controls whether or not task creator can Close Audits
'audit.can-author-close-audit' => false,
);
diff --git a/resources/sql/patches/20131025.repopush.sql b/resources/sql/patches/20131025.repopush.sql
new file mode 100644
index 0000000000..22f60c3cef
--- /dev/null
+++ b/resources/sql/patches/20131025.repopush.sql
@@ -0,0 +1,5 @@
+ALTER TABLE {$NAMESPACE}_repository.repository
+ ADD COLUMN pushPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin;
+
+UPDATE {$NAMESPACE}_repository.repository
+ SET pushPolicy = 'users' WHERE pushPolicy = '';
diff --git a/resources/sql/patches/20131026.commitstatus.sql b/resources/sql/patches/20131026.commitstatus.sql
new file mode 100644
index 0000000000..373fbddf3c
--- /dev/null
+++ b/resources/sql/patches/20131026.commitstatus.sql
@@ -0,0 +1,8 @@
+ALTER TABLE {$NAMESPACE}_repository.repository_commit
+ ADD COLUMN importStatus INT UNSIGNED NOT NULL COLLATE utf8_bin;
+
+UPDATE {$NAMESPACE}_repository.repository_commit
+ SET importStatus = 15;
+
+ALTER TABLE {$NAMESPACE}_repository.repository_commit
+ ADD KEY (repositoryID, importStatus);
diff --git a/resources/sshd/phabricator-ssh-hook.sh b/resources/sshd/phabricator-ssh-hook.sh
new file mode 100755
index 0000000000..e405729cef
--- /dev/null
+++ b/resources/sshd/phabricator-ssh-hook.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+###
+### WARNING: This feature is new and experimental. Use it at your own risk!
+###
+
+ROOT=/INSECURE/devtools/phabricator
+exec "$ROOT/bin/ssh-auth" $@
diff --git a/resources/sshd/sshd_config.example b/resources/sshd/sshd_config.example
new file mode 100644
index 0000000000..da3897fc8e
--- /dev/null
+++ b/resources/sshd/sshd_config.example
@@ -0,0 +1,24 @@
+###
+### WARNING: This feature is new and experimental. Use it at your own risk!
+###
+
+# You must have OpenSSHD 6.2 or newer; support for AuthorizedKeysCommand was
+# added in this version.
+
+Port 2222
+AuthorizedKeysCommand /etc/phabricator-ssh-hook.sh
+AuthorizedKeysCommandUser some-unprivileged-user
+
+# You may need to tweak these options, but mostly they just turn off everything
+# dangerous.
+
+Protocol 2
+PermitRootLogin no
+AllowAgentForwarding no
+AllowTcpForwarding no
+PrintMotd no
+PrintLastLog no
+PasswordAuthentication no
+AuthorizedKeysFile none
+
+PidFile /var/run/sshd-phabricator.pid
diff --git a/scripts/ssh/ssh-auth.php b/scripts/ssh/ssh-auth-key.php
similarity index 96%
copy from scripts/ssh/ssh-auth.php
copy to scripts/ssh/ssh-auth-key.php
index 96e6ef389b..362e8d1be4 100755
--- a/scripts/ssh/ssh-auth.php
+++ b/scripts/ssh/ssh-auth-key.php
@@ -1,61 +1,61 @@
#!/usr/bin/env php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
$cert = file_get_contents('php://stdin');
if (!$cert) {
exit(1);
}
$parts = preg_split('/\s+/', $cert);
if (count($parts) < 2) {
exit(1);
}
list($type, $body) = $parts;
$user_dao = new PhabricatorUser();
$ssh_dao = new PhabricatorUserSSHKey();
$conn_r = $user_dao->establishConnection('r');
$row = queryfx_one(
$conn_r,
'SELECT userName FROM %T u JOIN %T ssh ON u.phid = ssh.userPHID
WHERE ssh.keyType = %s AND ssh.keyBody = %s',
$user_dao->getTableName(),
$ssh_dao->getTableName(),
$type,
$body);
if (!$row) {
exit(1);
}
$user = idx($row, 'userName');
if (!$user) {
exit(1);
}
if (!PhabricatorUser::validateUsername($user)) {
exit(1);
}
$bin = $root.'/bin/ssh-exec';
$cmd = csprintf('%s --phabricator-ssh-user %s', $bin, $user);
// This is additional escaping for the SSH 'command="..."' string.
-$cmd = str_replace('"', '\\"', $cmd);
+$cmd = addcslashes($cmd, '"\\');
$options = array(
'command="'.$cmd.'"',
'no-port-forwarding',
'no-X11-forwarding',
'no-agent-forwarding',
'no-pty',
);
echo implode(',', $options);
exit(0);
diff --git a/scripts/ssh/ssh-auth.php b/scripts/ssh/ssh-auth.php
index 96e6ef389b..dc7b4d098e 100755
--- a/scripts/ssh/ssh-auth.php
+++ b/scripts/ssh/ssh-auth.php
@@ -1,61 +1,48 @@
#!/usr/bin/env php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
-$cert = file_get_contents('php://stdin');
-
-if (!$cert) {
- exit(1);
-}
-
-$parts = preg_split('/\s+/', $cert);
-if (count($parts) < 2) {
- exit(1);
-}
-
-list($type, $body) = $parts;
-
$user_dao = new PhabricatorUser();
$ssh_dao = new PhabricatorUserSSHKey();
$conn_r = $user_dao->establishConnection('r');
-$row = queryfx_one(
+$rows = queryfx_all(
$conn_r,
- 'SELECT userName FROM %T u JOIN %T ssh ON u.phid = ssh.userPHID
- WHERE ssh.keyType = %s AND ssh.keyBody = %s',
+ 'SELECT userName, keyBody, keyType FROM %T u JOIN %T ssh
+ ON u.phid = ssh.userPHID',
$user_dao->getTableName(),
- $ssh_dao->getTableName(),
- $type,
- $body);
+ $ssh_dao->getTableName());
-if (!$row) {
- exit(1);
-}
+$bin = $root.'/bin/ssh-exec';
+foreach ($rows as $row) {
+ $user = $row['userName'];
-$user = idx($row, 'userName');
+ $cmd = csprintf('%s --phabricator-ssh-user %s', $bin, $user);
+ // This is additional escaping for the SSH 'command="..."' string.
+ $cmd = addcslashes($cmd, '"\\');
-if (!$user) {
- exit(1);
-}
+ // Strip out newlines and other nonsense from the key type and key body.
+
+ $type = $row['keyType'];
+ $type = preg_replace('@[\x00-\x20]+@', '', $type);
+
+ $key = $row['keyBody'];
+ $key = preg_replace('@[\x00-\x20]+@', '', $key);
-if (!PhabricatorUser::validateUsername($user)) {
- exit(1);
+
+ $options = array(
+ 'command="'.$cmd.'"',
+ 'no-port-forwarding',
+ 'no-X11-forwarding',
+ 'no-agent-forwarding',
+ 'no-pty',
+ );
+ $options = implode(',', $options);
+
+ $lines[] = $options.' '.$type.' '.$key."\n";
}
-$bin = $root.'/bin/ssh-exec';
-$cmd = csprintf('%s --phabricator-ssh-user %s', $bin, $user);
-// This is additional escaping for the SSH 'command="..."' string.
-$cmd = str_replace('"', '\\"', $cmd);
-
-$options = array(
- 'command="'.$cmd.'"',
- 'no-port-forwarding',
- 'no-X11-forwarding',
- 'no-agent-forwarding',
- 'no-pty',
-);
-
-echo implode(',', $options);
+echo implode('', $lines);
exit(0);
diff --git a/scripts/ssh/ssh-exec.php b/scripts/ssh/ssh-exec.php
index a9c639f75d..cdc62d7a8d 100755
--- a/scripts/ssh/ssh-exec.php
+++ b/scripts/ssh/ssh-exec.php
@@ -1,91 +1,107 @@
#!/usr/bin/env php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
-$original_command = getenv('SSH_ORIGINAL_COMMAND');
-$original_argv = id(new PhutilShellLexer())->splitArguments($original_command);
-$argv = array_merge($argv, $original_argv);
-
+// First, figure out the authenticated user.
$args = new PhutilArgumentParser($argv);
$args->setTagline('receive SSH requests');
$args->setSynopsis(<<<EOSYNOPSIS
-**ssh-exec** --phabricator-ssh-user __user__ __commmand__ [__options__]
+**ssh-exec** --phabricator-ssh-user __user__ [--ssh-command __commmand__]
Receive SSH requests.
-
EOSYNOPSIS
);
-// NOTE: Do NOT parse standard arguments. Arguments are coming from a remote
-// client over SSH, and they should not be able to execute "--xprofile",
-// "--recon", etc.
-
-$args->parsePartial(
+$args->parse(
array(
array(
'name' => 'phabricator-ssh-user',
'param' => 'username',
),
+ array(
+ 'name' => 'ssh-command',
+ 'param' => 'command',
+ ),
));
try {
$user_name = $args->getArg('phabricator-ssh-user');
if (!strlen($user_name)) {
throw new Exception("No username.");
}
$user = id(new PhabricatorUser())->loadOneWhere(
'userName = %s',
$user_name);
if (!$user) {
throw new Exception("Invalid username.");
}
if ($user->getIsDisabled()) {
throw new Exception("You have been exiled.");
}
+ if ($args->getArg('ssh-command')) {
+ $original_command = $args->getArg('ssh-command');
+ } else {
+ $original_command = getenv('SSH_ORIGINAL_COMMAND');
+ }
+
+ // Now, rebuild the original command.
+ $original_argv = id(new PhutilShellLexer())
+ ->splitArguments($original_command);
+ if (!$original_argv) {
+ throw new Exception("No interactive logins.");
+ }
+ $command = head($original_argv);
+ array_unshift($original_argv, 'phabricator-ssh-exec');
+
+ $original_args = new PhutilArgumentParser($original_argv);
+
$workflows = array(
new ConduitSSHWorkflow(),
+
+ new DiffusionSSHGitUploadPackWorkflow(),
+ new DiffusionSSHGitReceivePackWorkflow(),
);
- // This duplicates logic in parseWorkflows(), but allows us to raise more
- // concise/relevant exceptions when the client is a remote SSH.
- $remain = $args->getUnconsumedArgumentVector();
- if (empty($remain)) {
- throw new Exception("No interactive logins.");
- } else {
- $command = head($remain);
- $workflow_names = mpull($workflows, 'getName', 'getName');
- if (empty($workflow_names[$command])) {
- throw new Exception("Invalid command.");
- }
+ $workflow_names = mpull($workflows, 'getName', 'getName');
+ if (empty($workflow_names[$command])) {
+ throw new Exception("Invalid command.");
}
- $workflow = $args->parseWorkflows($workflows);
+ $workflow = $original_args->parseWorkflows($workflows);
$workflow->setUser($user);
$sock_stdin = fopen('php://stdin', 'r');
if (!$sock_stdin) {
throw new Exception("Unable to open stdin.");
}
$sock_stdout = fopen('php://stdout', 'w');
if (!$sock_stdout) {
throw new Exception("Unable to open stdout.");
}
+ $sock_stderr = fopen('php://stderr', 'w');
+ if (!$sock_stderr) {
+ throw new Exception("Unable to open stderr.");
+ }
+
$socket_channel = new PhutilSocketChannel(
$sock_stdin,
$sock_stdout);
+ $error_channel = new PhutilSocketChannel(null, $sock_stderr);
$metrics_channel = new PhutilMetricsChannel($socket_channel);
$workflow->setIOChannel($metrics_channel);
+ $workflow->setErrorChannel($error_channel);
- $err = $workflow->execute($args);
+ $err = $workflow->execute($original_args);
$metrics_channel->flush();
+ $error_channel->flush();
} catch (Exception $ex) {
- echo "phabricator-ssh-exec: ".$ex->getMessage()."\n";
+ fwrite(STDERR, "phabricator-ssh-exec: ".$ex->getMessage()."\n");
exit(1);
}
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 2ee626fc2c..f69cf7c097 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,4618 +1,4640 @@
<?php
/**
* This file is automatically generated. Use 'arc liberate' to rebuild it.
* @generated
* @phutil-library-version 2
*/
phutil_register_library_map(array(
'__library_version__' => 2,
'class' =>
array(
'Aphront304Response' => 'aphront/response/Aphront304Response.php',
'Aphront400Response' => 'aphront/response/Aphront400Response.php',
'Aphront403Response' => 'aphront/response/Aphront403Response.php',
'Aphront404Response' => 'aphront/response/Aphront404Response.php',
'AphrontAbstractAttachedFileView' => 'view/control/AphrontAbstractAttachedFileView.php',
'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php',
'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php',
'AphrontBarView' => 'view/widget/bars/AphrontBarView.php',
'AphrontCSRFException' => 'aphront/exception/AphrontCSRFException.php',
'AphrontCalendarEventView' => 'applications/calendar/view/AphrontCalendarEventView.php',
'AphrontCalendarMonthView' => 'applications/calendar/view/AphrontCalendarMonthView.php',
'AphrontContextBarView' => 'view/layout/AphrontContextBarView.php',
'AphrontController' => 'aphront/AphrontController.php',
'AphrontCursorPagerView' => 'view/control/AphrontCursorPagerView.php',
'AphrontDefaultApplicationConfiguration' => 'aphront/configuration/AphrontDefaultApplicationConfiguration.php',
'AphrontDialogResponse' => 'aphront/response/AphrontDialogResponse.php',
'AphrontDialogView' => 'view/AphrontDialogView.php',
'AphrontErrorView' => 'view/form/AphrontErrorView.php',
'AphrontException' => 'aphront/exception/AphrontException.php',
'AphrontFileResponse' => 'aphront/response/AphrontFileResponse.php',
'AphrontFormCheckboxControl' => 'view/form/control/AphrontFormCheckboxControl.php',
'AphrontFormControl' => 'view/form/control/AphrontFormControl.php',
'AphrontFormCropControl' => 'view/form/control/AphrontFormCropControl.php',
'AphrontFormDateControl' => 'view/form/control/AphrontFormDateControl.php',
'AphrontFormDividerControl' => 'view/form/control/AphrontFormDividerControl.php',
'AphrontFormFileControl' => 'view/form/control/AphrontFormFileControl.php',
'AphrontFormImageControl' => 'view/form/control/AphrontFormImageControl.php',
'AphrontFormInsetView' => 'view/form/AphrontFormInsetView.php',
'AphrontFormMarkupControl' => 'view/form/control/AphrontFormMarkupControl.php',
'AphrontFormPasswordControl' => 'view/form/control/AphrontFormPasswordControl.php',
'AphrontFormPolicyControl' => 'view/form/control/AphrontFormPolicyControl.php',
'AphrontFormRadioButtonControl' => 'view/form/control/AphrontFormRadioButtonControl.php',
'AphrontFormRecaptchaControl' => 'view/form/control/AphrontFormRecaptchaControl.php',
'AphrontFormSelectControl' => 'view/form/control/AphrontFormSelectControl.php',
'AphrontFormStaticControl' => 'view/form/control/AphrontFormStaticControl.php',
'AphrontFormSubmitControl' => 'view/form/control/AphrontFormSubmitControl.php',
'AphrontFormTextAreaControl' => 'view/form/control/AphrontFormTextAreaControl.php',
'AphrontFormTextControl' => 'view/form/control/AphrontFormTextControl.php',
'AphrontFormToggleButtonsControl' => 'view/form/control/AphrontFormToggleButtonsControl.php',
'AphrontFormTokenizerControl' => 'view/form/control/AphrontFormTokenizerControl.php',
'AphrontFormView' => 'view/form/AphrontFormView.php',
'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php',
'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php',
'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php',
'AphrontHTTPSinkTestCase' => 'aphront/sink/__tests__/AphrontHTTPSinkTestCase.php',
'AphrontIsolatedDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontIsolatedDatabaseConnectionTestCase.php',
'AphrontIsolatedHTTPSink' => 'aphront/sink/AphrontIsolatedHTTPSink.php',
'AphrontJSONResponse' => 'aphront/response/AphrontJSONResponse.php',
'AphrontJavelinView' => 'view/AphrontJavelinView.php',
'AphrontKeyboardShortcutsAvailableView' => 'view/widget/AphrontKeyboardShortcutsAvailableView.php',
'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php',
'AphrontMiniPanelView' => 'view/layout/AphrontMiniPanelView.php',
'AphrontMoreView' => 'view/layout/AphrontMoreView.php',
'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php',
'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php',
'AphrontNoteView' => 'view/widget/AphrontNoteView.php',
'AphrontNullView' => 'view/AphrontNullView.php',
'AphrontPHPHTTPSink' => 'aphront/sink/AphrontPHPHTTPSink.php',
'AphrontPageView' => 'view/page/AphrontPageView.php',
'AphrontPagerView' => 'view/control/AphrontPagerView.php',
'AphrontPanelView' => 'view/layout/AphrontPanelView.php',
'AphrontPlainTextResponse' => 'aphront/response/AphrontPlainTextResponse.php',
'AphrontProgressBarView' => 'view/widget/bars/AphrontProgressBarView.php',
'AphrontProxyResponse' => 'aphront/response/AphrontProxyResponse.php',
'AphrontRedirectResponse' => 'aphront/response/AphrontRedirectResponse.php',
'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php',
'AphrontRequest' => 'aphront/AphrontRequest.php',
'AphrontRequestFailureView' => 'view/page/AphrontRequestFailureView.php',
'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php',
'AphrontResponse' => 'aphront/response/AphrontResponse.php',
'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php',
'AphrontTableView' => 'view/control/AphrontTableView.php',
'AphrontTagView' => 'view/AphrontTagView.php',
'AphrontTokenizerTemplateView' => 'view/control/AphrontTokenizerTemplateView.php',
'AphrontTwoColumnView' => 'view/layout/AphrontTwoColumnView.php',
'AphrontTypeaheadTemplateView' => 'view/control/AphrontTypeaheadTemplateView.php',
'AphrontURIMapper' => 'aphront/AphrontURIMapper.php',
'AphrontUsageException' => 'aphront/exception/AphrontUsageException.php',
'AphrontView' => 'view/AphrontView.php',
'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php',
'AuditActionMenuEventListener' => 'applications/audit/events/AuditActionMenuEventListener.php',
'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php',
'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php',
'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php',
'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php',
'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php',
'CelerityResourceTransformer' => 'infrastructure/celerity/CelerityResourceTransformer.php',
'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php',
'CeleritySpriteGenerator' => 'infrastructure/celerity/CeleritySpriteGenerator.php',
'CelerityStaticResourceResponse' => 'infrastructure/celerity/CelerityStaticResourceResponse.php',
'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php',
'ConduitAPIRequest' => 'applications/conduit/protocol/ConduitAPIRequest.php',
'ConduitAPIResponse' => 'applications/conduit/protocol/ConduitAPIResponse.php',
'ConduitAPI_arcanist_Method' => 'applications/arcanist/conduit/ConduitAPI_arcanist_Method.php',
'ConduitAPI_arcanist_projectinfo_Method' => 'applications/arcanist/conduit/ConduitAPI_arcanist_projectinfo_Method.php',
'ConduitAPI_audit_Method' => 'applications/audit/conduit/ConduitAPI_audit_Method.php',
'ConduitAPI_audit_query_Method' => 'applications/audit/conduit/ConduitAPI_audit_query_Method.php',
'ConduitAPI_chatlog_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_Method.php',
'ConduitAPI_chatlog_query_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_query_Method.php',
'ConduitAPI_chatlog_record_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_record_Method.php',
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/ConduitAPI_conduit_connect_Method.php',
'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/ConduitAPI_conduit_getcertificate_Method.php',
'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/ConduitAPI_conduit_ping_Method.php',
'ConduitAPI_conduit_query_Method' => 'applications/conduit/method/ConduitAPI_conduit_query_Method.php',
'ConduitAPI_conpherence_Method' => 'applications/conpherence/conduit/ConduitAPI_conpherence_Method.php',
'ConduitAPI_conpherence_createthread_Method' => 'applications/conpherence/conduit/ConduitAPI_conpherence_createthread_Method.php',
'ConduitAPI_conpherence_querythread_Method' => 'applications/conpherence/conduit/ConduitAPI_conpherence_querythread_Method.php',
'ConduitAPI_conpherence_querytransaction_Method' => 'applications/conpherence/conduit/ConduitAPI_conpherence_querytransaction_Method.php',
'ConduitAPI_conpherence_updatethread_Method' => 'applications/conpherence/conduit/ConduitAPI_conpherence_updatethread_Method.php',
'ConduitAPI_differential_Method' => 'applications/differential/conduit/ConduitAPI_differential_Method.php',
'ConduitAPI_differential_close_Method' => 'applications/differential/conduit/ConduitAPI_differential_close_Method.php',
'ConduitAPI_differential_createcomment_Method' => 'applications/differential/conduit/ConduitAPI_differential_createcomment_Method.php',
'ConduitAPI_differential_creatediff_Method' => 'applications/differential/conduit/ConduitAPI_differential_creatediff_Method.php',
'ConduitAPI_differential_createinline_Method' => 'applications/differential/conduit/ConduitAPI_differential_createinline_Method.php',
'ConduitAPI_differential_createrawdiff_Method' => 'applications/differential/conduit/ConduitAPI_differential_createrawdiff_Method.php',
'ConduitAPI_differential_createrevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_createrevision_Method.php',
'ConduitAPI_differential_find_Method' => 'applications/differential/conduit/ConduitAPI_differential_find_Method.php',
'ConduitAPI_differential_finishpostponedlinters_Method' => 'applications/differential/conduit/ConduitAPI_differential_finishpostponedlinters_Method.php',
'ConduitAPI_differential_getalldiffs_Method' => 'applications/differential/conduit/ConduitAPI_differential_getalldiffs_Method.php',
'ConduitAPI_differential_getcommitmessage_Method' => 'applications/differential/conduit/ConduitAPI_differential_getcommitmessage_Method.php',
'ConduitAPI_differential_getcommitpaths_Method' => 'applications/differential/conduit/ConduitAPI_differential_getcommitpaths_Method.php',
'ConduitAPI_differential_getdiff_Method' => 'applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php',
'ConduitAPI_differential_getrawdiff_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrawdiff_Method.php',
'ConduitAPI_differential_getrevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrevision_Method.php',
'ConduitAPI_differential_getrevisioncomments_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrevisioncomments_Method.php',
'ConduitAPI_differential_markcommitted_Method' => 'applications/differential/conduit/ConduitAPI_differential_markcommitted_Method.php',
'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/differential/conduit/ConduitAPI_differential_parsecommitmessage_Method.php',
'ConduitAPI_differential_query_Method' => 'applications/differential/conduit/ConduitAPI_differential_query_Method.php',
'ConduitAPI_differential_querydiffs_Method' => 'applications/differential/conduit/ConduitAPI_differential_querydiffs_Method.php',
'ConduitAPI_differential_setdiffproperty_Method' => 'applications/differential/conduit/ConduitAPI_differential_setdiffproperty_Method.php',
'ConduitAPI_differential_updaterevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_updaterevision_Method.php',
'ConduitAPI_differential_updateunitresults_Method' => 'applications/differential/conduit/ConduitAPI_differential_updateunitresults_Method.php',
'ConduitAPI_diffusion_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_Method.php',
'ConduitAPI_diffusion_abstractquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_abstractquery_Method.php',
'ConduitAPI_diffusion_branchquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_branchquery_Method.php',
'ConduitAPI_diffusion_browsequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_browsequery_Method.php',
'ConduitAPI_diffusion_commitbranchesquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_commitbranchesquery_Method.php',
'ConduitAPI_diffusion_commitparentsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_commitparentsquery_Method.php',
'ConduitAPI_diffusion_createcomment_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_createcomment_Method.php',
'ConduitAPI_diffusion_diffquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_diffquery_Method.php',
'ConduitAPI_diffusion_existsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_existsquery_Method.php',
'ConduitAPI_diffusion_expandshortcommitquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_expandshortcommitquery_Method.php',
'ConduitAPI_diffusion_filecontentquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_filecontentquery_Method.php',
'ConduitAPI_diffusion_findsymbols_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_findsymbols_Method.php',
'ConduitAPI_diffusion_getcommits_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php',
'ConduitAPI_diffusion_getlintmessages_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getlintmessages_Method.php',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php',
'ConduitAPI_diffusion_historyquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_historyquery_Method.php',
'ConduitAPI_diffusion_lastmodifiedquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_lastmodifiedquery_Method.php',
'ConduitAPI_diffusion_mergedcommitsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_mergedcommitsquery_Method.php',
'ConduitAPI_diffusion_rawdiffquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_rawdiffquery_Method.php',
'ConduitAPI_diffusion_readmequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_readmequery_Method.php',
'ConduitAPI_diffusion_refsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_refsquery_Method.php',
'ConduitAPI_diffusion_searchquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_searchquery_Method.php',
'ConduitAPI_diffusion_stablecommitnamequery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_stablecommitnamequery_Method.php',
'ConduitAPI_diffusion_tagsquery_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_tagsquery_Method.php',
'ConduitAPI_feed_Method' => 'applications/feed/conduit/ConduitAPI_feed_Method.php',
'ConduitAPI_feed_publish_Method' => 'applications/feed/conduit/ConduitAPI_feed_publish_Method.php',
'ConduitAPI_feed_query_Method' => 'applications/feed/conduit/ConduitAPI_feed_query_Method.php',
'ConduitAPI_file_Method' => 'applications/files/conduit/ConduitAPI_file_Method.php',
'ConduitAPI_file_download_Method' => 'applications/files/conduit/ConduitAPI_file_download_Method.php',
'ConduitAPI_file_info_Method' => 'applications/files/conduit/ConduitAPI_file_info_Method.php',
'ConduitAPI_file_upload_Method' => 'applications/files/conduit/ConduitAPI_file_upload_Method.php',
'ConduitAPI_file_uploadhash_Method' => 'applications/files/conduit/ConduitAPI_file_uploadhash_Method.php',
'ConduitAPI_flag_Method' => 'applications/flag/conduit/ConduitAPI_flag_Method.php',
'ConduitAPI_flag_delete_Method' => 'applications/flag/conduit/ConduitAPI_flag_delete_Method.php',
'ConduitAPI_flag_edit_Method' => 'applications/flag/conduit/ConduitAPI_flag_edit_Method.php',
'ConduitAPI_flag_query_Method' => 'applications/flag/conduit/ConduitAPI_flag_query_Method.php',
'ConduitAPI_macro_Method' => 'applications/macro/conduit/ConduitAPI_macro_Method.php',
'ConduitAPI_macro_creatememe_Method' => 'applications/macro/conduit/ConduitAPI_macro_creatememe_Method.php',
'ConduitAPI_macro_query_Method' => 'applications/macro/conduit/ConduitAPI_macro_query_Method.php',
'ConduitAPI_maniphest_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_Method.php',
'ConduitAPI_maniphest_createtask_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_createtask_Method.php',
'ConduitAPI_maniphest_find_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_find_Method.php',
'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_gettasktransactions_Method.php',
'ConduitAPI_maniphest_info_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_info_Method.php',
'ConduitAPI_maniphest_query_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_query_Method.php',
'ConduitAPI_maniphest_update_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_update_Method.php',
'ConduitAPI_owners_Method' => 'applications/owners/conduit/ConduitAPI_owners_Method.php',
'ConduitAPI_owners_query_Method' => 'applications/owners/conduit/ConduitAPI_owners_query_Method.php',
'ConduitAPI_paste_Method' => 'applications/paste/conduit/ConduitAPI_paste_Method.php',
'ConduitAPI_paste_create_Method' => 'applications/paste/conduit/ConduitAPI_paste_create_Method.php',
'ConduitAPI_paste_info_Method' => 'applications/paste/conduit/ConduitAPI_paste_info_Method.php',
'ConduitAPI_paste_query_Method' => 'applications/paste/conduit/ConduitAPI_paste_query_Method.php',
'ConduitAPI_phid_Method' => 'applications/phid/conduit/ConduitAPI_phid_Method.php',
'ConduitAPI_phid_info_Method' => 'applications/phid/conduit/ConduitAPI_phid_info_Method.php',
'ConduitAPI_phid_lookup_Method' => 'applications/phid/conduit/ConduitAPI_phid_lookup_Method.php',
'ConduitAPI_phid_query_Method' => 'applications/phid/conduit/ConduitAPI_phid_query_Method.php',
'ConduitAPI_phpast_Method' => 'applications/phpast/conduit/ConduitAPI_phpast_Method.php',
'ConduitAPI_phpast_getast_Method' => 'applications/phpast/conduit/ConduitAPI_phpast_getast_Method.php',
'ConduitAPI_phpast_version_Method' => 'applications/phpast/conduit/ConduitAPI_phpast_version_Method.php',
'ConduitAPI_phriction_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_Method.php',
'ConduitAPI_phriction_edit_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_edit_Method.php',
'ConduitAPI_phriction_history_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_history_Method.php',
'ConduitAPI_phriction_info_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_info_Method.php',
'ConduitAPI_project_Method' => 'applications/project/conduit/ConduitAPI_project_Method.php',
'ConduitAPI_project_query_Method' => 'applications/project/conduit/ConduitAPI_project_query_Method.php',
'ConduitAPI_releeph_Method' => 'applications/releeph/conduit/ConduitAPI_releeph_Method.php',
'ConduitAPI_releeph_getbranches_Method' => 'applications/releeph/conduit/ConduitAPI_releeph_getbranches_Method.php',
'ConduitAPI_releeph_projectinfo_Method' => 'applications/releeph/conduit/ConduitAPI_releeph_projectinfo_Method.php',
'ConduitAPI_releeph_queryrequests_Method' => 'applications/releeph/conduit/ConduitAPI_releeph_queryrequests_Method.php',
'ConduitAPI_releeph_request_Method' => 'applications/releeph/conduit/ConduitAPI_releeph_request_Method.php',
'ConduitAPI_releephwork_canpush_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_canpush_Method.php',
'ConduitAPI_releephwork_getauthorinfo_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_getauthorinfo_Method.php',
'ConduitAPI_releephwork_getbranch_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_getbranch_Method.php',
'ConduitAPI_releephwork_getbranchcommitmessage_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_getbranchcommitmessage_Method.php',
'ConduitAPI_releephwork_getcommitmessage_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_getcommitmessage_Method.php',
'ConduitAPI_releephwork_getorigcommitmessage_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_getorigcommitmessage_Method.php',
'ConduitAPI_releephwork_nextrequest_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_nextrequest_Method.php',
'ConduitAPI_releephwork_record_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_record_Method.php',
'ConduitAPI_releephwork_recordpickstatus_Method' => 'applications/releeph/conduit/work/ConduitAPI_releephwork_recordpickstatus_Method.php',
'ConduitAPI_remarkup_process_Method' => 'applications/remarkup/conduit/ConduitAPI_remarkup_process_Method.php',
'ConduitAPI_repository_Method' => 'applications/repository/conduit/ConduitAPI_repository_Method.php',
'ConduitAPI_repository_create_Method' => 'applications/repository/conduit/ConduitAPI_repository_create_Method.php',
'ConduitAPI_repository_query_Method' => 'applications/repository/conduit/ConduitAPI_repository_query_Method.php',
'ConduitAPI_slowvote_Method' => 'applications/slowvote/conduit/ConduitAPI_slowvote_Method.php',
'ConduitAPI_slowvote_info_Method' => 'applications/slowvote/conduit/ConduitAPI_slowvote_info_Method.php',
'ConduitAPI_token_Method' => 'applications/tokens/conduit/ConduitAPI_token_Method.php',
'ConduitAPI_token_give_Method' => 'applications/tokens/conduit/ConduitAPI_token_give_Method.php',
'ConduitAPI_token_given_Method' => 'applications/tokens/conduit/ConduitAPI_token_given_Method.php',
'ConduitAPI_token_query_Method' => 'applications/tokens/conduit/ConduitAPI_token_query_Method.php',
'ConduitAPI_user_Method' => 'applications/people/conduit/ConduitAPI_user_Method.php',
'ConduitAPI_user_addstatus_Method' => 'applications/people/conduit/ConduitAPI_user_addstatus_Method.php',
'ConduitAPI_user_disable_Method' => 'applications/people/conduit/ConduitAPI_user_disable_Method.php',
'ConduitAPI_user_enable_Method' => 'applications/people/conduit/ConduitAPI_user_enable_Method.php',
'ConduitAPI_user_find_Method' => 'applications/people/conduit/ConduitAPI_user_find_Method.php',
'ConduitAPI_user_info_Method' => 'applications/people/conduit/ConduitAPI_user_info_Method.php',
'ConduitAPI_user_query_Method' => 'applications/people/conduit/ConduitAPI_user_query_Method.php',
'ConduitAPI_user_removestatus_Method' => 'applications/people/conduit/ConduitAPI_user_removestatus_Method.php',
'ConduitAPI_user_whoami_Method' => 'applications/people/conduit/ConduitAPI_user_whoami_Method.php',
'ConduitCall' => 'applications/conduit/call/ConduitCall.php',
'ConduitCallTestCase' => 'applications/conduit/call/__tests__/ConduitCallTestCase.php',
'ConduitException' => 'applications/conduit/protocol/ConduitException.php',
'ConduitSSHWorkflow' => 'applications/conduit/ssh/ConduitSSHWorkflow.php',
'ConpherenceActionMenuEventListener' => 'applications/conpherence/events/ConpherenceActionMenuEventListener.php',
'ConpherenceConfigOptions' => 'applications/conpherence/config/ConpherenceConfigOptions.php',
'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php',
'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php',
'ConpherenceCreateThreadMailReceiver' => 'applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php',
'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php',
'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php',
'ConpherenceFileWidgetView' => 'applications/conpherence/view/ConpherenceFileWidgetView.php',
'ConpherenceHovercardEventListener' => 'applications/conpherence/events/ConpherenceHovercardEventListener.php',
'ConpherenceLayoutView' => 'applications/conpherence/view/ConpherenceLayoutView.php',
'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php',
'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php',
'ConpherenceNewController' => 'applications/conpherence/controller/ConpherenceNewController.php',
'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php',
'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php',
'ConpherenceParticipantCountQuery' => 'applications/conpherence/query/ConpherenceParticipantCountQuery.php',
'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php',
'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php',
'ConpherencePeopleWidgetView' => 'applications/conpherence/view/ConpherencePeopleWidgetView.php',
'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php',
'ConpherenceSettings' => 'applications/conpherence/constants/ConpherenceSettings.php',
'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php',
'ConpherenceThreadListView' => 'applications/conpherence/view/ConpherenceThreadListView.php',
'ConpherenceThreadMailReceiver' => 'applications/conpherence/mail/ConpherenceThreadMailReceiver.php',
'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php',
'ConpherenceTimeUtil' => 'applications/conpherence/util/ConpherenceTimeUtil.php',
'ConpherenceTimeUtilTestCase' => 'applications/conpherence/__tests__/ConpherenceTimeUtilTestCase.php',
'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php',
'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php',
'ConpherenceTransactionQuery' => 'applications/conpherence/query/ConpherenceTransactionQuery.php',
'ConpherenceTransactionType' => 'applications/conpherence/constants/ConpherenceTransactionType.php',
'ConpherenceTransactionView' => 'applications/conpherence/view/ConpherenceTransactionView.php',
'ConpherenceUpdateActions' => 'applications/conpherence/constants/ConpherenceUpdateActions.php',
'ConpherenceUpdateController' => 'applications/conpherence/controller/ConpherenceUpdateController.php',
'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php',
'ConpherenceWidgetController' => 'applications/conpherence/controller/ConpherenceWidgetController.php',
'ConpherenceWidgetView' => 'applications/conpherence/view/ConpherenceWidgetView.php',
'DarkConsoleController' => 'aphront/console/DarkConsoleController.php',
'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php',
'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php',
'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/DarkConsoleErrorLogPlugin.php',
'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/DarkConsoleErrorLogPluginAPI.php',
'DarkConsoleEventPlugin' => 'aphront/console/plugin/DarkConsoleEventPlugin.php',
'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/DarkConsoleEventPluginAPI.php',
'DarkConsolePlugin' => 'aphront/console/plugin/DarkConsolePlugin.php',
'DarkConsoleRequestPlugin' => 'aphront/console/plugin/DarkConsoleRequestPlugin.php',
'DarkConsoleServicesPlugin' => 'aphront/console/plugin/DarkConsoleServicesPlugin.php',
'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/DarkConsoleXHProfPlugin.php',
'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php',
'DatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DatabaseConfigurationProvider.php',
'DefaultDatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php',
'DifferentialAction' => 'applications/differential/constants/DifferentialAction.php',
'DifferentialActionHasNoEffectException' => 'applications/differential/exception/DifferentialActionHasNoEffectException.php',
'DifferentialActionMenuEventListener' => 'applications/differential/event/DifferentialActionMenuEventListener.php',
'DifferentialAddCommentView' => 'applications/differential/view/DifferentialAddCommentView.php',
'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php',
'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialApplyPatchFieldSpecification.php',
'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/DifferentialArcanistProjectFieldSpecification.php',
'DifferentialAsanaRepresentationFieldSpecification' => 'applications/differential/field/specification/DifferentialAsanaRepresentationFieldSpecification.php',
'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/DifferentialAuditorsFieldSpecification.php',
'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/DifferentialAuthorFieldSpecification.php',
'DifferentialAuxiliaryField' => 'applications/differential/storage/DifferentialAuxiliaryField.php',
'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/DifferentialBlameRevisionFieldSpecification.php',
'DifferentialBranchFieldSpecification' => 'applications/differential/field/specification/DifferentialBranchFieldSpecification.php',
'DifferentialCCWelcomeMail' => 'applications/differential/mail/DifferentialCCWelcomeMail.php',
'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/DifferentialCCsFieldSpecification.php',
'DifferentialCapabilityDefaultView' => 'applications/differential/capability/DifferentialCapabilityDefaultView.php',
'DifferentialChangeType' => 'applications/differential/constants/DifferentialChangeType.php',
'DifferentialChangeset' => 'applications/differential/storage/DifferentialChangeset.php',
'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php',
'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php',
'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php',
'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php',
'DifferentialChangesetOneUpRenderer' => 'applications/differential/render/DifferentialChangesetOneUpRenderer.php',
'DifferentialChangesetOneUpTestRenderer' => 'applications/differential/render/DifferentialChangesetOneUpTestRenderer.php',
'DifferentialChangesetParser' => 'applications/differential/parser/DifferentialChangesetParser.php',
'DifferentialChangesetParserTestCase' => 'applications/differential/parser/__tests__/DifferentialChangesetParserTestCase.php',
'DifferentialChangesetRenderer' => 'applications/differential/render/DifferentialChangesetRenderer.php',
'DifferentialChangesetTestRenderer' => 'applications/differential/render/DifferentialChangesetTestRenderer.php',
'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php',
'DifferentialChangesetTwoUpTestRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpTestRenderer.php',
'DifferentialChangesetViewController' => 'applications/differential/controller/DifferentialChangesetViewController.php',
'DifferentialComment' => 'applications/differential/storage/DifferentialComment.php',
'DifferentialCommentEditor' => 'applications/differential/editor/DifferentialCommentEditor.php',
'DifferentialCommentMail' => 'applications/differential/mail/DifferentialCommentMail.php',
'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php',
'DifferentialCommentQuery' => 'applications/differential/query/DifferentialCommentQuery.php',
'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php',
'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/DifferentialCommitsFieldSpecification.php',
'DifferentialConflictsFieldSpecification' => 'applications/differential/field/specification/DifferentialConflictsFieldSpecification.php',
'DifferentialController' => 'applications/differential/controller/DifferentialController.php',
'DifferentialCustomFieldNumericIndex' => 'applications/differential/storage/DifferentialCustomFieldNumericIndex.php',
'DifferentialCustomFieldStorage' => 'applications/differential/storage/DifferentialCustomFieldStorage.php',
'DifferentialCustomFieldStringIndex' => 'applications/differential/storage/DifferentialCustomFieldStringIndex.php',
'DifferentialDAO' => 'applications/differential/storage/DifferentialDAO.php',
'DifferentialDateCreatedFieldSpecification' => 'applications/differential/field/specification/DifferentialDateCreatedFieldSpecification.php',
'DifferentialDateModifiedFieldSpecification' => 'applications/differential/field/specification/DifferentialDateModifiedFieldSpecification.php',
'DifferentialDefaultFieldSelector' => 'applications/differential/field/selector/DifferentialDefaultFieldSelector.php',
'DifferentialDependenciesFieldSpecification' => 'applications/differential/field/specification/DifferentialDependenciesFieldSpecification.php',
'DifferentialDependsOnFieldSpecification' => 'applications/differential/field/specification/DifferentialDependsOnFieldSpecification.php',
'DifferentialDiff' => 'applications/differential/storage/DifferentialDiff.php',
'DifferentialDiffContentMail' => 'applications/differential/mail/DifferentialDiffContentMail.php',
'DifferentialDiffCreateController' => 'applications/differential/controller/DifferentialDiffCreateController.php',
'DifferentialDiffProperty' => 'applications/differential/storage/DifferentialDiffProperty.php',
'DifferentialDiffQuery' => 'applications/differential/query/DifferentialDiffQuery.php',
'DifferentialDiffTableOfContentsView' => 'applications/differential/view/DifferentialDiffTableOfContentsView.php',
'DifferentialDiffTestCase' => 'applications/differential/storage/__tests__/DifferentialDiffTestCase.php',
'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php',
'DifferentialDiffViewPolicyFieldSpecification' => 'applications/differential/field/specification/DifferentialDiffViewPolicyFieldSpecification.php',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'applications/differential/doorkeeper/DifferentialDoorkeeperRevisionFeedStoryPublisher.php',
'DifferentialEditPolicyFieldSpecification' => 'applications/differential/field/specification/DifferentialEditPolicyFieldSpecification.php',
'DifferentialException' => 'applications/differential/exception/DifferentialException.php',
'DifferentialExceptionMail' => 'applications/differential/mail/DifferentialExceptionMail.php',
'DifferentialExportPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialExportPatchFieldSpecification.php',
'DifferentialFieldDataNotAvailableException' => 'applications/differential/field/exception/DifferentialFieldDataNotAvailableException.php',
'DifferentialFieldParseException' => 'applications/differential/field/exception/DifferentialFieldParseException.php',
'DifferentialFieldSelector' => 'applications/differential/field/selector/DifferentialFieldSelector.php',
'DifferentialFieldSpecification' => 'applications/differential/field/specification/DifferentialFieldSpecification.php',
'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/DifferentialFieldSpecificationIncompleteException.php',
'DifferentialFieldValidationException' => 'applications/differential/field/exception/DifferentialFieldValidationException.php',
'DifferentialFreeformFieldSpecification' => 'applications/differential/field/specification/DifferentialFreeformFieldSpecification.php',
'DifferentialFreeformFieldTestCase' => 'applications/differential/field/specification/__tests__/DifferentialFreeformFieldTestCase.php',
'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/DifferentialGitSVNIDFieldSpecification.php',
'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/DifferentialHostFieldSpecification.php',
'DifferentialHovercardEventListener' => 'applications/differential/event/DifferentialHovercardEventListener.php',
'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php',
'DifferentialHunkParser' => 'applications/differential/parser/DifferentialHunkParser.php',
'DifferentialHunkParserTestCase' => 'applications/differential/parser/__tests__/DifferentialHunkParserTestCase.php',
'DifferentialHunkTestCase' => 'applications/differential/storage/__tests__/DifferentialHunkTestCase.php',
'DifferentialInlineComment' => 'applications/differential/storage/DifferentialInlineComment.php',
'DifferentialInlineCommentEditController' => 'applications/differential/controller/DifferentialInlineCommentEditController.php',
'DifferentialInlineCommentEditView' => 'applications/differential/view/DifferentialInlineCommentEditView.php',
'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/DifferentialInlineCommentPreviewController.php',
'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php',
'DifferentialInlineCommentView' => 'applications/differential/view/DifferentialInlineCommentView.php',
'DifferentialJIRAIssuesFieldSpecification' => 'applications/differential/field/specification/DifferentialJIRAIssuesFieldSpecification.php',
'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/DifferentialLinesFieldSpecification.php',
'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/DifferentialLintFieldSpecification.php',
'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php',
'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php',
'DifferentialMail' => 'applications/differential/mail/DifferentialMail.php',
'DifferentialMailPhase' => 'applications/differential/constants/DifferentialMailPhase.php',
'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/DifferentialManiphestTasksFieldSpecification.php',
'DifferentialNewDiffMail' => 'applications/differential/mail/DifferentialNewDiffMail.php',
'DifferentialPHIDTypeRevision' => 'applications/differential/phid/DifferentialPHIDTypeRevision.php',
'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php',
'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/DifferentialPathFieldSpecification.php',
'DifferentialPrimaryPaneView' => 'applications/differential/view/DifferentialPrimaryPaneView.php',
'DifferentialProjectReviewersFieldSpecification' => 'applications/differential/field/specification/DifferentialProjectReviewersFieldSpecification.php',
'DifferentialRawDiffRenderer' => 'applications/differential/render/DifferentialRawDiffRenderer.php',
'DifferentialReleephRequestFieldSpecification' => 'applications/releeph/differential/DifferentialReleephRequestFieldSpecification.php',
'DifferentialRemarkupRule' => 'applications/differential/remarkup/DifferentialRemarkupRule.php',
'DifferentialReplyHandler' => 'applications/differential/mail/DifferentialReplyHandler.php',
'DifferentialRepositoryFieldSpecification' => 'applications/differential/field/specification/DifferentialRepositoryFieldSpecification.php',
'DifferentialRepositoryLookup' => 'applications/differential/query/DifferentialRepositoryLookup.php',
'DifferentialResultsTableView' => 'applications/differential/view/DifferentialResultsTableView.php',
'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/DifferentialRevertPlanFieldSpecification.php',
'DifferentialReviewRequestMail' => 'applications/differential/mail/DifferentialReviewRequestMail.php',
'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewedByFieldSpecification.php',
'DifferentialReviewer' => 'applications/differential/storage/DifferentialReviewer.php',
'DifferentialReviewerStatus' => 'applications/differential/constants/DifferentialReviewerStatus.php',
'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewersFieldSpecification.php',
'DifferentialReviewersView' => 'applications/differential/view/DifferentialReviewersView.php',
'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php',
'DifferentialRevisionCommentListView' => 'applications/differential/view/DifferentialRevisionCommentListView.php',
'DifferentialRevisionCommentView' => 'applications/differential/view/DifferentialRevisionCommentView.php',
'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php',
'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/DifferentialRevisionDetailRenderer.php',
'DifferentialRevisionDetailView' => 'applications/differential/view/DifferentialRevisionDetailView.php',
'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php',
'DifferentialRevisionEditor' => 'applications/differential/editor/DifferentialRevisionEditor.php',
'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/__tests__/DifferentialRevisionIDFieldParserTestCase.php',
'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/DifferentialRevisionIDFieldSpecification.php',
'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php',
'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php',
'DifferentialRevisionMailReceiver' => 'applications/differential/mail/DifferentialRevisionMailReceiver.php',
'DifferentialRevisionQuery' => 'applications/differential/query/DifferentialRevisionQuery.php',
'DifferentialRevisionSearchEngine' => 'applications/differential/query/DifferentialRevisionSearchEngine.php',
'DifferentialRevisionStatsView' => 'applications/differential/view/DifferentialRevisionStatsView.php',
'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php',
'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/DifferentialRevisionStatusFieldSpecification.php',
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/DifferentialRevisionUpdateHistoryView.php',
'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php',
'DifferentialSearchIndexer' => 'applications/differential/search/DifferentialSearchIndexer.php',
'DifferentialSubscribeController' => 'applications/differential/controller/DifferentialSubscribeController.php',
'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/DifferentialSummaryFieldSpecification.php',
'DifferentialTasksAttacher' => 'applications/differential/DifferentialTasksAttacher.php',
'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/DifferentialTestPlanFieldSpecification.php',
'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/DifferentialTitleFieldSpecification.php',
'DifferentialTransaction' => 'applications/differential/storage/DifferentialTransaction.php',
'DifferentialTransactionComment' => 'applications/differential/storage/DifferentialTransactionComment.php',
'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/DifferentialUnitFieldSpecification.php',
'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php',
'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php',
'DifferentialViewPolicyFieldSpecification' => 'applications/differential/field/specification/DifferentialViewPolicyFieldSpecification.php',
'DiffusionBranchInformation' => 'applications/diffusion/data/DiffusionBranchInformation.php',
'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php',
'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php',
'DiffusionBrowseController' => 'applications/diffusion/controller/DiffusionBrowseController.php',
'DiffusionBrowseDirectoryController' => 'applications/diffusion/controller/DiffusionBrowseDirectoryController.php',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/DiffusionBrowseFileController.php',
'DiffusionBrowseMainController' => 'applications/diffusion/controller/DiffusionBrowseMainController.php',
'DiffusionBrowseResultSet' => 'applications/diffusion/data/DiffusionBrowseResultSet.php',
'DiffusionBrowseSearchController' => 'applications/diffusion/controller/DiffusionBrowseSearchController.php',
'DiffusionBrowseTableView' => 'applications/diffusion/view/DiffusionBrowseTableView.php',
+ 'DiffusionCapabilityCreateRepositories' => 'applications/diffusion/capability/DiffusionCapabilityCreateRepositories.php',
+ 'DiffusionCapabilityDefaultEdit' => 'applications/diffusion/capability/DiffusionCapabilityDefaultEdit.php',
+ 'DiffusionCapabilityDefaultPush' => 'applications/diffusion/capability/DiffusionCapabilityDefaultPush.php',
+ 'DiffusionCapabilityDefaultView' => 'applications/diffusion/capability/DiffusionCapabilityDefaultView.php',
+ 'DiffusionCapabilityPush' => 'applications/diffusion/capability/DiffusionCapabilityPush.php',
'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php',
'DiffusionCommentListView' => 'applications/diffusion/view/DiffusionCommentListView.php',
'DiffusionCommentView' => 'applications/diffusion/view/DiffusionCommentView.php',
'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php',
'DiffusionCommitChangeTableView' => 'applications/diffusion/view/DiffusionCommitChangeTableView.php',
'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php',
'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php',
'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php',
'DiffusionCommitQuery' => 'applications/diffusion/query/DiffusionCommitQuery.php',
'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php',
'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php',
'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php',
'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'applications/diffusion/doorkeeper/DiffusionDoorkeeperCommitFeedStoryPublisher.php',
'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php',
'DiffusionExpandCommitQueryException' => 'applications/diffusion/exception/DiffusionExpandCommitQueryException.php',
'DiffusionExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionExpandShortNameQuery.php',
'DiffusionExternalController' => 'applications/diffusion/controller/DiffusionExternalController.php',
'DiffusionFileContent' => 'applications/diffusion/data/DiffusionFileContent.php',
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionFileContentQuery.php',
'DiffusionGitBranch' => 'applications/diffusion/data/DiffusionGitBranch.php',
'DiffusionGitBranchTestCase' => 'applications/diffusion/data/__tests__/DiffusionGitBranchTestCase.php',
'DiffusionGitCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionGitCommitParentsQuery.php',
'DiffusionGitExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionGitExpandShortNameQuery.php',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php',
'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php',
'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php',
+ 'DiffusionGitResponse' => 'applications/diffusion/response/DiffusionGitResponse.php',
'DiffusionGitStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php',
'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php',
'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php',
'DiffusionHovercardEventListener' => 'applications/diffusion/events/DiffusionHovercardEventListener.php',
'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php',
'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php',
'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php',
'DiffusionLintController' => 'applications/diffusion/controller/DiffusionLintController.php',
'DiffusionLintDetailsController' => 'applications/diffusion/controller/DiffusionLintDetailsController.php',
'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php',
'DiffusionMercurialCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionMercurialCommitParentsQuery.php',
'DiffusionMercurialExpandShortNameQuery' => 'applications/diffusion/query/expandshortname/DiffusionMercurialExpandShortNameQuery.php',
'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php',
'DiffusionMercurialRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionMercurialRawDiffQuery.php',
'DiffusionMercurialRequest' => 'applications/diffusion/request/DiffusionMercurialRequest.php',
'DiffusionMercurialStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionMercurialStableCommitNameQuery.php',
'DiffusionPathChange' => 'applications/diffusion/data/DiffusionPathChange.php',
'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/DiffusionPathChangeQuery.php',
'DiffusionPathCompleteController' => 'applications/diffusion/controller/DiffusionPathCompleteController.php',
'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/DiffusionPathIDQuery.php',
'DiffusionPathQuery' => 'applications/diffusion/query/DiffusionPathQuery.php',
'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php',
'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php',
'DiffusionQuery' => 'applications/diffusion/query/DiffusionQuery.php',
'DiffusionRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php',
'DiffusionRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRemarkupRule.php',
'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php',
'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php',
'DiffusionRepositoryCreateController' => 'applications/diffusion/controller/DiffusionRepositoryCreateController.php',
+ 'DiffusionRepositoryDefaultController' => 'applications/diffusion/controller/DiffusionRepositoryDefaultController.php',
'DiffusionRepositoryEditActionsController' => 'applications/diffusion/controller/DiffusionRepositoryEditActionsController.php',
'DiffusionRepositoryEditActivateController' => 'applications/diffusion/controller/DiffusionRepositoryEditActivateController.php',
'DiffusionRepositoryEditBasicController' => 'applications/diffusion/controller/DiffusionRepositoryEditBasicController.php',
'DiffusionRepositoryEditBranchesController' => 'applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php',
'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php',
'DiffusionRepositoryEditDeleteController' => 'applications/diffusion/controller/DiffusionRepositoryEditDeleteController.php',
'DiffusionRepositoryEditEncodingController' => 'applications/diffusion/controller/DiffusionRepositoryEditEncodingController.php',
+ 'DiffusionRepositoryEditHostingController' => 'applications/diffusion/controller/DiffusionRepositoryEditHostingController.php',
'DiffusionRepositoryEditLocalController' => 'applications/diffusion/controller/DiffusionRepositoryEditLocalController.php',
'DiffusionRepositoryEditMainController' => 'applications/diffusion/controller/DiffusionRepositoryEditMainController.php',
'DiffusionRepositoryEditPolicyController' => 'applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php',
'DiffusionRepositoryEditSubversionController' => 'applications/diffusion/controller/DiffusionRepositoryEditSubversionController.php',
'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php',
'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php',
'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php',
'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php',
+ 'DiffusionSSHGitReceivePackWorkflow' => 'applications/diffusion/ssh/DiffusionSSHGitReceivePackWorkflow.php',
+ 'DiffusionSSHGitUploadPackWorkflow' => 'applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php',
+ 'DiffusionSSHGitWorkflow' => 'applications/diffusion/ssh/DiffusionSSHGitWorkflow.php',
+ 'DiffusionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSSHWorkflow.php',
'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php',
'DiffusionStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionStableCommitNameQuery.php',
'DiffusionSvnCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionSvnCommitParentsQuery.php',
'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php',
'DiffusionSvnRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionSvnRawDiffQuery.php',
'DiffusionSvnRequest' => 'applications/diffusion/request/DiffusionSvnRequest.php',
'DiffusionSvnStableCommitNameQuery' => 'applications/diffusion/query/stablecommitname/DiffusionSvnStableCommitNameQuery.php',
'DiffusionSymbolController' => 'applications/diffusion/controller/DiffusionSymbolController.php',
'DiffusionSymbolQuery' => 'applications/diffusion/query/DiffusionSymbolQuery.php',
'DiffusionTagListController' => 'applications/diffusion/controller/DiffusionTagListController.php',
'DiffusionTagListView' => 'applications/diffusion/view/DiffusionTagListView.php',
'DiffusionURITestCase' => 'applications/diffusion/request/__tests__/DiffusionURITestCase.php',
'DiffusionView' => 'applications/diffusion/view/DiffusionView.php',
'DivinerArticleAtomizer' => 'applications/diviner/atomizer/DivinerArticleAtomizer.php',
'DivinerAtom' => 'applications/diviner/atom/DivinerAtom.php',
'DivinerAtomCache' => 'applications/diviner/cache/DivinerAtomCache.php',
'DivinerAtomController' => 'applications/diviner/controller/DivinerAtomController.php',
'DivinerAtomListController' => 'applications/diviner/controller/DivinerAtomListController.php',
'DivinerAtomQuery' => 'applications/diviner/query/DivinerAtomQuery.php',
'DivinerAtomRef' => 'applications/diviner/atom/DivinerAtomRef.php',
'DivinerAtomSearchEngine' => 'applications/diviner/query/DivinerAtomSearchEngine.php',
'DivinerAtomizeWorkflow' => 'applications/diviner/workflow/DivinerAtomizeWorkflow.php',
'DivinerAtomizer' => 'applications/diviner/atomizer/DivinerAtomizer.php',
'DivinerBookController' => 'applications/diviner/controller/DivinerBookController.php',
'DivinerBookItemView' => 'applications/diviner/view/DivinerBookItemView.php',
'DivinerBookQuery' => 'applications/diviner/query/DivinerBookQuery.php',
'DivinerController' => 'applications/diviner/controller/DivinerController.php',
'DivinerDAO' => 'applications/diviner/storage/DivinerDAO.php',
'DivinerDefaultRenderer' => 'applications/diviner/renderer/DivinerDefaultRenderer.php',
'DivinerDiskCache' => 'applications/diviner/cache/DivinerDiskCache.php',
'DivinerFileAtomizer' => 'applications/diviner/atomizer/DivinerFileAtomizer.php',
'DivinerFindController' => 'applications/diviner/controller/DivinerFindController.php',
'DivinerGenerateWorkflow' => 'applications/diviner/workflow/DivinerGenerateWorkflow.php',
'DivinerLegacyController' => 'applications/diviner/controller/DivinerLegacyController.php',
'DivinerLiveAtom' => 'applications/diviner/storage/DivinerLiveAtom.php',
'DivinerLiveBook' => 'applications/diviner/storage/DivinerLiveBook.php',
'DivinerLivePublisher' => 'applications/diviner/publisher/DivinerLivePublisher.php',
'DivinerLiveSymbol' => 'applications/diviner/storage/DivinerLiveSymbol.php',
'DivinerPHIDTypeAtom' => 'applications/diviner/phid/DivinerPHIDTypeAtom.php',
'DivinerPHIDTypeBook' => 'applications/diviner/phid/DivinerPHIDTypeBook.php',
'DivinerPHPAtomizer' => 'applications/diviner/atomizer/DivinerPHPAtomizer.php',
'DivinerParameterTableView' => 'applications/diviner/view/DivinerParameterTableView.php',
'DivinerPublishCache' => 'applications/diviner/cache/DivinerPublishCache.php',
'DivinerPublisher' => 'applications/diviner/publisher/DivinerPublisher.php',
'DivinerRemarkupRuleSymbol' => 'applications/diviner/markup/DivinerRemarkupRuleSymbol.php',
'DivinerRenderer' => 'applications/diviner/renderer/DivinerRenderer.php',
'DivinerReturnTableView' => 'applications/diviner/view/DivinerReturnTableView.php',
'DivinerSectionView' => 'applications/diviner/view/DivinerSectionView.php',
'DivinerStaticPublisher' => 'applications/diviner/publisher/DivinerStaticPublisher.php',
'DivinerWorkflow' => 'applications/diviner/workflow/DivinerWorkflow.php',
'DoorkeeperBridge' => 'applications/doorkeeper/bridge/DoorkeeperBridge.php',
'DoorkeeperBridgeAsana' => 'applications/doorkeeper/bridge/DoorkeeperBridgeAsana.php',
'DoorkeeperBridgeJIRA' => 'applications/doorkeeper/bridge/DoorkeeperBridgeJIRA.php',
'DoorkeeperDAO' => 'applications/doorkeeper/storage/DoorkeeperDAO.php',
'DoorkeeperExternalObject' => 'applications/doorkeeper/storage/DoorkeeperExternalObject.php',
'DoorkeeperExternalObjectQuery' => 'applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php',
'DoorkeeperFeedStoryPublisher' => 'applications/doorkeeper/engine/DoorkeeperFeedStoryPublisher.php',
'DoorkeeperFeedWorker' => 'applications/doorkeeper/worker/DoorkeeperFeedWorker.php',
'DoorkeeperFeedWorkerAsana' => 'applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php',
'DoorkeeperFeedWorkerJIRA' => 'applications/doorkeeper/worker/DoorkeeperFeedWorkerJIRA.php',
'DoorkeeperImportEngine' => 'applications/doorkeeper/engine/DoorkeeperImportEngine.php',
'DoorkeeperObjectRef' => 'applications/doorkeeper/engine/DoorkeeperObjectRef.php',
'DoorkeeperRemarkupRule' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php',
'DoorkeeperRemarkupRuleAsana' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRuleAsana.php',
'DoorkeeperRemarkupRuleJIRA' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRuleJIRA.php',
'DoorkeeperTagsController' => 'applications/doorkeeper/controller/DoorkeeperTagsController.php',
'DrydockAllocatorWorker' => 'applications/drydock/worker/DrydockAllocatorWorker.php',
'DrydockApacheWebrootInterface' => 'applications/drydock/interface/webroot/DrydockApacheWebrootInterface.php',
'DrydockBlueprint' => 'applications/drydock/blueprint/DrydockBlueprint.php',
'DrydockBlueprintScopeGuard' => 'applications/drydock/util/DrydockBlueprintScopeGuard.php',
'DrydockCommandInterface' => 'applications/drydock/interface/command/DrydockCommandInterface.php',
'DrydockConstants' => 'applications/drydock/constants/DrydockConstants.php',
'DrydockController' => 'applications/drydock/controller/DrydockController.php',
'DrydockDAO' => 'applications/drydock/storage/DrydockDAO.php',
'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php',
'DrydockLease' => 'applications/drydock/storage/DrydockLease.php',
'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php',
'DrydockLeaseQuery' => 'applications/drydock/query/DrydockLeaseQuery.php',
'DrydockLeaseReleaseController' => 'applications/drydock/controller/DrydockLeaseReleaseController.php',
'DrydockLeaseStatus' => 'applications/drydock/constants/DrydockLeaseStatus.php',
'DrydockLeaseViewController' => 'applications/drydock/controller/DrydockLeaseViewController.php',
'DrydockLocalCommandInterface' => 'applications/drydock/interface/command/DrydockLocalCommandInterface.php',
'DrydockLocalHostBlueprint' => 'applications/drydock/blueprint/DrydockLocalHostBlueprint.php',
'DrydockLog' => 'applications/drydock/storage/DrydockLog.php',
'DrydockLogController' => 'applications/drydock/controller/DrydockLogController.php',
'DrydockLogQuery' => 'applications/drydock/query/DrydockLogQuery.php',
'DrydockManagementCloseWorkflow' => 'applications/drydock/management/DrydockManagementCloseWorkflow.php',
'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php',
'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php',
'DrydockManagementWaitForLeaseWorkflow' => 'applications/drydock/management/DrydockManagementWaitForLeaseWorkflow.php',
'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php',
'DrydockResource' => 'applications/drydock/storage/DrydockResource.php',
'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php',
'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php',
'DrydockResourceQuery' => 'applications/drydock/query/DrydockResourceQuery.php',
'DrydockResourceStatus' => 'applications/drydock/constants/DrydockResourceStatus.php',
'DrydockResourceViewController' => 'applications/drydock/controller/DrydockResourceViewController.php',
'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/DrydockSSHCommandInterface.php',
'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php',
'DrydockWorkingCopyBlueprint' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprint.php',
'FeedPublisherHTTPWorker' => 'applications/feed/worker/FeedPublisherHTTPWorker.php',
'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php',
'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php',
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
'FileReplyHandler' => 'applications/files/mail/FileReplyHandler.php',
'HarbormasterBuild' => 'applications/harbormaster/storage/build/HarbormasterBuild.php',
'HarbormasterBuildArtifact' => 'applications/harbormaster/storage/build/HarbormasterBuildArtifact.php',
'HarbormasterBuildItem' => 'applications/harbormaster/storage/build/HarbormasterBuildItem.php',
'HarbormasterBuildItemQuery' => 'applications/harbormaster/query/HarbormasterBuildItemQuery.php',
'HarbormasterBuildLog' => 'applications/harbormaster/storage/build/HarbormasterBuildLog.php',
'HarbormasterBuildPlan' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlan.php',
'HarbormasterBuildPlanEditor' => 'applications/harbormaster/editor/HarbormasterBuildPlanEditor.php',
'HarbormasterBuildPlanQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanQuery.php',
'HarbormasterBuildPlanSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildPlanSearchEngine.php',
'HarbormasterBuildPlanTransaction' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlanTransaction.php',
'HarbormasterBuildPlanTransactionComment' => 'applications/harbormaster/storage/configuration/HarbormasterBuildPlanTransactionComment.php',
'HarbormasterBuildPlanTransactionQuery' => 'applications/harbormaster/query/HarbormasterBuildPlanTransactionQuery.php',
'HarbormasterBuildQuery' => 'applications/harbormaster/query/HarbormasterBuildQuery.php',
'HarbormasterBuildStep' => 'applications/harbormaster/storage/configuration/HarbormasterBuildStep.php',
'HarbormasterBuildStepQuery' => 'applications/harbormaster/query/HarbormasterBuildStepQuery.php',
'HarbormasterBuildTarget' => 'applications/harbormaster/storage/build/HarbormasterBuildTarget.php',
'HarbormasterBuildTargetQuery' => 'applications/harbormaster/query/HarbormasterBuildTargetQuery.php',
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
'HarbormasterBuildableArtifactQuery' => 'applications/harbormaster/query/HarbormasterBuildableArtifactQuery.php',
'HarbormasterBuildableEditController' => 'applications/harbormaster/controller/HarbormasterBuildableEditController.php',
'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php',
'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php',
'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php',
'HarbormasterBuildableViewController' => 'applications/harbormaster/controller/HarbormasterBuildableViewController.php',
'HarbormasterCapabilityManagePlans' => 'applications/harbormaster/capability/HarbormasterCapabilityManagePlans.php',
'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php',
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
'HarbormasterPHIDTypeBuild' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuild.php',
'HarbormasterPHIDTypeBuildItem' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildItem.php',
'HarbormasterPHIDTypeBuildPlan' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildPlan.php',
'HarbormasterPHIDTypeBuildStep' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildStep.php',
'HarbormasterPHIDTypeBuildTarget' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildTarget.php',
'HarbormasterPHIDTypeBuildable' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildable.php',
'HarbormasterPlanController' => 'applications/harbormaster/controller/HarbormasterPlanController.php',
'HarbormasterPlanEditController' => 'applications/harbormaster/controller/HarbormasterPlanEditController.php',
'HarbormasterPlanExecuteController' => 'applications/harbormaster/controller/HarbormasterPlanExecuteController.php',
'HarbormasterPlanListController' => 'applications/harbormaster/controller/HarbormasterPlanListController.php',
'HarbormasterPlanViewController' => 'applications/harbormaster/controller/HarbormasterPlanViewController.php',
'HarbormasterRemarkupRule' => 'applications/harbormaster/remarkup/HarbormasterRemarkupRule.php',
'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php',
'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php',
'HeraldAction' => 'applications/herald/storage/HeraldAction.php',
'HeraldAdapter' => 'applications/herald/adapter/HeraldAdapter.php',
'HeraldApplyTranscript' => 'applications/herald/storage/transcript/HeraldApplyTranscript.php',
'HeraldCapabilityManageGlobalRules' => 'applications/herald/capability/HeraldCapabilityManageGlobalRules.php',
'HeraldCommitAdapter' => 'applications/herald/adapter/HeraldCommitAdapter.php',
'HeraldCondition' => 'applications/herald/storage/HeraldCondition.php',
'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php',
'HeraldController' => 'applications/herald/controller/HeraldController.php',
'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php',
'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/HeraldDifferentialRevisionAdapter.php',
'HeraldDisableController' => 'applications/herald/controller/HeraldDisableController.php',
'HeraldEditLogQuery' => 'applications/herald/query/HeraldEditLogQuery.php',
'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php',
'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php',
'HeraldInvalidActionException' => 'applications/herald/engine/exception/HeraldInvalidActionException.php',
'HeraldInvalidConditionException' => 'applications/herald/engine/exception/HeraldInvalidConditionException.php',
'HeraldInvalidFieldException' => 'applications/herald/engine/exception/HeraldInvalidFieldException.php',
'HeraldManiphestTaskAdapter' => 'applications/herald/adapter/HeraldManiphestTaskAdapter.php',
'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php',
'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php',
'HeraldPHIDTypeRule' => 'applications/herald/phid/HeraldPHIDTypeRule.php',
'HeraldPholioMockAdapter' => 'applications/herald/adapter/HeraldPholioMockAdapter.php',
'HeraldRecursiveConditionsException' => 'applications/herald/engine/exception/HeraldRecursiveConditionsException.php',
'HeraldRepetitionPolicyConfig' => 'applications/herald/config/HeraldRepetitionPolicyConfig.php',
'HeraldRule' => 'applications/herald/storage/HeraldRule.php',
'HeraldRuleController' => 'applications/herald/controller/HeraldRuleController.php',
'HeraldRuleEdit' => 'applications/herald/storage/HeraldRuleEdit.php',
'HeraldRuleEditHistoryController' => 'applications/herald/controller/HeraldRuleEditHistoryController.php',
'HeraldRuleEditHistoryView' => 'applications/herald/view/HeraldRuleEditHistoryView.php',
'HeraldRuleEditor' => 'applications/herald/editor/HeraldRuleEditor.php',
'HeraldRuleListController' => 'applications/herald/controller/HeraldRuleListController.php',
'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php',
'HeraldRuleSearchEngine' => 'applications/herald/query/HeraldRuleSearchEngine.php',
'HeraldRuleTransaction' => 'applications/herald/storage/HeraldRuleTransaction.php',
'HeraldRuleTransactionComment' => 'applications/herald/storage/HeraldRuleTransactionComment.php',
'HeraldRuleTranscript' => 'applications/herald/storage/transcript/HeraldRuleTranscript.php',
'HeraldRuleTypeConfig' => 'applications/herald/config/HeraldRuleTypeConfig.php',
'HeraldRuleViewController' => 'applications/herald/controller/HeraldRuleViewController.php',
'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php',
'HeraldTransactionQuery' => 'applications/herald/query/HeraldTransactionQuery.php',
'HeraldTranscript' => 'applications/herald/storage/transcript/HeraldTranscript.php',
'HeraldTranscriptController' => 'applications/herald/controller/HeraldTranscriptController.php',
'HeraldTranscriptListController' => 'applications/herald/controller/HeraldTranscriptListController.php',
'HeraldTranscriptQuery' => 'applications/herald/query/HeraldTranscriptQuery.php',
'Javelin' => 'infrastructure/javelin/Javelin.php',
'JavelinReactorExample' => 'applications/uiexample/examples/JavelinReactorExample.php',
'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php',
'JavelinViewExample' => 'applications/uiexample/examples/JavelinViewExample.php',
'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php',
'LegalpadConstants' => 'applications/legalpad/constants/LegalpadConstants.php',
'LegalpadController' => 'applications/legalpad/controller/LegalpadController.php',
'LegalpadDAO' => 'applications/legalpad/storage/LegalpadDAO.php',
'LegalpadDocument' => 'applications/legalpad/storage/LegalpadDocument.php',
'LegalpadDocumentBody' => 'applications/legalpad/storage/LegalpadDocumentBody.php',
'LegalpadDocumentCommentController' => 'applications/legalpad/controller/LegalpadDocumentCommentController.php',
'LegalpadDocumentEditController' => 'applications/legalpad/controller/LegalpadDocumentEditController.php',
'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php',
'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php',
'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php',
'LegalpadDocumentSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSearchEngine.php',
'LegalpadDocumentSignController' => 'applications/legalpad/controller/LegalpadDocumentSignController.php',
'LegalpadDocumentSignature' => 'applications/legalpad/storage/LegalpadDocumentSignature.php',
'LegalpadDocumentViewController' => 'applications/legalpad/controller/LegalpadDocumentViewController.php',
'LegalpadMockMailReceiver' => 'applications/legalpad/mail/LegalpadMockMailReceiver.php',
'LegalpadReplyHandler' => 'applications/legalpad/mail/LegalpadReplyHandler.php',
'LegalpadTransaction' => 'applications/legalpad/storage/LegalpadTransaction.php',
'LegalpadTransactionComment' => 'applications/legalpad/storage/LegalpadTransactionComment.php',
'LegalpadTransactionQuery' => 'applications/legalpad/query/LegalpadTransactionQuery.php',
'LegalpadTransactionType' => 'applications/legalpad/constants/LegalpadTransactionType.php',
'LegalpadTransactionView' => 'applications/legalpad/view/LegalpadTransactionView.php',
'LiskChunkTestCase' => 'infrastructure/storage/lisk/__tests__/LiskChunkTestCase.php',
'LiskDAO' => 'infrastructure/storage/lisk/LiskDAO.php',
'LiskDAOSet' => 'infrastructure/storage/lisk/LiskDAOSet.php',
'LiskDAOTestCase' => 'infrastructure/storage/lisk/__tests__/LiskDAOTestCase.php',
'LiskEphemeralObjectException' => 'infrastructure/storage/lisk/LiskEphemeralObjectException.php',
'LiskFixtureTestCase' => 'infrastructure/storage/lisk/__tests__/LiskFixtureTestCase.php',
'LiskIsolationTestCase' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestCase.php',
'LiskIsolationTestDAO' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAO.php',
'LiskIsolationTestDAOException' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAOException.php',
'LiskMigrationIterator' => 'infrastructure/storage/lisk/LiskMigrationIterator.php',
'LiskRawMigrationIterator' => 'infrastructure/storage/lisk/LiskRawMigrationIterator.php',
'ManiphestActionMenuEventListener' => 'applications/maniphest/event/ManiphestActionMenuEventListener.php',
'ManiphestBatchEditController' => 'applications/maniphest/controller/ManiphestBatchEditController.php',
'ManiphestCapabilityBulkEdit' => 'applications/maniphest/capability/ManiphestCapabilityBulkEdit.php',
'ManiphestCapabilityDefaultEdit' => 'applications/maniphest/capability/ManiphestCapabilityDefaultEdit.php',
'ManiphestCapabilityDefaultView' => 'applications/maniphest/capability/ManiphestCapabilityDefaultView.php',
'ManiphestCapabilityEditAssign' => 'applications/maniphest/capability/ManiphestCapabilityEditAssign.php',
'ManiphestCapabilityEditPolicies' => 'applications/maniphest/capability/ManiphestCapabilityEditPolicies.php',
'ManiphestCapabilityEditPriority' => 'applications/maniphest/capability/ManiphestCapabilityEditPriority.php',
'ManiphestCapabilityEditProjects' => 'applications/maniphest/capability/ManiphestCapabilityEditProjects.php',
'ManiphestCapabilityEditStatus' => 'applications/maniphest/capability/ManiphestCapabilityEditStatus.php',
'ManiphestConfiguredCustomField' => 'applications/maniphest/field/ManiphestConfiguredCustomField.php',
'ManiphestConstants' => 'applications/maniphest/constants/ManiphestConstants.php',
'ManiphestController' => 'applications/maniphest/controller/ManiphestController.php',
'ManiphestCreateMailReceiver' => 'applications/maniphest/mail/ManiphestCreateMailReceiver.php',
'ManiphestCustomField' => 'applications/maniphest/field/ManiphestCustomField.php',
'ManiphestCustomFieldNumericIndex' => 'applications/maniphest/storage/ManiphestCustomFieldNumericIndex.php',
'ManiphestCustomFieldStorage' => 'applications/maniphest/storage/ManiphestCustomFieldStorage.php',
'ManiphestCustomFieldStringIndex' => 'applications/maniphest/storage/ManiphestCustomFieldStringIndex.php',
'ManiphestDAO' => 'applications/maniphest/storage/ManiphestDAO.php',
'ManiphestEdgeEventListener' => 'applications/maniphest/event/ManiphestEdgeEventListener.php',
'ManiphestExcelDefaultFormat' => 'applications/maniphest/export/ManiphestExcelDefaultFormat.php',
'ManiphestExcelFormat' => 'applications/maniphest/export/ManiphestExcelFormat.php',
'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php',
'ManiphestHovercardEventListener' => 'applications/maniphest/event/ManiphestHovercardEventListener.php',
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
'ManiphestNameIndexEventListener' => 'applications/maniphest/event/ManiphestNameIndexEventListener.php',
'ManiphestPHIDTypeTask' => 'applications/maniphest/phid/ManiphestPHIDTypeTask.php',
'ManiphestRemarkupRule' => 'applications/maniphest/remarkup/ManiphestRemarkupRule.php',
'ManiphestReplyHandler' => 'applications/maniphest/mail/ManiphestReplyHandler.php',
'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php',
'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php',
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
'ManiphestSubscribeController' => 'applications/maniphest/controller/ManiphestSubscribeController.php',
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/ManiphestTaskDescriptionPreviewController.php',
'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php',
'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php',
'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php',
'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php',
'ManiphestTaskMailReceiver' => 'applications/maniphest/mail/ManiphestTaskMailReceiver.php',
'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php',
'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php',
'ManiphestTaskProject' => 'applications/maniphest/storage/ManiphestTaskProject.php',
'ManiphestTaskProjectsView' => 'applications/maniphest/view/ManiphestTaskProjectsView.php',
'ManiphestTaskQuery' => 'applications/maniphest/query/ManiphestTaskQuery.php',
'ManiphestTaskSearchEngine' => 'applications/maniphest/query/ManiphestTaskSearchEngine.php',
'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php',
'ManiphestTaskSubscriber' => 'applications/maniphest/storage/ManiphestTaskSubscriber.php',
'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php',
'ManiphestTransactionComment' => 'applications/maniphest/storage/ManiphestTransactionComment.php',
'ManiphestTransactionEditor' => 'applications/maniphest/editor/ManiphestTransactionEditor.php',
'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/ManiphestTransactionPreviewController.php',
'ManiphestTransactionQuery' => 'applications/maniphest/query/ManiphestTransactionQuery.php',
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/ManiphestTransactionSaveController.php',
'ManiphestView' => 'applications/maniphest/view/ManiphestView.php',
'MetaMTAConstants' => 'applications/metamta/constants/MetaMTAConstants.php',
'MetaMTANotificationType' => 'applications/metamta/constants/MetaMTANotificationType.php',
'MetaMTAReceivedMailStatus' => 'applications/metamta/constants/MetaMTAReceivedMailStatus.php',
'OwnersPackageReplyHandler' => 'applications/owners/mail/OwnersPackageReplyHandler.php',
'PHUI' => 'view/phui/PHUI.php',
'PHUIBoxExample' => 'applications/uiexample/examples/PHUIBoxExample.php',
'PHUIBoxView' => 'view/phui/PHUIBoxView.php',
'PHUIButtonExample' => 'applications/uiexample/examples/PHUIButtonExample.php',
'PHUIButtonView' => 'view/phui/PHUIButtonView.php',
'PHUIColorPalletteExample' => 'applications/uiexample/examples/PHUIColorPalletteExample.php',
'PHUIDocumentExample' => 'applications/uiexample/examples/PHUIDocumentExample.php',
'PHUIDocumentView' => 'view/phui/PHUIDocumentView.php',
'PHUIFeedStoryExample' => 'applications/uiexample/examples/PHUIFeedStoryExample.php',
'PHUIFeedStoryView' => 'view/phui/PHUIFeedStoryView.php',
'PHUIFormDividerControl' => 'view/form/control/PHUIFormDividerControl.php',
'PHUIFormFreeformDateControl' => 'view/form/control/PHUIFormFreeformDateControl.php',
'PHUIFormLayoutView' => 'view/form/PHUIFormLayoutView.php',
'PHUIFormMultiSubmitControl' => 'view/form/control/PHUIFormMultiSubmitControl.php',
'PHUIFormPageView' => 'view/form/PHUIFormPageView.php',
'PHUIHeaderView' => 'view/phui/PHUIHeaderView.php',
'PHUIIconExample' => 'applications/uiexample/examples/PHUIIconExample.php',
'PHUIIconView' => 'view/phui/PHUIIconView.php',
'PHUIInfoPanelExample' => 'applications/uiexample/examples/PHUIInfoPanelExample.php',
'PHUIInfoPanelView' => 'view/phui/PHUIInfoPanelView.php',
'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php',
'PHUIListItemView' => 'view/phui/PHUIListItemView.php',
'PHUIListView' => 'view/phui/PHUIListView.php',
'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.php',
'PHUIObjectBoxView' => 'view/phui/PHUIObjectBoxView.php',
'PHUIObjectItemListExample' => 'applications/uiexample/examples/PHUIObjectItemListExample.php',
'PHUIObjectItemListView' => 'view/phui/PHUIObjectItemListView.php',
'PHUIObjectItemView' => 'view/phui/PHUIObjectItemView.php',
'PHUIPagedFormView' => 'view/form/PHUIPagedFormView.php',
'PHUIPinboardItemView' => 'view/phui/PHUIPinboardItemView.php',
'PHUIPinboardView' => 'view/phui/PHUIPinboardView.php',
'PHUIPropertyGroupView' => 'view/phui/PHUIPropertyGroupView.php',
'PHUIPropertyListExample' => 'applications/uiexample/examples/PHUIPropertyListExample.php',
'PHUIPropertyListView' => 'view/phui/PHUIPropertyListView.php',
'PHUIRemarkupPreviewPanel' => 'view/phui/PHUIRemarkupPreviewPanel.php',
'PHUIStatusItemView' => 'view/phui/PHUIStatusItemView.php',
'PHUIStatusListView' => 'view/phui/PHUIStatusListView.php',
'PHUITextExample' => 'applications/uiexample/examples/PHUITextExample.php',
'PHUITextView' => 'view/phui/PHUITextView.php',
'PHUIWorkboardExample' => 'applications/uiexample/examples/PHUIWorkboardExample.php',
'PHUIWorkboardView' => 'view/phui/PHUIWorkboardView.php',
'PHUIWorkpanelView' => 'view/phui/PHUIWorkpanelView.php',
'PackageCreateMail' => 'applications/owners/mail/PackageCreateMail.php',
'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php',
'PackageMail' => 'applications/owners/mail/PackageMail.php',
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
'PasteCapabilityDefaultView' => 'applications/paste/capability/PasteCapabilityDefaultView.php',
'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php',
'PasteEmbedView' => 'applications/paste/view/PasteEmbedView.php',
'PasteMockMailReceiver' => 'applications/paste/mail/PasteMockMailReceiver.php',
'PasteReplyHandler' => 'applications/paste/mail/PasteReplyHandler.php',
'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php',
'PhabricatorAWSConfigOptions' => 'applications/config/option/PhabricatorAWSConfigOptions.php',
'PhabricatorAccessControlTestCase' => 'applications/base/controller/__tests__/PhabricatorAccessControlTestCase.php',
'PhabricatorAccessLog' => 'infrastructure/PhabricatorAccessLog.php',
'PhabricatorAccessLogConfigOptions' => 'applications/config/option/PhabricatorAccessLogConfigOptions.php',
'PhabricatorActionHeaderExample' => 'applications/uiexample/examples/PhabricatorActionHeaderExample.php',
'PhabricatorActionHeaderView' => 'view/layout/PhabricatorActionHeaderView.php',
'PhabricatorActionListExample' => 'applications/uiexample/examples/PhabricatorActionListExample.php',
'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php',
'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php',
'PhabricatorAllCapsTranslation' => 'infrastructure/internationalization/PhabricatorAllCapsTranslation.php',
'PhabricatorAnchorView' => 'view/layout/PhabricatorAnchorView.php',
'PhabricatorAphrontBarExample' => 'applications/uiexample/examples/PhabricatorAphrontBarExample.php',
'PhabricatorAphrontViewTestCase' => 'view/__tests__/PhabricatorAphrontViewTestCase.php',
'PhabricatorAppSearchEngine' => 'applications/meta/query/PhabricatorAppSearchEngine.php',
'PhabricatorApplication' => 'applications/base/PhabricatorApplication.php',
'PhabricatorApplicationApplications' => 'applications/meta/application/PhabricatorApplicationApplications.php',
'PhabricatorApplicationAudit' => 'applications/audit/application/PhabricatorApplicationAudit.php',
'PhabricatorApplicationAuth' => 'applications/auth/application/PhabricatorApplicationAuth.php',
'PhabricatorApplicationCalendar' => 'applications/calendar/application/PhabricatorApplicationCalendar.php',
'PhabricatorApplicationChatLog' => 'applications/chatlog/applications/PhabricatorApplicationChatLog.php',
'PhabricatorApplicationConduit' => 'applications/conduit/application/PhabricatorApplicationConduit.php',
'PhabricatorApplicationConfig' => 'applications/config/application/PhabricatorApplicationConfig.php',
'PhabricatorApplicationConfigOptions' => 'applications/config/option/PhabricatorApplicationConfigOptions.php',
'PhabricatorApplicationConpherence' => 'applications/conpherence/application/PhabricatorApplicationConpherence.php',
'PhabricatorApplicationCountdown' => 'applications/countdown/application/PhabricatorApplicationCountdown.php',
'PhabricatorApplicationDaemons' => 'applications/daemon/application/PhabricatorApplicationDaemons.php',
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
'PhabricatorApplicationDifferential' => 'applications/differential/application/PhabricatorApplicationDifferential.php',
'PhabricatorApplicationDiffusion' => 'applications/diffusion/application/PhabricatorApplicationDiffusion.php',
'PhabricatorApplicationDiviner' => 'applications/diviner/application/PhabricatorApplicationDiviner.php',
'PhabricatorApplicationDoorkeeper' => 'applications/doorkeeper/application/PhabricatorApplicationDoorkeeper.php',
'PhabricatorApplicationDrydock' => 'applications/drydock/application/PhabricatorApplicationDrydock.php',
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
'PhabricatorApplicationFact' => 'applications/fact/application/PhabricatorApplicationFact.php',
'PhabricatorApplicationFeed' => 'applications/feed/application/PhabricatorApplicationFeed.php',
'PhabricatorApplicationFiles' => 'applications/files/application/PhabricatorApplicationFiles.php',
'PhabricatorApplicationFlags' => 'applications/flag/application/PhabricatorApplicationFlags.php',
'PhabricatorApplicationHarbormaster' => 'applications/harbormaster/application/PhabricatorApplicationHarbormaster.php',
'PhabricatorApplicationHerald' => 'applications/herald/application/PhabricatorApplicationHerald.php',
'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php',
'PhabricatorApplicationLegalpad' => 'applications/legalpad/application/PhabricatorApplicationLegalpad.php',
'PhabricatorApplicationMacro' => 'applications/macro/application/PhabricatorApplicationMacro.php',
'PhabricatorApplicationMailingLists' => 'applications/mailinglists/application/PhabricatorApplicationMailingLists.php',
'PhabricatorApplicationManiphest' => 'applications/maniphest/application/PhabricatorApplicationManiphest.php',
'PhabricatorApplicationMetaMTA' => 'applications/metamta/application/PhabricatorApplicationMetaMTA.php',
'PhabricatorApplicationOwners' => 'applications/owners/application/PhabricatorApplicationOwners.php',
'PhabricatorApplicationPHIDTypeApplication' => 'applications/meta/phid/PhabricatorApplicationPHIDTypeApplication.php',
'PhabricatorApplicationPHPAST' => 'applications/phpast/application/PhabricatorApplicationPHPAST.php',
'PhabricatorApplicationPaste' => 'applications/paste/application/PhabricatorApplicationPaste.php',
'PhabricatorApplicationPeople' => 'applications/people/application/PhabricatorApplicationPeople.php',
'PhabricatorApplicationPhame' => 'applications/phame/application/PhabricatorApplicationPhame.php',
'PhabricatorApplicationPhlux' => 'applications/phlux/application/PhabricatorApplicationPhlux.php',
'PhabricatorApplicationPholio' => 'applications/pholio/application/PhabricatorApplicationPholio.php',
'PhabricatorApplicationPhortune' => 'applications/phortune/application/PhabricatorApplicationPhortune.php',
'PhabricatorApplicationPhrequent' => 'applications/phrequent/application/PhabricatorApplicationPhrequent.php',
'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php',
'PhabricatorApplicationPolicy' => 'applications/policy/application/PhabricatorApplicationPolicy.php',
'PhabricatorApplicationPonder' => 'applications/ponder/application/PhabricatorApplicationPonder.php',
'PhabricatorApplicationProject' => 'applications/project/application/PhabricatorApplicationProject.php',
'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php',
'PhabricatorApplicationReleeph' => 'applications/releeph/application/PhabricatorApplicationReleeph.php',
'PhabricatorApplicationReleephConfigOptions' => 'applications/releeph/config/PhabricatorApplicationReleephConfigOptions.php',
'PhabricatorApplicationRepositories' => 'applications/repository/application/PhabricatorApplicationRepositories.php',
'PhabricatorApplicationSearch' => 'applications/search/application/PhabricatorApplicationSearch.php',
'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php',
'PhabricatorApplicationSearchEngine' => 'applications/search/engine/PhabricatorApplicationSearchEngine.php',
'PhabricatorApplicationSearchResultsControllerInterface' => 'applications/search/interface/PhabricatorApplicationSearchResultsControllerInterface.php',
'PhabricatorApplicationSettings' => 'applications/settings/application/PhabricatorApplicationSettings.php',
'PhabricatorApplicationSlowvote' => 'applications/slowvote/application/PhabricatorApplicationSlowvote.php',
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
'PhabricatorApplicationSubscriptions' => 'applications/subscriptions/application/PhabricatorApplicationSubscriptions.php',
'PhabricatorApplicationTest' => 'applications/base/controller/__tests__/PhabricatorApplicationTest.php',
'PhabricatorApplicationTokens' => 'applications/tokens/application/PhabricatorApplicationTokens.php',
'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php',
'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php',
'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php',
'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php',
'PhabricatorApplicationTransactionCommentHistoryController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php',
'PhabricatorApplicationTransactionCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php',
'PhabricatorApplicationTransactionCommentView' => 'applications/transactions/view/PhabricatorApplicationTransactionCommentView.php',
'PhabricatorApplicationTransactionController' => 'applications/transactions/controller/PhabricatorApplicationTransactionController.php',
'PhabricatorApplicationTransactionDetailController' => 'applications/transactions/controller/PhabricatorApplicationTransactionDetailController.php',
'PhabricatorApplicationTransactionEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionEditor.php',
'PhabricatorApplicationTransactionFeedStory' => 'applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php',
'PhabricatorApplicationTransactionInterface' => 'applications/transactions/interface/PhabricatorApplicationTransactionInterface.php',
'PhabricatorApplicationTransactionNoEffectException' => 'applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php',
'PhabricatorApplicationTransactionNoEffectResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php',
'PhabricatorApplicationTransactionPHIDTypeTransaction' => 'applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php',
'PhabricatorApplicationTransactionQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionQuery.php',
'PhabricatorApplicationTransactionResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionResponse.php',
'PhabricatorApplicationTransactionTextDiffDetailView' => 'applications/transactions/view/PhabricatorApplicationTransactionTextDiffDetailView.php',
'PhabricatorApplicationTransactionValidationError' => 'applications/transactions/error/PhabricatorApplicationTransactionValidationError.php',
'PhabricatorApplicationTransactionValidationException' => 'applications/transactions/exception/PhabricatorApplicationTransactionValidationException.php',
'PhabricatorApplicationTransactionView' => 'applications/transactions/view/PhabricatorApplicationTransactionView.php',
'PhabricatorApplicationTransactions' => 'applications/transactions/application/PhabricatorApplicationTransactions.php',
'PhabricatorApplicationUIExamples' => 'applications/uiexample/application/PhabricatorApplicationUIExamples.php',
'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php',
'PhabricatorApplicationXHProf' => 'applications/xhprof/application/PhabricatorApplicationXHProf.php',
'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php',
'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php',
'PhabricatorAsanaConfigOptions' => 'applications/doorkeeper/option/PhabricatorAsanaConfigOptions.php',
'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php',
'PhabricatorAuditAddCommentController' => 'applications/audit/controller/PhabricatorAuditAddCommentController.php',
'PhabricatorAuditComment' => 'applications/audit/storage/PhabricatorAuditComment.php',
'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php',
'PhabricatorAuditCommitListView' => 'applications/audit/view/PhabricatorAuditCommitListView.php',
'PhabricatorAuditCommitQuery' => 'applications/audit/query/PhabricatorAuditCommitQuery.php',
'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php',
'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php',
'PhabricatorAuditDAO' => 'applications/audit/storage/PhabricatorAuditDAO.php',
'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php',
'PhabricatorAuditListController' => 'applications/audit/controller/PhabricatorAuditListController.php',
'PhabricatorAuditListView' => 'applications/audit/view/PhabricatorAuditListView.php',
'PhabricatorAuditMailReceiver' => 'applications/audit/mail/PhabricatorAuditMailReceiver.php',
'PhabricatorAuditManagementDeleteWorkflow' => 'applications/audit/management/PhabricatorAuditManagementDeleteWorkflow.php',
'PhabricatorAuditManagementWorkflow' => 'applications/audit/management/PhabricatorAuditManagementWorkflow.php',
'PhabricatorAuditPreviewController' => 'applications/audit/controller/PhabricatorAuditPreviewController.php',
'PhabricatorAuditQuery' => 'applications/audit/query/PhabricatorAuditQuery.php',
'PhabricatorAuditReplyHandler' => 'applications/audit/mail/PhabricatorAuditReplyHandler.php',
'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php',
'PhabricatorAuthAccountView' => 'applications/auth/view/PhabricatorAuthAccountView.php',
'PhabricatorAuthConfirmLinkController' => 'applications/auth/controller/PhabricatorAuthConfirmLinkController.php',
'PhabricatorAuthController' => 'applications/auth/controller/PhabricatorAuthController.php',
'PhabricatorAuthDAO' => 'applications/auth/storage/PhabricatorAuthDAO.php',
'PhabricatorAuthDisableController' => 'applications/auth/controller/config/PhabricatorAuthDisableController.php',
'PhabricatorAuthEditController' => 'applications/auth/controller/config/PhabricatorAuthEditController.php',
'PhabricatorAuthLinkController' => 'applications/auth/controller/PhabricatorAuthLinkController.php',
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
'PhabricatorAuthManagementLDAPWorkflow' => 'applications/auth/management/PhabricatorAuthManagementLDAPWorkflow.php',
'PhabricatorAuthManagementRecoverWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRecoverWorkflow.php',
'PhabricatorAuthManagementRefreshWorkflow' => 'applications/auth/management/PhabricatorAuthManagementRefreshWorkflow.php',
'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php',
'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php',
'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php',
'PhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorAuthProvider.php',
'PhabricatorAuthProviderConfig' => 'applications/auth/storage/PhabricatorAuthProviderConfig.php',
'PhabricatorAuthProviderConfigController' => 'applications/auth/controller/config/PhabricatorAuthProviderConfigController.php',
'PhabricatorAuthProviderConfigEditor' => 'applications/auth/editor/PhabricatorAuthProviderConfigEditor.php',
'PhabricatorAuthProviderConfigQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigQuery.php',
'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php',
'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php',
'PhabricatorAuthProviderLDAP' => 'applications/auth/provider/PhabricatorAuthProviderLDAP.php',
'PhabricatorAuthProviderOAuth' => 'applications/auth/provider/PhabricatorAuthProviderOAuth.php',
'PhabricatorAuthProviderOAuth1' => 'applications/auth/provider/PhabricatorAuthProviderOAuth1.php',
'PhabricatorAuthProviderOAuth1JIRA' => 'applications/auth/provider/PhabricatorAuthProviderOAuth1JIRA.php',
'PhabricatorAuthProviderOAuth1Twitter' => 'applications/auth/provider/PhabricatorAuthProviderOAuth1Twitter.php',
'PhabricatorAuthProviderOAuthAmazon' => 'applications/auth/provider/PhabricatorAuthProviderOAuthAmazon.php',
'PhabricatorAuthProviderOAuthAsana' => 'applications/auth/provider/PhabricatorAuthProviderOAuthAsana.php',
'PhabricatorAuthProviderOAuthDisqus' => 'applications/auth/provider/PhabricatorAuthProviderOAuthDisqus.php',
'PhabricatorAuthProviderOAuthFacebook' => 'applications/auth/provider/PhabricatorAuthProviderOAuthFacebook.php',
'PhabricatorAuthProviderOAuthGitHub' => 'applications/auth/provider/PhabricatorAuthProviderOAuthGitHub.php',
'PhabricatorAuthProviderOAuthGoogle' => 'applications/auth/provider/PhabricatorAuthProviderOAuthGoogle.php',
'PhabricatorAuthProviderOAuthTwitch' => 'applications/auth/provider/PhabricatorAuthProviderOAuthTwitch.php',
'PhabricatorAuthProviderPassword' => 'applications/auth/provider/PhabricatorAuthProviderPassword.php',
'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php',
'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php',
'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php',
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php',
'PhabricatorBarePageExample' => 'applications/uiexample/examples/PhabricatorBarePageExample.php',
'PhabricatorBarePageView' => 'view/page/PhabricatorBarePageView.php',
'PhabricatorBaseEnglishTranslation' => 'infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php',
'PhabricatorBaseProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorBaseProtocolAdapter.php',
'PhabricatorBot' => 'infrastructure/daemon/bot/PhabricatorBot.php',
'PhabricatorBotBaseStreamingProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorBotBaseStreamingProtocolAdapter.php',
'PhabricatorBotChannel' => 'infrastructure/daemon/bot/target/PhabricatorBotChannel.php',
'PhabricatorBotDebugLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php',
'PhabricatorBotDifferentialNotificationHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotDifferentialNotificationHandler.php',
'PhabricatorBotFeedNotificationHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php',
'PhabricatorBotFlowdockProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorBotFlowdockProtocolAdapter.php',
'PhabricatorBotHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotHandler.php',
'PhabricatorBotLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php',
'PhabricatorBotMacroHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php',
'PhabricatorBotMessage' => 'infrastructure/daemon/bot/PhabricatorBotMessage.php',
'PhabricatorBotObjectNameHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php',
'PhabricatorBotSymbolHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php',
'PhabricatorBotTarget' => 'infrastructure/daemon/bot/target/PhabricatorBotTarget.php',
'PhabricatorBotUser' => 'infrastructure/daemon/bot/target/PhabricatorBotUser.php',
'PhabricatorBotWhatsNewHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php',
'PhabricatorBuiltinPatchList' => 'infrastructure/storage/patch/PhabricatorBuiltinPatchList.php',
'PhabricatorBusyExample' => 'applications/uiexample/examples/PhabricatorBusyExample.php',
'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php',
'PhabricatorCacheManagementPurgeWorkflow' => 'applications/cache/management/PhabricatorCacheManagementPurgeWorkflow.php',
'PhabricatorCacheManagementWorkflow' => 'applications/cache/management/PhabricatorCacheManagementWorkflow.php',
'PhabricatorCaches' => 'applications/cache/PhabricatorCaches.php',
'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/PhabricatorCalendarBrowseController.php',
'PhabricatorCalendarController' => 'applications/calendar/controller/PhabricatorCalendarController.php',
'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php',
'PhabricatorCalendarDeleteStatusController' => 'applications/calendar/controller/PhabricatorCalendarDeleteStatusController.php',
'PhabricatorCalendarEditStatusController' => 'applications/calendar/controller/PhabricatorCalendarEditStatusController.php',
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
'PhabricatorCalendarViewStatusController' => 'applications/calendar/controller/PhabricatorCalendarViewStatusController.php',
'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php',
'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php',
'PhabricatorChatLogChannel' => 'applications/chatlog/storage/PhabricatorChatLogChannel.php',
'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php',
'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/PhabricatorChatLogChannelLogController.php',
'PhabricatorChatLogChannelQuery' => 'applications/chatlog/PhabricatorChatLogChannelQuery.php',
'PhabricatorChatLogConstants' => 'applications/chatlog/constants/PhabricatorChatLogConstants.php',
'PhabricatorChatLogController' => 'applications/chatlog/controller/PhabricatorChatLogController.php',
'PhabricatorChatLogDAO' => 'applications/chatlog/storage/PhabricatorChatLogDAO.php',
'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php',
'PhabricatorChatLogEventType' => 'applications/chatlog/constants/PhabricatorChatLogEventType.php',
'PhabricatorChatLogQuery' => 'applications/chatlog/PhabricatorChatLogQuery.php',
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
'PhabricatorConduitConfigOptions' => 'applications/conduit/config/PhabricatorConduitConfigOptions.php',
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php',
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
'PhabricatorConduitDAO' => 'applications/conduit/storage/PhabricatorConduitDAO.php',
'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php',
'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php',
'PhabricatorConduitLogQuery' => 'applications/conduit/query/PhabricatorConduitLogQuery.php',
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php',
'PhabricatorConduitMethodQuery' => 'applications/conduit/query/PhabricatorConduitMethodQuery.php',
'PhabricatorConduitSearchEngine' => 'applications/conduit/query/PhabricatorConduitSearchEngine.php',
'PhabricatorConduitTokenController' => 'applications/conduit/controller/PhabricatorConduitTokenController.php',
'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php',
'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php',
'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php',
'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php',
'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php',
'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php',
'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php',
'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php',
'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php',
'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php',
'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php',
'PhabricatorConfigGroupController' => 'applications/config/controller/PhabricatorConfigGroupController.php',
'PhabricatorConfigIgnoreController' => 'applications/config/controller/PhabricatorConfigIgnoreController.php',
'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php',
'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php',
'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php',
'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php',
'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php',
'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php',
'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php',
'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php',
'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php',
'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php',
'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php',
'PhabricatorConfigOptionType' => 'applications/config/custom/PhabricatorConfigOptionType.php',
'PhabricatorConfigPHIDTypeConfig' => 'applications/config/phid/PhabricatorConfigPHIDTypeConfig.php',
'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php',
'PhabricatorConfigResponse' => 'applications/config/response/PhabricatorConfigResponse.php',
'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php',
'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php',
'PhabricatorConfigTransaction' => 'applications/config/storage/PhabricatorConfigTransaction.php',
'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php',
'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php',
'PhabricatorConpherencePHIDTypeThread' => 'applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php',
'PhabricatorContentSource' => 'applications/metamta/contentsource/PhabricatorContentSource.php',
'PhabricatorContentSourceView' => 'applications/metamta/contentsource/PhabricatorContentSourceView.php',
'PhabricatorController' => 'applications/base/controller/PhabricatorController.php',
'PhabricatorCoreConfigOptions' => 'applications/config/option/PhabricatorCoreConfigOptions.php',
'PhabricatorCountdown' => 'applications/countdown/storage/PhabricatorCountdown.php',
'PhabricatorCountdownCapabilityDefaultView' => 'applications/countdown/capability/PhabricatorCountdownCapabilityDefaultView.php',
'PhabricatorCountdownController' => 'applications/countdown/controller/PhabricatorCountdownController.php',
'PhabricatorCountdownDAO' => 'applications/countdown/storage/PhabricatorCountdownDAO.php',
'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/PhabricatorCountdownDeleteController.php',
'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php',
'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php',
'PhabricatorCountdownPHIDTypeCountdown' => 'applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php',
'PhabricatorCountdownQuery' => 'applications/countdown/query/PhabricatorCountdownQuery.php',
'PhabricatorCountdownRemarkupRule' => 'applications/countdown/remarkup/PhabricatorCountdownRemarkupRule.php',
'PhabricatorCountdownSearchEngine' => 'applications/countdown/query/PhabricatorCountdownSearchEngine.php',
'PhabricatorCountdownView' => 'applications/countdown/view/PhabricatorCountdownView.php',
'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php',
'PhabricatorCrumbView' => 'view/layout/PhabricatorCrumbView.php',
'PhabricatorCrumbsView' => 'view/layout/PhabricatorCrumbsView.php',
'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php',
'PhabricatorCustomField' => 'infrastructure/customfield/field/PhabricatorCustomField.php',
'PhabricatorCustomFieldAttachment' => 'infrastructure/customfield/field/PhabricatorCustomFieldAttachment.php',
'PhabricatorCustomFieldConfigOptionType' => 'infrastructure/customfield/config/PhabricatorCustomFieldConfigOptionType.php',
'PhabricatorCustomFieldDataNotAvailableException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldDataNotAvailableException.php',
'PhabricatorCustomFieldImplementationIncompleteException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldImplementationIncompleteException.php',
'PhabricatorCustomFieldIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldIndexStorage.php',
'PhabricatorCustomFieldInterface' => 'infrastructure/customfield/interface/PhabricatorCustomFieldInterface.php',
'PhabricatorCustomFieldList' => 'infrastructure/customfield/field/PhabricatorCustomFieldList.php',
'PhabricatorCustomFieldNotAttachedException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotAttachedException.php',
'PhabricatorCustomFieldNotProxyException' => 'infrastructure/customfield/exception/PhabricatorCustomFieldNotProxyException.php',
'PhabricatorCustomFieldNumericIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldNumericIndexStorage.php',
'PhabricatorCustomFieldStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStorage.php',
'PhabricatorCustomFieldStringIndexStorage' => 'infrastructure/customfield/storage/PhabricatorCustomFieldStringIndexStorage.php',
'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php',
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/PhabricatorDaemonCombinedLogController.php',
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/PhabricatorDaemonConsoleController.php',
'PhabricatorDaemonController' => 'applications/daemon/controller/PhabricatorDaemonController.php',
'PhabricatorDaemonDAO' => 'applications/daemon/storage/PhabricatorDaemonDAO.php',
'PhabricatorDaemonEventListener' => 'applications/daemon/event/PhabricatorDaemonEventListener.php',
'PhabricatorDaemonLog' => 'applications/daemon/storage/PhabricatorDaemonLog.php',
'PhabricatorDaemonLogEvent' => 'applications/daemon/storage/PhabricatorDaemonLogEvent.php',
'PhabricatorDaemonLogEventViewController' => 'applications/daemon/controller/PhabricatorDaemonLogEventViewController.php',
'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/PhabricatorDaemonLogEventsView.php',
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/PhabricatorDaemonLogListController.php',
'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php',
'PhabricatorDaemonLogQuery' => 'applications/daemon/query/PhabricatorDaemonLogQuery.php',
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php',
'PhabricatorDaemonManagementDebugWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementDebugWorkflow.php',
'PhabricatorDaemonManagementLaunchWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementLaunchWorkflow.php',
'PhabricatorDaemonManagementListWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementListWorkflow.php',
'PhabricatorDaemonManagementLogWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementLogWorkflow.php',
'PhabricatorDaemonManagementRestartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php',
'PhabricatorDaemonManagementStartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStartWorkflow.php',
'PhabricatorDaemonManagementStatusWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php',
'PhabricatorDaemonManagementStopWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php',
'PhabricatorDaemonManagementWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementWorkflow.php',
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php',
'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php',
'PhabricatorDebugController' => 'applications/system/PhabricatorDebugController.php',
'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php',
'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/PhabricatorDefaultSearchEngineSelector.php',
'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php',
'PhabricatorDifferenceEngine' => 'infrastructure/diff/PhabricatorDifferenceEngine.php',
'PhabricatorDifferentialConfigOptions' => 'applications/differential/config/PhabricatorDifferentialConfigOptions.php',
'PhabricatorDifferentialRevisionTestDataGenerator' => 'applications/differential/lipsum/PhabricatorDifferentialRevisionTestDataGenerator.php',
'PhabricatorDiffusionConfigOptions' => 'applications/diffusion/config/PhabricatorDiffusionConfigOptions.php',
'PhabricatorDirectoryController' => 'applications/directory/controller/PhabricatorDirectoryController.php',
'PhabricatorDirectoryMainController' => 'applications/directory/controller/PhabricatorDirectoryMainController.php',
'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php',
'PhabricatorDisqusConfigOptions' => 'applications/config/option/PhabricatorDisqusConfigOptions.php',
'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php',
'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php',
'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php',
'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php',
'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php',
'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/PhabricatorEdgeEditor.php',
'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php',
'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php',
'PhabricatorEdgeTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeTestCase.php',
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php',
'PhabricatorEmailTokenController' => 'applications/auth/controller/PhabricatorEmailTokenController.php',
'PhabricatorEmailVerificationController' => 'applications/auth/controller/PhabricatorEmailVerificationController.php',
'PhabricatorEmptyQueryException' => 'infrastructure/query/PhabricatorEmptyQueryException.php',
'PhabricatorEnglishTranslation' => 'infrastructure/internationalization/PhabricatorEnglishTranslation.php',
'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php',
'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php',
'PhabricatorErrorExample' => 'applications/uiexample/examples/PhabricatorErrorExample.php',
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
'PhabricatorEventListener' => 'infrastructure/events/PhabricatorEventListener.php',
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php',
'PhabricatorExternalAccount' => 'applications/people/storage/PhabricatorExternalAccount.php',
'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php',
'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.php',
'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php',
'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php',
'PhabricatorFactCountEngine' => 'applications/fact/engine/PhabricatorFactCountEngine.php',
'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php',
'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php',
'PhabricatorFactDaemon' => 'applications/fact/daemon/PhabricatorFactDaemon.php',
'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php',
'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php',
'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.php',
'PhabricatorFactManagementAnalyzeWorkflow' => 'applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php',
'PhabricatorFactManagementCursorsWorkflow' => 'applications/fact/management/PhabricatorFactManagementCursorsWorkflow.php',
'PhabricatorFactManagementDestroyWorkflow' => 'applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php',
'PhabricatorFactManagementListWorkflow' => 'applications/fact/management/PhabricatorFactManagementListWorkflow.php',
'PhabricatorFactManagementStatusWorkflow' => 'applications/fact/management/PhabricatorFactManagementStatusWorkflow.php',
'PhabricatorFactManagementWorkflow' => 'applications/fact/management/PhabricatorFactManagementWorkflow.php',
'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php',
'PhabricatorFactSimpleSpec' => 'applications/fact/spec/PhabricatorFactSimpleSpec.php',
'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php',
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php',
'PhabricatorFeedConfigOptions' => 'applications/feed/config/PhabricatorFeedConfigOptions.php',
'PhabricatorFeedConstants' => 'applications/feed/constants/PhabricatorFeedConstants.php',
'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php',
'PhabricatorFeedDAO' => 'applications/feed/storage/PhabricatorFeedDAO.php',
'PhabricatorFeedDetailController' => 'applications/feed/controller/PhabricatorFeedDetailController.php',
'PhabricatorFeedListController' => 'applications/feed/controller/PhabricatorFeedListController.php',
'PhabricatorFeedManagementRepublishWorkflow' => 'applications/feed/management/PhabricatorFeedManagementRepublishWorkflow.php',
'PhabricatorFeedManagementWorkflow' => 'applications/feed/management/PhabricatorFeedManagementWorkflow.php',
'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/PhabricatorFeedPublicStreamController.php',
'PhabricatorFeedQuery' => 'applications/feed/query/PhabricatorFeedQuery.php',
'PhabricatorFeedSearchEngine' => 'applications/feed/query/PhabricatorFeedSearchEngine.php',
'PhabricatorFeedStory' => 'applications/feed/story/PhabricatorFeedStory.php',
'PhabricatorFeedStoryAggregate' => 'applications/feed/story/PhabricatorFeedStoryAggregate.php',
'PhabricatorFeedStoryAudit' => 'applications/feed/story/PhabricatorFeedStoryAudit.php',
'PhabricatorFeedStoryCommit' => 'applications/feed/story/PhabricatorFeedStoryCommit.php',
'PhabricatorFeedStoryData' => 'applications/feed/storage/PhabricatorFeedStoryData.php',
'PhabricatorFeedStoryDifferential' => 'applications/feed/story/PhabricatorFeedStoryDifferential.php',
'PhabricatorFeedStoryDifferentialAggregate' => 'applications/feed/story/PhabricatorFeedStoryDifferentialAggregate.php',
'PhabricatorFeedStoryManiphestAggregate' => 'applications/feed/story/PhabricatorFeedStoryManiphestAggregate.php',
'PhabricatorFeedStoryNotification' => 'applications/notification/storage/PhabricatorFeedStoryNotification.php',
'PhabricatorFeedStoryPhriction' => 'applications/feed/story/PhabricatorFeedStoryPhriction.php',
'PhabricatorFeedStoryPublisher' => 'applications/feed/PhabricatorFeedStoryPublisher.php',
'PhabricatorFeedStoryReference' => 'applications/feed/storage/PhabricatorFeedStoryReference.php',
'PhabricatorFeedStoryStatus' => 'applications/feed/story/PhabricatorFeedStoryStatus.php',
'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/PhabricatorFeedStoryTypeConstants.php',
'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php',
'PhabricatorFileBundleLoader' => 'applications/files/query/PhabricatorFileBundleLoader.php',
'PhabricatorFileCommentController' => 'applications/files/controller/PhabricatorFileCommentController.php',
'PhabricatorFileComposeController' => 'applications/files/controller/PhabricatorFileComposeController.php',
'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php',
'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php',
'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php',
'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php',
'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php',
'PhabricatorFileEditor' => 'applications/files/editor/PhabricatorFileEditor.php',
'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php',
'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php',
'PhabricatorFileLinkListView' => 'view/layout/PhabricatorFileLinkListView.php',
'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php',
'PhabricatorFileListController' => 'applications/files/controller/PhabricatorFileListController.php',
'PhabricatorFilePHIDTypeFile' => 'applications/files/phid/PhabricatorFilePHIDTypeFile.php',
'PhabricatorFileQuery' => 'applications/files/query/PhabricatorFileQuery.php',
'PhabricatorFileSearchEngine' => 'applications/files/query/PhabricatorFileSearchEngine.php',
'PhabricatorFileShortcutController' => 'applications/files/controller/PhabricatorFileShortcutController.php',
'PhabricatorFileStorageBlob' => 'applications/files/storage/PhabricatorFileStorageBlob.php',
'PhabricatorFileStorageConfigurationException' => 'applications/files/exception/PhabricatorFileStorageConfigurationException.php',
'PhabricatorFileStorageEngine' => 'applications/files/engine/PhabricatorFileStorageEngine.php',
'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorFileStorageEngineSelector.php',
'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.php',
'PhabricatorFileTestDataGenerator' => 'applications/files/lipsum/PhabricatorFileTestDataGenerator.php',
'PhabricatorFileTransaction' => 'applications/files/storage/PhabricatorFileTransaction.php',
'PhabricatorFileTransactionComment' => 'applications/files/storage/PhabricatorFileTransactionComment.php',
'PhabricatorFileTransactionQuery' => 'applications/files/query/PhabricatorFileTransactionQuery.php',
'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php',
'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php',
'PhabricatorFileUploadDialogController' => 'applications/files/controller/PhabricatorFileUploadDialogController.php',
'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php',
'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php',
'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php',
'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php',
'PhabricatorFilesManagementPurgeWorkflow' => 'applications/files/management/PhabricatorFilesManagementPurgeWorkflow.php',
'PhabricatorFilesManagementRebuildWorkflow' => 'applications/files/management/PhabricatorFilesManagementRebuildWorkflow.php',
'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php',
'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php',
'PhabricatorFlagColor' => 'applications/flag/constants/PhabricatorFlagColor.php',
'PhabricatorFlagConstants' => 'applications/flag/constants/PhabricatorFlagConstants.php',
'PhabricatorFlagController' => 'applications/flag/controller/PhabricatorFlagController.php',
'PhabricatorFlagDAO' => 'applications/flag/storage/PhabricatorFlagDAO.php',
'PhabricatorFlagDeleteController' => 'applications/flag/controller/PhabricatorFlagDeleteController.php',
'PhabricatorFlagEditController' => 'applications/flag/controller/PhabricatorFlagEditController.php',
'PhabricatorFlagListController' => 'applications/flag/controller/PhabricatorFlagListController.php',
'PhabricatorFlagQuery' => 'applications/flag/query/PhabricatorFlagQuery.php',
'PhabricatorFlagSearchEngine' => 'applications/flag/query/PhabricatorFlagSearchEngine.php',
'PhabricatorFlagSelectControl' => 'applications/flag/view/PhabricatorFlagSelectControl.php',
'PhabricatorFlaggableInterface' => 'applications/flag/interface/PhabricatorFlaggableInterface.php',
'PhabricatorFlagsUIEventListener' => 'applications/flag/events/PhabricatorFlagsUIEventListener.php',
'PhabricatorFormExample' => 'applications/uiexample/examples/PhabricatorFormExample.php',
'PhabricatorGarbageCollectorConfigOptions' => 'applications/config/option/PhabricatorGarbageCollectorConfigOptions.php',
'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/PhabricatorGarbageCollectorDaemon.php',
'PhabricatorGestureExample' => 'applications/uiexample/examples/PhabricatorGestureExample.php',
'PhabricatorGitGraphStream' => 'applications/repository/daemon/PhabricatorGitGraphStream.php',
'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php',
'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php',
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php',
'PhabricatorHandleQuery' => 'applications/phid/query/PhabricatorHandleQuery.php',
'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php',
'PhabricatorHashTestCase' => 'infrastructure/util/__tests__/PhabricatorHashTestCase.php',
'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php',
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php',
'PhabricatorHovercardExample' => 'applications/uiexample/examples/PhabricatorHovercardExample.php',
'PhabricatorHovercardView' => 'view/widget/hovercard/PhabricatorHovercardView.php',
'PhabricatorIRCBot' => 'infrastructure/daemon/bot/PhabricatorIRCBot.php',
'PhabricatorIRCProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php',
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/bot/handler/PhabricatorIRCProtocolHandler.php',
'PhabricatorImageTransformer' => 'applications/files/PhabricatorImageTransformer.php',
'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__/PhabricatorInfrastructureTestCase.php',
'PhabricatorInlineCommentController' => 'infrastructure/diff/PhabricatorInlineCommentController.php',
'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php',
'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php',
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php',
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
'PhabricatorLegalpadConfigOptions' => 'applications/legalpad/config/PhabricatorLegalpadConfigOptions.php',
'PhabricatorLegalpadPHIDTypeDocument' => 'applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php',
'PhabricatorLintEngine' => 'infrastructure/lint/PhabricatorLintEngine.php',
'PhabricatorLipsumArtist' => 'applications/lipsum/image/PhabricatorLipsumArtist.php',
'PhabricatorLipsumGenerateWorkflow' => 'applications/lipsum/management/PhabricatorLipsumGenerateWorkflow.php',
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php',
'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php',
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php',
'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php',
'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php',
'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php',
'PhabricatorMacroCapabilityManage' => 'applications/macro/capability/PhabricatorMacroCapabilityManage.php',
'PhabricatorMacroCommentController' => 'applications/macro/controller/PhabricatorMacroCommentController.php',
'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php',
'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php',
'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php',
'PhabricatorMacroEditController' => 'applications/macro/controller/PhabricatorMacroEditController.php',
'PhabricatorMacroEditor' => 'applications/macro/editor/PhabricatorMacroEditor.php',
'PhabricatorMacroListController' => 'applications/macro/controller/PhabricatorMacroListController.php',
'PhabricatorMacroMailReceiver' => 'applications/macro/mail/PhabricatorMacroMailReceiver.php',
'PhabricatorMacroMemeController' => 'applications/macro/controller/PhabricatorMacroMemeController.php',
'PhabricatorMacroMemeDialogController' => 'applications/macro/controller/PhabricatorMacroMemeDialogController.php',
'PhabricatorMacroPHIDTypeMacro' => 'applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php',
'PhabricatorMacroQuery' => 'applications/macro/query/PhabricatorMacroQuery.php',
'PhabricatorMacroReplyHandler' => 'applications/macro/mail/PhabricatorMacroReplyHandler.php',
'PhabricatorMacroSearchEngine' => 'applications/macro/query/PhabricatorMacroSearchEngine.php',
'PhabricatorMacroTransaction' => 'applications/macro/storage/PhabricatorMacroTransaction.php',
'PhabricatorMacroTransactionComment' => 'applications/macro/storage/PhabricatorMacroTransactionComment.php',
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
'PhabricatorMacroTransactionType' => 'applications/macro/constants/PhabricatorMacroTransactionType.php',
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
'PhabricatorMail' => 'applications/metamta/PhabricatorMail.php',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php',
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php',
'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php',
'PhabricatorMailManagementResendWorkflow' => 'applications/metamta/management/PhabricatorMailManagementResendWorkflow.php',
'PhabricatorMailManagementSendTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php',
'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php',
'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php',
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
'PhabricatorMailingListPHIDTypeList' => 'applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php',
'PhabricatorMailingListQuery' => 'applications/mailinglists/query/PhabricatorMailingListQuery.php',
'PhabricatorMailingListSearchEngine' => 'applications/mailinglists/query/PhabricatorMailingListSearchEngine.php',
'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php',
'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php',
'PhabricatorMailingListsListController' => 'applications/mailinglists/controller/PhabricatorMailingListsListController.php',
'PhabricatorMainMenuGroupView' => 'view/page/menu/PhabricatorMainMenuGroupView.php',
'PhabricatorMainMenuIconView' => 'view/page/menu/PhabricatorMainMenuIconView.php',
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php',
'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php',
'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php',
'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php',
'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php',
'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php',
'PhabricatorMarkupOneOff' => 'infrastructure/markup/PhabricatorMarkupOneOff.php',
'PhabricatorMarkupPreviewController' => 'infrastructure/markup/PhabricatorMarkupPreviewController.php',
'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php',
'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php',
'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php',
'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php',
'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php',
'PhabricatorMetaMTADAO' => 'applications/metamta/storage/PhabricatorMetaMTADAO.php',
'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser/PhabricatorMetaMTAEmailBodyParser.php',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__/PhabricatorMetaMTAEmailBodyParserTestCase.php',
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php',
'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php',
'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php',
'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php',
'PhabricatorMetaMTAMailingList' => 'applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php',
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php',
'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php',
'PhabricatorMetaMTAWorker' => 'applications/metamta/PhabricatorMetaMTAWorker.php',
'PhabricatorMultiColumnExample' => 'applications/uiexample/examples/PhabricatorMultiColumnExample.php',
'PhabricatorMustVerifyEmailController' => 'applications/auth/controller/PhabricatorMustVerifyEmailController.php',
'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php',
'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php',
'PhabricatorNamedQuery' => 'applications/search/storage/PhabricatorNamedQuery.php',
'PhabricatorNamedQueryQuery' => 'applications/search/query/PhabricatorNamedQueryQuery.php',
'PhabricatorNoteExample' => 'applications/uiexample/examples/PhabricatorNoteExample.php',
'PhabricatorNotificationBuilder' => 'applications/notification/builder/PhabricatorNotificationBuilder.php',
'PhabricatorNotificationClearController' => 'applications/notification/controller/PhabricatorNotificationClearController.php',
'PhabricatorNotificationConfigOptions' => 'applications/config/option/PhabricatorNotificationConfigOptions.php',
'PhabricatorNotificationController' => 'applications/notification/controller/PhabricatorNotificationController.php',
'PhabricatorNotificationIndividualController' => 'applications/notification/controller/PhabricatorNotificationIndividualController.php',
'PhabricatorNotificationListController' => 'applications/notification/controller/PhabricatorNotificationListController.php',
'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php',
'PhabricatorNotificationQuery' => 'applications/notification/PhabricatorNotificationQuery.php',
'PhabricatorNotificationStatusController' => 'applications/notification/controller/PhabricatorNotificationStatusController.php',
'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php',
'PhabricatorOAuthClientAuthorizationBaseController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationBaseController.php',
'PhabricatorOAuthClientAuthorizationDeleteController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationDeleteController.php',
'PhabricatorOAuthClientAuthorizationEditController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationEditController.php',
'PhabricatorOAuthClientAuthorizationListController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationListController.php',
'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php',
'PhabricatorOAuthClientBaseController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientBaseController.php',
'PhabricatorOAuthClientDeleteController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientDeleteController.php',
'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientEditController.php',
'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientListController.php',
'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientViewController.php',
'PhabricatorOAuthResponse' => 'applications/oauthserver/PhabricatorOAuthResponse.php',
'PhabricatorOAuthServer' => 'applications/oauthserver/PhabricatorOAuthServer.php',
'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php',
'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php',
'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php',
'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/PhabricatorOAuthServerClient.php',
'PhabricatorOAuthServerClientQuery' => 'applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php',
'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/PhabricatorOAuthServerController.php',
'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/PhabricatorOAuthServerDAO.php',
'PhabricatorOAuthServerScope' => 'applications/oauthserver/PhabricatorOAuthServerScope.php',
'PhabricatorOAuthServerTestCase' => 'applications/oauthserver/__tests__/PhabricatorOAuthServerTestCase.php',
'PhabricatorOAuthServerTestController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTestController.php',
'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTokenController.php',
'PhabricatorObjectHandle' => 'applications/phid/PhabricatorObjectHandle.php',
'PhabricatorObjectHandleConstants' => 'applications/phid/handle/const/PhabricatorObjectHandleConstants.php',
'PhabricatorObjectHandleStatus' => 'applications/phid/handle/const/PhabricatorObjectHandleStatus.php',
'PhabricatorObjectListView' => 'view/control/PhabricatorObjectListView.php',
'PhabricatorObjectMailReceiver' => 'applications/metamta/receiver/PhabricatorObjectMailReceiver.php',
'PhabricatorObjectMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php',
'PhabricatorObjectQuery' => 'applications/phid/query/PhabricatorObjectQuery.php',
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php',
'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php',
'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php',
'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php',
'PhabricatorOwnersDeleteController' => 'applications/owners/controller/PhabricatorOwnersDeleteController.php',
'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php',
'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php',
'PhabricatorOwnersListController' => 'applications/owners/controller/PhabricatorOwnersListController.php',
'PhabricatorOwnersOwner' => 'applications/owners/storage/PhabricatorOwnersOwner.php',
'PhabricatorOwnersPHIDTypePackage' => 'applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php',
'PhabricatorOwnersPackage' => 'applications/owners/storage/PhabricatorOwnersPackage.php',
'PhabricatorOwnersPackagePathValidator' => 'applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php',
'PhabricatorOwnersPackageQuery' => 'applications/owners/query/PhabricatorOwnersPackageQuery.php',
'PhabricatorOwnersPackageTestCase' => 'applications/owners/storage/__tests__/PhabricatorOwnersPackageTestCase.php',
'PhabricatorOwnersPath' => 'applications/owners/storage/PhabricatorOwnersPath.php',
'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php',
'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php',
'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php',
'PhabricatorPHIDInterface' => 'applications/phid/interface/PhabricatorPHIDInterface.php',
'PhabricatorPHIDType' => 'applications/phid/type/PhabricatorPHIDType.php',
'PhabricatorPHPMailerConfigOptions' => 'applications/config/option/PhabricatorPHPMailerConfigOptions.php',
'PhabricatorPagedFormExample' => 'applications/uiexample/examples/PhabricatorPagedFormExample.php',
'PhabricatorPaste' => 'applications/paste/storage/PhabricatorPaste.php',
'PhabricatorPasteCommentController' => 'applications/paste/controller/PhabricatorPasteCommentController.php',
'PhabricatorPasteConfigOptions' => 'applications/paste/config/PhabricatorPasteConfigOptions.php',
'PhabricatorPasteController' => 'applications/paste/controller/PhabricatorPasteController.php',
'PhabricatorPasteDAO' => 'applications/paste/storage/PhabricatorPasteDAO.php',
'PhabricatorPasteEditController' => 'applications/paste/controller/PhabricatorPasteEditController.php',
'PhabricatorPasteEditor' => 'applications/paste/editor/PhabricatorPasteEditor.php',
'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php',
'PhabricatorPastePHIDTypePaste' => 'applications/paste/phid/PhabricatorPastePHIDTypePaste.php',
'PhabricatorPasteQuery' => 'applications/paste/query/PhabricatorPasteQuery.php',
'PhabricatorPasteRemarkupRule' => 'applications/paste/remarkup/PhabricatorPasteRemarkupRule.php',
'PhabricatorPasteSearchEngine' => 'applications/paste/query/PhabricatorPasteSearchEngine.php',
'PhabricatorPasteTestDataGenerator' => 'applications/paste/lipsum/PhabricatorPasteTestDataGenerator.php',
'PhabricatorPasteTransaction' => 'applications/paste/storage/PhabricatorPasteTransaction.php',
'PhabricatorPasteTransactionComment' => 'applications/paste/storage/PhabricatorPasteTransactionComment.php',
'PhabricatorPasteTransactionQuery' => 'applications/paste/query/PhabricatorPasteTransactionQuery.php',
'PhabricatorPasteViewController' => 'applications/paste/controller/PhabricatorPasteViewController.php',
'PhabricatorPeopleController' => 'applications/people/controller/PhabricatorPeopleController.php',
'PhabricatorPeopleEditController' => 'applications/people/controller/PhabricatorPeopleEditController.php',
'PhabricatorPeopleHovercardEventListener' => 'applications/people/event/PhabricatorPeopleHovercardEventListener.php',
'PhabricatorPeopleLdapController' => 'applications/people/controller/PhabricatorPeopleLdapController.php',
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
'PhabricatorPeoplePHIDTypeExternal' => 'applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php',
'PhabricatorPeoplePHIDTypeUser' => 'applications/people/phid/PhabricatorPeoplePHIDTypeUser.php',
'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php',
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php',
'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php',
'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php',
'PhabricatorPhameConfigOptions' => 'applications/phame/config/PhabricatorPhameConfigOptions.php',
'PhabricatorPhamePHIDTypeBlog' => 'applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php',
'PhabricatorPhamePHIDTypePost' => 'applications/phame/phid/PhabricatorPhamePHIDTypePost.php',
'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php',
'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php',
'PhabricatorPhortuneConfigOptions' => 'applications/phortune/option/PhabricatorPhortuneConfigOptions.php',
'PhabricatorPhrequentConfigOptions' => 'applications/phrequent/config/PhabricatorPhrequentConfigOptions.php',
'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php',
'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php',
'PhabricatorPolicy' => 'applications/policy/storage/PhabricatorPolicy.php',
'PhabricatorPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorPolicyAwareQuery.php',
'PhabricatorPolicyAwareTestQuery' => 'applications/policy/__tests__/PhabricatorPolicyAwareTestQuery.php',
'PhabricatorPolicyCapability' => 'applications/policy/capability/PhabricatorPolicyCapability.php',
'PhabricatorPolicyCapabilityCanEdit' => 'applications/policy/capability/PhabricatorPolicyCapabilityCanEdit.php',
'PhabricatorPolicyCapabilityCanJoin' => 'applications/policy/capability/PhabricatorPolicyCapabilityCanJoin.php',
'PhabricatorPolicyCapabilityCanView' => 'applications/policy/capability/PhabricatorPolicyCapabilityCanView.php',
'PhabricatorPolicyConfigOptions' => 'applications/policy/config/PhabricatorPolicyConfigOptions.php',
'PhabricatorPolicyConstants' => 'applications/policy/constants/PhabricatorPolicyConstants.php',
'PhabricatorPolicyController' => 'applications/policy/controller/PhabricatorPolicyController.php',
'PhabricatorPolicyDAO' => 'applications/policy/storage/PhabricatorPolicyDAO.php',
'PhabricatorPolicyDataTestCase' => 'applications/policy/__tests__/PhabricatorPolicyDataTestCase.php',
'PhabricatorPolicyEditController' => 'applications/policy/controller/PhabricatorPolicyEditController.php',
'PhabricatorPolicyException' => 'applications/policy/exception/PhabricatorPolicyException.php',
'PhabricatorPolicyExplainController' => 'applications/policy/controller/PhabricatorPolicyExplainController.php',
'PhabricatorPolicyFilter' => 'applications/policy/filter/PhabricatorPolicyFilter.php',
'PhabricatorPolicyInterface' => 'applications/policy/interface/PhabricatorPolicyInterface.php',
'PhabricatorPolicyManagementShowWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementShowWorkflow.php',
'PhabricatorPolicyManagementUnlockWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementUnlockWorkflow.php',
'PhabricatorPolicyManagementWorkflow' => 'applications/policy/management/PhabricatorPolicyManagementWorkflow.php',
'PhabricatorPolicyPHIDTypePolicy' => 'applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php',
'PhabricatorPolicyQuery' => 'applications/policy/query/PhabricatorPolicyQuery.php',
'PhabricatorPolicyRule' => 'applications/policy/rule/PhabricatorPolicyRule.php',
'PhabricatorPolicyRuleAdministrators' => 'applications/policy/rule/PhabricatorPolicyRuleAdministrators.php',
'PhabricatorPolicyRuleLunarPhase' => 'applications/policy/rule/PhabricatorPolicyRuleLunarPhase.php',
'PhabricatorPolicyRuleProjects' => 'applications/policy/rule/PhabricatorPolicyRuleProjects.php',
'PhabricatorPolicyRuleUsers' => 'applications/policy/rule/PhabricatorPolicyRuleUsers.php',
'PhabricatorPolicyTestCase' => 'applications/policy/__tests__/PhabricatorPolicyTestCase.php',
'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php',
'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php',
'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php',
'PhabricatorProjectBoardController' => 'applications/project/controller/PhabricatorProjectBoardController.php',
'PhabricatorProjectColumn' => 'applications/project/storage/PhabricatorProjectColumn.php',
'PhabricatorProjectColumnQuery' => 'applications/project/query/PhabricatorProjectColumnQuery.php',
'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php',
'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php',
'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php',
'PhabricatorProjectCustomFieldNumericIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldNumericIndex.php',
'PhabricatorProjectCustomFieldStorage' => 'applications/project/storage/PhabricatorProjectCustomFieldStorage.php',
'PhabricatorProjectCustomFieldStringIndex' => 'applications/project/storage/PhabricatorProjectCustomFieldStringIndex.php',
'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php',
'PhabricatorProjectEditor' => 'applications/project/editor/PhabricatorProjectEditor.php',
'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php',
'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php',
'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php',
'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
'PhabricatorProjectNameCollisionException' => 'applications/project/exception/PhabricatorProjectNameCollisionException.php',
'PhabricatorProjectPHIDTypeColumn' => 'applications/project/phid/PhabricatorProjectPHIDTypeColumn.php',
'PhabricatorProjectPHIDTypeProject' => 'applications/project/phid/PhabricatorProjectPHIDTypeProject.php',
'PhabricatorProjectProfile' => 'applications/project/storage/PhabricatorProjectProfile.php',
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
'PhabricatorProjectProfileEditController' => 'applications/project/controller/PhabricatorProjectProfileEditController.php',
'PhabricatorProjectProfilePictureController' => 'applications/project/controller/PhabricatorProjectProfilePictureController.php',
'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php',
'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php',
'PhabricatorProjectSearchIndexer' => 'applications/project/search/PhabricatorProjectSearchIndexer.php',
'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php',
'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php',
'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php',
'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php',
'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php',
'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php',
'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php',
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php',
'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php',
'PhabricatorRemarkupBlockInterpreterCowsay' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterCowsay.php',
'PhabricatorRemarkupBlockInterpreterFiglet' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterFiglet.php',
'PhabricatorRemarkupBlockInterpreterGraphviz' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterGraphviz.php',
'PhabricatorRemarkupControl' => 'view/form/control/PhabricatorRemarkupControl.php',
'PhabricatorRemarkupCustomBlockRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomBlockRule.php',
'PhabricatorRemarkupCustomInlineRule' => 'infrastructure/markup/rule/PhabricatorRemarkupCustomInlineRule.php',
'PhabricatorRemarkupRuleEmbedFile' => 'applications/files/remarkup/PhabricatorRemarkupRuleEmbedFile.php',
'PhabricatorRemarkupRuleImageMacro' => 'applications/macro/remarkup/PhabricatorRemarkupRuleImageMacro.php',
'PhabricatorRemarkupRuleMeme' => 'applications/macro/remarkup/PhabricatorRemarkupRuleMeme.php',
'PhabricatorRemarkupRuleMention' => 'applications/people/remarkup/PhabricatorRemarkupRuleMention.php',
'PhabricatorRemarkupRuleObject' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObject.php',
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php',
'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php',
'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/PhabricatorRepositoryArcanistProject.php',
'PhabricatorRepositoryArcanistProjectDeleteController' => 'applications/repository/controller/PhabricatorRepositoryArcanistProjectDeleteController.php',
'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/PhabricatorRepositoryArcanistProjectEditController.php',
'PhabricatorRepositoryArcanistProjectQuery' => 'applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php',
'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php',
'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/PhabricatorRepositoryCommit.php',
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php',
'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php',
'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php',
'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php',
'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitParserWorker.php',
'PhabricatorRepositoryCommitRef' => 'applications/repository/engine/PhabricatorRepositoryCommitRef.php',
'PhabricatorRepositoryCommitSearchIndexer' => 'applications/repository/search/PhabricatorRepositoryCommitSearchIndexer.php',
'PhabricatorRepositoryConfigOptions' => 'applications/repository/PhabricatorRepositoryConfigOptions.php',
'PhabricatorRepositoryController' => 'applications/repository/controller/PhabricatorRepositoryController.php',
- 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/PhabricatorRepositoryCreateController.php',
'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php',
'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php',
- 'PhabricatorRepositoryEditController' => 'applications/repository/controller/PhabricatorRepositoryEditController.php',
'PhabricatorRepositoryEditor' => 'applications/repository/editor/PhabricatorRepositoryEditor.php',
'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php',
'PhabricatorRepositoryListController' => 'applications/repository/controller/PhabricatorRepositoryListController.php',
'PhabricatorRepositoryManagementDeleteWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php',
'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php',
'PhabricatorRepositoryManagementPullWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php',
'PhabricatorRepositoryManagementWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementWorkflow.php',
'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryMercurialCommitChangeParserWorker.php',
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php',
'PhabricatorRepositoryPHIDTypeArcanistProject' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php',
'PhabricatorRepositoryPHIDTypeCommit' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php',
'PhabricatorRepositoryPHIDTypeRepository' => 'applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php',
'PhabricatorRepositoryPullEngine' => 'applications/repository/engine/PhabricatorRepositoryPullEngine.php',
'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php',
'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php',
'PhabricatorRepositorySearchEngine' => 'applications/repository/query/PhabricatorRepositorySearchEngine.php',
'PhabricatorRepositoryShortcut' => 'applications/repository/storage/PhabricatorRepositoryShortcut.php',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php',
'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php',
'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php',
'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php',
'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php',
'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php',
'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php',
'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php',
'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php',
'PhabricatorSavedQuery' => 'applications/search/storage/PhabricatorSavedQuery.php',
'PhabricatorSavedQueryQuery' => 'applications/search/query/PhabricatorSavedQueryQuery.php',
'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php',
'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php',
'PhabricatorSearchAttachController' => 'applications/search/controller/PhabricatorSearchAttachController.php',
'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php',
'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php',
'PhabricatorSearchController' => 'applications/search/controller/PhabricatorSearchController.php',
'PhabricatorSearchDAO' => 'applications/search/storage/PhabricatorSearchDAO.php',
'PhabricatorSearchDeleteController' => 'applications/search/controller/PhabricatorSearchDeleteController.php',
'PhabricatorSearchDocument' => 'applications/search/storage/document/PhabricatorSearchDocument.php',
'PhabricatorSearchDocumentField' => 'applications/search/storage/document/PhabricatorSearchDocumentField.php',
'PhabricatorSearchDocumentIndexer' => 'applications/search/index/PhabricatorSearchDocumentIndexer.php',
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/PhabricatorSearchDocumentRelationship.php',
'PhabricatorSearchEditController' => 'applications/search/controller/PhabricatorSearchEditController.php',
'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php',
'PhabricatorSearchEngineElastic' => 'applications/search/engine/PhabricatorSearchEngineElastic.php',
'PhabricatorSearchEngineMySQL' => 'applications/search/engine/PhabricatorSearchEngineMySQL.php',
'PhabricatorSearchEngineSelector' => 'applications/search/selector/PhabricatorSearchEngineSelector.php',
'PhabricatorSearchField' => 'applications/search/constants/PhabricatorSearchField.php',
'PhabricatorSearchHovercardController' => 'applications/search/controller/PhabricatorSearchHovercardController.php',
'PhabricatorSearchIndexer' => 'applications/search/index/PhabricatorSearchIndexer.php',
'PhabricatorSearchManagementIndexWorkflow' => 'applications/search/management/PhabricatorSearchManagementIndexWorkflow.php',
'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php',
'PhabricatorSearchOrderController' => 'applications/search/controller/PhabricatorSearchOrderController.php',
'PhabricatorSearchQuery' => 'applications/search/storage/PhabricatorSearchQuery.php',
'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php',
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
'PhabricatorSearchScope' => 'applications/search/constants/PhabricatorSearchScope.php',
'PhabricatorSearchSelectController' => 'applications/search/controller/PhabricatorSearchSelectController.php',
'PhabricatorSecurityConfigOptions' => 'applications/config/option/PhabricatorSecurityConfigOptions.php',
'PhabricatorSendGridConfigOptions' => 'applications/config/option/PhabricatorSendGridConfigOptions.php',
'PhabricatorSettingsAdjustController' => 'applications/settings/controller/PhabricatorSettingsAdjustController.php',
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php',
'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php',
'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.php',
'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php',
'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php',
'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php',
'PhabricatorSettingsPanelExternalAccounts' => 'applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php',
'PhabricatorSettingsPanelHomePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php',
'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php',
'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php',
'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php',
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php',
'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php',
'PhabricatorSetupCheckBaseURI' => 'applications/config/check/PhabricatorSetupCheckBaseURI.php',
'PhabricatorSetupCheckBinaries' => 'applications/config/check/PhabricatorSetupCheckBinaries.php',
'PhabricatorSetupCheckDatabase' => 'applications/config/check/PhabricatorSetupCheckDatabase.php',
'PhabricatorSetupCheckExtensions' => 'applications/config/check/PhabricatorSetupCheckExtensions.php',
'PhabricatorSetupCheckExtraConfig' => 'applications/config/check/PhabricatorSetupCheckExtraConfig.php',
'PhabricatorSetupCheckFileinfo' => 'applications/config/check/PhabricatorSetupCheckFileinfo.php',
'PhabricatorSetupCheckGD' => 'applications/config/check/PhabricatorSetupCheckGD.php',
'PhabricatorSetupCheckImagemagick' => 'applications/config/check/PhabricatorSetupCheckImagemagick.php',
'PhabricatorSetupCheckInvalidConfig' => 'applications/config/check/PhabricatorSetupCheckInvalidConfig.php',
'PhabricatorSetupCheckMail' => 'applications/config/check/PhabricatorSetupCheckMail.php',
'PhabricatorSetupCheckMySQL' => 'applications/config/check/PhabricatorSetupCheckMySQL.php',
'PhabricatorSetupCheckPHPConfig' => 'applications/config/check/PhabricatorSetupCheckPHPConfig.php',
'PhabricatorSetupCheckPath' => 'applications/config/check/PhabricatorSetupCheckPath.php',
'PhabricatorSetupCheckPygment' => 'applications/config/check/PhabricatorSetupCheckPygment.php',
'PhabricatorSetupCheckStorage' => 'applications/config/check/PhabricatorSetupCheckStorage.php',
'PhabricatorSetupCheckTimezone' => 'applications/config/check/PhabricatorSetupCheckTimezone.php',
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
'PhabricatorSetupIssueExample' => 'applications/uiexample/examples/PhabricatorSetupIssueExample.php',
'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php',
'PhabricatorSlowvoteCapabilityDefaultView' => 'applications/slowvote/capability/PhabricatorSlowvoteCapabilityDefaultView.php',
'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php',
'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php',
'PhabricatorSlowvoteCommentController' => 'applications/slowvote/controller/PhabricatorSlowvoteCommentController.php',
'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php',
'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/PhabricatorSlowvoteDAO.php',
'PhabricatorSlowvoteEditController' => 'applications/slowvote/controller/PhabricatorSlowvoteEditController.php',
'PhabricatorSlowvoteEditor' => 'applications/slowvote/editor/PhabricatorSlowvoteEditor.php',
'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php',
'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php',
'PhabricatorSlowvotePHIDTypePoll' => 'applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php',
'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php',
'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php',
'PhabricatorSlowvoteQuery' => 'applications/slowvote/query/PhabricatorSlowvoteQuery.php',
'PhabricatorSlowvoteSearchEngine' => 'applications/slowvote/query/PhabricatorSlowvoteSearchEngine.php',
'PhabricatorSlowvoteTransaction' => 'applications/slowvote/storage/PhabricatorSlowvoteTransaction.php',
'PhabricatorSlowvoteTransactionComment' => 'applications/slowvote/storage/PhabricatorSlowvoteTransactionComment.php',
'PhabricatorSlowvoteTransactionQuery' => 'applications/slowvote/query/PhabricatorSlowvoteTransactionQuery.php',
'PhabricatorSlowvoteVoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteVoteController.php',
'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php',
'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php',
'PhabricatorSortTableExample' => 'applications/uiexample/examples/PhabricatorSortTableExample.php',
'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php',
'PhabricatorStandardCustomField' => 'infrastructure/customfield/standard/PhabricatorStandardCustomField.php',
'PhabricatorStandardCustomFieldBool' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php',
'PhabricatorStandardCustomFieldDate' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php',
'PhabricatorStandardCustomFieldHeader' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php',
'PhabricatorStandardCustomFieldInt' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php',
'PhabricatorStandardCustomFieldInterface' => 'infrastructure/customfield/interface/PhabricatorStandardCustomFieldInterface.php',
'PhabricatorStandardCustomFieldPHIDs' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php',
'PhabricatorStandardCustomFieldRemarkup' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php',
'PhabricatorStandardCustomFieldSelect' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php',
'PhabricatorStandardCustomFieldText' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldText.php',
'PhabricatorStandardCustomFieldUsers' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php',
'PhabricatorStandardPageView' => 'view/page/PhabricatorStandardPageView.php',
'PhabricatorStatusController' => 'applications/system/PhabricatorStatusController.php',
'PhabricatorStorageFixtureScopeGuard' => 'infrastructure/testing/fixture/PhabricatorStorageFixtureScopeGuard.php',
'PhabricatorStorageManagementAPI' => 'infrastructure/storage/management/PhabricatorStorageManagementAPI.php',
'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php',
'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php',
'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php',
'PhabricatorStorageManagementProbeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php',
'PhabricatorStorageManagementStatusWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php',
'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php',
'PhabricatorStorageManagementWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php',
'PhabricatorStoragePatch' => 'infrastructure/storage/management/PhabricatorStoragePatch.php',
'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php',
'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php',
'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php',
'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php',
'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php',
'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/PhabricatorSymbolNameLinter.php',
'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php',
'PhabricatorSyntaxHighlightingConfigOptions' => 'applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php',
'PhabricatorTagExample' => 'applications/uiexample/examples/PhabricatorTagExample.php',
'PhabricatorTagView' => 'view/layout/PhabricatorTagView.php',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php',
'PhabricatorTestCase' => 'infrastructure/testing/PhabricatorTestCase.php',
'PhabricatorTestController' => 'applications/base/controller/__tests__/PhabricatorTestController.php',
'PhabricatorTestDataGenerator' => 'applications/lipsum/generator/PhabricatorTestDataGenerator.php',
'PhabricatorTestStorageEngine' => 'applications/files/engine/PhabricatorTestStorageEngine.php',
'PhabricatorTestWorker' => 'infrastructure/daemon/workers/__tests__/PhabricatorTestWorker.php',
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php',
'PhabricatorTimeTestCase' => 'infrastructure/time/__tests__/PhabricatorTimeTestCase.php',
'PhabricatorTimelineEventView' => 'view/layout/PhabricatorTimelineEventView.php',
'PhabricatorTimelineExample' => 'applications/uiexample/examples/PhabricatorTimelineExample.php',
'PhabricatorTimelineView' => 'view/layout/PhabricatorTimelineView.php',
'PhabricatorToken' => 'applications/tokens/storage/PhabricatorToken.php',
'PhabricatorTokenController' => 'applications/tokens/controller/PhabricatorTokenController.php',
'PhabricatorTokenCount' => 'applications/tokens/storage/PhabricatorTokenCount.php',
'PhabricatorTokenCountQuery' => 'applications/tokens/query/PhabricatorTokenCountQuery.php',
'PhabricatorTokenDAO' => 'applications/tokens/storage/PhabricatorTokenDAO.php',
'PhabricatorTokenGiveController' => 'applications/tokens/controller/PhabricatorTokenGiveController.php',
'PhabricatorTokenGiven' => 'applications/tokens/storage/PhabricatorTokenGiven.php',
'PhabricatorTokenGivenController' => 'applications/tokens/controller/PhabricatorTokenGivenController.php',
'PhabricatorTokenGivenEditor' => 'applications/tokens/editor/PhabricatorTokenGivenEditor.php',
'PhabricatorTokenGivenFeedStory' => 'applications/tokens/feed/PhabricatorTokenGivenFeedStory.php',
'PhabricatorTokenGivenQuery' => 'applications/tokens/query/PhabricatorTokenGivenQuery.php',
'PhabricatorTokenLeaderController' => 'applications/tokens/controller/PhabricatorTokenLeaderController.php',
'PhabricatorTokenPHIDTypeToken' => 'applications/tokens/phid/PhabricatorTokenPHIDTypeToken.php',
'PhabricatorTokenQuery' => 'applications/tokens/query/PhabricatorTokenQuery.php',
'PhabricatorTokenReceiverInterface' => 'applications/tokens/interface/PhabricatorTokenReceiverInterface.php',
'PhabricatorTokenReceiverQuery' => 'applications/tokens/query/PhabricatorTokenReceiverQuery.php',
'PhabricatorTokenUIEventListener' => 'applications/tokens/event/PhabricatorTokenUIEventListener.php',
'PhabricatorTransactionView' => 'view/layout/PhabricatorTransactionView.php',
'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php',
'PhabricatorTransformedFile' => 'applications/files/storage/PhabricatorTransformedFile.php',
'PhabricatorTranslation' => 'infrastructure/internationalization/PhabricatorTranslation.php',
'PhabricatorTranslationsConfigOptions' => 'applications/config/option/PhabricatorTranslationsConfigOptions.php',
'PhabricatorTrivialTestCase' => 'infrastructure/testing/__tests__/PhabricatorTrivialTestCase.php',
'PhabricatorTwoColumnExample' => 'applications/uiexample/examples/PhabricatorTwoColumnExample.php',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadDatasourceController.php',
'PhabricatorTypeaheadResult' => 'applications/typeahead/storage/PhabricatorTypeaheadResult.php',
'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php',
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php',
'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/PhabricatorUIListFilterExample.php',
'PhabricatorUINotificationExample' => 'applications/uiexample/examples/PhabricatorUINotificationExample.php',
'PhabricatorUIPagerExample' => 'applications/uiexample/examples/PhabricatorUIPagerExample.php',
'PhabricatorUIStatusExample' => 'applications/uiexample/examples/PhabricatorUIStatusExample.php',
'PhabricatorUITooltipExample' => 'applications/uiexample/examples/PhabricatorUITooltipExample.php',
'PhabricatorUnitsTestCase' => 'view/__tests__/PhabricatorUnitsTestCase.php',
'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php',
'PhabricatorUserBlurbField' => 'applications/people/customfield/PhabricatorUserBlurbField.php',
'PhabricatorUserConfigOptions' => 'applications/people/config/PhabricatorUserConfigOptions.php',
'PhabricatorUserConfiguredCustomField' => 'applications/people/customfield/PhabricatorUserConfiguredCustomField.php',
'PhabricatorUserConfiguredCustomFieldStorage' => 'applications/people/storage/PhabricatorUserConfiguredCustomFieldStorage.php',
'PhabricatorUserCustomField' => 'applications/people/customfield/PhabricatorUserCustomField.php',
'PhabricatorUserCustomFieldNumericIndex' => 'applications/people/storage/PhabricatorUserCustomFieldNumericIndex.php',
'PhabricatorUserCustomFieldStringIndex' => 'applications/people/storage/PhabricatorUserCustomFieldStringIndex.php',
'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php',
'PhabricatorUserEditor' => 'applications/people/editor/PhabricatorUserEditor.php',
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php',
'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php',
'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php',
'PhabricatorUserRealNameField' => 'applications/people/customfield/PhabricatorUserRealNameField.php',
'PhabricatorUserRolesField' => 'applications/people/customfield/PhabricatorUserRolesField.php',
'PhabricatorUserSSHKey' => 'applications/settings/storage/PhabricatorUserSSHKey.php',
'PhabricatorUserSearchIndexer' => 'applications/people/search/PhabricatorUserSearchIndexer.php',
'PhabricatorUserSinceField' => 'applications/people/customfield/PhabricatorUserSinceField.php',
'PhabricatorUserStatus' => 'applications/people/storage/PhabricatorUserStatus.php',
'PhabricatorUserStatusField' => 'applications/people/customfield/PhabricatorUserStatusField.php',
'PhabricatorUserStatusInvalidEpochException' => 'applications/people/exception/PhabricatorUserStatusInvalidEpochException.php',
'PhabricatorUserStatusOverlapException' => 'applications/people/exception/PhabricatorUserStatusOverlapException.php',
'PhabricatorUserTestCase' => 'applications/people/storage/__tests__/PhabricatorUserTestCase.php',
'PhabricatorUserTitleField' => 'applications/people/customfield/PhabricatorUserTitleField.php',
'PhabricatorUserTransaction' => 'applications/people/storage/PhabricatorUserTransaction.php',
+ 'PhabricatorVCSResponse' => 'applications/repository/response/PhabricatorVCSResponse.php',
'PhabricatorWorker' => 'infrastructure/daemon/workers/PhabricatorWorker.php',
'PhabricatorWorkerActiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php',
'PhabricatorWorkerArchiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerArchiveTask.php',
'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerDAO.php',
'PhabricatorWorkerLeaseQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php',
'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php',
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php',
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php',
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php',
'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/PhabricatorWorkerTaskUpdateController.php',
'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php',
'PhabricatorWorkingCopyDiscoveryTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyDiscoveryTestCase.php',
'PhabricatorWorkingCopyPullTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php',
'PhabricatorWorkingCopyTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php',
'PhabricatorXHPASTViewController' => 'applications/phpast/controller/PhabricatorXHPASTViewController.php',
'PhabricatorXHPASTViewDAO' => 'applications/phpast/storage/PhabricatorXHPASTViewDAO.php',
'PhabricatorXHPASTViewFrameController' => 'applications/phpast/controller/PhabricatorXHPASTViewFrameController.php',
'PhabricatorXHPASTViewFramesetController' => 'applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php',
'PhabricatorXHPASTViewInputController' => 'applications/phpast/controller/PhabricatorXHPASTViewInputController.php',
'PhabricatorXHPASTViewPanelController' => 'applications/phpast/controller/PhabricatorXHPASTViewPanelController.php',
'PhabricatorXHPASTViewParseTree' => 'applications/phpast/storage/PhabricatorXHPASTViewParseTree.php',
'PhabricatorXHPASTViewRunController' => 'applications/phpast/controller/PhabricatorXHPASTViewRunController.php',
'PhabricatorXHPASTViewStreamController' => 'applications/phpast/controller/PhabricatorXHPASTViewStreamController.php',
'PhabricatorXHPASTViewTreeController' => 'applications/phpast/controller/PhabricatorXHPASTViewTreeController.php',
'PhabricatorXHProfController' => 'applications/xhprof/controller/PhabricatorXHProfController.php',
'PhabricatorXHProfDAO' => 'applications/xhprof/storage/PhabricatorXHProfDAO.php',
'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/PhabricatorXHProfProfileController.php',
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php',
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php',
'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php',
'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php',
'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php',
'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php',
'PhameBasicTemplateBlogSkin' => 'applications/phame/skins/PhameBasicTemplateBlogSkin.php',
'PhameBlog' => 'applications/phame/storage/PhameBlog.php',
'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php',
'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php',
'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php',
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php',
'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php',
'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php',
'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php',
'PhameController' => 'applications/phame/controller/PhameController.php',
'PhameDAO' => 'applications/phame/storage/PhameDAO.php',
'PhamePost' => 'applications/phame/storage/PhamePost.php',
'PhamePostDeleteController' => 'applications/phame/controller/post/PhamePostDeleteController.php',
'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php',
'PhamePostFramedController' => 'applications/phame/controller/post/PhamePostFramedController.php',
'PhamePostListController' => 'applications/phame/controller/post/PhamePostListController.php',
'PhamePostNewController' => 'applications/phame/controller/post/PhamePostNewController.php',
'PhamePostNotLiveController' => 'applications/phame/controller/post/PhamePostNotLiveController.php',
'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php',
'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php',
'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php',
'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php',
'PhamePostView' => 'applications/phame/view/PhamePostView.php',
'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php',
'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php',
'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php',
'PhluxController' => 'applications/phlux/controller/PhluxController.php',
'PhluxDAO' => 'applications/phlux/storage/PhluxDAO.php',
'PhluxEditController' => 'applications/phlux/controller/PhluxEditController.php',
'PhluxListController' => 'applications/phlux/controller/PhluxListController.php',
'PhluxPHIDTypeVariable' => 'applications/phlux/phid/PhluxPHIDTypeVariable.php',
'PhluxTransaction' => 'applications/phlux/storage/PhluxTransaction.php',
'PhluxTransactionQuery' => 'applications/phlux/query/PhluxTransactionQuery.php',
'PhluxVariable' => 'applications/phlux/storage/PhluxVariable.php',
'PhluxVariableEditor' => 'applications/phlux/editor/PhluxVariableEditor.php',
'PhluxVariableQuery' => 'applications/phlux/query/PhluxVariableQuery.php',
'PhluxViewController' => 'applications/phlux/controller/PhluxViewController.php',
'PholioActionMenuEventListener' => 'applications/pholio/event/PholioActionMenuEventListener.php',
'PholioConstants' => 'applications/pholio/constants/PholioConstants.php',
'PholioController' => 'applications/pholio/controller/PholioController.php',
'PholioDAO' => 'applications/pholio/storage/PholioDAO.php',
'PholioImage' => 'applications/pholio/storage/PholioImage.php',
'PholioImageHistoryController' => 'applications/pholio/controller/PholioImageHistoryController.php',
'PholioImageQuery' => 'applications/pholio/query/PholioImageQuery.php',
'PholioImageUploadController' => 'applications/pholio/controller/PholioImageUploadController.php',
'PholioInlineCommentEditView' => 'applications/pholio/view/PholioInlineCommentEditView.php',
'PholioInlineCommentSaveView' => 'applications/pholio/view/PholioInlineCommentSaveView.php',
'PholioInlineCommentView' => 'applications/pholio/view/PholioInlineCommentView.php',
'PholioInlineController' => 'applications/pholio/controller/PholioInlineController.php',
'PholioInlineDeleteController' => 'applications/pholio/controller/PholioInlineDeleteController.php',
'PholioInlineEditController' => 'applications/pholio/controller/PholioInlineEditController.php',
'PholioInlineSaveController' => 'applications/pholio/controller/PholioInlineSaveController.php',
'PholioInlineThumbController' => 'applications/pholio/controller/PholioInlineThumbController.php',
'PholioInlineViewController' => 'applications/pholio/controller/PholioInlineViewController.php',
'PholioMock' => 'applications/pholio/storage/PholioMock.php',
'PholioMockCommentController' => 'applications/pholio/controller/PholioMockCommentController.php',
'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php',
'PholioMockEditor' => 'applications/pholio/editor/PholioMockEditor.php',
'PholioMockEmbedView' => 'applications/pholio/view/PholioMockEmbedView.php',
'PholioMockImagesView' => 'applications/pholio/view/PholioMockImagesView.php',
'PholioMockListController' => 'applications/pholio/controller/PholioMockListController.php',
'PholioMockMailReceiver' => 'applications/pholio/mail/PholioMockMailReceiver.php',
'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php',
'PholioMockSearchEngine' => 'applications/pholio/query/PholioMockSearchEngine.php',
'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php',
'PholioPHIDTypeImage' => 'applications/pholio/phid/PholioPHIDTypeImage.php',
'PholioPHIDTypeMock' => 'applications/pholio/phid/PholioPHIDTypeMock.php',
'PholioRemarkupRule' => 'applications/pholio/remarkup/PholioRemarkupRule.php',
'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php',
'PholioSearchIndexer' => 'applications/pholio/search/PholioSearchIndexer.php',
'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php',
'PholioTransactionComment' => 'applications/pholio/storage/PholioTransactionComment.php',
'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php',
'PholioTransactionType' => 'applications/pholio/constants/PholioTransactionType.php',
'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php',
'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php',
'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php',
'PhortuneAccountBuyController' => 'applications/phortune/controller/PhortuneAccountBuyController.php',
'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php',
'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php',
'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php',
'PhortuneAccountTransactionQuery' => 'applications/phortune/query/PhortuneAccountTransactionQuery.php',
'PhortuneAccountViewController' => 'applications/phortune/controller/PhortuneAccountViewController.php',
'PhortuneBalancedPaymentProvider' => 'applications/phortune/provider/PhortuneBalancedPaymentProvider.php',
'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php',
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
'PhortuneConstants' => 'applications/phortune/constants/PhortuneConstants.php',
'PhortuneController' => 'applications/phortune/controller/PhortuneController.php',
'PhortuneCreditCardForm' => 'applications/phortune/view/PhortuneCreditCardForm.php',
'PhortuneCurrency' => 'applications/phortune/currency/PhortuneCurrency.php',
'PhortuneCurrencyTestCase' => 'applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php',
'PhortuneDAO' => 'applications/phortune/storage/PhortuneDAO.php',
'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php',
'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php',
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
'PhortuneMultiplePaymentProvidersException' => 'applications/phortune/exception/PhortuneMultiplePaymentProvidersException.php',
'PhortuneNoPaymentProviderException' => 'applications/phortune/exception/PhortuneNoPaymentProviderException.php',
'PhortuneNotImplementedException' => 'applications/phortune/exception/PhortuneNotImplementedException.php',
'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php',
'PhortunePaymentMethodEditController' => 'applications/phortune/controller/PhortunePaymentMethodEditController.php',
'PhortunePaymentMethodListController' => 'applications/phortune/controller/PhortunePaymentMethodListController.php',
'PhortunePaymentMethodQuery' => 'applications/phortune/query/PhortunePaymentMethodQuery.php',
'PhortunePaymentMethodViewController' => 'applications/phortune/controller/PhortunePaymentMethodViewController.php',
'PhortunePaymentProvider' => 'applications/phortune/provider/PhortunePaymentProvider.php',
'PhortunePaymentProviderTestCase' => 'applications/phortune/provider/__tests__/PhortunePaymentProviderTestCase.php',
'PhortunePaypalPaymentProvider' => 'applications/phortune/provider/PhortunePaypalPaymentProvider.php',
'PhortuneProduct' => 'applications/phortune/storage/PhortuneProduct.php',
'PhortuneProductEditController' => 'applications/phortune/controller/PhortuneProductEditController.php',
'PhortuneProductEditor' => 'applications/phortune/editor/PhortuneProductEditor.php',
'PhortuneProductListController' => 'applications/phortune/controller/PhortuneProductListController.php',
'PhortuneProductQuery' => 'applications/phortune/query/PhortuneProductQuery.php',
'PhortuneProductTransaction' => 'applications/phortune/storage/PhortuneProductTransaction.php',
'PhortuneProductTransactionQuery' => 'applications/phortune/query/PhortuneProductTransactionQuery.php',
'PhortuneProductViewController' => 'applications/phortune/controller/PhortuneProductViewController.php',
'PhortuneProviderController' => 'applications/phortune/controller/PhortuneProviderController.php',
'PhortunePurchase' => 'applications/phortune/storage/PhortunePurchase.php',
'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php',
'PhortuneTestExtraPaymentProvider' => 'applications/phortune/provider/__tests__/PhortuneTestExtraPaymentProvider.php',
'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php',
'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php',
'PhrequentController' => 'applications/phrequent/controller/PhrequentController.php',
'PhrequentDAO' => 'applications/phrequent/storage/PhrequentDAO.php',
'PhrequentListController' => 'applications/phrequent/controller/PhrequentListController.php',
'PhrequentSearchEngine' => 'applications/phrequent/query/PhrequentSearchEngine.php',
'PhrequentTimeBlock' => 'applications/phrequent/storage/PhrequentTimeBlock.php',
'PhrequentTimeBlockTestCase' => 'applications/phrequent/storage/__tests__/PhrequentTimeBlockTestCase.php',
'PhrequentTrackController' => 'applications/phrequent/controller/PhrequentTrackController.php',
'PhrequentTrackableInterface' => 'applications/phrequent/interface/PhrequentTrackableInterface.php',
'PhrequentUIEventListener' => 'applications/phrequent/event/PhrequentUIEventListener.php',
'PhrequentUserTime' => 'applications/phrequent/storage/PhrequentUserTime.php',
'PhrequentUserTimeQuery' => 'applications/phrequent/query/PhrequentUserTimeQuery.php',
'PhrictionActionConstants' => 'applications/phriction/constants/PhrictionActionConstants.php',
'PhrictionActionMenuEventListener' => 'applications/phriction/event/PhrictionActionMenuEventListener.php',
'PhrictionChangeType' => 'applications/phriction/constants/PhrictionChangeType.php',
'PhrictionConstants' => 'applications/phriction/constants/PhrictionConstants.php',
'PhrictionContent' => 'applications/phriction/storage/PhrictionContent.php',
'PhrictionController' => 'applications/phriction/controller/PhrictionController.php',
'PhrictionDAO' => 'applications/phriction/storage/PhrictionDAO.php',
'PhrictionDeleteController' => 'applications/phriction/controller/PhrictionDeleteController.php',
'PhrictionDiffController' => 'applications/phriction/controller/PhrictionDiffController.php',
'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php',
'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php',
'PhrictionDocumentEditor' => 'applications/phriction/editor/PhrictionDocumentEditor.php',
'PhrictionDocumentPreviewController' => 'applications/phriction/controller/PhrictionDocumentPreviewController.php',
'PhrictionDocumentQuery' => 'applications/phriction/query/PhrictionDocumentQuery.php',
'PhrictionDocumentStatus' => 'applications/phriction/constants/PhrictionDocumentStatus.php',
'PhrictionDocumentTestCase' => 'applications/phriction/storage/__tests__/PhrictionDocumentTestCase.php',
'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php',
'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php',
'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php',
'PhrictionMoveController' => 'applications/phriction/controller/PhrictionMoveController.php',
'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php',
'PhrictionPHIDTypeDocument' => 'applications/phriction/phid/PhrictionPHIDTypeDocument.php',
'PhrictionRemarkupRule' => 'applications/phriction/remarkup/PhrictionRemarkupRule.php',
'PhrictionSearchEngine' => 'applications/phriction/query/PhrictionSearchEngine.php',
'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php',
'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php',
'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php',
'PonderAnswerCommentController' => 'applications/ponder/controller/PonderAnswerCommentController.php',
'PonderAnswerEditController' => 'applications/ponder/controller/PonderAnswerEditController.php',
'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php',
'PonderAnswerHistoryController' => 'applications/ponder/controller/PonderAnswerHistoryController.php',
'PonderAnswerQuery' => 'applications/ponder/query/PonderAnswerQuery.php',
'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php',
'PonderAnswerTransaction' => 'applications/ponder/storage/PonderAnswerTransaction.php',
'PonderAnswerTransactionComment' => 'applications/ponder/storage/PonderAnswerTransactionComment.php',
'PonderAnswerTransactionQuery' => 'applications/ponder/query/PonderAnswerTransactionQuery.php',
'PonderComment' => 'applications/ponder/storage/PonderComment.php',
'PonderCommentQuery' => 'applications/ponder/query/PonderCommentQuery.php',
'PonderConstants' => 'applications/ponder/constants/PonderConstants.php',
'PonderController' => 'applications/ponder/controller/PonderController.php',
'PonderDAO' => 'applications/ponder/storage/PonderDAO.php',
'PonderEditor' => 'applications/ponder/editor/PonderEditor.php',
'PonderPHIDTypeAnswer' => 'applications/ponder/phid/PonderPHIDTypeAnswer.php',
'PonderPHIDTypeQuestion' => 'applications/ponder/phid/PonderPHIDTypeQuestion.php',
'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php',
'PonderQuestionCommentController' => 'applications/ponder/controller/PonderQuestionCommentController.php',
'PonderQuestionEditController' => 'applications/ponder/controller/PonderQuestionEditController.php',
'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php',
'PonderQuestionHistoryController' => 'applications/ponder/controller/PonderQuestionHistoryController.php',
'PonderQuestionListController' => 'applications/ponder/controller/PonderQuestionListController.php',
'PonderQuestionMailReceiver' => 'applications/ponder/mail/PonderQuestionMailReceiver.php',
'PonderQuestionQuery' => 'applications/ponder/query/PonderQuestionQuery.php',
'PonderQuestionReplyHandler' => 'applications/ponder/mail/PonderQuestionReplyHandler.php',
'PonderQuestionSearchEngine' => 'applications/ponder/query/PonderQuestionSearchEngine.php',
'PonderQuestionStatus' => 'applications/ponder/constants/PonderQuestionStatus.php',
'PonderQuestionStatusController' => 'applications/ponder/controller/PonderQuestionStatusController.php',
'PonderQuestionTransaction' => 'applications/ponder/storage/PonderQuestionTransaction.php',
'PonderQuestionTransactionComment' => 'applications/ponder/storage/PonderQuestionTransactionComment.php',
'PonderQuestionTransactionQuery' => 'applications/ponder/query/PonderQuestionTransactionQuery.php',
'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php',
'PonderRemarkupRule' => 'applications/ponder/remarkup/PonderRemarkupRule.php',
'PonderSearchIndexer' => 'applications/ponder/search/PonderSearchIndexer.php',
'PonderTransactionFeedStory' => 'applications/ponder/feed/PonderTransactionFeedStory.php',
'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php',
'PonderVotableView' => 'applications/ponder/view/PonderVotableView.php',
'PonderVote' => 'applications/ponder/constants/PonderVote.php',
'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php',
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
'ProjectCapabilityCreateProjects' => 'applications/project/capability/ProjectCapabilityCreateProjects.php',
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php',
'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php',
'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php',
'ReleephBranchAccessController' => 'applications/releeph/controller/branch/ReleephBranchAccessController.php',
'ReleephBranchCommitFieldSpecification' => 'applications/releeph/field/specification/ReleephBranchCommitFieldSpecification.php',
'ReleephBranchCreateController' => 'applications/releeph/controller/branch/ReleephBranchCreateController.php',
'ReleephBranchEditController' => 'applications/releeph/controller/branch/ReleephBranchEditController.php',
'ReleephBranchEditor' => 'applications/releeph/editor/ReleephBranchEditor.php',
'ReleephBranchHistoryController' => 'applications/releeph/controller/branch/ReleephBranchHistoryController.php',
'ReleephBranchNamePreviewController' => 'applications/releeph/controller/branch/ReleephBranchNamePreviewController.php',
'ReleephBranchPreviewView' => 'applications/releeph/view/branch/ReleephBranchPreviewView.php',
'ReleephBranchQuery' => 'applications/releeph/query/ReleephBranchQuery.php',
'ReleephBranchSearchEngine' => 'applications/releeph/query/ReleephBranchSearchEngine.php',
'ReleephBranchTemplate' => 'applications/releeph/view/branch/ReleephBranchTemplate.php',
'ReleephBranchTransaction' => 'applications/releeph/storage/ReleephBranchTransaction.php',
'ReleephBranchTransactionQuery' => 'applications/releeph/query/ReleephBranchTransactionQuery.php',
'ReleephBranchViewController' => 'applications/releeph/controller/branch/ReleephBranchViewController.php',
'ReleephCommitFinder' => 'applications/releeph/commitfinder/ReleephCommitFinder.php',
'ReleephCommitFinderException' => 'applications/releeph/commitfinder/ReleephCommitFinderException.php',
'ReleephCommitMessageFieldSpecification' => 'applications/releeph/field/specification/ReleephCommitMessageFieldSpecification.php',
'ReleephController' => 'applications/releeph/controller/ReleephController.php',
'ReleephDAO' => 'applications/releeph/storage/ReleephDAO.php',
'ReleephDefaultFieldSelector' => 'applications/releeph/field/selector/ReleephDefaultFieldSelector.php',
'ReleephDefaultUserView' => 'applications/releeph/view/user/ReleephDefaultUserView.php',
'ReleephDiffChurnFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffChurnFieldSpecification.php',
'ReleephDiffMessageFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffMessageFieldSpecification.php',
'ReleephDiffSizeFieldSpecification' => 'applications/releeph/field/specification/ReleephDiffSizeFieldSpecification.php',
'ReleephDifferentialRevisionDetailRenderer' => 'applications/releeph/differential/ReleephDifferentialRevisionDetailRenderer.php',
'ReleephFieldParseException' => 'applications/releeph/field/exception/ReleephFieldParseException.php',
'ReleephFieldSelector' => 'applications/releeph/field/selector/ReleephFieldSelector.php',
'ReleephFieldSpecification' => 'applications/releeph/field/specification/ReleephFieldSpecification.php',
'ReleephIntentFieldSpecification' => 'applications/releeph/field/specification/ReleephIntentFieldSpecification.php',
'ReleephLevelFieldSpecification' => 'applications/releeph/field/specification/ReleephLevelFieldSpecification.php',
'ReleephOriginalCommitFieldSpecification' => 'applications/releeph/field/specification/ReleephOriginalCommitFieldSpecification.php',
'ReleephPHIDTypeBranch' => 'applications/releeph/phid/ReleephPHIDTypeBranch.php',
'ReleephPHIDTypeProject' => 'applications/releeph/phid/ReleephPHIDTypeProject.php',
'ReleephPHIDTypeRequest' => 'applications/releeph/phid/ReleephPHIDTypeRequest.php',
'ReleephProject' => 'applications/releeph/storage/ReleephProject.php',
'ReleephProjectActionController' => 'applications/releeph/controller/project/ReleephProjectActionController.php',
'ReleephProjectController' => 'applications/releeph/controller/ReleephProjectController.php',
'ReleephProjectCreateController' => 'applications/releeph/controller/project/ReleephProjectCreateController.php',
'ReleephProjectEditController' => 'applications/releeph/controller/project/ReleephProjectEditController.php',
'ReleephProjectHistoryController' => 'applications/releeph/controller/project/ReleephProjectHistoryController.php',
'ReleephProjectListController' => 'applications/releeph/controller/project/ReleephProjectListController.php',
'ReleephProjectQuery' => 'applications/releeph/query/ReleephProjectQuery.php',
'ReleephProjectSearchEngine' => 'applications/releeph/query/ReleephProjectSearchEngine.php',
'ReleephProjectTransaction' => 'applications/releeph/storage/ReleephProjectTransaction.php',
'ReleephProjectTransactionQuery' => 'applications/releeph/query/ReleephProjectTransactionQuery.php',
'ReleephProjectViewController' => 'applications/releeph/controller/project/ReleephProjectViewController.php',
'ReleephReasonFieldSpecification' => 'applications/releeph/field/specification/ReleephReasonFieldSpecification.php',
'ReleephRequest' => 'applications/releeph/storage/ReleephRequest.php',
'ReleephRequestActionController' => 'applications/releeph/controller/request/ReleephRequestActionController.php',
'ReleephRequestCommentController' => 'applications/releeph/controller/request/ReleephRequestCommentController.php',
'ReleephRequestDifferentialCreateController' => 'applications/releeph/controller/request/ReleephRequestDifferentialCreateController.php',
'ReleephRequestEditController' => 'applications/releeph/controller/request/ReleephRequestEditController.php',
'ReleephRequestHeaderListView' => 'applications/releeph/view/request/header/ReleephRequestHeaderListView.php',
'ReleephRequestHeaderView' => 'applications/releeph/view/request/header/ReleephRequestHeaderView.php',
'ReleephRequestIntentsView' => 'applications/releeph/view/request/ReleephRequestIntentsView.php',
'ReleephRequestMailReceiver' => 'applications/releeph/mail/ReleephRequestMailReceiver.php',
'ReleephRequestQuery' => 'applications/releeph/query/ReleephRequestQuery.php',
'ReleephRequestReplyHandler' => 'applications/releeph/mail/ReleephRequestReplyHandler.php',
'ReleephRequestSearchEngine' => 'applications/releeph/query/ReleephRequestSearchEngine.php',
'ReleephRequestStatus' => 'applications/releeph/constants/ReleephRequestStatus.php',
'ReleephRequestStatusView' => 'applications/releeph/view/request/ReleephRequestStatusView.php',
'ReleephRequestTransaction' => 'applications/releeph/storage/ReleephRequestTransaction.php',
'ReleephRequestTransactionComment' => 'applications/releeph/storage/ReleephRequestTransactionComment.php',
'ReleephRequestTransactionQuery' => 'applications/releeph/query/ReleephRequestTransactionQuery.php',
'ReleephRequestTransactionalEditor' => 'applications/releeph/editor/ReleephRequestTransactionalEditor.php',
'ReleephRequestTypeaheadControl' => 'applications/releeph/view/request/ReleephRequestTypeaheadControl.php',
'ReleephRequestTypeaheadController' => 'applications/releeph/controller/request/ReleephRequestTypeaheadController.php',
'ReleephRequestViewController' => 'applications/releeph/controller/request/ReleephRequestViewController.php',
'ReleephRequestorFieldSpecification' => 'applications/releeph/field/specification/ReleephRequestorFieldSpecification.php',
'ReleephRevisionFieldSpecification' => 'applications/releeph/field/specification/ReleephRevisionFieldSpecification.php',
'ReleephSeverityFieldSpecification' => 'applications/releeph/field/specification/ReleephSeverityFieldSpecification.php',
'ReleephStatusFieldSpecification' => 'applications/releeph/field/specification/ReleephStatusFieldSpecification.php',
'ReleephSummaryFieldSpecification' => 'applications/releeph/field/specification/ReleephSummaryFieldSpecification.php',
'ReleephUserView' => 'applications/releeph/view/user/ReleephUserView.php',
'SlowvoteEmbedView' => 'applications/slowvote/view/SlowvoteEmbedView.php',
'SlowvoteRemarkupRule' => 'applications/slowvote/remarkup/SlowvoteRemarkupRule.php',
),
'function' =>
array(
'_phabricator_date_format' => 'view/viewutils.php',
'_phabricator_time_format' => 'view/viewutils.php',
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api.php',
'celerity_get_resource_uri' => 'infrastructure/celerity/api.php',
'celerity_register_resource_map' => 'infrastructure/celerity/map.php',
'implode_selected_handle_links' => 'applications/phid/handle/view/render.php',
'javelin_tag' => 'infrastructure/javelin/markup.php',
'phabricator_date' => 'view/viewutils.php',
'phabricator_datetime' => 'view/viewutils.php',
'phabricator_form' => 'infrastructure/javelin/markup.php',
'phabricator_format_bytes' => 'view/viewutils.php',
'phabricator_format_local_time' => 'view/viewutils.php',
'phabricator_format_relative_time' => 'view/viewutils.php',
'phabricator_format_relative_time_detailed' => 'view/viewutils.php',
'phabricator_format_units_generic' => 'view/viewutils.php',
'phabricator_on_relative_date' => 'view/viewutils.php',
'phabricator_parse_bytes' => 'view/viewutils.php',
'phabricator_relative_date' => 'view/viewutils.php',
'phabricator_time' => 'view/viewutils.php',
'phid_get_subtype' => 'applications/phid/utils.php',
'phid_get_type' => 'applications/phid/utils.php',
'phid_group_by_type' => 'applications/phid/utils.php',
'require_celerity_resource' => 'infrastructure/celerity/api.php',
),
'xmap' =>
array(
'Aphront304Response' => 'AphrontResponse',
'Aphront400Response' => 'AphrontResponse',
'Aphront403Response' => 'AphrontHTMLResponse',
'Aphront404Response' => 'AphrontHTMLResponse',
'AphrontAbstractAttachedFileView' => 'AphrontView',
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontBarView' => 'AphrontView',
'AphrontCSRFException' => 'AphrontException',
'AphrontCalendarEventView' => 'AphrontView',
'AphrontCalendarMonthView' => 'AphrontView',
'AphrontContextBarView' => 'AphrontView',
'AphrontController' => 'Phobject',
'AphrontCursorPagerView' => 'AphrontView',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDialogResponse' => 'AphrontResponse',
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
'AphrontException' => 'Exception',
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormCropControl' => 'AphrontFormControl',
'AphrontFormDateControl' => 'AphrontFormControl',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormImageControl' => 'AphrontFormControl',
'AphrontFormInsetView' => 'AphrontView',
'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl',
'AphrontFormPolicyControl' => 'AphrontFormControl',
'AphrontFormRadioButtonControl' => 'AphrontFormControl',
'AphrontFormRecaptchaControl' => 'AphrontFormControl',
'AphrontFormSelectControl' => 'AphrontFormControl',
'AphrontFormStaticControl' => 'AphrontFormControl',
'AphrontFormSubmitControl' => 'AphrontFormControl',
'AphrontFormTextAreaControl' => 'AphrontFormControl',
'AphrontFormTextControl' => 'AphrontFormControl',
'AphrontFormToggleButtonsControl' => 'AphrontFormControl',
'AphrontFormTokenizerControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
'AphrontGlyphBarView' => 'AphrontBarView',
'AphrontHTMLResponse' => 'AphrontResponse',
'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase',
'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink',
'AphrontJSONResponse' => 'AphrontResponse',
'AphrontJavelinView' => 'AphrontView',
'AphrontKeyboardShortcutsAvailableView' => 'AphrontView',
'AphrontListFilterView' => 'AphrontView',
'AphrontMiniPanelView' => 'AphrontView',
'AphrontMoreView' => 'AphrontView',
'AphrontMultiColumnView' => 'AphrontView',
'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontNoteView' => 'AphrontView',
'AphrontNullView' => 'AphrontView',
'AphrontPHPHTTPSink' => 'AphrontHTTPSink',
'AphrontPageView' => 'AphrontView',
'AphrontPagerView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontPlainTextResponse' => 'AphrontResponse',
'AphrontProgressBarView' => 'AphrontBarView',
'AphrontProxyResponse' => 'AphrontResponse',
'AphrontRedirectResponse' => 'AphrontResponse',
'AphrontReloadResponse' => 'AphrontRedirectResponse',
'AphrontRequestFailureView' => 'AphrontView',
'AphrontRequestTestCase' => 'PhabricatorTestCase',
'AphrontSideNavFilterView' => 'AphrontView',
'AphrontTableView' => 'AphrontView',
'AphrontTagView' => 'AphrontView',
'AphrontTokenizerTemplateView' => 'AphrontView',
'AphrontTwoColumnView' => 'AphrontView',
'AphrontTypeaheadTemplateView' => 'AphrontView',
'AphrontUsageException' => 'AphrontException',
'AphrontView' =>
array(
0 => 'Phobject',
1 => 'PhutilSafeHTMLProducerInterface',
),
'AphrontWebpageResponse' => 'AphrontHTMLResponse',
'AuditActionMenuEventListener' => 'PhabricatorEventListener',
'CelerityPhabricatorResourceController' => 'CelerityResourceController',
'CelerityResourceController' => 'PhabricatorController',
'CelerityResourceGraph' => 'AbstractDirectedGraph',
'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase',
'ConduitAPIMethod' =>
array(
0 => 'Phobject',
1 => 'PhabricatorPolicyInterface',
),
'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
'ConduitAPI_audit_Method' => 'ConduitAPIMethod',
'ConduitAPI_audit_query_Method' => 'ConduitAPI_audit_Method',
'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod',
'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method',
'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method',
'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_query_Method' => 'ConduitAPIMethod',
'ConduitAPI_conpherence_Method' => 'ConduitAPIMethod',
'ConduitAPI_conpherence_createthread_Method' => 'ConduitAPI_conpherence_Method',
'ConduitAPI_conpherence_querythread_Method' => 'ConduitAPI_conpherence_Method',
'ConduitAPI_conpherence_querytransaction_Method' => 'ConduitAPI_conpherence_Method',
'ConduitAPI_conpherence_updatethread_Method' => 'ConduitAPI_conpherence_Method',
'ConduitAPI_differential_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_close_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createcomment_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createinline_Method' => 'ConduitAPI_differential_Method',
'ConduitAPI_differential_createrawdiff_Method' => 'ConduitAPI_differential_Method',
'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_finishpostponedlinters_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrawdiff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevisioncomments_Method' => 'ConduitAPI_differential_Method',
'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_querydiffs_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_abstractquery_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_branchquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_browsequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_commitbranchesquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_commitparentsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_createcomment_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_diffquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_existsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_expandshortcommitquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_filecontentquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_getlintmessages_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPI_diffusion_Method',
'ConduitAPI_diffusion_historyquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_lastmodifiedquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_mergedcommitsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_rawdiffquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_readmequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_refsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_searchquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_stablecommitnamequery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_diffusion_tagsquery_Method' => 'ConduitAPI_diffusion_abstractquery_Method',
'ConduitAPI_feed_Method' => 'ConduitAPIMethod',
'ConduitAPI_feed_publish_Method' => 'ConduitAPI_feed_Method',
'ConduitAPI_feed_query_Method' => 'ConduitAPI_feed_Method',
'ConduitAPI_file_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_download_Method' => 'ConduitAPI_file_Method',
'ConduitAPI_file_info_Method' => 'ConduitAPI_file_Method',
'ConduitAPI_file_upload_Method' => 'ConduitAPI_file_Method',
'ConduitAPI_file_uploadhash_Method' => 'ConduitAPI_file_Method',
'ConduitAPI_flag_Method' => 'ConduitAPIMethod',
'ConduitAPI_flag_delete_Method' => 'ConduitAPI_flag_Method',
'ConduitAPI_flag_edit_Method' => 'ConduitAPI_flag_Method',
'ConduitAPI_flag_query_Method' => 'ConduitAPI_flag_Method',
'ConduitAPI_macro_Method' => 'ConduitAPIMethod',
'ConduitAPI_macro_creatememe_Method' => 'ConduitAPI_macro_Method',
'ConduitAPI_macro_query_Method' => 'ConduitAPI_macro_Method',
'ConduitAPI_maniphest_Method' => 'ConduitAPIMethod',
'ConduitAPI_maniphest_createtask_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_find_Method' => 'ConduitAPI_maniphest_query_Method',
'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_query_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method',
'ConduitAPI_owners_Method' => 'ConduitAPIMethod',
'ConduitAPI_owners_query_Method' => 'ConduitAPI_owners_Method',
'ConduitAPI_paste_Method' => 'ConduitAPIMethod',
'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_paste_query_Method' => 'ConduitAPI_paste_Method',
'ConduitAPI_phid_Method' => 'ConduitAPIMethod',
'ConduitAPI_phid_info_Method' => 'ConduitAPI_phid_Method',
'ConduitAPI_phid_lookup_Method' => 'ConduitAPI_phid_Method',
'ConduitAPI_phid_query_Method' => 'ConduitAPI_phid_Method',
'ConduitAPI_phpast_Method' => 'ConduitAPIMethod',
'ConduitAPI_phpast_getast_Method' => 'ConduitAPI_phpast_Method',
'ConduitAPI_phpast_version_Method' => 'ConduitAPI_phpast_Method',
'ConduitAPI_phriction_Method' => 'ConduitAPIMethod',
'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_phriction_info_Method' => 'ConduitAPI_phriction_Method',
'ConduitAPI_project_Method' => 'ConduitAPIMethod',
'ConduitAPI_project_query_Method' => 'ConduitAPI_project_Method',
'ConduitAPI_releeph_Method' => 'ConduitAPIMethod',
'ConduitAPI_releeph_getbranches_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releeph_projectinfo_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releeph_queryrequests_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releeph_request_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_canpush_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_getauthorinfo_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_getbranch_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_getbranchcommitmessage_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_getcommitmessage_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_getorigcommitmessage_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_nextrequest_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_record_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_releephwork_recordpickstatus_Method' => 'ConduitAPI_releeph_Method',
'ConduitAPI_remarkup_process_Method' => 'ConduitAPIMethod',
'ConduitAPI_repository_Method' => 'ConduitAPIMethod',
'ConduitAPI_repository_create_Method' => 'ConduitAPI_repository_Method',
'ConduitAPI_repository_query_Method' => 'ConduitAPI_repository_Method',
'ConduitAPI_slowvote_Method' => 'ConduitAPIMethod',
'ConduitAPI_slowvote_info_Method' => 'ConduitAPI_slowvote_Method',
'ConduitAPI_token_Method' => 'ConduitAPIMethod',
'ConduitAPI_token_give_Method' => 'ConduitAPI_token_Method',
'ConduitAPI_token_given_Method' => 'ConduitAPI_token_Method',
'ConduitAPI_token_query_Method' => 'ConduitAPI_token_Method',
'ConduitAPI_user_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_addstatus_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_disable_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_enable_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_find_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_info_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_query_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_removestatus_Method' => 'ConduitAPI_user_Method',
'ConduitAPI_user_whoami_Method' => 'ConduitAPI_user_Method',
'ConduitCallTestCase' => 'PhabricatorTestCase',
'ConduitException' => 'Exception',
'ConduitSSHWorkflow' => 'PhabricatorSSHWorkflow',
'ConpherenceActionMenuEventListener' => 'PhabricatorEventListener',
'ConpherenceConfigOptions' => 'PhabricatorApplicationConfigOptions',
'ConpherenceController' => 'PhabricatorController',
'ConpherenceCreateThreadMailReceiver' => 'PhabricatorMailReceiver',
'ConpherenceDAO' => 'PhabricatorLiskDAO',
'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor',
'ConpherenceFileWidgetView' => 'ConpherenceWidgetView',
'ConpherenceHovercardEventListener' => 'PhabricatorEventListener',
'ConpherenceLayoutView' => 'AphrontView',
'ConpherenceListController' => 'ConpherenceController',
'ConpherenceMenuItemView' => 'AphrontTagView',
'ConpherenceNewController' => 'ConpherenceController',
'ConpherenceNotificationPanelController' => 'ConpherenceController',
'ConpherenceParticipant' => 'ConpherenceDAO',
'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipationStatus' => 'ConpherenceConstants',
'ConpherencePeopleWidgetView' => 'ConpherenceWidgetView',
'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler',
'ConpherenceSettings' => 'ConpherenceConstants',
'ConpherenceThread' =>
array(
0 => 'ConpherenceDAO',
1 => 'PhabricatorPolicyInterface',
),
'ConpherenceThreadListView' => 'AphrontView',
'ConpherenceThreadMailReceiver' => 'PhabricatorObjectMailReceiver',
'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'ConpherenceTimeUtilTestCase' => 'PhabricatorTestCase',
'ConpherenceTransaction' => 'PhabricatorApplicationTransaction',
'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment',
'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ConpherenceTransactionType' => 'ConpherenceConstants',
'ConpherenceTransactionView' => 'AphrontView',
'ConpherenceUpdateActions' => 'ConpherenceConstants',
'ConpherenceUpdateController' => 'ConpherenceController',
'ConpherenceViewController' => 'ConpherenceController',
'ConpherenceWidgetController' => 'ConpherenceController',
'ConpherenceWidgetView' => 'AphrontView',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleDataController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
'DarkConsoleEventPlugin' => 'DarkConsolePlugin',
'DarkConsoleEventPluginAPI' => 'PhabricatorEventListener',
'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
'DefaultDatabaseConfigurationProvider' => 'DatabaseConfigurationProvider',
'DifferentialActionHasNoEffectException' => 'DifferentialException',
'DifferentialActionMenuEventListener' => 'PhabricatorEventListener',
'DifferentialAddCommentView' => 'AphrontView',
'DifferentialAffectedPath' => 'DifferentialDAO',
'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAsanaRepresentationFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialAuxiliaryField' => 'DifferentialDAO',
'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialBranchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail',
'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'DifferentialChangeset' => 'DifferentialDAO',
'DifferentialChangesetDetailView' => 'AphrontView',
'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer',
'DifferentialChangesetListView' => 'AphrontView',
'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer',
'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer',
'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase',
'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer',
'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer',
'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer',
'DifferentialChangesetViewController' => 'DifferentialController',
'DifferentialComment' =>
array(
0 => 'DifferentialDAO',
1 => 'PhabricatorMarkupInterface',
),
'DifferentialCommentEditor' => 'PhabricatorEditor',
'DifferentialCommentMail' => 'DifferentialMail',
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentQuery' => 'PhabricatorOffsetPagedQuery',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialConflictsFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialController' => 'PhabricatorController',
'DifferentialCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'DifferentialCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
'DifferentialCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'DifferentialDAO' => 'PhabricatorLiskDAO',
'DifferentialDateCreatedFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDateModifiedFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDefaultFieldSelector' => 'DifferentialFieldSelector',
'DifferentialDependenciesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDependsOnFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDiff' =>
array(
0 => 'DifferentialDAO',
1 => 'PhabricatorPolicyInterface',
),
'DifferentialDiffContentMail' => 'DifferentialMail',
'DifferentialDiffCreateController' => 'DifferentialController',
'DifferentialDiffProperty' => 'DifferentialDAO',
'DifferentialDiffQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DifferentialDiffTableOfContentsView' => 'AphrontView',
'DifferentialDiffTestCase' => 'ArcanistPhutilTestCase',
'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialDiffViewPolicyFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialDoorkeeperRevisionFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher',
'DifferentialEditPolicyFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialException' => 'Exception',
'DifferentialExceptionMail' => 'DifferentialMail',
'DifferentialExportPatchFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialFieldDataNotAvailableException' => 'Exception',
'DifferentialFieldParseException' => 'Exception',
'DifferentialFieldSpecificationIncompleteException' => 'Exception',
'DifferentialFieldValidationException' => 'Exception',
'DifferentialFreeformFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialFreeformFieldTestCase' => 'PhabricatorTestCase',
'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialHovercardEventListener' => 'PhabricatorEventListener',
'DifferentialHunk' => 'DifferentialDAO',
'DifferentialHunkParserTestCase' => 'PhabricatorTestCase',
'DifferentialHunkTestCase' => 'ArcanistPhutilTestCase',
'DifferentialInlineComment' => 'PhabricatorInlineCommentInterface',
'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController',
'DifferentialInlineCommentEditView' => 'AphrontView',
'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery',
'DifferentialInlineCommentView' => 'AphrontView',
'DifferentialJIRAIssuesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialLocalCommitsView' => 'AphrontView',
'DifferentialMail' => 'PhabricatorMail',
'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail',
'DifferentialPHIDTypeRevision' => 'PhabricatorPHIDType',
'DifferentialParseRenderTestCase' => 'PhabricatorTestCase',
'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialPrimaryPaneView' => 'AphrontView',
'DifferentialProjectReviewersFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReleephRequestFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler',
'DifferentialRepositoryFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRepositoryLookup' => 'Phobject',
'DifferentialResultsTableView' => 'AphrontView',
'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReviewRequestMail' => 'DifferentialMail',
'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialReviewersView' => 'AphrontView',
'DifferentialRevision' =>
array(
0 => 'DifferentialDAO',
1 => 'PhabricatorTokenReceiverInterface',
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhrequentTrackableInterface',
),
'DifferentialRevisionCommentListView' => 'AphrontView',
'DifferentialRevisionCommentView' => 'AphrontView',
'DifferentialRevisionDetailView' => 'AphrontView',
'DifferentialRevisionEditController' => 'DifferentialController',
'DifferentialRevisionEditor' => 'PhabricatorEditor',
'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase',
'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRevisionListController' =>
array(
0 => 'DifferentialController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'DifferentialRevisionListView' => 'AphrontView',
'DifferentialRevisionMailReceiver' => 'PhabricatorObjectMailReceiver',
'DifferentialRevisionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DifferentialRevisionSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DifferentialRevisionStatsView' => 'AphrontView',
'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'DifferentialSubscribeController' => 'DifferentialController',
'DifferentialSummaryFieldSpecification' => 'DifferentialFreeformFieldSpecification',
'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialTitleFieldSpecification' => 'DifferentialFreeformFieldSpecification',
'DifferentialTransaction' => 'PhabricatorApplicationTransaction',
'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment',
'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification',
'DifferentialViewPolicyFieldSpecification' => 'DifferentialFieldSpecification',
'DiffusionBranchTableController' => 'DiffusionController',
'DiffusionBranchTableView' => 'DiffusionView',
'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseDirectoryController' => 'DiffusionBrowseController',
'DiffusionBrowseFileController' => 'DiffusionBrowseController',
'DiffusionBrowseMainController' => 'DiffusionBrowseController',
'DiffusionBrowseSearchController' => 'DiffusionBrowseController',
'DiffusionBrowseTableView' => 'DiffusionView',
+ 'DiffusionCapabilityCreateRepositories' => 'PhabricatorPolicyCapability',
+ 'DiffusionCapabilityDefaultEdit' => 'PhabricatorPolicyCapability',
+ 'DiffusionCapabilityDefaultPush' => 'PhabricatorPolicyCapability',
+ 'DiffusionCapabilityDefaultView' => 'PhabricatorPolicyCapability',
+ 'DiffusionCapabilityPush' => 'PhabricatorPolicyCapability',
'DiffusionChangeController' => 'DiffusionController',
'DiffusionCommentListView' => 'AphrontView',
'DiffusionCommentView' => 'AphrontView',
'DiffusionCommitBranchesController' => 'DiffusionController',
'DiffusionCommitChangeTableView' => 'DiffusionView',
'DiffusionCommitController' => 'DiffusionController',
'DiffusionCommitEditController' => 'DiffusionController',
'DiffusionCommitParentsQuery' => 'DiffusionQuery',
'DiffusionCommitQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DiffusionCommitTagsController' => 'DiffusionController',
'DiffusionController' => 'PhabricatorController',
'DiffusionDiffController' => 'DiffusionController',
'DiffusionDoorkeeperCommitFeedStoryPublisher' => 'DoorkeeperFeedStoryPublisher',
'DiffusionEmptyResultView' => 'DiffusionView',
'DiffusionExpandCommitQueryException' => 'Exception',
'DiffusionExpandShortNameQuery' => 'DiffusionQuery',
'DiffusionExternalController' => 'DiffusionController',
'DiffusionFileContentQuery' => 'DiffusionQuery',
'DiffusionGitBranchTestCase' => 'PhabricatorTestCase',
'DiffusionGitCommitParentsQuery' => 'DiffusionCommitParentsQuery',
'DiffusionGitExpandShortNameQuery' => 'DiffusionExpandShortNameQuery',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
+ 'DiffusionGitResponse' => 'AphrontResponse',
'DiffusionGitStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'DiffusionView',
'DiffusionHovercardEventListener' => 'PhabricatorEventListener',
'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController',
'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController',
'DiffusionLastModifiedController' => 'DiffusionController',
'DiffusionLintController' => 'DiffusionController',
'DiffusionLintDetailsController' => 'DiffusionController',
'DiffusionMercurialCommitParentsQuery' => 'DiffusionCommitParentsQuery',
'DiffusionMercurialExpandShortNameQuery' => 'DiffusionExpandShortNameQuery',
'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionMercurialRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionMercurialRequest' => 'DiffusionRequest',
'DiffusionMercurialStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
'DiffusionPathCompleteController' => 'DiffusionController',
'DiffusionPathQueryTestCase' => 'PhabricatorTestCase',
'DiffusionPathValidateController' => 'DiffusionController',
'DiffusionQuery' => 'PhabricatorQuery',
'DiffusionRawDiffQuery' => 'DiffusionQuery',
'DiffusionRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'DiffusionRepositoryController' => 'DiffusionController',
'DiffusionRepositoryCreateController' => 'DiffusionRepositoryEditController',
+ 'DiffusionRepositoryDefaultController' => 'DiffusionController',
'DiffusionRepositoryEditActionsController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditActivateController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditBasicController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditBranchesController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditController' => 'DiffusionController',
'DiffusionRepositoryEditDeleteController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditEncodingController' => 'DiffusionRepositoryEditController',
+ 'DiffusionRepositoryEditHostingController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditLocalController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditMainController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditPolicyController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryEditSubversionController' => 'DiffusionRepositoryEditController',
'DiffusionRepositoryListController' =>
array(
0 => 'DiffusionController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
+ 'DiffusionSSHGitReceivePackWorkflow' => 'DiffusionSSHGitWorkflow',
+ 'DiffusionSSHGitUploadPackWorkflow' => 'DiffusionSSHGitWorkflow',
+ 'DiffusionSSHGitWorkflow' => 'DiffusionSSHWorkflow',
+ 'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow',
'DiffusionSetupException' => 'AphrontUsageException',
'DiffusionStableCommitNameQuery' => 'DiffusionQuery',
'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery',
'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionSvnRawDiffQuery' => 'DiffusionRawDiffQuery',
'DiffusionSvnRequest' => 'DiffusionRequest',
'DiffusionSvnStableCommitNameQuery' => 'DiffusionStableCommitNameQuery',
'DiffusionSymbolController' => 'DiffusionController',
'DiffusionSymbolQuery' => 'PhabricatorOffsetPagedQuery',
'DiffusionTagListController' => 'DiffusionController',
'DiffusionTagListView' => 'DiffusionView',
'DiffusionURITestCase' => 'ArcanistPhutilTestCase',
'DiffusionView' => 'AphrontView',
'DivinerArticleAtomizer' => 'DivinerAtomizer',
'DivinerAtomCache' => 'DivinerDiskCache',
'DivinerAtomController' => 'DivinerController',
'DivinerAtomListController' =>
array(
0 => 'DivinerController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'DivinerAtomQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DivinerAtomSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DivinerAtomizeWorkflow' => 'DivinerWorkflow',
'DivinerBookController' => 'DivinerController',
'DivinerBookItemView' => 'AphrontTagView',
'DivinerBookQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DivinerController' => 'PhabricatorController',
'DivinerDAO' => 'PhabricatorLiskDAO',
'DivinerDefaultRenderer' => 'DivinerRenderer',
'DivinerFileAtomizer' => 'DivinerAtomizer',
'DivinerFindController' => 'DivinerController',
'DivinerGenerateWorkflow' => 'DivinerWorkflow',
'DivinerLegacyController' => 'DivinerController',
'DivinerLiveAtom' => 'DivinerDAO',
'DivinerLiveBook' =>
array(
0 => 'DivinerDAO',
1 => 'PhabricatorPolicyInterface',
),
'DivinerLivePublisher' => 'DivinerPublisher',
'DivinerLiveSymbol' =>
array(
0 => 'DivinerDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorMarkupInterface',
),
'DivinerPHIDTypeAtom' => 'PhabricatorPHIDType',
'DivinerPHIDTypeBook' => 'PhabricatorPHIDType',
'DivinerPHPAtomizer' => 'DivinerAtomizer',
'DivinerParameterTableView' => 'AphrontTagView',
'DivinerPublishCache' => 'DivinerDiskCache',
'DivinerRemarkupRuleSymbol' => 'PhutilRemarkupRule',
'DivinerReturnTableView' => 'AphrontTagView',
'DivinerSectionView' => 'AphrontTagView',
'DivinerStaticPublisher' => 'DivinerPublisher',
'DivinerWorkflow' => 'PhutilArgumentWorkflow',
'DoorkeeperBridge' => 'Phobject',
'DoorkeeperBridgeAsana' => 'DoorkeeperBridge',
'DoorkeeperBridgeJIRA' => 'DoorkeeperBridge',
'DoorkeeperDAO' => 'PhabricatorLiskDAO',
'DoorkeeperExternalObject' =>
array(
0 => 'DoorkeeperDAO',
1 => 'PhabricatorPolicyInterface',
),
'DoorkeeperExternalObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'DoorkeeperFeedWorker' => 'FeedPushWorker',
'DoorkeeperFeedWorkerAsana' => 'DoorkeeperFeedWorker',
'DoorkeeperFeedWorkerJIRA' => 'DoorkeeperFeedWorker',
'DoorkeeperImportEngine' => 'Phobject',
'DoorkeeperObjectRef' => 'Phobject',
'DoorkeeperRemarkupRule' => 'PhutilRemarkupRule',
'DoorkeeperRemarkupRuleAsana' => 'DoorkeeperRemarkupRule',
'DoorkeeperRemarkupRuleJIRA' => 'DoorkeeperRemarkupRule',
'DoorkeeperTagsController' => 'PhabricatorController',
'DrydockAllocatorWorker' => 'PhabricatorWorker',
'DrydockApacheWebrootInterface' => 'DrydockWebrootInterface',
'DrydockCommandInterface' => 'DrydockInterface',
'DrydockController' => 'PhabricatorController',
'DrydockDAO' => 'PhabricatorLiskDAO',
'DrydockLease' => 'DrydockDAO',
'DrydockLeaseListController' => 'DrydockController',
'DrydockLeaseQuery' => 'PhabricatorOffsetPagedQuery',
'DrydockLeaseReleaseController' => 'DrydockController',
'DrydockLeaseStatus' => 'DrydockConstants',
'DrydockLeaseViewController' => 'DrydockController',
'DrydockLocalCommandInterface' => 'DrydockCommandInterface',
'DrydockLocalHostBlueprint' => 'DrydockBlueprint',
'DrydockLog' => 'DrydockDAO',
'DrydockLogController' => 'DrydockController',
'DrydockLogQuery' => 'PhabricatorOffsetPagedQuery',
'DrydockManagementCloseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWaitForLeaseWorkflow' => 'DrydockManagementWorkflow',
'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow',
'DrydockResource' => 'DrydockDAO',
'DrydockResourceCloseController' => 'DrydockController',
'DrydockResourceListController' => 'DrydockController',
'DrydockResourceQuery' => 'PhabricatorOffsetPagedQuery',
'DrydockResourceStatus' => 'DrydockConstants',
'DrydockResourceViewController' => 'DrydockController',
'DrydockSSHCommandInterface' => 'DrydockCommandInterface',
'DrydockWebrootInterface' => 'DrydockInterface',
'DrydockWorkingCopyBlueprint' => 'DrydockBlueprint',
'FeedPublisherHTTPWorker' => 'FeedPushWorker',
'FeedPublisherWorker' => 'FeedPushWorker',
'FeedPushWorker' => 'PhabricatorWorker',
'FileCreateMailReceiver' => 'PhabricatorMailReceiver',
'FileMailReceiver' => 'PhabricatorObjectMailReceiver',
'FileReplyHandler' => 'PhabricatorMailReplyHandler',
'HarbormasterBuild' =>
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildArtifact' =>
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildItem' => 'HarbormasterDAO',
'HarbormasterBuildItemQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildLog' => 'HarbormasterDAO',
'HarbormasterBuildPlan' =>
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorSubscribableInterface',
),
'HarbormasterBuildPlanEditor' => 'PhabricatorApplicationTransactionEditor',
'HarbormasterBuildPlanQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildPlanSearchEngine' => 'PhabricatorApplicationSearchEngine',
'HarbormasterBuildPlanTransaction' => 'PhabricatorApplicationTransaction',
'HarbormasterBuildPlanTransactionComment' => 'PhabricatorApplicationTransactionComment',
'HarbormasterBuildPlanTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'HarbormasterBuildQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildStep' => 'HarbormasterDAO',
'HarbormasterBuildStepQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildTarget' => 'HarbormasterDAO',
'HarbormasterBuildTargetQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildable' =>
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
),
'HarbormasterBuildableArtifactQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildableEditController' => 'HarbormasterController',
'HarbormasterBuildableListController' =>
array(
0 => 'HarbormasterController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'HarbormasterBuildableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HarbormasterBuildableSearchEngine' => 'PhabricatorApplicationSearchEngine',
'HarbormasterBuildableViewController' => 'HarbormasterController',
'HarbormasterCapabilityManagePlans' => 'PhabricatorPolicyCapability',
'HarbormasterController' => 'PhabricatorController',
'HarbormasterDAO' => 'PhabricatorLiskDAO',
'HarbormasterObject' => 'HarbormasterDAO',
'HarbormasterPHIDTypeBuild' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildItem' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildPlan' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildStep' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildTarget' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildable' => 'PhabricatorPHIDType',
'HarbormasterPlanController' => 'PhabricatorController',
'HarbormasterPlanEditController' => 'HarbormasterPlanController',
'HarbormasterPlanExecuteController' => 'HarbormasterPlanController',
'HarbormasterPlanListController' =>
array(
0 => 'HarbormasterPlanController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'HarbormasterPlanViewController' => 'HarbormasterPlanController',
'HarbormasterRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'HarbormasterRunnerWorker' => 'PhabricatorWorker',
'HarbormasterScratchTable' => 'HarbormasterDAO',
'HeraldAction' => 'HeraldDAO',
'HeraldApplyTranscript' => 'HeraldDAO',
'HeraldCapabilityManageGlobalRules' => 'PhabricatorPolicyCapability',
'HeraldCommitAdapter' => 'HeraldAdapter',
'HeraldCondition' => 'HeraldDAO',
'HeraldController' => 'PhabricatorController',
'HeraldDAO' => 'PhabricatorLiskDAO',
'HeraldDifferentialRevisionAdapter' => 'HeraldAdapter',
'HeraldDisableController' => 'HeraldController',
'HeraldEditLogQuery' => 'PhabricatorOffsetPagedQuery',
'HeraldInvalidActionException' => 'Exception',
'HeraldInvalidConditionException' => 'Exception',
'HeraldInvalidFieldException' => 'Exception',
'HeraldManiphestTaskAdapter' => 'HeraldAdapter',
'HeraldNewController' => 'HeraldController',
'HeraldPHIDTypeRule' => 'PhabricatorPHIDType',
'HeraldPholioMockAdapter' => 'HeraldAdapter',
'HeraldRecursiveConditionsException' => 'Exception',
'HeraldRule' =>
array(
0 => 'HeraldDAO',
1 => 'PhabricatorFlaggableInterface',
2 => 'PhabricatorPolicyInterface',
),
'HeraldRuleController' => 'HeraldController',
'HeraldRuleEdit' => 'HeraldDAO',
'HeraldRuleEditHistoryController' => 'HeraldController',
'HeraldRuleEditHistoryView' => 'AphrontView',
'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor',
'HeraldRuleListController' =>
array(
0 => 'HeraldController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'HeraldRuleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HeraldRuleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'HeraldRuleTransaction' => 'PhabricatorApplicationTransaction',
'HeraldRuleTransactionComment' => 'PhabricatorApplicationTransactionComment',
'HeraldRuleViewController' => 'HeraldController',
'HeraldTestConsoleController' => 'HeraldController',
'HeraldTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'HeraldTranscript' =>
array(
0 => 'HeraldDAO',
1 => 'PhabricatorPolicyInterface',
),
'HeraldTranscriptController' => 'HeraldController',
'HeraldTranscriptListController' => 'HeraldController',
'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'JavelinReactorExample' => 'PhabricatorUIExample',
'JavelinUIExample' => 'PhabricatorUIExample',
'JavelinViewExample' => 'PhabricatorUIExample',
'JavelinViewExampleServerView' => 'AphrontView',
'LegalpadController' => 'PhabricatorController',
'LegalpadDAO' => 'PhabricatorLiskDAO',
'LegalpadDocument' =>
array(
0 => 'LegalpadDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorSubscribableInterface',
3 => 'PhabricatorApplicationTransactionInterface',
),
'LegalpadDocumentBody' =>
array(
0 => 'LegalpadDAO',
1 => 'PhabricatorMarkupInterface',
),
'LegalpadDocumentCommentController' => 'LegalpadController',
'LegalpadDocumentEditController' => 'LegalpadController',
'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor',
'LegalpadDocumentListController' =>
array(
0 => 'LegalpadController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine',
'LegalpadDocumentSignController' => 'LegalpadController',
'LegalpadDocumentSignature' => 'LegalpadDAO',
'LegalpadDocumentViewController' => 'LegalpadController',
'LegalpadMockMailReceiver' => 'PhabricatorObjectMailReceiver',
'LegalpadReplyHandler' => 'PhabricatorMailReplyHandler',
'LegalpadTransaction' => 'PhabricatorApplicationTransaction',
'LegalpadTransactionComment' => 'PhabricatorApplicationTransactionComment',
'LegalpadTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'LegalpadTransactionType' => 'LegalpadConstants',
'LegalpadTransactionView' => 'PhabricatorApplicationTransactionView',
'LiskChunkTestCase' => 'PhabricatorTestCase',
'LiskDAOTestCase' => 'PhabricatorTestCase',
'LiskEphemeralObjectException' => 'Exception',
'LiskFixtureTestCase' => 'PhabricatorTestCase',
'LiskIsolationTestCase' => 'PhabricatorTestCase',
'LiskIsolationTestDAO' => 'LiskDAO',
'LiskIsolationTestDAOException' => 'Exception',
'LiskMigrationIterator' => 'PhutilBufferedIterator',
'LiskRawMigrationIterator' => 'PhutilBufferedIterator',
'ManiphestActionMenuEventListener' => 'PhabricatorEventListener',
'ManiphestBatchEditController' => 'ManiphestController',
'ManiphestCapabilityBulkEdit' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityDefaultEdit' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityEditAssign' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityEditPolicies' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityEditPriority' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityEditProjects' => 'PhabricatorPolicyCapability',
'ManiphestCapabilityEditStatus' => 'PhabricatorPolicyCapability',
'ManiphestConfiguredCustomField' =>
array(
0 => 'ManiphestCustomField',
1 => 'PhabricatorStandardCustomFieldInterface',
),
'ManiphestController' => 'PhabricatorController',
'ManiphestCreateMailReceiver' => 'PhabricatorMailReceiver',
'ManiphestCustomField' => 'PhabricatorCustomField',
'ManiphestCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'ManiphestCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
'ManiphestCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'ManiphestDAO' => 'PhabricatorLiskDAO',
'ManiphestEdgeEventListener' => 'PhabricatorEventListener',
'ManiphestExcelDefaultFormat' => 'ManiphestExcelFormat',
'ManiphestExportController' => 'ManiphestController',
'ManiphestHovercardEventListener' => 'PhabricatorEventListener',
'ManiphestNameIndex' => 'ManiphestDAO',
'ManiphestNameIndexEventListener' => 'PhabricatorEventListener',
'ManiphestPHIDTypeTask' => 'PhabricatorPHIDType',
'ManiphestRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler',
'ManiphestReportController' => 'ManiphestController',
'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'ManiphestSubpriorityController' => 'ManiphestController',
'ManiphestSubscribeController' => 'ManiphestController',
'ManiphestTask' =>
array(
0 => 'ManiphestDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorTokenReceiverInterface',
4 => 'PhabricatorFlaggableInterface',
5 => 'PhrequentTrackableInterface',
6 => 'PhabricatorCustomFieldInterface',
),
'ManiphestTaskDescriptionPreviewController' => 'ManiphestController',
'ManiphestTaskDetailController' => 'ManiphestController',
'ManiphestTaskEditController' => 'ManiphestController',
'ManiphestTaskListController' =>
array(
0 => 'ManiphestController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'ManiphestTaskListView' => 'ManiphestView',
'ManiphestTaskMailReceiver' => 'PhabricatorObjectMailReceiver',
'ManiphestTaskOwner' => 'ManiphestConstants',
'ManiphestTaskPriority' => 'ManiphestConstants',
'ManiphestTaskProject' => 'ManiphestDAO',
'ManiphestTaskProjectsView' => 'ManiphestView',
'ManiphestTaskQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'ManiphestTaskSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ManiphestTaskStatus' => 'ManiphestConstants',
'ManiphestTaskSubscriber' => 'ManiphestDAO',
'ManiphestTransaction' => 'PhabricatorApplicationTransaction',
'ManiphestTransactionComment' => 'PhabricatorApplicationTransactionComment',
'ManiphestTransactionEditor' => 'PhabricatorApplicationTransactionEditor',
'ManiphestTransactionPreviewController' => 'ManiphestController',
'ManiphestTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ManiphestTransactionSaveController' => 'ManiphestController',
'ManiphestView' => 'AphrontView',
'MetaMTANotificationType' => 'MetaMTAConstants',
'MetaMTAReceivedMailStatus' => 'MetaMTAConstants',
'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler',
'PHUIBoxExample' => 'PhabricatorUIExample',
'PHUIBoxView' => 'AphrontTagView',
'PHUIButtonExample' => 'PhabricatorUIExample',
'PHUIButtonView' => 'AphrontTagView',
'PHUIColorPalletteExample' => 'PhabricatorUIExample',
'PHUIDocumentExample' => 'PhabricatorUIExample',
'PHUIDocumentView' => 'AphrontTagView',
'PHUIFeedStoryExample' => 'PhabricatorUIExample',
'PHUIFeedStoryView' => 'AphrontView',
'PHUIFormDividerControl' => 'AphrontFormControl',
'PHUIFormFreeformDateControl' => 'AphrontFormControl',
'PHUIFormLayoutView' => 'AphrontView',
'PHUIFormMultiSubmitControl' => 'AphrontFormControl',
'PHUIFormPageView' => 'AphrontView',
'PHUIHeaderView' => 'AphrontView',
'PHUIIconExample' => 'PhabricatorUIExample',
'PHUIIconView' => 'AphrontTagView',
'PHUIInfoPanelExample' => 'PhabricatorUIExample',
'PHUIInfoPanelView' => 'AphrontView',
'PHUIListExample' => 'PhabricatorUIExample',
'PHUIListItemView' => 'AphrontTagView',
'PHUIListView' => 'AphrontTagView',
'PHUIListViewTestCase' => 'PhabricatorTestCase',
'PHUIObjectBoxView' => 'AphrontView',
'PHUIObjectItemListExample' => 'PhabricatorUIExample',
'PHUIObjectItemListView' => 'AphrontTagView',
'PHUIObjectItemView' => 'AphrontTagView',
'PHUIPagedFormView' => 'AphrontTagView',
'PHUIPinboardItemView' => 'AphrontView',
'PHUIPinboardView' => 'AphrontView',
'PHUIPropertyGroupView' => 'AphrontTagView',
'PHUIPropertyListExample' => 'PhabricatorUIExample',
'PHUIPropertyListView' => 'AphrontView',
'PHUIRemarkupPreviewPanel' => 'AphrontTagView',
'PHUIStatusItemView' => 'AphrontTagView',
'PHUIStatusListView' => 'AphrontTagView',
'PHUITextExample' => 'PhabricatorUIExample',
'PHUITextView' => 'AphrontTagView',
'PHUIWorkboardExample' => 'PhabricatorUIExample',
'PHUIWorkboardView' => 'AphrontView',
'PHUIWorkpanelView' => 'AphrontView',
'PackageCreateMail' => 'PackageMail',
'PackageDeleteMail' => 'PackageMail',
'PackageMail' => 'PhabricatorMail',
'PackageModifyMail' => 'PackageMail',
'PasteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'PasteCreateMailReceiver' => 'PhabricatorMailReceiver',
'PasteEmbedView' => 'AphrontView',
'PasteMockMailReceiver' => 'PhabricatorObjectMailReceiver',
'PasteReplyHandler' => 'PhabricatorMailReplyHandler',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAccessControlTestCase' => 'PhabricatorTestCase',
'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorActionHeaderExample' => 'PhabricatorUIExample',
'PhabricatorActionHeaderView' => 'AphrontView',
'PhabricatorActionListExample' => 'PhabricatorUIExample',
'PhabricatorActionListView' => 'AphrontView',
'PhabricatorActionView' => 'AphrontView',
'PhabricatorAllCapsTranslation' => 'PhabricatorTranslation',
'PhabricatorAnchorView' => 'AphrontView',
'PhabricatorAphrontBarExample' => 'PhabricatorUIExample',
'PhabricatorAphrontViewTestCase' => 'PhabricatorTestCase',
'PhabricatorAppSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorApplication' => 'PhabricatorPolicyInterface',
'PhabricatorApplicationApplications' => 'PhabricatorApplication',
'PhabricatorApplicationAudit' => 'PhabricatorApplication',
'PhabricatorApplicationAuth' => 'PhabricatorApplication',
'PhabricatorApplicationCalendar' => 'PhabricatorApplication',
'PhabricatorApplicationChatLog' => 'PhabricatorApplication',
'PhabricatorApplicationConduit' => 'PhabricatorApplication',
'PhabricatorApplicationConfig' => 'PhabricatorApplication',
'PhabricatorApplicationConfigOptions' => 'Phobject',
'PhabricatorApplicationConpherence' => 'PhabricatorApplication',
'PhabricatorApplicationCountdown' => 'PhabricatorApplication',
'PhabricatorApplicationDaemons' => 'PhabricatorApplication',
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationDifferential' => 'PhabricatorApplication',
'PhabricatorApplicationDiffusion' => 'PhabricatorApplication',
'PhabricatorApplicationDiviner' => 'PhabricatorApplication',
'PhabricatorApplicationDoorkeeper' => 'PhabricatorApplication',
'PhabricatorApplicationDrydock' => 'PhabricatorApplication',
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationFact' => 'PhabricatorApplication',
'PhabricatorApplicationFeed' => 'PhabricatorApplication',
'PhabricatorApplicationFiles' => 'PhabricatorApplication',
'PhabricatorApplicationFlags' => 'PhabricatorApplication',
'PhabricatorApplicationHarbormaster' => 'PhabricatorApplication',
'PhabricatorApplicationHerald' => 'PhabricatorApplication',
'PhabricatorApplicationLaunchView' => 'AphrontView',
'PhabricatorApplicationLegalpad' => 'PhabricatorApplication',
'PhabricatorApplicationMacro' => 'PhabricatorApplication',
'PhabricatorApplicationMailingLists' => 'PhabricatorApplication',
'PhabricatorApplicationManiphest' => 'PhabricatorApplication',
'PhabricatorApplicationMetaMTA' => 'PhabricatorApplication',
'PhabricatorApplicationOwners' => 'PhabricatorApplication',
'PhabricatorApplicationPHIDTypeApplication' => 'PhabricatorPHIDType',
'PhabricatorApplicationPHPAST' => 'PhabricatorApplication',
'PhabricatorApplicationPaste' => 'PhabricatorApplication',
'PhabricatorApplicationPeople' => 'PhabricatorApplication',
'PhabricatorApplicationPhame' => 'PhabricatorApplication',
'PhabricatorApplicationPhlux' => 'PhabricatorApplication',
'PhabricatorApplicationPholio' => 'PhabricatorApplication',
'PhabricatorApplicationPhortune' => 'PhabricatorApplication',
'PhabricatorApplicationPhrequent' => 'PhabricatorApplication',
'PhabricatorApplicationPhriction' => 'PhabricatorApplication',
'PhabricatorApplicationPolicy' => 'PhabricatorApplication',
'PhabricatorApplicationPonder' => 'PhabricatorApplication',
'PhabricatorApplicationProject' => 'PhabricatorApplication',
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorApplicationReleeph' => 'PhabricatorApplication',
'PhabricatorApplicationReleephConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorApplicationRepositories' => 'PhabricatorApplication',
'PhabricatorApplicationSearch' => 'PhabricatorApplication',
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorApplicationSettings' => 'PhabricatorApplication',
'PhabricatorApplicationSlowvote' => 'PhabricatorApplication',
'PhabricatorApplicationStatusView' => 'AphrontView',
'PhabricatorApplicationSubscriptions' => 'PhabricatorApplication',
'PhabricatorApplicationTest' => 'PhabricatorApplication',
'PhabricatorApplicationTokens' => 'PhabricatorApplication',
'PhabricatorApplicationTransaction' =>
array(
0 => 'PhabricatorLiskDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorApplicationTransactionComment' =>
array(
0 => 'PhabricatorLiskDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PhabricatorPolicyInterface',
),
'PhabricatorApplicationTransactionCommentEditController' => 'PhabricatorApplicationTransactionController',
'PhabricatorApplicationTransactionCommentEditor' => 'PhabricatorEditor',
'PhabricatorApplicationTransactionCommentHistoryController' => 'PhabricatorApplicationTransactionController',
'PhabricatorApplicationTransactionCommentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorApplicationTransactionCommentView' => 'AphrontView',
'PhabricatorApplicationTransactionController' => 'PhabricatorController',
'PhabricatorApplicationTransactionDetailController' => 'PhabricatorApplicationTransactionController',
'PhabricatorApplicationTransactionEditor' => 'PhabricatorEditor',
'PhabricatorApplicationTransactionFeedStory' => 'PhabricatorFeedStory',
'PhabricatorApplicationTransactionNoEffectException' => 'Exception',
'PhabricatorApplicationTransactionNoEffectResponse' => 'AphrontProxyResponse',
'PhabricatorApplicationTransactionPHIDTypeTransaction' => 'PhabricatorPHIDType',
'PhabricatorApplicationTransactionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorApplicationTransactionResponse' => 'AphrontProxyResponse',
'PhabricatorApplicationTransactionTextDiffDetailView' => 'AphrontView',
'PhabricatorApplicationTransactionValidationError' => 'Phobject',
'PhabricatorApplicationTransactionValidationException' => 'Exception',
'PhabricatorApplicationTransactionView' => 'AphrontView',
'PhabricatorApplicationTransactions' => 'PhabricatorApplication',
'PhabricatorApplicationUIExamples' => 'PhabricatorApplication',
'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationXHProf' => 'PhabricatorApplication',
'PhabricatorApplicationsController' => 'PhabricatorController',
'PhabricatorApplicationsListController' =>
array(
0 => 'PhabricatorApplicationsController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorAsanaConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
'PhabricatorAuditComment' =>
array(
0 => 'PhabricatorAuditDAO',
1 => 'PhabricatorMarkupInterface',
),
'PhabricatorAuditCommentEditor' => 'PhabricatorEditor',
'PhabricatorAuditCommitListView' => 'AphrontView',
'PhabricatorAuditController' => 'PhabricatorController',
'PhabricatorAuditDAO' => 'PhabricatorLiskDAO',
'PhabricatorAuditInlineComment' =>
array(
0 => 'PhabricatorAuditDAO',
1 => 'PhabricatorInlineCommentInterface',
),
'PhabricatorAuditListController' => 'PhabricatorAuditController',
'PhabricatorAuditListView' => 'AphrontView',
'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver',
'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow',
'PhabricatorAuditManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorAuditPreviewController' => 'PhabricatorAuditController',
'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler',
'PhabricatorAuthAccountView' => 'AphrontView',
'PhabricatorAuthConfirmLinkController' => 'PhabricatorAuthController',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorAuthDAO' => 'PhabricatorLiskDAO',
'PhabricatorAuthDisableController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthLinkController' => 'PhabricatorAuthController',
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorAuthManagementLDAPWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementRecoverWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementRefreshWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController',
'PhabricatorAuthProviderConfig' =>
array(
0 => 'PhabricatorAuthDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthController',
'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthProviderLDAP' => 'PhabricatorAuthProvider',
'PhabricatorAuthProviderOAuth' => 'PhabricatorAuthProvider',
'PhabricatorAuthProviderOAuth1' => 'PhabricatorAuthProvider',
'PhabricatorAuthProviderOAuth1JIRA' => 'PhabricatorAuthProviderOAuth1',
'PhabricatorAuthProviderOAuth1Twitter' => 'PhabricatorAuthProviderOAuth1',
'PhabricatorAuthProviderOAuthAmazon' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthAsana' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthDisqus' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthFacebook' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthGitHub' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthGoogle' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderOAuthTwitch' => 'PhabricatorAuthProviderOAuth',
'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider',
'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider',
'PhabricatorAuthRegisterController' => 'PhabricatorAuthController',
'PhabricatorAuthStartController' => 'PhabricatorAuthController',
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorBarePageExample' => 'PhabricatorUIExample',
'PhabricatorBarePageView' => 'AphrontPageView',
'PhabricatorBaseEnglishTranslation' => 'PhabricatorTranslation',
'PhabricatorBot' => 'PhabricatorDaemon',
'PhabricatorBotBaseStreamingProtocolAdapter' => 'PhabricatorBaseProtocolAdapter',
'PhabricatorBotChannel' => 'PhabricatorBotTarget',
'PhabricatorBotDebugLogHandler' => 'PhabricatorBotHandler',
'PhabricatorBotDifferentialNotificationHandler' => 'PhabricatorBotHandler',
'PhabricatorBotFeedNotificationHandler' => 'PhabricatorBotHandler',
'PhabricatorBotFlowdockProtocolAdapter' => 'PhabricatorBotBaseStreamingProtocolAdapter',
'PhabricatorBotLogHandler' => 'PhabricatorBotHandler',
'PhabricatorBotMacroHandler' => 'PhabricatorBotHandler',
'PhabricatorBotObjectNameHandler' => 'PhabricatorBotHandler',
'PhabricatorBotSymbolHandler' => 'PhabricatorBotHandler',
'PhabricatorBotUser' => 'PhabricatorBotTarget',
'PhabricatorBotWhatsNewHandler' => 'PhabricatorBotHandler',
'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList',
'PhabricatorBusyExample' => 'PhabricatorUIExample',
'PhabricatorCacheDAO' => 'PhabricatorLiskDAO',
'PhabricatorCacheManagementPurgeWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorCacheManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
'PhabricatorCalendarController' => 'PhabricatorController',
'PhabricatorCalendarDAO' => 'PhabricatorLiskDAO',
'PhabricatorCalendarDeleteStatusController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEditStatusController' => 'PhabricatorCalendarController',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
'PhabricatorCalendarViewStatusController' => 'PhabricatorCalendarController',
'PhabricatorCampfireProtocolAdapter' => 'PhabricatorBotBaseStreamingProtocolAdapter',
'PhabricatorChangesetResponse' => 'AphrontProxyResponse',
'PhabricatorChatLogChannel' =>
array(
0 => 'PhabricatorChatLogDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController',
'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController',
'PhabricatorChatLogChannelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorChatLogController' => 'PhabricatorController',
'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO',
'PhabricatorChatLogEvent' =>
array(
0 => 'PhabricatorChatLogDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants',
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
'PhabricatorConduitConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
'PhabricatorConduitController' => 'PhabricatorController',
'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
'PhabricatorConduitListController' =>
array(
0 => 'PhabricatorConduitController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
'PhabricatorConduitLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorConduitMethodCallLog' =>
array(
0 => 'PhabricatorConduitDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorConduitMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorConduitSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorConduitTokenController' => 'PhabricatorConduitController',
'PhabricatorConfigAllController' => 'PhabricatorConfigController',
'PhabricatorConfigController' => 'PhabricatorController',
'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource',
'PhabricatorConfigEditController' => 'PhabricatorConfigController',
'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorConfigEntry' =>
array(
0 => 'PhabricatorConfigEntryDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO',
'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigGroupController' => 'PhabricatorConfigController',
'PhabricatorConfigIgnoreController' => 'PhabricatorApplicationsController',
'PhabricatorConfigIssueListController' => 'PhabricatorConfigController',
'PhabricatorConfigIssueViewController' => 'PhabricatorConfigController',
'PhabricatorConfigListController' => 'PhabricatorConfigController',
'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource',
'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow',
'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow',
'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow',
'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow',
'PhabricatorConfigManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorConfigOption' =>
array(
0 => 'Phobject',
1 => 'PhabricatorMarkupInterface',
),
'PhabricatorConfigPHIDTypeConfig' => 'PhabricatorPHIDType',
'PhabricatorConfigProxySource' => 'PhabricatorConfigSource',
'PhabricatorConfigResponse' => 'AphrontHTMLResponse',
'PhabricatorConfigStackSource' => 'PhabricatorConfigSource',
'PhabricatorConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorConfigValidationException' => 'Exception',
'PhabricatorConpherencePHIDTypeThread' => 'PhabricatorPHIDType',
'PhabricatorContentSourceView' => 'AphrontView',
'PhabricatorController' => 'AphrontController',
'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorCountdown' =>
array(
0 => 'PhabricatorCountdownDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorCountdownCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'PhabricatorCountdownController' => 'PhabricatorController',
'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
'PhabricatorCountdownListController' =>
array(
0 => 'PhabricatorCountdownController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorCountdownPHIDTypeCountdown' => 'PhabricatorPHIDType',
'PhabricatorCountdownQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCountdownRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PhabricatorCountdownSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorCountdownView' => 'AphrontTagView',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorCrumbView' => 'AphrontView',
'PhabricatorCrumbsView' => 'AphrontView',
'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery',
'PhabricatorCustomFieldConfigOptionType' => 'PhabricatorConfigOptionType',
'PhabricatorCustomFieldDataNotAvailableException' => 'Exception',
'PhabricatorCustomFieldImplementationIncompleteException' => 'Exception',
'PhabricatorCustomFieldIndexStorage' => 'PhabricatorLiskDAO',
'PhabricatorCustomFieldList' => 'Phobject',
'PhabricatorCustomFieldNotAttachedException' => 'Exception',
'PhabricatorCustomFieldNotProxyException' => 'Exception',
'PhabricatorCustomFieldNumericIndexStorage' => 'PhabricatorCustomFieldIndexStorage',
'PhabricatorCustomFieldStorage' => 'PhabricatorLiskDAO',
'PhabricatorCustomFieldStringIndexStorage' => 'PhabricatorCustomFieldIndexStorage',
'PhabricatorDaemon' => 'PhutilDaemon',
'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController',
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonController' => 'PhabricatorController',
'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO',
'PhabricatorDaemonEventListener' => 'PhabricatorEventListener',
'PhabricatorDaemonLog' =>
array(
0 => 'PhabricatorDaemonDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO',
'PhabricatorDaemonLogEventViewController' => 'PhabricatorDaemonController',
'PhabricatorDaemonLogEventsView' => 'AphrontView',
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
'PhabricatorDaemonLogListView' => 'AphrontView',
'PhabricatorDaemonLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
'PhabricatorDaemonManagementDebugWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementLaunchWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementListWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementLogWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementRestartWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementStartWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementStatusWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementStopWorkflow' => 'PhabricatorDaemonManagementWorkflow',
'PhabricatorDaemonManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorDataNotAttachedException' => 'Exception',
'PhabricatorDebugController' => 'PhabricatorController',
'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorDifferentialConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorDifferentialRevisionTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorDirectoryController' => 'PhabricatorController',
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
'PhabricatorDisqusConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants',
'PhabricatorEdgeCycleException' => 'Exception',
'PhabricatorEdgeEditor' => 'PhabricatorEditor',
'PhabricatorEdgeGraph' => 'AbstractDirectedGraph',
'PhabricatorEdgeQuery' => 'PhabricatorQuery',
'PhabricatorEdgeTestCase' => 'PhabricatorTestCase',
'PhabricatorEditor' => 'Phobject',
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
'PhabricatorEmailVerificationController' => 'PhabricatorAuthController',
'PhabricatorEmptyQueryException' => 'Exception',
'PhabricatorEnglishTranslation' => 'PhabricatorBaseEnglishTranslation',
'PhabricatorEnvTestCase' => 'PhabricatorTestCase',
'PhabricatorErrorExample' => 'PhabricatorUIExample',
'PhabricatorEvent' => 'PhutilEvent',
'PhabricatorEventListener' => 'PhutilEventListener',
'PhabricatorEventType' => 'PhutilEventType',
'PhabricatorExampleEventListener' => 'PhabricatorEventListener',
'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorExternalAccount' =>
array(
0 => 'PhabricatorUserDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorFactAggregate' => 'PhabricatorFactDAO',
'PhabricatorFactChartController' => 'PhabricatorFactController',
'PhabricatorFactController' => 'PhabricatorController',
'PhabricatorFactCountEngine' => 'PhabricatorFactEngine',
'PhabricatorFactCursor' => 'PhabricatorFactDAO',
'PhabricatorFactDAO' => 'PhabricatorLiskDAO',
'PhabricatorFactDaemon' => 'PhabricatorDaemon',
'PhabricatorFactHomeController' => 'PhabricatorFactController',
'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine',
'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementStatusWorkflow' => 'PhabricatorFactManagementWorkflow',
'PhabricatorFactManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorFactRaw' => 'PhabricatorFactDAO',
'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec',
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
'PhabricatorFeedConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorFeedController' => 'PhabricatorController',
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
'PhabricatorFeedDetailController' => 'PhabricatorFeedController',
'PhabricatorFeedListController' =>
array(
0 => 'PhabricatorFeedController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorFeedManagementRepublishWorkflow' => 'PhabricatorFeedManagementWorkflow',
'PhabricatorFeedManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorFeedSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorFeedStory' => 'PhabricatorPolicyInterface',
'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryDifferentialAggregate' => 'PhabricatorFeedStoryAggregate',
'PhabricatorFeedStoryManiphestAggregate' => 'PhabricatorFeedStoryAggregate',
'PhabricatorFeedStoryNotification' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryPhriction' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants',
'PhabricatorFile' =>
array(
0 => 'PhabricatorFileDAO',
1 => 'PhabricatorTokenReceiverInterface',
2 => 'PhabricatorSubscribableInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhabricatorPolicyInterface',
),
'PhabricatorFileCommentController' => 'PhabricatorFileController',
'PhabricatorFileComposeController' => 'PhabricatorFileController',
'PhabricatorFileController' => 'PhabricatorController',
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
'PhabricatorFileDataController' => 'PhabricatorFileController',
'PhabricatorFileDeleteController' => 'PhabricatorFileController',
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
'PhabricatorFileEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorFileImageMacro' =>
array(
0 => 'PhabricatorFileDAO',
1 => 'PhabricatorSubscribableInterface',
2 => 'PhabricatorApplicationTransactionInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhabricatorPolicyInterface',
),
'PhabricatorFileInfoController' => 'PhabricatorFileController',
'PhabricatorFileLinkListView' => 'AphrontView',
'PhabricatorFileLinkView' => 'AphrontView',
'PhabricatorFileListController' =>
array(
0 => 'PhabricatorFileController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorFilePHIDTypeFile' => 'PhabricatorPHIDType',
'PhabricatorFileQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorFileSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorFileShortcutController' => 'PhabricatorFileController',
'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
'PhabricatorFileStorageConfigurationException' => 'Exception',
'PhabricatorFileTestCase' => 'PhabricatorTestCase',
'PhabricatorFileTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorFileTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorFileTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorFileTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorFileTransformController' => 'PhabricatorFileController',
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileUploadDialogController' => 'PhabricatorFileController',
'PhabricatorFileUploadException' => 'Exception',
'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementRebuildWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorFlag' =>
array(
0 => 'PhabricatorFlagDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorFlagColor' => 'PhabricatorFlagConstants',
'PhabricatorFlagController' => 'PhabricatorController',
'PhabricatorFlagDAO' => 'PhabricatorLiskDAO',
'PhabricatorFlagDeleteController' => 'PhabricatorFlagController',
'PhabricatorFlagEditController' => 'PhabricatorFlagController',
'PhabricatorFlagListController' =>
array(
0 => 'PhabricatorFlagController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorFlagQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorFlagSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorFlagSelectControl' => 'AphrontFormControl',
'PhabricatorFlaggableInterface' => 'PhabricatorPHIDInterface',
'PhabricatorFlagsUIEventListener' => 'PhabricatorEventListener',
'PhabricatorFormExample' => 'PhabricatorUIExample',
'PhabricatorGarbageCollectorConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon',
'PhabricatorGestureExample' => 'PhabricatorUIExample',
'PhabricatorGlobalLock' => 'PhutilLock',
'PhabricatorGlobalUploadTargetView' => 'AphrontView',
'PhabricatorHandleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorHashTestCase' => 'PhabricatorTestCase',
'PhabricatorHelpController' => 'PhabricatorController',
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
'PhabricatorHovercardExample' => 'PhabricatorUIExample',
'PhabricatorHovercardView' => 'AphrontView',
'PhabricatorIRCBot' => 'PhabricatorDaemon',
'PhabricatorIRCProtocolAdapter' => 'PhabricatorBaseProtocolAdapter',
'PhabricatorIRCProtocolHandler' => 'PhabricatorBotHandler',
'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase',
'PhabricatorInlineCommentController' => 'PhabricatorController',
'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface',
'PhabricatorInlineCommentPreviewController' => 'PhabricatorController',
'PhabricatorInlineSummaryView' => 'AphrontView',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
'PhabricatorLegalpadConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorLegalpadPHIDTypeDocument' => 'PhabricatorPHIDType',
'PhabricatorLintEngine' => 'PhutilLintEngine',
'PhabricatorLipsumGenerateWorkflow' => 'PhabricatorLipsumManagementWorkflow',
'PhabricatorLipsumManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorLipsumMondrianArtist' => 'PhabricatorLipsumArtist',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase',
'PhabricatorLogoutController' => 'PhabricatorAuthController',
'PhabricatorMacroAudioController' => 'PhabricatorMacroController',
'PhabricatorMacroCapabilityManage' => 'PhabricatorPolicyCapability',
'PhabricatorMacroCommentController' => 'PhabricatorMacroController',
'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMacroController' => 'PhabricatorController',
'PhabricatorMacroDisableController' => 'PhabricatorMacroController',
'PhabricatorMacroEditController' => 'PhabricatorMacroController',
'PhabricatorMacroEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorMacroListController' =>
array(
0 => 'PhabricatorMacroController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorMacroMailReceiver' => 'PhabricatorObjectMailReceiver',
'PhabricatorMacroMemeController' => 'PhabricatorMacroController',
'PhabricatorMacroMemeDialogController' => 'PhabricatorMacroController',
'PhabricatorMacroPHIDTypeMacro' => 'PhabricatorPHIDType',
'PhabricatorMacroQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMacroReplyHandler' => 'PhabricatorMailReplyHandler',
'PhabricatorMacroSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMacroTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorMacroTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementResendWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementSendTestWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorMailingListPHIDTypeList' => 'PhabricatorPHIDType',
'PhabricatorMailingListQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMailingListSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMailingListsController' => 'PhabricatorController',
'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController',
'PhabricatorMailingListsListController' =>
array(
0 => 'PhabricatorMailingListsController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorMainMenuGroupView' => 'AphrontView',
'PhabricatorMainMenuIconView' => 'AphrontView',
'PhabricatorMainMenuSearchView' => 'AphrontView',
'PhabricatorMainMenuView' => 'AphrontView',
'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorMarkupCache' => 'PhabricatorCacheDAO',
'PhabricatorMarkupOneOff' => 'PhabricatorMarkupInterface',
'PhabricatorMarkupPreviewController' => 'PhabricatorController',
'PhabricatorMetaMTAActorQuery' => 'PhabricatorQuery',
'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailingList' =>
array(
0 => 'PhabricatorMetaMTADAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAWorker' => 'PhabricatorWorker',
'PhabricatorMultiColumnExample' => 'PhabricatorUIExample',
'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController',
'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorNamedQuery' =>
array(
0 => 'PhabricatorSearchDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorNamedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorNoteExample' => 'PhabricatorUIExample',
'PhabricatorNotificationClearController' => 'PhabricatorNotificationController',
'PhabricatorNotificationConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorNotificationController' => 'PhabricatorController',
'PhabricatorNotificationIndividualController' => 'PhabricatorNotificationController',
'PhabricatorNotificationListController' => 'PhabricatorNotificationController',
'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController',
'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorNotificationStatusController' => 'PhabricatorNotificationController',
'PhabricatorOAuthClientAuthorization' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthClientAuthorizationBaseController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthClientAuthorizationDeleteController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientAuthorizationEditController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientAuthorizationListController' => 'PhabricatorOAuthClientAuthorizationBaseController',
'PhabricatorOAuthClientAuthorizationQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController',
'PhabricatorOAuthResponse' => 'AphrontResponse',
'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController',
'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerClient' => 'PhabricatorOAuthServerDAO',
'PhabricatorOAuthServerClientQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorOAuthServerController' => 'PhabricatorController',
'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO',
'PhabricatorOAuthServerTestCase' => 'PhabricatorTestCase',
'PhabricatorOAuthServerTestController' => 'PhabricatorOAuthServerController',
'PhabricatorOAuthServerTokenController' => 'PhabricatorAuthController',
'PhabricatorObjectHandle' => 'PhabricatorPolicyInterface',
'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants',
'PhabricatorObjectListView' => 'AphrontView',
'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver',
'PhabricatorObjectMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorObjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorOwnersController' => 'PhabricatorController',
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController',
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPHIDTypePackage' => 'PhabricatorPHIDType',
'PhabricatorOwnersPackage' =>
array(
0 => 'PhabricatorOwnersDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorOwnersPackageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorOwnersPackageTestCase' => 'PhabricatorTestCase',
'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO',
'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPHPMailerConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPagedFormExample' => 'PhabricatorUIExample',
'PhabricatorPaste' =>
array(
0 => 'PhabricatorPasteDAO',
1 => 'PhabricatorSubscribableInterface',
2 => 'PhabricatorTokenReceiverInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhabricatorPolicyInterface',
),
'PhabricatorPasteCommentController' => 'PhabricatorPasteController',
'PhabricatorPasteConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPasteController' => 'PhabricatorController',
'PhabricatorPasteDAO' => 'PhabricatorLiskDAO',
'PhabricatorPasteEditController' => 'PhabricatorPasteController',
'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorPasteListController' =>
array(
0 => 'PhabricatorPasteController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorPastePHIDTypePaste' => 'PhabricatorPHIDType',
'PhabricatorPasteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPasteRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PhabricatorPasteSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPasteTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPasteTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorPasteTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorPasteTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorPasteViewController' => 'PhabricatorPasteController',
'PhabricatorPeopleController' => 'PhabricatorController',
'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleHovercardEventListener' => 'PhabricatorEventListener',
'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController',
'PhabricatorPeopleListController' =>
array(
0 => 'PhabricatorPeopleController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeoplePHIDTypeExternal' => 'PhabricatorPHIDType',
'PhabricatorPeoplePHIDTypeUser' => 'PhabricatorPHIDType',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleController',
'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPhameConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhamePHIDTypeBlog' => 'PhabricatorPHIDType',
'PhabricatorPhamePHIDTypePost' => 'PhabricatorPHIDType',
'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPhortuneConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhrequentConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPolicies' => 'PhabricatorPolicyConstants',
'PhabricatorPolicy' =>
array(
0 => 'PhabricatorPolicyDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorPolicyAwareQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorPolicyAwareTestQuery' => 'PhabricatorPolicyAwareQuery',
'PhabricatorPolicyCapability' => 'Phobject',
'PhabricatorPolicyCapabilityCanEdit' => 'PhabricatorPolicyCapability',
'PhabricatorPolicyCapabilityCanJoin' => 'PhabricatorPolicyCapability',
'PhabricatorPolicyCapabilityCanView' => 'PhabricatorPolicyCapability',
'PhabricatorPolicyConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPolicyController' => 'PhabricatorController',
'PhabricatorPolicyDAO' => 'PhabricatorLiskDAO',
'PhabricatorPolicyDataTestCase' => 'PhabricatorTestCase',
'PhabricatorPolicyEditController' => 'PhabricatorPolicyController',
'PhabricatorPolicyException' => 'Exception',
'PhabricatorPolicyExplainController' => 'PhabricatorPolicyController',
'PhabricatorPolicyInterface' => 'PhabricatorPHIDInterface',
'PhabricatorPolicyManagementShowWorkflow' => 'PhabricatorPolicyManagementWorkflow',
'PhabricatorPolicyManagementUnlockWorkflow' => 'PhabricatorPolicyManagementWorkflow',
'PhabricatorPolicyManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorPolicyPHIDTypePolicy' => 'PhabricatorPHIDType',
'PhabricatorPolicyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPolicyRuleAdministrators' => 'PhabricatorPolicyRule',
'PhabricatorPolicyRuleLunarPhase' => 'PhabricatorPolicyRule',
'PhabricatorPolicyRuleProjects' => 'PhabricatorPolicyRule',
'PhabricatorPolicyRuleUsers' => 'PhabricatorPolicyRule',
'PhabricatorPolicyTestCase' => 'PhabricatorTestCase',
'PhabricatorPolicyTestObject' => 'PhabricatorPolicyInterface',
'PhabricatorPolicyType' => 'PhabricatorPolicyConstants',
'PhabricatorProject' =>
array(
0 => 'PhabricatorProjectDAO',
1 => 'PhabricatorFlaggableInterface',
2 => 'PhabricatorPolicyInterface',
),
'PhabricatorProjectBoardController' => 'PhabricatorProjectController',
'PhabricatorProjectColumn' =>
array(
0 => 'PhabricatorProjectDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorProjectColumnQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
'PhabricatorProjectCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'PhabricatorProjectCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
'PhabricatorProjectCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectEditor' => 'PhabricatorEditor',
'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase',
'PhabricatorProjectHistoryController' => 'PhabricatorProjectController',
'PhabricatorProjectListController' =>
array(
0 => 'PhabricatorProjectController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
'PhabricatorProjectNameCollisionException' => 'Exception',
'PhabricatorProjectPHIDTypeColumn' => 'PhabricatorPHIDType',
'PhabricatorProjectPHIDTypeProject' => 'PhabricatorPHIDType',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
'PhabricatorProjectProfilePictureController' => 'PhabricatorProjectController',
'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorProjectSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorProjectUpdateController' => 'PhabricatorProjectController',
'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
'PhabricatorRegistrationProfile' => 'Phobject',
'PhabricatorRemarkupBlockInterpreterCowsay' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupBlockInterpreterFiglet' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupBlockInterpreterGraphviz' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl',
'PhabricatorRemarkupCustomBlockRule' => 'PhutilRemarkupEngineBlockRule',
'PhabricatorRemarkupCustomInlineRule' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleEmbedFile' => 'PhabricatorRemarkupRuleObject',
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleMeme' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleObject' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
'PhabricatorRepository' =>
array(
0 => 'PhabricatorRepositoryDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorFlaggableInterface',
3 => 'PhabricatorMarkupInterface',
),
'PhabricatorRepositoryArcanistProject' =>
array(
0 => 'PhabricatorRepositoryDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorRepositoryArcanistProjectDeleteController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryArcanistProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommit' =>
array(
0 => 'PhabricatorRepositoryDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorFlaggableInterface',
3 => 'PhabricatorTokenReceiverInterface',
),
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
'PhabricatorRepositoryCommitSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorRepositoryController' => 'PhabricatorController',
- 'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine',
- 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryManagementDeleteWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementPullWorkflow' => 'PhabricatorRepositoryManagementWorkflow',
'PhabricatorRepositoryManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryPHIDTypeArcanistProject' => 'PhabricatorPHIDType',
'PhabricatorRepositoryPHIDTypeCommit' => 'PhabricatorPHIDType',
'PhabricatorRepositoryPHIDTypeRepository' => 'PhabricatorPHIDType',
'PhabricatorRepositoryPullEngine' => 'PhabricatorRepositoryEngine',
'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon',
'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositorySearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorSSHWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorSavedQuery' =>
array(
0 => 'PhabricatorSearchDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorSavedQueryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
'PhabricatorSearchDeleteController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
'PhabricatorSearchEditController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchEngineElastic' => 'PhabricatorSearchEngine',
'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine',
'PhabricatorSearchHovercardController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchManagementIndexWorkflow' => 'PhabricatorSearchManagementWorkflow',
'PhabricatorSearchManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorSearchOrderController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorSearchResultView' => 'AphrontView',
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
'PhabricatorSecurityConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorSendGridConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorSettingsAdjustController' => 'PhabricatorController',
'PhabricatorSettingsMainController' => 'PhabricatorController',
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelDiffPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelExternalAccounts' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelHomePreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel',
'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckBaseURI' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckBinaries' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckDatabase' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckExtensions' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckExtraConfig' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckFileinfo' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckGD' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckImagemagick' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckInvalidConfig' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckMail' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckMySQL' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckPHPConfig' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckPath' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckPygment' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckStorage' => 'PhabricatorSetupCheck',
'PhabricatorSetupCheckTimezone' => 'PhabricatorSetupCheck',
'PhabricatorSetupIssueExample' => 'PhabricatorUIExample',
'PhabricatorSetupIssueView' => 'AphrontView',
'PhabricatorSlowvoteCapabilityDefaultView' => 'PhabricatorPolicyCapability',
'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvoteCommentController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteController' => 'PhabricatorController',
'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO',
'PhabricatorSlowvoteEditController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorSlowvoteListController' =>
array(
0 => 'PhabricatorSlowvoteController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO',
'PhabricatorSlowvotePHIDTypePoll' => 'PhabricatorPHIDType',
'PhabricatorSlowvotePoll' =>
array(
0 => 'PhabricatorSlowvoteDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorSubscribableInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhabricatorTokenReceiverInterface',
),
'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController',
'PhabricatorSlowvoteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorSlowvoteSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorSlowvoteTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorSlowvoteTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PhabricatorSlowvoteTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorSlowvoteVoteController' => 'PhabricatorSlowvoteController',
'PhabricatorSlugTestCase' => 'PhabricatorTestCase',
'PhabricatorSortTableExample' => 'PhabricatorUIExample',
'PhabricatorSourceCodeView' => 'AphrontView',
'PhabricatorStandardCustomField' => 'PhabricatorCustomField',
'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldDate' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldHeader' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldInt' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldPHIDs' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldRemarkup' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldSelect' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldText' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldUsers' => 'PhabricatorStandardCustomFieldPHIDs',
'PhabricatorStandardPageView' => 'PhabricatorBarePageView',
'PhabricatorStatusController' => 'PhabricatorController',
'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementProbeWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow',
'PhabricatorStorageManagementWorkflow' => 'PhutilArgumentWorkflow',
'PhabricatorSubscribersQuery' => 'PhabricatorQuery',
'PhabricatorSubscriptionsEditController' => 'PhabricatorController',
'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor',
'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener',
'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook',
'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorTagExample' => 'PhabricatorUIExample',
'PhabricatorTagView' => 'AphrontView',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
'PhabricatorTestController' => 'PhabricatorController',
'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine',
'PhabricatorTestWorker' => 'PhabricatorWorker',
'PhabricatorTimeTestCase' => 'PhabricatorTestCase',
'PhabricatorTimelineEventView' => 'AphrontView',
'PhabricatorTimelineExample' => 'PhabricatorUIExample',
'PhabricatorTimelineView' => 'AphrontView',
'PhabricatorToken' =>
array(
0 => 'PhabricatorTokenDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorTokenController' => 'PhabricatorController',
'PhabricatorTokenCount' => 'PhabricatorTokenDAO',
'PhabricatorTokenCountQuery' => 'PhabricatorOffsetPagedQuery',
'PhabricatorTokenDAO' => 'PhabricatorLiskDAO',
'PhabricatorTokenGiveController' => 'PhabricatorTokenController',
'PhabricatorTokenGiven' =>
array(
0 => 'PhabricatorTokenDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhabricatorTokenGivenController' => 'PhabricatorTokenController',
'PhabricatorTokenGivenEditor' => 'PhabricatorEditor',
'PhabricatorTokenGivenFeedStory' => 'PhabricatorFeedStory',
'PhabricatorTokenGivenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenLeaderController' => 'PhabricatorTokenController',
'PhabricatorTokenPHIDTypeToken' => 'PhabricatorPHIDType',
'PhabricatorTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenReceiverQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorTokenUIEventListener' => 'PhabricatorEventListener',
'PhabricatorTransactionView' => 'AphrontView',
'PhabricatorTransformedFile' => 'PhabricatorFileDAO',
'PhabricatorTranslationsConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorTrivialTestCase' => 'PhabricatorTestCase',
'PhabricatorTwoColumnExample' => 'PhabricatorUIExample',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
'PhabricatorUIExampleRenderController' => 'PhabricatorController',
'PhabricatorUIListFilterExample' => 'PhabricatorUIExample',
'PhabricatorUINotificationExample' => 'PhabricatorUIExample',
'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
'PhabricatorUIStatusExample' => 'PhabricatorUIExample',
'PhabricatorUITooltipExample' => 'PhabricatorUIExample',
'PhabricatorUnitsTestCase' => 'PhabricatorTestCase',
'PhabricatorUser' =>
array(
0 => 'PhabricatorUserDAO',
1 => 'PhutilPerson',
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorCustomFieldInterface',
),
'PhabricatorUserBlurbField' => 'PhabricatorUserCustomField',
'PhabricatorUserConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorUserConfiguredCustomField' =>
array(
0 => 'PhabricatorUserCustomField',
1 => 'PhabricatorStandardCustomFieldInterface',
),
'PhabricatorUserConfiguredCustomFieldStorage' => 'PhabricatorCustomFieldStorage',
'PhabricatorUserCustomField' => 'PhabricatorCustomField',
'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserEditor' => 'PhabricatorEditor',
'PhabricatorUserEmail' => 'PhabricatorUserDAO',
'PhabricatorUserLog' => 'PhabricatorUserDAO',
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorUserRealNameField' => 'PhabricatorUserCustomField',
'PhabricatorUserRolesField' => 'PhabricatorUserCustomField',
'PhabricatorUserSSHKey' => 'PhabricatorUserDAO',
'PhabricatorUserSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorUserSinceField' => 'PhabricatorUserCustomField',
'PhabricatorUserStatus' => 'PhabricatorUserDAO',
'PhabricatorUserStatusField' => 'PhabricatorUserCustomField',
'PhabricatorUserStatusInvalidEpochException' => 'Exception',
'PhabricatorUserStatusOverlapException' => 'Exception',
'PhabricatorUserTestCase' => 'PhabricatorTestCase',
'PhabricatorUserTitleField' => 'PhabricatorUserCustomField',
'PhabricatorUserTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorVCSResponse' => 'AphrontResponse',
'PhabricatorWorkerActiveTask' => 'PhabricatorWorkerTask',
'PhabricatorWorkerArchiveTask' => 'PhabricatorWorkerTask',
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
'PhabricatorWorkerLeaseQuery' => 'PhabricatorQuery',
'PhabricatorWorkerPermanentFailureException' => 'Exception',
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController',
'PhabricatorWorkerTestCase' => 'PhabricatorTestCase',
'PhabricatorWorkingCopyDiscoveryTestCase' => 'PhabricatorWorkingCopyTestCase',
'PhabricatorWorkingCopyPullTestCase' => 'PhabricatorWorkingCopyTestCase',
'PhabricatorWorkingCopyTestCase' => 'PhabricatorTestCase',
'PhabricatorXHPASTViewController' => 'PhabricatorController',
'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO',
'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO',
'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHProfController' => 'PhabricatorController',
'PhabricatorXHProfDAO' => 'PhabricatorLiskDAO',
'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController',
'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView',
'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView',
'PhabricatorXHProfProfileView' => 'AphrontView',
'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO',
'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController',
'PhameBasicBlogSkin' => 'PhameBlogSkin',
'PhameBasicTemplateBlogSkin' => 'PhameBasicBlogSkin',
'PhameBlog' =>
array(
0 => 'PhameDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorMarkupInterface',
),
'PhameBlogDeleteController' => 'PhameController',
'PhameBlogEditController' => 'PhameController',
'PhameBlogFeedController' => 'PhameController',
'PhameBlogListController' => 'PhameController',
'PhameBlogLiveController' => 'PhameController',
'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhameBlogSkin' => 'PhabricatorController',
'PhameBlogViewController' => 'PhameController',
'PhameController' => 'PhabricatorController',
'PhameDAO' => 'PhabricatorLiskDAO',
'PhamePost' =>
array(
0 => 'PhameDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorMarkupInterface',
3 => 'PhabricatorTokenReceiverInterface',
),
'PhamePostDeleteController' => 'PhameController',
'PhamePostEditController' => 'PhameController',
'PhamePostFramedController' => 'PhameController',
'PhamePostListController' => 'PhameController',
'PhamePostNewController' => 'PhameController',
'PhamePostNotLiveController' => 'PhameController',
'PhamePostPreviewController' => 'PhameController',
'PhamePostPublishController' => 'PhameController',
'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhamePostUnpublishController' => 'PhameController',
'PhamePostView' => 'AphrontView',
'PhamePostViewController' => 'PhameController',
'PhameResourceController' => 'CelerityResourceController',
'PhluxController' => 'PhabricatorController',
'PhluxDAO' => 'PhabricatorLiskDAO',
'PhluxEditController' => 'PhluxController',
'PhluxListController' => 'PhluxController',
'PhluxPHIDTypeVariable' => 'PhabricatorPHIDType',
'PhluxTransaction' => 'PhabricatorApplicationTransaction',
'PhluxTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhluxVariable' =>
array(
0 => 'PhluxDAO',
1 => 'PhabricatorFlaggableInterface',
2 => 'PhabricatorPolicyInterface',
),
'PhluxVariableEditor' => 'PhabricatorApplicationTransactionEditor',
'PhluxVariableQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhluxViewController' => 'PhluxController',
'PholioActionMenuEventListener' => 'PhabricatorEventListener',
'PholioController' => 'PhabricatorController',
'PholioDAO' => 'PhabricatorLiskDAO',
'PholioImage' =>
array(
0 => 'PholioDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PhabricatorPolicyInterface',
),
'PholioImageHistoryController' => 'PholioController',
'PholioImageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PholioImageUploadController' => 'PholioController',
'PholioInlineCommentEditView' => 'AphrontView',
'PholioInlineCommentSaveView' => 'AphrontView',
'PholioInlineCommentView' => 'AphrontView',
'PholioInlineController' => 'PholioController',
'PholioInlineDeleteController' => 'PholioController',
'PholioInlineEditController' => 'PholioController',
'PholioInlineSaveController' => 'PholioController',
'PholioInlineThumbController' => 'PholioController',
'PholioInlineViewController' => 'PholioController',
'PholioMock' =>
array(
0 => 'PholioDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorSubscribableInterface',
4 => 'PhabricatorTokenReceiverInterface',
5 => 'PhabricatorFlaggableInterface',
6 => 'PhabricatorApplicationTransactionInterface',
),
'PholioMockCommentController' => 'PholioController',
'PholioMockEditController' => 'PholioController',
'PholioMockEditor' => 'PhabricatorApplicationTransactionEditor',
'PholioMockEmbedView' => 'AphrontView',
'PholioMockImagesView' => 'AphrontView',
'PholioMockListController' =>
array(
0 => 'PholioController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PholioMockMailReceiver' => 'PhabricatorObjectMailReceiver',
'PholioMockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PholioMockSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PholioMockViewController' => 'PholioController',
'PholioPHIDTypeImage' => 'PhabricatorPHIDType',
'PholioPHIDTypeMock' => 'PhabricatorPHIDType',
'PholioRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PholioReplyHandler' => 'PhabricatorMailReplyHandler',
'PholioSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PholioTransaction' => 'PhabricatorApplicationTransaction',
'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PholioTransactionType' => 'PholioConstants',
'PholioTransactionView' => 'PhabricatorApplicationTransactionView',
'PholioUploadedImageView' => 'AphrontView',
'PhortuneAccount' =>
array(
0 => 'PhortuneDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhortuneAccountBuyController' => 'PhortuneController',
'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor',
'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneAccountTransaction' => 'PhabricatorApplicationTransaction',
'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhortuneAccountViewController' => 'PhortuneController',
'PhortuneBalancedPaymentProvider' => 'PhortunePaymentProvider',
'PhortuneCart' => 'PhortuneDAO',
'PhortuneCharge' => 'PhortuneDAO',
'PhortuneController' => 'PhabricatorController',
'PhortuneCurrencyTestCase' => 'PhabricatorTestCase',
'PhortuneDAO' => 'PhabricatorLiskDAO',
'PhortuneErrCode' => 'PhortuneConstants',
'PhortuneLandingController' => 'PhortuneController',
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
'PhortuneMultiplePaymentProvidersException' => 'Exception',
'PhortuneNoPaymentProviderException' => 'Exception',
'PhortuneNotImplementedException' => 'Exception',
'PhortunePaymentMethod' =>
array(
0 => 'PhortuneDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhortunePaymentMethodEditController' => 'PhortuneController',
'PhortunePaymentMethodListController' => 'PhabricatorController',
'PhortunePaymentMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortunePaymentMethodViewController' => 'PhabricatorController',
'PhortunePaymentProviderTestCase' => 'PhabricatorTestCase',
'PhortunePaypalPaymentProvider' => 'PhortunePaymentProvider',
'PhortuneProduct' =>
array(
0 => 'PhortuneDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhortuneProductEditController' => 'PhabricatorController',
'PhortuneProductEditor' => 'PhabricatorApplicationTransactionEditor',
'PhortuneProductListController' => 'PhabricatorController',
'PhortuneProductQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneProductTransaction' => 'PhabricatorApplicationTransaction',
'PhortuneProductTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhortuneProductViewController' => 'PhortuneController',
'PhortuneProviderController' => 'PhortuneController',
'PhortunePurchase' => 'PhortuneDAO',
'PhortuneStripePaymentProvider' => 'PhortunePaymentProvider',
'PhortuneTestExtraPaymentProvider' => 'PhortunePaymentProvider',
'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider',
'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider',
'PhrequentController' => 'PhabricatorController',
'PhrequentDAO' => 'PhabricatorLiskDAO',
'PhrequentListController' =>
array(
0 => 'PhrequentController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhrequentSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhrequentTimeBlock' => 'Phobject',
'PhrequentTimeBlockTestCase' => 'PhabricatorTestCase',
'PhrequentTrackController' => 'PhrequentController',
'PhrequentUIEventListener' => 'PhabricatorEventListener',
'PhrequentUserTime' =>
array(
0 => 'PhrequentDAO',
1 => 'PhabricatorPolicyInterface',
),
'PhrequentUserTimeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhrictionActionConstants' => 'PhrictionConstants',
'PhrictionActionMenuEventListener' => 'PhabricatorEventListener',
'PhrictionChangeType' => 'PhrictionConstants',
'PhrictionContent' =>
array(
0 => 'PhrictionDAO',
1 => 'PhabricatorMarkupInterface',
),
'PhrictionController' => 'PhabricatorController',
'PhrictionDAO' => 'PhabricatorLiskDAO',
'PhrictionDeleteController' => 'PhrictionController',
'PhrictionDiffController' => 'PhrictionController',
'PhrictionDocument' =>
array(
0 => 'PhrictionDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorSubscribableInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhabricatorTokenReceiverInterface',
),
'PhrictionDocumentController' => 'PhrictionController',
'PhrictionDocumentEditor' => 'PhabricatorEditor',
'PhrictionDocumentPreviewController' => 'PhrictionController',
'PhrictionDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhrictionDocumentStatus' => 'PhrictionConstants',
'PhrictionDocumentTestCase' => 'PhabricatorTestCase',
'PhrictionEditController' => 'PhrictionController',
'PhrictionHistoryController' => 'PhrictionController',
'PhrictionListController' =>
array(
0 => 'PhrictionController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhrictionMoveController' => 'PhrictionController',
'PhrictionNewController' => 'PhrictionController',
'PhrictionPHIDTypeDocument' => 'PhabricatorPHIDType',
'PhrictionRemarkupRule' => 'PhutilRemarkupRule',
'PhrictionSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PonderAddAnswerView' => 'AphrontView',
'PonderAnswer' =>
array(
0 => 'PonderDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PonderVotableInterface',
3 => 'PhabricatorPolicyInterface',
4 => 'PhabricatorFlaggableInterface',
5 => 'PhabricatorSubscribableInterface',
6 => 'PhabricatorTokenReceiverInterface',
),
'PonderAnswerCommentController' => 'PonderController',
'PonderAnswerEditController' => 'PonderController',
'PonderAnswerEditor' => 'PonderEditor',
'PonderAnswerHistoryController' => 'PonderController',
'PonderAnswerQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PonderAnswerSaveController' => 'PonderController',
'PonderAnswerTransaction' => 'PhabricatorApplicationTransaction',
'PonderAnswerTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PonderAnswerTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PonderComment' =>
array(
0 => 'PonderDAO',
1 => 'PhabricatorMarkupInterface',
),
'PonderCommentQuery' => 'PhabricatorQuery',
'PonderController' => 'PhabricatorController',
'PonderDAO' => 'PhabricatorLiskDAO',
'PonderEditor' => 'PhabricatorApplicationTransactionEditor',
'PonderPHIDTypeAnswer' => 'PhabricatorPHIDType',
'PonderPHIDTypeQuestion' => 'PhabricatorPHIDType',
'PonderQuestion' =>
array(
0 => 'PonderDAO',
1 => 'PhabricatorMarkupInterface',
2 => 'PonderVotableInterface',
3 => 'PhabricatorSubscribableInterface',
4 => 'PhabricatorFlaggableInterface',
5 => 'PhabricatorPolicyInterface',
6 => 'PhabricatorTokenReceiverInterface',
),
'PonderQuestionCommentController' => 'PonderController',
'PonderQuestionEditController' => 'PonderController',
'PonderQuestionEditor' => 'PonderEditor',
'PonderQuestionHistoryController' => 'PonderController',
'PonderQuestionListController' =>
array(
0 => 'PonderController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PonderQuestionMailReceiver' => 'PhabricatorObjectMailReceiver',
'PonderQuestionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PonderQuestionReplyHandler' => 'PhabricatorMailReplyHandler',
'PonderQuestionSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PonderQuestionStatus' => 'PonderConstants',
'PonderQuestionStatusController' => 'PonderController',
'PonderQuestionTransaction' => 'PhabricatorApplicationTransaction',
'PonderQuestionTransactionComment' => 'PhabricatorApplicationTransactionComment',
'PonderQuestionTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PonderQuestionViewController' => 'PonderController',
'PonderRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'PonderSearchIndexer' => 'PhabricatorSearchDocumentIndexer',
'PonderTransactionFeedStory' => 'PhabricatorApplicationTransactionFeedStory',
'PonderVotableView' => 'AphrontView',
'PonderVote' => 'PonderConstants',
'PonderVoteEditor' => 'PhabricatorEditor',
'PonderVoteSaveController' => 'PonderController',
'ProjectCapabilityCreateProjects' => 'PhabricatorPolicyCapability',
'ProjectRemarkupRule' => 'PhabricatorRemarkupRuleObject',
'QueryFormattingTestCase' => 'PhabricatorTestCase',
'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification',
'ReleephBranch' =>
array(
0 => 'ReleephDAO',
1 => 'PhabricatorPolicyInterface',
),
'ReleephBranchAccessController' => 'ReleephProjectController',
'ReleephBranchCommitFieldSpecification' => 'ReleephFieldSpecification',
'ReleephBranchCreateController' => 'ReleephProjectController',
'ReleephBranchEditController' => 'ReleephProjectController',
'ReleephBranchEditor' => 'PhabricatorEditor',
'ReleephBranchHistoryController' => 'ReleephProjectController',
'ReleephBranchNamePreviewController' => 'ReleephController',
'ReleephBranchPreviewView' => 'AphrontFormControl',
'ReleephBranchQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'ReleephBranchSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ReleephBranchTransaction' => 'PhabricatorApplicationTransaction',
'ReleephBranchTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ReleephBranchViewController' =>
array(
0 => 'ReleephProjectController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'ReleephCommitFinderException' => 'Exception',
'ReleephCommitMessageFieldSpecification' => 'ReleephFieldSpecification',
'ReleephController' => 'PhabricatorController',
'ReleephDAO' => 'PhabricatorLiskDAO',
'ReleephDefaultFieldSelector' => 'ReleephFieldSelector',
'ReleephDefaultUserView' => 'ReleephUserView',
'ReleephDiffChurnFieldSpecification' => 'ReleephFieldSpecification',
'ReleephDiffMessageFieldSpecification' => 'ReleephFieldSpecification',
'ReleephDiffSizeFieldSpecification' => 'ReleephFieldSpecification',
'ReleephFieldParseException' => 'Exception',
'ReleephFieldSpecification' =>
array(
0 => 'PhabricatorCustomField',
1 => 'PhabricatorMarkupInterface',
),
'ReleephIntentFieldSpecification' => 'ReleephFieldSpecification',
'ReleephLevelFieldSpecification' => 'ReleephFieldSpecification',
'ReleephOriginalCommitFieldSpecification' => 'ReleephFieldSpecification',
'ReleephPHIDTypeBranch' => 'PhabricatorPHIDType',
'ReleephPHIDTypeProject' => 'PhabricatorPHIDType',
'ReleephPHIDTypeRequest' => 'PhabricatorPHIDType',
'ReleephProject' =>
array(
0 => 'ReleephDAO',
1 => 'PhabricatorPolicyInterface',
),
'ReleephProjectActionController' => 'ReleephProjectController',
'ReleephProjectController' => 'ReleephController',
'ReleephProjectCreateController' => 'ReleephProjectController',
'ReleephProjectEditController' => 'ReleephProjectController',
'ReleephProjectHistoryController' => 'ReleephProjectController',
'ReleephProjectListController' =>
array(
0 => 'ReleephController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'ReleephProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'ReleephProjectSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ReleephProjectTransaction' => 'PhabricatorApplicationTransaction',
'ReleephProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ReleephProjectViewController' =>
array(
0 => 'ReleephProjectController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'ReleephReasonFieldSpecification' => 'ReleephFieldSpecification',
'ReleephRequest' =>
array(
0 => 'ReleephDAO',
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorCustomFieldInterface',
),
'ReleephRequestActionController' => 'ReleephProjectController',
'ReleephRequestCommentController' => 'ReleephProjectController',
'ReleephRequestDifferentialCreateController' => 'ReleephProjectController',
'ReleephRequestEditController' => 'ReleephProjectController',
'ReleephRequestHeaderListView' => 'AphrontView',
'ReleephRequestHeaderView' => 'AphrontView',
'ReleephRequestIntentsView' => 'AphrontView',
'ReleephRequestMailReceiver' => 'PhabricatorObjectMailReceiver',
'ReleephRequestQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'ReleephRequestReplyHandler' => 'PhabricatorMailReplyHandler',
'ReleephRequestSearchEngine' => 'PhabricatorApplicationSearchEngine',
'ReleephRequestStatusView' => 'AphrontView',
'ReleephRequestTransaction' => 'PhabricatorApplicationTransaction',
'ReleephRequestTransactionComment' => 'PhabricatorApplicationTransactionComment',
'ReleephRequestTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ReleephRequestTransactionalEditor' => 'PhabricatorApplicationTransactionEditor',
'ReleephRequestTypeaheadControl' => 'AphrontFormControl',
'ReleephRequestTypeaheadController' => 'PhabricatorTypeaheadDatasourceController',
'ReleephRequestViewController' => 'ReleephProjectController',
'ReleephRequestorFieldSpecification' => 'ReleephFieldSpecification',
'ReleephRevisionFieldSpecification' => 'ReleephFieldSpecification',
'ReleephSeverityFieldSpecification' => 'ReleephLevelFieldSpecification',
'ReleephStatusFieldSpecification' => 'ReleephFieldSpecification',
'ReleephSummaryFieldSpecification' => 'ReleephFieldSpecification',
'ReleephUserView' => 'AphrontView',
'SlowvoteEmbedView' => 'AphrontView',
'SlowvoteRemarkupRule' => 'PhabricatorRemarkupRuleObject',
),
));
diff --git a/src/aphront/response/AphrontResponse.php b/src/aphront/response/AphrontResponse.php
index 20ce8f7a62..67da4aee93 100644
--- a/src/aphront/response/AphrontResponse.php
+++ b/src/aphront/response/AphrontResponse.php
@@ -1,147 +1,151 @@
<?php
/**
* @group aphront
*/
abstract class AphrontResponse {
private $request;
private $cacheable = false;
private $responseCode = 200;
private $lastModified = null;
protected $frameable;
public function setRequest($request) {
$this->request = $request;
return $this;
}
public function getRequest() {
return $this->request;
}
public function getHeaders() {
$headers = array();
if (!$this->frameable) {
$headers[] = array('X-Frame-Options', 'Deny');
}
return $headers;
}
public function setCacheDurationInSeconds($duration) {
$this->cacheable = $duration;
return $this;
}
public function setLastModified($epoch_timestamp) {
$this->lastModified = $epoch_timestamp;
return $this;
}
public function setHTTPResponseCode($code) {
$this->responseCode = $code;
return $this;
}
public function getHTTPResponseCode() {
return $this->responseCode;
}
+ public function getHTTPResponseMessage() {
+ return '';
+ }
+
public function setFrameable($frameable) {
$this->frameable = $frameable;
return $this;
}
public static function processValueForJSONEncoding(&$value, $key) {
if ($value instanceof PhutilSafeHTMLProducerInterface) {
// This renders the producer down to PhutilSafeHTML, which will then
// be simplified into a string below.
$value = hsprintf('%s', $value);
}
if ($value instanceof PhutilSafeHTML) {
// TODO: Javelin supports implicity conversion of '__html' objects to
// JX.HTML, but only for Ajax responses, not behaviors. Just leave things
// as they are for now (where behaviors treat responses as HTML or plain
// text at their discretion).
$value = $value->getHTMLContent();
}
}
public static function encodeJSONForHTTPResponse(array $object) {
array_walk_recursive(
$object,
array('AphrontResponse', 'processValueForJSONEncoding'));
$response = json_encode($object);
// Prevent content sniffing attacks by encoding "<" and ">", so browsers
// won't try to execute the document as HTML even if they ignore
// Content-Type and X-Content-Type-Options. See T865.
$response = str_replace(
array('<', '>'),
array('\u003c', '\u003e'),
$response);
return $response;
}
protected function addJSONShield($json_response) {
// Add a shield to prevent "JSON Hijacking" attacks where an attacker
// requests a JSON response using a normal <script /> tag and then uses
// Object.prototype.__defineSetter__() or similar to read response data.
// This header causes the browser to loop infinitely instead of handing over
// sensitive data.
$shield = 'for (;;);';
$response = $shield.$json_response;
return $response;
}
public function getCacheHeaders() {
$headers = array();
if ($this->cacheable) {
$headers[] = array(
'Expires',
$this->formatEpochTimestampForHTTPHeader(time() + $this->cacheable));
} else {
$headers[] = array(
'Cache-Control',
'private, no-cache, no-store, must-revalidate');
$headers[] = array(
'Pragma',
'no-cache');
$headers[] = array(
'Expires',
'Sat, 01 Jan 2000 00:00:00 GMT');
}
if ($this->lastModified) {
$headers[] = array(
'Last-Modified',
$this->formatEpochTimestampForHTTPHeader($this->lastModified));
}
// IE has a feature where it may override an explicit Content-Type
// declaration by inferring a content type. This can be a security risk
// and we always explicitly transmit the correct Content-Type header, so
// prevent IE from using inferred content types. This only offers protection
// on recent versions of IE; IE6/7 and Opera currently ignore this header.
$headers[] = array('X-Content-Type-Options', 'nosniff');
return $headers;
}
private function formatEpochTimestampForHTTPHeader($epoch_timestamp) {
return gmdate('D, d M Y H:i:s', $epoch_timestamp).' GMT';
}
abstract public function buildResponseString();
}
diff --git a/src/aphront/sink/AphrontHTTPSink.php b/src/aphront/sink/AphrontHTTPSink.php
index 875aafa3f0..15822051e4 100644
--- a/src/aphront/sink/AphrontHTTPSink.php
+++ b/src/aphront/sink/AphrontHTTPSink.php
@@ -1,118 +1,120 @@
<?php
/**
* Abstract class which wraps some sort of output mechanism for HTTP responses.
* Normally this is just @{class:AphrontPHPHTTPSink}, which uses "echo" and
* "header()" to emit responses.
*
* Mostly, this class allows us to do install security or metrics hooks in the
* output pipeline.
*
* @task write Writing Response Components
* @task emit Emitting the Response
*
* @group aphront
*/
abstract class AphrontHTTPSink {
/* -( Writing Response Components )---------------------------------------- */
/**
* Write an HTTP status code to the output.
*
* @param int Numeric HTTP status code.
* @return void
*/
- final public function writeHTTPStatus($code) {
+ final public function writeHTTPStatus($code, $message = '') {
if (!preg_match('/^\d{3}$/', $code)) {
throw new Exception("Malformed HTTP status code '{$code}'!");
}
$code = (int)$code;
- $this->emitHTTPStatus($code);
+ $this->emitHTTPStatus($code, $message);
}
/**
* Write HTTP headers to the output.
*
* @param list<pair> List of <name, value> pairs.
* @return void
*/
final public function writeHeaders(array $headers) {
foreach ($headers as $header) {
if (!is_array($header) || count($header) !== 2) {
throw new Exception('Malformed header.');
}
list($name, $value) = $header;
if (strpos($name, ':') !== false) {
throw new Exception(
"Declining to emit response with malformed HTTP header name: ".
$name);
}
// Attackers may perform an "HTTP response splitting" attack by making
// the application emit certain types of headers containing newlines:
//
// http://en.wikipedia.org/wiki/HTTP_response_splitting
//
// PHP has built-in protections against HTTP response-splitting, but they
// are of dubious trustworthiness:
//
// http://news.php.net/php.internals/57655
if (preg_match('/[\r\n\0]/', $name.$value)) {
throw new Exception(
"Declining to emit response with unsafe HTTP header: ".
"<'".$name."', '".$value."'>.");
}
}
foreach ($headers as $header) {
list($name, $value) = $header;
$this->emitHeader($name, $value);
}
}
/**
* Write HTTP body data to the output.
*
* @param string Body data.
* @return void
*/
final public function writeData($data) {
$this->emitData($data);
}
/**
* Write an entire @{class:AphrontResponse} to the output.
*
* @param AphrontResponse The response object to write.
* @return void
*/
final public function writeResponse(AphrontResponse $response) {
// Do this first, in case it throws.
$response_string = $response->buildResponseString();
$all_headers = array_merge(
$response->getHeaders(),
$response->getCacheHeaders());
- $this->writeHTTPStatus($response->getHTTPResponseCode());
+ $this->writeHTTPStatus(
+ $response->getHTTPResponseCode(),
+ $response->getHTTPResponseMessage());
$this->writeHeaders($all_headers);
$this->writeData($response_string);
}
/* -( Emitting the Response )---------------------------------------------- */
- abstract protected function emitHTTPStatus($code);
+ abstract protected function emitHTTPStatus($code, $message = '');
abstract protected function emitHeader($name, $value);
abstract protected function emitData($data);
}
diff --git a/src/aphront/sink/AphrontIsolatedHTTPSink.php b/src/aphront/sink/AphrontIsolatedHTTPSink.php
index ced5536553..1f8a48f016 100644
--- a/src/aphront/sink/AphrontIsolatedHTTPSink.php
+++ b/src/aphront/sink/AphrontIsolatedHTTPSink.php
@@ -1,38 +1,38 @@
<?php
/**
* Isolated HTTP sink for testing.
*
* @group aphront
*/
final class AphrontIsolatedHTTPSink extends AphrontHTTPSink {
private $status;
private $headers;
private $data;
- protected function emitHTTPStatus($code) {
+ protected function emitHTTPStatus($code, $message = '') {
$this->status = $code;
}
protected function emitHeader($name, $value) {
$this->headers[] = array($name, $value);
}
protected function emitData($data) {
$this->data .= $data;
}
public function getEmittedHTTPStatus() {
return $this->status;
}
public function getEmittedHeaders() {
return $this->headers;
}
public function getEmittedData() {
return $this->data;
}
}
diff --git a/src/aphront/sink/AphrontPHPHTTPSink.php b/src/aphront/sink/AphrontPHPHTTPSink.php
index d94e2b6558..f983abac95 100644
--- a/src/aphront/sink/AphrontPHPHTTPSink.php
+++ b/src/aphront/sink/AphrontPHPHTTPSink.php
@@ -1,24 +1,28 @@
<?php
/**
* Concrete HTTP sink which uses "echo" and "header()" to emit data.
*
* @group aphront
*/
final class AphrontPHPHTTPSink extends AphrontHTTPSink {
- protected function emitHTTPStatus($code) {
+ protected function emitHTTPStatus($code, $message = '') {
if ($code != 200) {
- header("HTTP/1.0 {$code}");
+ $header = "HTTP/1.0 {$code}";
+ if (strlen($message)) {
+ $header .= " {$message}";
+ }
+ header($header);
}
}
protected function emitHeader($name, $value) {
header("{$name}: {$value}", $replace = false);
}
protected function emitData($data) {
echo $data;
}
}
diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php
index 60abcfff8d..149f40ee25 100644
--- a/src/applications/base/controller/PhabricatorController.php
+++ b/src/applications/base/controller/PhabricatorController.php
@@ -1,409 +1,409 @@
<?php
abstract class PhabricatorController extends AphrontController {
private $handles;
public function shouldRequireLogin() {
return true;
}
public function shouldRequireAdmin() {
return false;
}
public function shouldRequireEnabledUser() {
return true;
}
public function shouldAllowPublic() {
return false;
}
public function shouldRequireEmailVerification() {
return PhabricatorUserEmail::isEmailVerificationRequired();
}
- final public function willBeginExecution() {
+ public function willBeginExecution() {
$request = $this->getRequest();
if ($request->getUser()) {
// NOTE: Unit tests can set a user explicitly. Normal requests are not
// permitted to do this.
PhabricatorTestCase::assertExecutingUnitTests();
$user = $request->getUser();
} else {
$user = new PhabricatorUser();
$phusr = $request->getCookie('phusr');
$phsid = $request->getCookie('phsid');
if (strlen($phusr) && $phsid) {
$info = queryfx_one(
$user->establishConnection('r'),
'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
AND s.type LIKE %> AND s.sessionKey = %s',
$user->getTableName(),
'phabricator_session',
'web-',
PhabricatorHash::digest($phsid));
if ($info) {
$user->loadFromArray($info);
}
}
$request->setUser($user);
}
$translation = $user->getTranslation();
if ($translation &&
$translation != PhabricatorEnv::getEnvConfig('translation.provider')) {
$translation = newv($translation, array());
PhutilTranslator::getInstance()
->setLanguage($translation->getLanguage())
->addTranslations($translation->getTranslations());
}
$preferences = $user->loadPreferences();
if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) {
$dark_console = PhabricatorUserPreferences::PREFERENCE_DARK_CONSOLE;
if ($preferences->getPreference($dark_console) ||
PhabricatorEnv::getEnvConfig('darkconsole.always-on')) {
$console = new DarkConsoleCore();
$request->getApplicationConfiguration()->setConsole($console);
}
}
if ($user->getIsDisabled() && $this->shouldRequireEnabledUser()) {
$disabled_user_controller = new PhabricatorDisabledUserController(
$request);
return $this->delegateToController($disabled_user_controller);
}
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST,
array(
'request' => $request,
'controller' => $this,
));
$event->setUser($user);
PhutilEventEngine::dispatchEvent($event);
$checker_controller = $event->getValue('controller');
if ($checker_controller != $this) {
return $this->delegateToController($checker_controller);
}
if ($this->shouldRequireLogin()) {
// This actually means we need either:
// - a valid user, or a public controller; and
// - permission to see the application.
$auth_class = 'PhabricatorApplicationAuth';
$auth_application = PhabricatorApplication::getByClass($auth_class);
$allow_public = $this->shouldAllowPublic() &&
PhabricatorEnv::getEnvConfig('policy.allow-public');
// If this controller isn't public, and the user isn't logged in, require
// login.
if (!$allow_public && !$user->isLoggedIn()) {
$login_controller = new PhabricatorAuthStartController($request);
$this->setCurrentApplication($auth_application);
return $this->delegateToController($login_controller);
}
if ($user->isLoggedIn()) {
if ($this->shouldRequireEmailVerification()) {
$email = $user->loadPrimaryEmail();
if (!$email) {
throw new Exception(
"No primary email address associated with this account!");
}
if (!$email->getIsVerified()) {
$controller = new PhabricatorMustVerifyEmailController($request);
$this->setCurrentApplication($auth_application);
return $this->delegateToController($controller);
}
}
}
// If the user doesn't have access to the application, don't let them use
// any of its controllers. We query the application in order to generate
// a policy exception if the viewer doesn't have permission.
$application = $this->getCurrentApplication();
if ($application) {
id(new PhabricatorApplicationQuery())
->setViewer($user)
->withPHIDs(array($application->getPHID()))
->executeOne();
}
}
// NOTE: We do this last so that users get a login page instead of a 403
// if they need to login.
if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) {
return new Aphront403Response();
}
}
public function buildStandardPageView() {
$view = new PhabricatorStandardPageView();
$view->setRequest($this->getRequest());
$view->setController($this);
return $view;
}
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->appendChild($view);
$response = new AphrontWebpageResponse();
$response->setContent($page->render());
return $response;
}
public function getApplicationURI($path = '') {
if (!$this->getCurrentApplication()) {
throw new Exception("No application!");
}
return $this->getCurrentApplication()->getApplicationURI($path);
}
public function buildApplicationPage($view, array $options) {
$page = $this->buildStandardPageView();
$title = PhabricatorEnv::getEnvConfig('phabricator.serious-business') ?
'Phabricator' :
pht('Bacon Ice Cream for Breakfast');
$application = $this->getCurrentApplication();
$page->setTitle(idx($options, 'title', $title));
if ($application) {
$page->setApplicationName($application->getName());
if ($application->getTitleGlyph()) {
$page->setGlyph($application->getTitleGlyph());
}
}
if (!($view instanceof AphrontSideNavFilterView)) {
$nav = new AphrontSideNavFilterView();
$nav->appendChild($view);
$view = $nav;
}
$user = $this->getRequest()->getUser();
$view->setUser($user);
$page->appendChild($view);
$object_phids = idx($options, 'pageObjects', array());
if ($object_phids) {
$page->appendPageObjects($object_phids);
foreach ($object_phids as $object_phid) {
PhabricatorFeedStoryNotification::updateObjectNotificationViews(
$user,
$object_phid);
}
}
if (idx($options, 'device')) {
$page->setDeviceReady(true);
}
$page->setShowChrome(idx($options, 'chrome', true));
$application_menu = $this->buildApplicationMenu();
if ($application_menu) {
$page->setApplicationMenu($application_menu);
}
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
public function didProcessRequest($response) {
$request = $this->getRequest();
$response->setRequest($request);
$seen = array();
while ($response instanceof AphrontProxyResponse) {
$hash = spl_object_hash($response);
if (isset($seen[$hash])) {
$seen[] = get_class($response);
throw new Exception(
"Cycle while reducing proxy responses: ".
implode(' -> ', $seen));
}
$seen[$hash] = get_class($response);
$response = $response->reduceProxyResponse();
}
if ($response instanceof AphrontDialogResponse) {
if (!$request->isAjax()) {
$view = new PhabricatorStandardPageView();
$view->setRequest($request);
$view->setController($this);
$view->appendChild(hsprintf(
'<div style="padding: 2em 0;">%s</div>',
$response->buildResponseString()));
$response = new AphrontWebpageResponse();
$response->setContent($view->render());
return $response;
} else {
$response->getDialog()->setIsStandalone(true);
return id(new AphrontAjaxResponse())
->setContent(array(
'dialog' => $response->buildResponseString(),
));
}
} else if ($response instanceof AphrontRedirectResponse) {
if ($request->isAjax()) {
return id(new AphrontAjaxResponse())
->setContent(
array(
'redirect' => $response->getURI(),
));
}
}
return $response;
}
protected function getHandle($phid) {
if (empty($this->handles[$phid])) {
throw new Exception(
"Attempting to access handle which wasn't loaded: {$phid}");
}
return $this->handles[$phid];
}
protected function loadHandles(array $phids) {
$phids = array_filter($phids);
$this->handles = $this->loadViewerHandles($phids);
return $this;
}
protected function getLoadedHandles() {
return $this->handles;
}
protected function loadViewerHandles(array $phids) {
return id(new PhabricatorHandleQuery())
->setViewer($this->getRequest()->getUser())
->withPHIDs($phids)
->execute();
}
/**
* Render a list of links to handles, identified by PHIDs. The handles must
* already be loaded.
*
* @param list<phid> List of PHIDs to render links to.
* @param string Style, one of "\n" (to put each item on its own line)
* or "," (to list items inline, separated by commas).
* @return string Rendered list of handle links.
*/
protected function renderHandlesForPHIDs(array $phids, $style = "\n") {
$style_map = array(
"\n" => phutil_tag('br'),
',' => ', ',
);
if (empty($style_map[$style])) {
throw new Exception("Unknown handle list style '{$style}'!");
}
return implode_selected_handle_links($style_map[$style],
$this->getLoadedHandles(),
array_filter($phids));
}
protected function buildApplicationMenu() {
return null;
}
protected function buildApplicationCrumbs() {
$crumbs = array();
$application = $this->getCurrentApplication();
if ($application) {
$sprite = $application->getIconName();
if (!$sprite) {
$sprite = 'application';
}
$crumbs[] = id(new PhabricatorCrumbView())
->setHref($this->getApplicationURI())
->setIcon($sprite);
}
$view = new PhabricatorCrumbsView();
foreach ($crumbs as $crumb) {
$view->addCrumb($crumb);
}
return $view;
}
protected function hasApplicationCapability($capability) {
return PhabricatorPolicyFilter::hasCapability(
$this->getRequest()->getUser(),
$this->getCurrentApplication(),
$capability);
}
protected function requireApplicationCapability($capability) {
PhabricatorPolicyFilter::requireCapability(
$this->getRequest()->getUser(),
$this->getCurrentApplication(),
$capability);
}
protected function explainApplicationCapability(
$capability,
$positive_message,
$negative_message) {
$can_act = $this->hasApplicationCapability($capability);
if ($can_act) {
$message = $positive_message;
$icon_name = 'enable-grey';
} else {
$message = $negative_message;
$icon_name = 'lock';
}
$icon = id(new PHUIIconView())
->setSpriteSheet(PHUIIconView::SPRITE_ICONS)
->setSpriteIcon($icon_name);
require_celerity_resource('policy-css');
$phid = $this->getCurrentApplication()->getPHID();
$explain_uri = "/policy/explain/{$phid}/{$capability}/";
$message = phutil_tag(
'div',
array(
'class' => 'policy-capability-explanation',
),
array(
$icon,
javelin_tag(
'a',
array(
'href' => $explain_uri,
'sigil' => 'workflow',
),
$message),
));
return array($can_act, $message);
}
}
diff --git a/src/applications/conduit/ssh/ConduitSSHWorkflow.php b/src/applications/conduit/ssh/ConduitSSHWorkflow.php
index ba456efaca..74221b51dc 100644
--- a/src/applications/conduit/ssh/ConduitSSHWorkflow.php
+++ b/src/applications/conduit/ssh/ConduitSSHWorkflow.php
@@ -1,83 +1,83 @@
<?php
final class ConduitSSHWorkflow extends PhabricatorSSHWorkflow {
public function didConstruct() {
$this->setName('conduit');
$this->setArguments(
array(
array(
'name' => 'method',
'wildcard' => true,
),
));
}
public function execute(PhutilArgumentParser $args) {
$time_start = microtime(true);
$methodv = $args->getArg('method');
if (!$methodv) {
throw new Exception("No Conduit method provided.");
} else if (count($methodv) > 1) {
throw new Exception("Too many Conduit methods provided.");
}
$method = head($methodv);
$json = $this->readAllInput();
$raw_params = json_decode($json, true);
if (!is_array($raw_params)) {
throw new Exception("Invalid JSON input.");
}
- $params = idx($raw_params, 'params', array());
+ $params = idx($raw_params, 'params', '[]');
$params = json_decode($params, true);
$metadata = idx($params, '__conduit__', array());
unset($params['__conduit__']);
$call = null;
$error_code = null;
$error_info = null;
try {
$call = new ConduitCall($method, $params);
$call->setUser($this->getUser());
$result = $call->execute();
} catch (ConduitException $ex) {
$result = null;
$error_code = $ex->getMessage();
if ($ex->getErrorDescription()) {
$error_info = $ex->getErrorDescription();
} else if ($call) {
$error_info = $call->getErrorDescription($error_code);
}
}
$response = id(new ConduitAPIResponse())
->setResult($result)
->setErrorCode($error_code)
->setErrorInfo($error_info);
$json_out = json_encode($response->toDictionary());
$json_out = $json_out."\n";
$this->getIOChannel()->write($json_out);
// NOTE: Flush here so we can get an accurate result for the duration,
// if the response is large and the receiver is slow to read it.
$this->getIOChannel()->flush();
$time_end = microtime(true);
$connection_id = idx($metadata, 'connectionID');
$log = id(new PhabricatorConduitMethodCallLog())
->setCallerPHID($this->getUser()->getPHID())
->setConnectionID($connection_id)
->setMethod($method)
->setError((string)$error_code)
->setDuration(1000000 * ($time_end - $time_start))
->save();
}
}
diff --git a/src/applications/config/check/PhabricatorSetupCheckExtraConfig.php b/src/applications/config/check/PhabricatorSetupCheckExtraConfig.php
index 8190b187b2..ed76ab1997 100644
--- a/src/applications/config/check/PhabricatorSetupCheckExtraConfig.php
+++ b/src/applications/config/check/PhabricatorSetupCheckExtraConfig.php
@@ -1,169 +1,171 @@
<?php
final class PhabricatorSetupCheckExtraConfig extends PhabricatorSetupCheck {
protected function executeChecks() {
$ancient_config = self::getAncientConfig();
$all_keys = PhabricatorEnv::getAllConfigKeys();
$all_keys = array_keys($all_keys);
sort($all_keys);
$defined_keys = PhabricatorApplicationConfigOptions::loadAllOptions();
foreach ($all_keys as $key) {
if (isset($defined_keys[$key])) {
continue;
}
if (isset($ancient_config[$key])) {
$summary = pht(
'This option has been removed. You may delete it at your '.
'convenience.');
$message = pht(
"The configuration option '%s' has been removed. You may delete ".
"it at your convenience.".
"\n\n%s",
$key,
$ancient_config[$key]);
$short = pht('Obsolete Config');
$name = pht('Obsolete Configuration Option "%s"', $key);
} else {
$summary = pht("This option is not recognized. It may be misspelled.");
$message = pht(
"The configuration option '%s' is not recognized. It may be ".
"misspelled, or it might have existed in an older version of ".
"Phabricator. It has no effect, and should be corrected or deleted.",
$key);
$short = pht('Unknown Config');
$name = pht('Unknown Configuration Option "%s"', $key);
}
$issue = $this->newIssue('config.unknown.'.$key)
->setShortName($short)
->setName($name)
->setSummary($summary);
$stack = PhabricatorEnv::getConfigSourceStack();
$stack = $stack->getStack();
$found = array();
$found_local = false;
$found_database = false;
foreach ($stack as $source_key => $source) {
$value = $source->getKeys(array($key));
if ($value) {
$found[] = $source->getName();
if ($source instanceof PhabricatorConfigDatabaseSource) {
$found_database = true;
}
if ($source instanceof PhabricatorConfigLocalSource) {
$found_local = true;
}
}
}
$message = $message."\n\n".pht(
"This configuration value is defined in these %d ".
"configuration source(s): %s.",
count($found),
implode(', ', $found));
$issue->setMessage($message);
if ($found_local) {
$command = csprintf('phabricator/ $ ./bin/config delete %s', $key);
$issue->addCommand($command);
}
if ($found_database) {
$issue->addPhabricatorConfig($key);
}
}
}
/**
* Return a map of deleted config options. Keys are option keys; values are
* explanations of what happened to the option.
*/
public static function getAncientConfig() {
$reason_auth = pht(
'This option has been migrated to the "Auth" application. Your old '.
'configuration is still in effect, but now stored in "Auth" instead of '.
'configuration. Going forward, you can manage authentication from '.
'the web UI.');
$auth_config = array(
'controller.oauth-registration',
'auth.password-auth-enabled',
'facebook.auth-enabled',
'facebook.registration-enabled',
'facebook.auth-permanent',
'facebook.application-id',
'facebook.application-secret',
'facebook.require-https-auth',
'github.auth-enabled',
'github.registration-enabled',
'github.auth-permanent',
'github.application-id',
'github.application-secret',
'google.auth-enabled',
'google.registration-enabled',
'google.auth-permanent',
'google.application-id',
'google.application-secret',
'ldap.auth-enabled',
'ldap.hostname',
'ldap.port',
'ldap.base_dn',
'ldap.search_attribute',
'ldap.search-first',
'ldap.username-attribute',
'ldap.real_name_attributes',
'ldap.activedirectory_domain',
'ldap.version',
'ldap.referrals',
'ldap.anonymous-user-name',
'ldap.anonymous-user-password',
'ldap.start-tls',
'disqus.auth-enabled',
'disqus.registration-enabled',
'disqus.auth-permanent',
'disqus.application-id',
'disqus.application-secret',
'phabricator.oauth-uri',
'phabricator.auth-enabled',
'phabricator.registration-enabled',
'phabricator.auth-permanent',
'phabricator.application-id',
'phabricator.application-secret',
);
$ancient_config = array_fill_keys($auth_config, $reason_auth);
$markup_reason = pht(
'Custom remarkup rules are now added by subclassing '.
'PhabricatorRemarkupCustomInlineRule or '.
'PhabricatorRemarkupCustomBlockRule.');
$ancient_config += array(
'phid.external-loaders' =>
pht(
'External loaders have been replaced. Extend `PhabricatorPHIDType` '.
'to implement new PHID and handle types.'),
'maniphest.custom-task-extensions-class' =>
pht(
'Maniphest fields are now loaded automatically. You can configure '.
'them with `maniphest.fields`.'),
'maniphest.custom-fields' =>
pht(
'Maniphest fields are now defined in '.
'`maniphest.custom-field-definitions`. Existing definitions have '.
'been migrated.'),
'differential.custom-remarkup-rules' => $markup_reason,
'differential.custom-remarkup-block-rules' => $markup_reason,
+ 'auth.sshkeys.enabled' => pht(
+ 'SSH keys are now actually useful, so they are always enabled.'),
);
return $ancient_config;
}
}
diff --git a/src/applications/config/option/PhabricatorAuthenticationConfigOptions.php b/src/applications/config/option/PhabricatorAuthenticationConfigOptions.php
index 9be99adff2..dffe91e7be 100644
--- a/src/applications/config/option/PhabricatorAuthenticationConfigOptions.php
+++ b/src/applications/config/option/PhabricatorAuthenticationConfigOptions.php
@@ -1,110 +1,95 @@
<?php
final class PhabricatorAuthenticationConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht("Authentication");
}
public function getDescription() {
return pht("Options relating to authentication.");
}
public function getOptions() {
return array(
$this->newOption('auth.sessions.web', 'int', 5)
->setSummary(
pht("Number of web sessions a user can have simultaneously."))
->setDescription(
pht(
"Maximum number of simultaneous web sessions each user is ".
"permitted to have. Setting this to '1' will prevent a user from ".
"logging in on more than one browser at the same time.")),
$this->newOption('auth.sessions.conduit', 'int', 5)
->setSummary(
pht(
"Number of simultaneous Conduit sessions each user is permitted."))
->setDescription(
pht(
"Maximum number of simultaneous Conduit sessions each user is ".
"permitted to have.")),
- $this->newOption('auth.sshkeys.enabled', 'bool', false)
- ->setBoolOptions(
- array(
- pht("Enable SSH key storage"),
- pht("Disable SSH key storage")))
- ->setSummary(
- pht("Allow users to associate SSH keys with their accounts."))
- ->setDescription(
- pht(
- "Set this true to enable the Settings -> SSH Public Keys panel, ".
- "which will allow users to associated SSH public keys with their ".
- "accounts. This is only really useful if you're setting up ".
- "services over SSH and want to use Phabricator for ".
- "authentication; in most situations you can leave this ".
- "disabled.")),
$this->newOption('auth.require-email-verification', 'bool', false)
->setBoolOptions(
array(
pht("Require email verification"),
pht("Don't require email verification")
))
->setSummary(
pht("Require email verification before a user can log in."))
->setDescription(
pht(
"If true, email addresses must be verified (by clicking a link ".
"in an email) before a user can login. By default, verification ".
"is optional unless 'auth.email-domains' is nonempty.")),
$this->newOption('auth.email-domains', 'list<string>', array())
->setSummary(pht("Only allow registration from particular domains."))
->setDescription(
pht(
"You can restrict allowed email addresses to certain domains ".
"(like 'yourcompany.com') by setting a list of allowed domains ".
"here. Users will only be allowed to register using email ".
"addresses at one of the domains, and will only be able to add ".
"new email addresses for these domains. If you configure this, ".
"it implies 'auth.require-email-verification'.\n\n".
"You should omit the '@' from domains. Note that the domain must ".
"match exactly. If you allow 'yourcompany.com', that permits ".
"'joe@yourcompany.com' but rejects 'joe@mail.yourcompany.com'."))
->addExample(
"yourcompany.com\nmail.yourcompany.com",
pht('Valid Setting')),
$this->newOption('auth.login-message', 'string', null)
->setLocked(true)
->setSummary(pht("A block of HTML displayed on the login screen."))
->setDescription(
pht(
"You can provide an arbitrary block of HTML here, which will ".
"appear on the login screen. Normally, you'd use this to provide ".
"login or registration instructions to users.")),
$this->newOption('account.editable', 'bool', true)
->setBoolOptions(
array(
pht("Allow editing"),
pht("Prevent editing")
))
->setSummary(
pht(
"Determines whether or not basic account information is ".
"editable."))
->setDescription(
pht(
"Is basic account information (email, real name, profile ".
"picture) editable? If you set up Phabricator to automatically ".
"synchronize account information from some other authoritative ".
"system, you can disable this to ensure information remains ".
"consistent across both systems.")),
$this->newOption('account.minimum-password-length', 'int', 8)
->setSummary(pht("Minimum password length."))
->setDescription(
pht(
"When users set or reset a password, it must have at least this ".
"many characters.")),
);
}
}
diff --git a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
index a13fba9528..708070f9df 100644
--- a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
+++ b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
@@ -1,106 +1,130 @@
<?php
final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
public function getShortDescription() {
return pht('Repository Browser');
}
public function getBaseURI() {
return '/diffusion/';
}
public function getIconName() {
return 'diffusion';
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Diffusion_User_Guide.html');
}
public function getFactObjectsForAnalysis() {
return array(
new PhabricatorRepositoryCommit(),
);
}
public function getEventListeners() {
return array(
new DiffusionHovercardEventListener(),
);
}
public function getRemarkupRules() {
return array(
new DiffusionRemarkupRule(),
);
}
public function getRoutes() {
return array(
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)'
=> 'DiffusionCommitController',
'/diffusion/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?'
=> 'DiffusionRepositoryListController',
'create/' => 'DiffusionRepositoryCreateController',
'(?P<callsign>[A-Z]+)/' => array(
'' => 'DiffusionRepositoryController',
'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
'change/(?P<dblob>.*)' => 'DiffusionChangeController',
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
'browse/(?P<dblob>.*)' => 'DiffusionBrowseMainController',
'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController',
'diff/' => 'DiffusionDiffController',
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',
'branches/(?P<dblob>.*)' => 'DiffusionBranchTableController',
'lint/(?P<dblob>.*)' => 'DiffusionLintController',
'commit/(?P<commit>[a-z0-9]+)/branches/'
=> 'DiffusionCommitBranchesController',
'commit/(?P<commit>[a-z0-9]+)/tags/'
=> 'DiffusionCommitTagsController',
'commit/(?P<commit>[a-z0-9]+)/edit/'
=> 'DiffusionCommitEditController',
'edit/' => array(
'' => 'DiffusionRepositoryEditMainController',
'basic/' => 'DiffusionRepositoryEditBasicController',
'encoding/' => 'DiffusionRepositoryEditEncodingController',
'activate/' => 'DiffusionRepositoryEditActivateController',
'policy/' => 'DiffusionRepositoryEditPolicyController',
'branches/' => 'DiffusionRepositoryEditBranchesController',
'subversion/' => 'DiffusionRepositoryEditSubversionController',
'actions/' => 'DiffusionRepositoryEditActionsController',
'(?P<edit>remote)/' => 'DiffusionRepositoryCreateController',
'local/' => 'DiffusionRepositoryEditLocalController',
'delete/' => 'DiffusionRepositoryEditDeleteController',
+ 'hosting/' => 'DiffusionRepositoryEditHostingController',
+ '(?P<serve>serve)/' => 'DiffusionRepositoryEditHostingController',
),
),
+
+ // NOTE: This must come after the rule above; it just gives us a
+ // catch-all for serving repositories over HTTP. We must accept
+ // requests without the trailing "/" because SVN commands don't
+ // necessarily include it.
+ '(?P<callsign>[A-Z]+)(/|$).*' => 'DiffusionRepositoryDefaultController',
+
'inline/' => array(
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
'preview/(?P<phid>[^/]+)/' =>
'DiffusionInlineCommentPreviewController',
),
'services/' => array(
'path/' => array(
'complete/' => 'DiffusionPathCompleteController',
'validate/' => 'DiffusionPathValidateController',
),
),
'symbol/(?P<name>[^/]+)/' => 'DiffusionSymbolController',
'external/' => 'DiffusionExternalController',
'lint/' => 'DiffusionLintController',
),
);
}
public function getApplicationGroup() {
return self::GROUP_CORE;
}
public function getApplicationOrder() {
return 0.120;
}
+ protected function getCustomCapabilities() {
+ return array(
+ DiffusionCapabilityDefaultView::CAPABILITY => array(
+ ),
+ DiffusionCapabilityDefaultEdit::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ ),
+ DiffusionCapabilityDefaultPush::CAPABILITY => array(
+ ),
+ DiffusionCapabilityCreateRepositories::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ ),
+ );
+ }
+
}
diff --git a/src/applications/diffusion/capability/DiffusionCapabilityCreateRepositories.php b/src/applications/diffusion/capability/DiffusionCapabilityCreateRepositories.php
new file mode 100644
index 0000000000..c831c95af5
--- /dev/null
+++ b/src/applications/diffusion/capability/DiffusionCapabilityCreateRepositories.php
@@ -0,0 +1,20 @@
+<?php
+
+final class DiffusionCapabilityCreateRepositories
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diffusion.create';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Can Create Repositories');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to create new repositories.');
+ }
+
+}
diff --git a/src/applications/diffusion/capability/DiffusionCapabilityDefaultEdit.php b/src/applications/diffusion/capability/DiffusionCapabilityDefaultEdit.php
new file mode 100644
index 0000000000..f2631de831
--- /dev/null
+++ b/src/applications/diffusion/capability/DiffusionCapabilityDefaultEdit.php
@@ -0,0 +1,16 @@
+<?php
+
+final class DiffusionCapabilityDefaultEdit
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diffusion.default.edit';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Default Edit Policy');
+ }
+
+}
diff --git a/src/applications/diffusion/capability/DiffusionCapabilityDefaultPush.php b/src/applications/diffusion/capability/DiffusionCapabilityDefaultPush.php
new file mode 100644
index 0000000000..3ceaadb255
--- /dev/null
+++ b/src/applications/diffusion/capability/DiffusionCapabilityDefaultPush.php
@@ -0,0 +1,16 @@
+<?php
+
+final class DiffusionCapabilityDefaultPush
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diffusion.default.push';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Default Push Policy');
+ }
+
+}
diff --git a/src/applications/diffusion/capability/DiffusionCapabilityDefaultView.php b/src/applications/diffusion/capability/DiffusionCapabilityDefaultView.php
new file mode 100644
index 0000000000..ed5d617a37
--- /dev/null
+++ b/src/applications/diffusion/capability/DiffusionCapabilityDefaultView.php
@@ -0,0 +1,20 @@
+<?php
+
+final class DiffusionCapabilityDefaultView
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diffusion.default.view';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Default View Policy');
+ }
+
+ public function shouldAllowPublicPolicySetting() {
+ return true;
+ }
+
+}
diff --git a/src/applications/diffusion/capability/DiffusionCapabilityPush.php b/src/applications/diffusion/capability/DiffusionCapabilityPush.php
new file mode 100644
index 0000000000..820e3694c6
--- /dev/null
+++ b/src/applications/diffusion/capability/DiffusionCapabilityPush.php
@@ -0,0 +1,20 @@
+<?php
+
+final class DiffusionCapabilityPush
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diffusion.push';
+
+ public function getCapabilityKey() {
+ return self::CAPABILITY;
+ }
+
+ public function getCapabilityName() {
+ return pht('Can Push');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to push to this repository.');
+ }
+
+}
diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php
index a79ef123c0..6ff102fd63 100644
--- a/src/applications/diffusion/controller/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/DiffusionCommitController.php
@@ -1,1087 +1,1084 @@
<?php
final class DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100;
private $auditAuthorityPHIDs;
private $highlightedAudits;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
// This controller doesn't use blob/path stuff, just pass the dictionary
// in directly instead of using the AphrontRequest parsing mechanism.
$data['user'] = $this->getRequest()->getUser();
$drequest = DiffusionRequest::newFromDictionary($data);
$this->diffusionRequest = $drequest;
}
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
$user = $request->getUser();
if ($request->getStr('diff')) {
return $this->buildRawDiffResponse($drequest);
}
$callsign = $drequest->getRepository()->getCallsign();
$content = array();
$repository = $drequest->getRepository();
$commit = $drequest->loadCommit();
$crumbs = $this->buildCrumbs(array(
'commit' => true,
));
if (!$commit) {
$exists = $this->callConduitWithDiffusionRequest(
'diffusion.existsquery',
array('commit' => $drequest->getCommit()));
if (!$exists) {
return new Aphront404Response();
}
$error = id(new AphrontErrorView())
->setTitle(pht('Commit Still Parsing'))
->appendChild(
pht(
'Failed to load the commit because the commit has not been '.
'parsed yet.'));
return $this->buildApplicationPage(
array(
$crumbs,
$error,
),
array(
'title' => pht('Commit Still Parsing'),
));
}
$commit_data = $drequest->loadCommitData();
$commit->attachCommitData($commit_data);
$top_anchor = id(new PhabricatorAnchorView())
->setAnchorName('top')
->setNavigationMarker(true);
$audit_requests = id(new PhabricatorAuditQuery())
->withCommitPHIDs(array($commit->getPHID()))
->execute();
$this->auditAuthorityPHIDs =
PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
-
$is_foreign = $commit_data->getCommitDetail('foreign-svn-stub');
$changesets = null;
if ($is_foreign) {
$subpath = $commit_data->getCommitDetail('svn-subpath');
$error_panel = new AphrontErrorView();
$error_panel->setTitle(pht('Commit Not Tracked'));
$error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING);
$error_panel->appendChild(
pht("This Diffusion repository is configured to track only one ".
"subdirectory of the entire Subversion repository, and this commit ".
"didn't affect the tracked subdirectory ('%s'), so no ".
"information is available.", $subpath));
$content[] = $error_panel;
$content[] = $top_anchor;
} else {
$engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine();
$engine->setConfig('viewer', $user);
require_celerity_resource('diffusion-commit-view-css');
require_celerity_resource('phabricator-remarkup-css');
$parents = $this->callConduitWithDiffusionRequest(
'diffusion.commitparentsquery',
array('commit' => $drequest->getCommit()));
$headsup_view = id(new PHUIHeaderView())
->setHeader(nonempty($commit->getSummary(), pht('Commit Detail')));
$headsup_actions = $this->renderHeadsupActionList($commit, $repository);
$commit_properties = $this->loadCommitProperties(
$commit,
$commit_data,
$parents,
$audit_requests);
$property_list = id(new PHUIPropertyListView())
->setHasKeyboardShortcuts(true)
->setUser($user)
->setObject($commit);
foreach ($commit_properties as $key => $value) {
$property_list->addProperty($key, $value);
}
$message = $commit_data->getCommitMessage();
$revision = $commit->getCommitIdentifier();
$message = $this->linkBugtraq($message);
$message = $engine->markupText($message);
$property_list->invokeWillRenderEvent();
$property_list->setActionList($headsup_actions);
$detail_list = new PHUIPropertyListView();
$detail_list->addSectionHeader(pht('Description'));
$detail_list->addTextContent(
phutil_tag(
'div',
array(
'class' => 'diffusion-commit-message phabricator-remarkup',
),
$message));
$content[] = $top_anchor;
$object_box = id(new PHUIObjectBoxView())
->setHeader($headsup_view)
->addPropertyList($property_list)
->addPropertyList($detail_list);
$content[] = $object_box;
}
$content[] = $this->buildComments($commit);
$hard_limit = 1000;
- $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
- $drequest);
- $change_query->setLimit($hard_limit + 1);
- $changes = $change_query->loadChanges();
+ if ($commit->isImported()) {
+ $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
+ $drequest);
+ $change_query->setLimit($hard_limit + 1);
+ $changes = $change_query->loadChanges();
+ } else {
+ $changes = array();
+ }
$was_limited = (count($changes) > $hard_limit);
if ($was_limited) {
$changes = array_slice($changes, 0, $hard_limit);
}
$content[] = $this->buildMergesTable($commit);
// TODO: This is silly, but the logic to figure out which audits are
// highlighted currently lives in PhabricatorAuditListView. Refactor this
// to be less goofy.
$highlighted_audits = id(new PhabricatorAuditListView())
->setAudits($audit_requests)
->setAuthorityPHIDs($this->auditAuthorityPHIDs)
->setUser($user)
->setCommits(array($commit->getPHID() => $commit))
->getHighlightedAudits();
$owners_paths = array();
if ($highlighted_audits) {
$packages = id(new PhabricatorOwnersPackage())->loadAllWhere(
'phid IN (%Ls)',
mpull($highlighted_audits, 'getAuditorPHID'));
if ($packages) {
$owners_paths = id(new PhabricatorOwnersPath())->loadAllWhere(
'repositoryPHID = %s AND packageID IN (%Ld)',
$repository->getPHID(),
mpull($packages, 'getID'));
}
}
$change_table = new DiffusionCommitChangeTableView();
$change_table->setDiffusionRequest($drequest);
$change_table->setPathChanges($changes);
$change_table->setOwnersPaths($owners_paths);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
'r'.$callsign.$commit->getCommitIdentifier());
}
if ($bad_commit) {
- $error_panel = new AphrontErrorView();
- $error_panel->setTitle(pht('Bad Commit'));
- $error_panel->appendChild($bad_commit['description']);
-
- $content[] = $error_panel;
+ $content[] = $this->renderStatusMessage(
+ pht('Bad Commit'),
+ $bad_commit['description']);
} else if ($is_foreign) {
// Don't render anything else.
+ } else if (!$commit->isImported()) {
+ $content[] = $this->renderStatusMessage(
+ pht('Still Importing...'),
+ pht(
+ 'This commit is still importing. Changes will be visible once '.
+ 'the import finishes.'));
} else if (!count($changes)) {
- $no_changes = new AphrontErrorView();
- $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING);
- $no_changes->setTitle(pht('Not Yet Parsed'));
- // TODO: This can also happen with weird SVN changes that don't do
- // anything (or only alter properties?), although the real no-changes case
- // is extremely rare and might be impossible to produce organically. We
- // should probably write some kind of "Nothing Happened!" change into the
- // DB once we parse these changes so we can distinguish between
- // "not parsed yet" and "no changes".
- $no_changes->appendChild(
- pht("This commit hasn't been fully parsed yet (or doesn't affect any ".
- "paths)."));
- $content[] = $no_changes;
+ $content[] = $this->renderStatusMessage(
+ pht('Empty Commit'),
+ pht(
+ 'This commit is empty and does not affect any paths.'));
} else if ($was_limited) {
- $huge_commit = new AphrontErrorView();
- $huge_commit->setSeverity(AphrontErrorView::SEVERITY_WARNING);
- $huge_commit->setTitle(pht('Enormous Commit'));
- $huge_commit->appendChild(
+ $content[] = $this->renderStatusMessage(
+ pht('Enormous Commit'),
pht(
'This commit is enormous, and affects more than %d files. '.
'Changes are not shown.',
$hard_limit));
- $content[] = $huge_commit;
} else {
// The user has clicked "Show All Changes", and we should show all the
// changes inline even if there are more than the soft limit.
$show_all_details = $request->getBool('show_all');
$change_panel = new AphrontPanelView();
$change_panel->setHeader("Changes (".number_format($count).")");
$change_panel->setID('toc');
if ($count > self::CHANGES_LIMIT && !$show_all_details) {
$show_all_button = phutil_tag(
'a',
array(
'class' => 'button green',
'href' => '?show_all=true',
),
pht('Show All Changes'));
+
$warning_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
->setTitle('Very Large Commit')
->appendChild(phutil_tag(
'p',
array(),
pht("This commit is very large. Load each file individually.")));
$change_panel->appendChild($warning_view);
$change_panel->addButton($show_all_button);
}
$change_panel->appendChild($change_table);
$change_panel->setNoBackground();
$content[] = $change_panel;
$changesets = DiffusionPathChange::convertToDifferentialChangesets(
$changes);
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$vcs_supports_directory_changes = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$vcs_supports_directory_changes = false;
break;
default:
throw new Exception("Unknown VCS.");
}
$references = array();
foreach ($changesets as $key => $changeset) {
$file_type = $changeset->getFileType();
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
if (!$vcs_supports_directory_changes) {
unset($changesets[$key]);
continue;
}
}
$references[$key] = $drequest->generateURI(
array(
'action' => 'rendering-ref',
'path' => $changeset->getFilename(),
));
}
// TODO: Some parts of the views still rely on properties of the
// DifferentialChangeset. Make the objects ephemeral to make sure we don't
// accidentally save them, and then set their ID to the appropriate ID for
// this application (the path IDs).
$path_ids = array_flip(mpull($changes, 'getPath'));
foreach ($changesets as $changeset) {
$changeset->makeEphemeral();
$changeset->setID($path_ids[$changeset->getFilename()]);
}
if ($count <= self::CHANGES_LIMIT || $show_all_details) {
$visible_changesets = $changesets;
} else {
$visible_changesets = array();
$inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere(
'commitPHID = %s AND (auditCommentID IS NOT NULL OR authorPHID = %s)',
$commit->getPHID(),
$user->getPHID());
$path_ids = mpull($inlines, null, 'getPathID');
foreach ($changesets as $key => $changeset) {
if (array_key_exists($changeset->getID(), $path_ids)) {
$visible_changesets[$key] = $changeset;
}
}
}
$change_list_title = DiffusionView::nameCommit(
$repository,
$commit->getCommitIdentifier());
$change_list = new DifferentialChangesetListView();
$change_list->setTitle($change_list_title);
$change_list->setChangesets($changesets);
$change_list->setVisibleChangesets($visible_changesets);
$change_list->setRenderingReferences($references);
$change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
$change_list->setRepository($repository);
$change_list->setUser($user);
// pick the first branch for "Browse in Diffusion" View Option
$branches = $commit_data->getCommitDetail('seenOnBranches', array());
$first_branch = reset($branches);
$change_list->setBranch($first_branch);
$change_list->setStandaloneURI(
'/diffusion/'.$callsign.'/diff/');
$change_list->setRawFileURIs(
// TODO: Implement this, somewhat tricky if there's an octopus merge
// or whatever?
null,
'/diffusion/'.$callsign.'/diff/?view=r');
$change_list->setInlineCommentControllerURI(
'/diffusion/inline/edit/'.phutil_escape_uri($commit->getPHID()).'/');
$change_references = array();
foreach ($changesets as $key => $changeset) {
$change_references[$changeset->getID()] = $references[$key];
}
$change_table->setRenderingReferences($change_references);
$content[] = $change_list->render();
}
$content[] = $this->renderAddCommentPanel($commit, $audit_requests);
$commit_id = 'r'.$callsign.$commit->getCommitIdentifier();
$short_name = DiffusionView::nameCommit(
$repository,
$commit->getCommitIdentifier());
$prefs = $user->loadPreferences();
$pref_filetree = PhabricatorUserPreferences::PREFERENCE_DIFF_FILETREE;
$pref_collapse = PhabricatorUserPreferences::PREFERENCE_NAV_COLLAPSED;
$show_filetree = $prefs->getPreference($pref_filetree);
$collapsed = $prefs->getPreference($pref_collapse);
if ($changesets && $show_filetree) {
$nav = id(new DifferentialChangesetFileTreeSideNavBuilder())
->setAnchorName('top')
->setTitle($short_name)
->setBaseURI(new PhutilURI('/'.$commit_id))
->build($changesets)
->setCrumbs($crumbs)
->setCollapsed((bool)$collapsed)
->appendChild($content);
$content = $nav;
} else {
$content = array($crumbs, $content);
}
return $this->buildApplicationPage(
$content,
array(
'title' => $commit_id,
'pageObjects' => array($commit->getPHID()),
));
}
private function loadCommitProperties(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data,
array $parents,
array $audit_requests) {
assert_instances_of($parents, 'PhabricatorRepositoryCommit');
$user = $this->getRequest()->getUser();
$commit_phid = $commit->getPHID();
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($commit_phid))
->withEdgeTypes(array(
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK,
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT,
PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV,
));
$edges = $edge_query->execute();
$task_phids = array_keys(
$edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK]);
$proj_phids = array_keys(
$edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT]);
$revision_phid = key(
$edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV]);
$phids = $edge_query->getDestinationPHIDs(array($commit_phid));
if ($data->getCommitDetail('authorPHID')) {
$phids[] = $data->getCommitDetail('authorPHID');
}
if ($data->getCommitDetail('reviewerPHID')) {
$phids[] = $data->getCommitDetail('reviewerPHID');
}
if ($data->getCommitDetail('committerPHID')) {
$phids[] = $data->getCommitDetail('committerPHID');
}
if ($parents) {
foreach ($parents as $parent) {
$phids[] = $parent->getPHID();
}
}
$handles = array();
if ($phids) {
$handles = $this->loadViewerHandles($phids);
}
$props = array();
if ($commit->getAuditStatus()) {
$status = PhabricatorAuditCommitStatusConstants::getStatusName(
$commit->getAuditStatus());
$tag = id(new PhabricatorTagView())
->setType(PhabricatorTagView::TYPE_STATE)
->setName($status);
switch ($commit->getAuditStatus()) {
case PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT:
$tag->setBackgroundColor(PhabricatorTagView::COLOR_ORANGE);
break;
case PhabricatorAuditCommitStatusConstants::CONCERN_RAISED:
$tag->setBackgroundColor(PhabricatorTagView::COLOR_RED);
break;
case PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED:
$tag->setBackgroundColor(PhabricatorTagView::COLOR_BLUE);
break;
case PhabricatorAuditCommitStatusConstants::FULLY_AUDITED:
$tag->setBackgroundColor(PhabricatorTagView::COLOR_GREEN);
break;
}
$props['Status'] = $tag;
}
if ($audit_requests) {
$user_requests = array();
$other_requests = array();
foreach ($audit_requests as $audit_request) {
if ($audit_request->isUser()) {
$user_requests[] = $audit_request;
} else {
$other_requests[] = $audit_request;
}
}
if ($user_requests) {
$props['Auditors'] = $this->renderAuditStatusView(
$user_requests);
}
if ($other_requests) {
$props['Project/Package Auditors'] = $this->renderAuditStatusView(
$other_requests);
}
}
$props['Committed'] = phabricator_datetime($commit->getEpoch(), $user);
$author_phid = $data->getCommitDetail('authorPHID');
if ($data->getCommitDetail('authorPHID')) {
$props['Author'] = $handles[$author_phid]->renderLink();
} else {
$props['Author'] = $data->getAuthorName();
}
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
if ($reviewer_phid) {
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
}
$committer = $data->getCommitDetail('committer');
if ($committer) {
$committer_phid = $data->getCommitDetail('committerPHID');
if ($data->getCommitDetail('committerPHID')) {
$props['Committer'] = $handles[$committer_phid]->renderLink();
} else {
$props['Committer'] = $committer;
}
}
if ($revision_phid) {
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
}
if ($parents) {
$parent_links = array();
foreach ($parents as $parent) {
$parent_links[] = $handles[$parent->getPHID()]->renderLink();
}
$props['Parents'] = phutil_implode_html(" \xC2\xB7 ", $parent_links);
}
$request = $this->getDiffusionRequest();
$props['Branches'] = phutil_tag(
'span',
array(
'id' => 'commit-branches',
),
pht('Unknown'));
$props['Tags'] = phutil_tag(
'span',
array(
'id' => 'commit-tags',
),
pht('Unknown'));
$callsign = $request->getRepository()->getCallsign();
$root = '/diffusion/'.$callsign.'/commit/'.$commit->getCommitIdentifier();
Javelin::initBehavior(
'diffusion-commit-branches',
array(
$root.'/branches/' => 'commit-branches',
$root.'/tags/' => 'commit-tags',
));
$refs = $this->buildRefs($request);
if ($refs) {
$props['References'] = $refs;
}
if ($task_phids) {
$task_list = array();
foreach ($task_phids as $phid) {
$task_list[] = $handles[$phid]->renderLink();
}
$task_list = phutil_implode_html(phutil_tag('br'), $task_list);
$props['Tasks'] = $task_list;
}
if ($proj_phids) {
$proj_list = array();
foreach ($proj_phids as $phid) {
$proj_list[] = $handles[$phid]->renderLink();
}
$proj_list = phutil_implode_html(phutil_tag('br'), $proj_list);
$props['Projects'] = $proj_list;
}
return $props;
}
private function buildComments(PhabricatorRepositoryCommit $commit) {
$user = $this->getRequest()->getUser();
$comments = id(new PhabricatorAuditComment())->loadAllWhere(
'targetPHID = %s ORDER BY dateCreated ASC',
$commit->getPHID());
$inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere(
'commitPHID = %s AND auditCommentID IS NOT NULL',
$commit->getPHID());
$path_ids = mpull($inlines, 'getPathID');
$path_map = array();
if ($path_ids) {
$path_map = id(new DiffusionPathQuery())
->withPathIDs($path_ids)
->execute();
$path_map = ipull($path_map, 'path', 'id');
}
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($user);
foreach ($comments as $comment) {
$engine->addObject(
$comment,
PhabricatorAuditComment::MARKUP_FIELD_BODY);
}
foreach ($inlines as $inline) {
$engine->addObject(
$inline,
PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY);
}
$engine->process();
$view = new DiffusionCommentListView();
$view->setMarkupEngine($engine);
$view->setUser($user);
$view->setComments($comments);
$view->setInlineComments($inlines);
$view->setPathMap($path_map);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
return $view;
}
private function renderAddCommentPanel(
PhabricatorRepositoryCommit $commit,
array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$request = $this->getRequest();
$user = $request->getUser();
if (!$user->isLoggedIn()) {
return id(new PhabricatorApplicationTransactionCommentView())
->setUser($user)
->setRequestURI($request->getRequestURI());
}
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$pane_id = celerity_generate_unique_node_id();
Javelin::initBehavior(
'differential-keyboard-navigation',
array(
'haunt' => $pane_id,
));
$draft = id(new PhabricatorDraft())->loadOneWhere(
'authorPHID = %s AND draftKey = %s',
$user->getPHID(),
'diffusion-audit-'.$commit->getID());
if ($draft) {
$draft = $draft->getDraft();
} else {
$draft = null;
}
$actions = $this->getAuditActions($commit, $audit_requests);
$form = id(new AphrontFormView())
->setUser($user)
->setAction('/audit/addcomment/')
->addHiddenInput('commit', $commit->getPHID())
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Action'))
->setName('action')
->setID('audit-action')
->setOptions($actions))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add Auditors'))
->setName('auditors')
->setControlID('add-auditors')
->setControlStyle('display: none')
->setID('add-auditors-tokenizer')
->setDisableBehavior(true))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Add CCs'))
->setName('ccs')
->setControlID('add-ccs')
->setControlStyle('display: none')
->setID('add-ccs-tokenizer')
->setDisableBehavior(true))
->appendChild(
id(new PhabricatorRemarkupControl())
->setLabel(pht('Comments'))
->setName('content')
->setValue($draft)
->setID('audit-content')
->setUser($user))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue($is_serious ? pht('Submit') : pht('Cook the Books')));
$header = new PHUIHeaderView();
$header->setHeader(
$is_serious ? pht('Audit Commit') : pht('Creative Accounting'));
require_celerity_resource('phabricator-transaction-view-css');
Javelin::initBehavior(
'differential-add-reviewers-and-ccs',
array(
'dynamic' => array(
'add-auditors-tokenizer' => array(
'actions' => array('add_auditors' => 1),
'src' => '/typeahead/common/users/',
'row' => 'add-auditors',
'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'),
'placeholder' => pht('Type a user name...'),
),
'add-ccs-tokenizer' => array(
'actions' => array('add_ccs' => 1),
'src' => '/typeahead/common/mailable/',
'row' => 'add-ccs',
'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'),
'placeholder' => pht('Type a user or mailing list...'),
),
),
'select' => 'audit-action',
));
Javelin::initBehavior('differential-feedback-preview', array(
'uri' => '/audit/preview/'.$commit->getID().'/',
'preview' => 'audit-preview',
'content' => 'audit-content',
'action' => 'audit-action',
'previewTokenizers' => array(
'auditors' => 'add-auditors-tokenizer',
'ccs' => 'add-ccs-tokenizer',
),
'inline' => 'inline-comment-preview',
'inlineuri' => '/diffusion/inline/preview/'.$commit->getPHID().'/',
));
$preview_panel = hsprintf(
'<div class="aphront-panel-preview aphront-panel-flush">
<div id="audit-preview">
<div class="aphront-panel-preview-loading-text">
Loading preview...
</div>
</div>
<div id="inline-comment-preview">
</div>
</div>');
// TODO: This is pretty awkward, unify the CSS between Diffusion and
// Differential better.
require_celerity_resource('differential-core-view-css');
$comment_box = id(new PHUIObjectBoxView())
->setHeader($header)
->appendChild($form);
return phutil_tag(
'div',
array(
'id' => $pane_id,
),
hsprintf(
'<div class="differential-add-comment-panel">%s%s%s</div>',
id(new PhabricatorAnchorView())
->setAnchorName('comment')
->setNavigationMarker(true)
->render(),
$comment_box,
$preview_panel));
}
/**
* Return a map of available audit actions for rendering into a <select />.
* This shows the user valid actions, and does not show nonsense/invalid
* actions (like closing an already-closed commit, or resigning from a commit
* you have no association with).
*/
private function getAuditActions(
PhabricatorRepositoryCommit $commit,
array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$user = $this->getRequest()->getUser();
$user_is_author = ($commit->getAuthorPHID() == $user->getPHID());
$user_request = null;
foreach ($audit_requests as $audit_request) {
if ($audit_request->getAuditorPHID() == $user->getPHID()) {
$user_request = $audit_request;
break;
}
}
$actions = array();
$actions[PhabricatorAuditActionConstants::COMMENT] = true;
$actions[PhabricatorAuditActionConstants::ADD_CCS] = true;
$actions[PhabricatorAuditActionConstants::ADD_AUDITORS] = true;
// We allow you to accept your own commits. A use case here is that you
// notice an issue with your own commit and "Raise Concern" as an indicator
// to other auditors that you're on top of the issue, then later resolve it
// and "Accept". You can not accept on behalf of projects or packages,
// however.
$actions[PhabricatorAuditActionConstants::ACCEPT] = true;
$actions[PhabricatorAuditActionConstants::CONCERN] = true;
// To resign, a user must have authority on some request and not be the
// commit's author.
if (!$user_is_author) {
$may_resign = false;
$authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
foreach ($audit_requests as $request) {
if (empty($authority_map[$request->getAuditorPHID()])) {
continue;
}
$may_resign = true;
break;
}
// If the user has already resigned, don't show "Resign...".
$status_resigned = PhabricatorAuditStatusConstants::RESIGNED;
if ($user_request) {
if ($user_request->getAuditStatus() == $status_resigned) {
$may_resign = false;
}
}
if ($may_resign) {
$actions[PhabricatorAuditActionConstants::RESIGN] = true;
}
}
$status_concern = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
$concern_raised = ($commit->getAuditStatus() == $status_concern);
$can_close_option = PhabricatorEnv::getEnvConfig(
'audit.can-author-close-audit');
if ($can_close_option && $user_is_author && $concern_raised) {
$actions[PhabricatorAuditActionConstants::CLOSE] = true;
}
foreach ($actions as $constant => $ignored) {
$actions[$constant] =
PhabricatorAuditActionConstants::getActionName($constant);
}
return $actions;
}
private function buildMergesTable(PhabricatorRepositoryCommit $commit) {
$drequest = $this->getDiffusionRequest();
$limit = 50;
$merges = array();
try {
$merges = $this->callConduitWithDiffusionRequest(
'diffusion.mergedcommitsquery',
array(
'commit' => $drequest->getCommit(),
'limit' => $limit + 1));
} catch (ConduitException $ex) {
if ($ex->getMessage() != 'ERR-UNSUPPORTED-VCS') {
throw $ex;
}
}
if (!$merges) {
return null;
}
$caption = null;
if (count($merges) > $limit) {
$merges = array_slice($merges, 0, $limit);
$caption =
"This commit merges more than {$limit} changes. Only the first ".
"{$limit} are shown.";
}
$history_table = new DiffusionHistoryTableView();
$history_table->setUser($this->getRequest()->getUser());
$history_table->setDiffusionRequest($drequest);
$history_table->setHistory($merges);
$history_table->loadRevisions();
$phids = $history_table->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$history_table->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader(pht('Merged Changes'));
$panel->setCaption($caption);
$panel->appendChild($history_table);
$panel->setNoBackground();
return $panel;
}
private function renderHeadsupActionList(
PhabricatorRepositoryCommit $commit,
PhabricatorRepository $repository) {
$request = $this->getRequest();
$user = $request->getUser();
$actions = id(new PhabricatorActionListView())
->setUser($user)
->setObject($commit)
->setObjectURI($request->getRequestURI());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$user,
$commit,
PhabricatorPolicyCapability::CAN_EDIT);
$uri = '/diffusion/'.$repository->getCallsign().'/commit/'.
$commit->getCommitIdentifier().'/edit/';
$action = id(new PhabricatorActionView())
->setName(pht('Edit Commit'))
->setHref($uri)
->setIcon('edit')
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit);
$actions->addAction($action);
require_celerity_resource('phabricator-object-selector-css');
require_celerity_resource('javelin-behavior-phabricator-object-selector');
$maniphest = 'PhabricatorApplicationManiphest';
if (PhabricatorApplication::isClassInstalled($maniphest)) {
$action = id(new PhabricatorActionView())
->setName(pht('Edit Maniphest Tasks'))
->setIcon('attach')
->setHref('/search/attach/'.$commit->getPHID().'/TASK/edge/')
->setWorkflow(true)
->setDisabled(!$can_edit);
$actions->addAction($action);
}
$action = id(new PhabricatorActionView())
->setName(pht('Download Raw Diff'))
->setHref($request->getRequestURI()->alter('diff', true))
->setIcon('download');
$actions->addAction($action);
return $actions;
}
private function buildRefs(DiffusionRequest $request) {
// this is git-only, so save a conduit round trip and just get out of
// here if the repository isn't git
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
$repository = $request->getRepository();
if ($repository->getVersionControlSystem() != $type_git) {
return null;
}
$results = $this->callConduitWithDiffusionRequest(
'diffusion.refsquery',
array('commit' => $request->getCommit()));
$ref_links = array();
foreach ($results as $ref_data) {
$ref_links[] = phutil_tag('a',
array('href' => $ref_data['href']),
$ref_data['ref']);
}
return phutil_implode_html(', ', $ref_links);
}
private function buildRawDiffResponse(DiffusionRequest $drequest) {
$raw_diff = $this->callConduitWithDiffusionRequest(
'diffusion.rawdiffquery',
array(
'commit' => $drequest->getCommit(),
'path' => $drequest->getPath()));
$file = PhabricatorFile::buildFromFileDataOrHash(
$raw_diff,
array(
'name' => $drequest->getCommit().'.diff',
));
return id(new AphrontRedirectResponse())->setURI($file->getBestURI());
}
private function renderAuditStatusView(array $audit_requests) {
assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest');
$phids = mpull($audit_requests, 'getAuditorPHID');
$this->loadHandles($phids);
$authority_map = array_fill_keys($this->auditAuthorityPHIDs, true);
$view = new PHUIStatusListView();
foreach ($audit_requests as $request) {
$item = new PHUIStatusItemView();
switch ($request->getAuditStatus()) {
case PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED:
$item->setIcon('open-blue', pht('Commented'));
break;
case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
$item->setIcon('warning-blue', pht('Audit Required'));
break;
case PhabricatorAuditStatusConstants::CONCERNED:
$item->setIcon('reject-red', pht('Concern Raised'));
break;
case PhabricatorAuditStatusConstants::ACCEPTED:
$item->setIcon('accept-green', pht('Accepted'));
break;
case PhabricatorAuditStatusConstants::AUDIT_REQUESTED:
$item->setIcon('warning-dark', pht('Audit Requested'));
break;
case PhabricatorAuditStatusConstants::RESIGNED:
$item->setIcon('open-dark', pht('Resigned'));
break;
case PhabricatorAuditStatusConstants::CLOSED:
$item->setIcon('accept-blue', pht('Closed'));
break;
case PhabricatorAuditStatusConstants::CC:
$item->setIcon('info-dark', pht('Subscribed'));
break;
default:
$item->setIcon(
'question-dark',
pht('%s?', $request->getAuditStatus()));
break;
}
$note = array();
foreach ($request->getAuditReasons() as $reason) {
$note[] = phutil_tag('div', array(), $reason);
}
$item->setNote($note);
$auditor_phid = $request->getAuditorPHID();
$target = $this->getHandle($auditor_phid)->renderLink();
$item->setTarget($target);
if (isset($authority_map[$auditor_phid])) {
$item->setHighlighted(true);
}
$view->addItem($item);
}
return $view;
}
private function linkBugtraq($corpus) {
$url = PhabricatorEnv::getEnvConfig('bugtraq.url');
if (!strlen($url)) {
return $corpus;
}
$regexes = PhabricatorEnv::getEnvConfig('bugtraq.logregex');
if (!$regexes) {
return $corpus;
}
$parser = id(new PhutilBugtraqParser())
->setBugtraqPattern("[[ {$url} | %BUGID% ]]")
->setBugtraqCaptureExpression(array_shift($regexes));
$select = array_shift($regexes);
if ($select) {
$parser->setBugtraqSelectExpression($select);
}
return $parser->processCorpus($corpus);
}
+
}
diff --git a/src/applications/diffusion/controller/DiffusionController.php b/src/applications/diffusion/controller/DiffusionController.php
index 7778375028..9d8f7c18cc 100644
--- a/src/applications/diffusion/controller/DiffusionController.php
+++ b/src/applications/diffusion/controller/DiffusionController.php
@@ -1,217 +1,452 @@
<?php
abstract class DiffusionController extends PhabricatorController {
protected $diffusionRequest;
+ public function willBeginExecution() {
+ $request = $this->getRequest();
+ $uri = $request->getRequestURI();
+
+ // Check if this is a VCS request, e.g. from "git clone", "hg clone", or
+ // "svn checkout". If it is, we jump off into repository serving code to
+ // process the request.
+
+ $regex = '@^/diffusion/(?P<callsign>[A-Z]+)(/|$)@';
+ $matches = null;
+ if (preg_match($regex, (string)$uri, $matches)) {
+ $vcs = null;
+
+ $content_type = $request->getHTTPHeader('Content-Type');
+
+ if ($request->getExists('__vcs__')) {
+ // This is magic to make it easier for us to debug stuff by telling
+ // users to run:
+ //
+ // curl http://example.phabricator.com/diffusion/X/?__vcs__=1
+ //
+ // ...to get a human-readable error.
+ $vcs = $request->getExists('__vcs__');
+ } else if ($request->getExists('service')) {
+ $service = $request->getStr('service');
+ // We get this initially for `info/refs`.
+ // Git also gives us a User-Agent like "git/1.8.2.3".
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
+ } else if ($content_type == 'application/x-git-upload-pack-request') {
+ // We get this for `git-upload-pack`.
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
+ } else if ($request->getExists('cmd')) {
+ // Mercurial also sends an Accept header like
+ // "application/mercurial-0.1", and a User-Agent like
+ // "mercurial/proto-1.0".
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL;
+ } else {
+ // Subversion also sends an initial OPTIONS request (vs GET/POST), and
+ // has a User-Agent like "SVN/1.8.3 (x86_64-apple-darwin11.4.2)
+ // serf/1.3.2".
+ $dav = $request->getHTTPHeader('DAV');
+ $dav = new PhutilURI($dav);
+ if ($dav->getDomain() === 'subversion.tigris.org') {
+ $vcs = PhabricatorRepositoryType::REPOSITORY_TYPE_SVN;
+ }
+ }
+
+ if ($vcs) {
+ return $this->processVCSRequest($matches['callsign']);
+ }
+ }
+
+ parent::willBeginExecution();
+ }
+
+ private function processVCSRequest($callsign) {
+
+ // TODO: Authenticate user.
+
+ $viewer = new PhabricatorUser();
+
+ $allow_public = PhabricatorEnv::getEnvConfig('policy.allow-public');
+ if (!$allow_public) {
+ if (!$viewer->isLoggedIn()) {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('You must log in to access repositories.'));
+ }
+ }
+
+ try {
+ $repository = id(new PhabricatorRepositoryQuery())
+ ->setViewer($viewer)
+ ->withCallsigns(array($callsign))
+ ->executeOne();
+ if (!$repository) {
+ return new PhabricatorVCSResponse(
+ 404,
+ pht('No such repository exists.'));
+ }
+ } catch (PhabricatorPolicyException $ex) {
+ if ($viewer->isLoggedIn()) {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('You do not have permission to access this repository.'));
+ } else {
+ return new PhabricatorVCSResponse(
+ 401,
+ pht('You must log in to access this repository.'));
+ }
+ }
+
+ $is_push = !$this->isReadOnlyRequest($repository);
+
+ switch ($repository->getServeOverHTTP()) {
+ case PhabricatorRepository::SERVE_READONLY:
+ if ($is_push) {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('This repository is read-only over HTTP.'));
+ }
+ break;
+ case PhabricatorRepository::SERVE_READWRITE:
+ if ($is_push) {
+ $can_push = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $repository,
+ DiffusionCapabilityPush::CAPABILITY);
+ if (!$can_push) {
+ if ($viewer->isLoggedIn()) {
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('You do not have permission to push to this repository.'));
+ } else {
+ return new PhabricatorVCSResponse(
+ 401,
+ pht('You must log in to push to this repository.'));
+ }
+ }
+ }
+ break;
+ case PhabricatorRepository::SERVE_OFF:
+ default:
+ return new PhabricatorVCSResponse(
+ 403,
+ pht('This repository is not available over HTTP.'));
+ }
+
+ switch ($repository->getVersionControlSystem()) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ return $this->serveGitRequest($repository);
+ default:
+ break;
+ }
+
+ return new PhabricatorVCSResponse(
+ 999,
+ pht('TODO: Implement meaningful responses.'));
+ }
+
+ private function isReadOnlyRequest(
+ PhabricatorRepository $repository) {
+ $request = $this->getRequest();
+ $method = $_SERVER['REQUEST_METHOD'];
+
+ // TODO: This implementation is safe by default, but very incomplete.
+
+ switch ($repository->getVersionControlSystem()) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
+ $service = $request->getStr('service');
+ $path = $this->getRequestDirectoryPath();
+ // NOTE: Service names are the reverse of what you might expect, as they
+ // are from the point of view of the server. The main read service is
+ // "git-upload-pack", and the main write service is "git-receive-pack".
+
+ if ($method == 'GET' &&
+ $path == '/info/refs' &&
+ $service == 'git-upload-pack') {
+ return true;
+ }
+
+ if ($path == '/git-upload-pack') {
+ return true;
+ }
+
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
+ $cmd = $request->getStr('cmd');
+ switch ($cmd) {
+ case 'capabilities':
+ return true;
+ default:
+ return false;
+ }
+ break;
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_SUBVERSION:
+ break;
+ }
+
+ return false;
+ }
+
public function willProcessRequest(array $data) {
if (isset($data['callsign'])) {
$drequest = DiffusionRequest::newFromAphrontRequestDictionary(
$data,
$this->getRequest());
$this->diffusionRequest = $drequest;
}
}
public function setDiffusionRequest(DiffusionRequest $request) {
$this->diffusionRequest = $request;
return $this;
}
protected function getDiffusionRequest() {
if (!$this->diffusionRequest) {
throw new Exception("No Diffusion request object!");
}
return $this->diffusionRequest;
}
public function buildCrumbs(array $spec = array()) {
$crumbs = $this->buildApplicationCrumbs();
$crumb_list = $this->buildCrumbList($spec);
foreach ($crumb_list as $crumb) {
$crumbs->addCrumb($crumb);
}
return $crumbs;
}
private function buildCrumbList(array $spec = array()) {
$spec = $spec + array(
'commit' => null,
'tags' => null,
'branches' => null,
'view' => null,
);
$crumb_list = array();
// On the home page, we don't have a DiffusionRequest.
if ($this->diffusionRequest) {
$drequest = $this->getDiffusionRequest();
$repository = $drequest->getRepository();
} else {
$drequest = null;
$repository = null;
}
if (!$repository) {
return $crumb_list;
}
$callsign = $repository->getCallsign();
$repository_name = 'r'.$callsign;
if (!$spec['commit'] && !$spec['tags'] && !$spec['branches']) {
$branch_name = $drequest->getBranch();
if ($branch_name) {
$repository_name .= ' ('.$branch_name.')';
}
}
$crumb = id(new PhabricatorCrumbView())
->setName($repository_name);
if (!$spec['view'] && !$spec['commit'] &&
!$spec['tags'] && !$spec['branches']) {
$crumb_list[] = $crumb;
return $crumb_list;
}
$crumb->setHref(
$drequest->generateURI(
array(
'action' => 'branch',
'path' => '/',
)));
$crumb_list[] = $crumb;
$raw_commit = $drequest->getRawCommit();
if ($spec['tags']) {
$crumb = new PhabricatorCrumbView();
if ($spec['commit']) {
$crumb->setName(
pht("Tags for %s", 'r'.$callsign.$raw_commit));
$crumb->setHref($drequest->generateURI(
array(
'action' => 'commit',
'commit' => $raw_commit,
)));
} else {
$crumb->setName(pht('Tags'));
}
$crumb_list[] = $crumb;
return $crumb_list;
}
if ($spec['branches']) {
$crumb = id(new PhabricatorCrumbView())
->setName(pht('Branches'));
$crumb_list[] = $crumb;
return $crumb_list;
}
if ($spec['commit']) {
$crumb = id(new PhabricatorCrumbView())
->setName("r{$callsign}{$raw_commit}")
->setHref("r{$callsign}{$raw_commit}");
$crumb_list[] = $crumb;
return $crumb_list;
}
$crumb = new PhabricatorCrumbView();
$view = $spec['view'];
switch ($view) {
case 'history':
$view_name = pht('History');
break;
case 'browse':
$view_name = pht('Browse');
break;
case 'lint':
$view_name = pht('Lint');
break;
case 'change':
$view_name = pht('Change');
break;
}
$crumb = id(new PhabricatorCrumbView())
->setName($view_name);
$crumb_list[] = $crumb;
return $crumb_list;
}
protected function callConduitWithDiffusionRequest(
$method,
array $params = array()) {
$user = $this->getRequest()->getUser();
$drequest = $this->getDiffusionRequest();
return DiffusionQuery::callConduitWithDiffusionRequest(
$user,
$drequest,
$method,
$params);
}
protected function getRepositoryControllerURI(
PhabricatorRepository $repository,
$path) {
return $this->getApplicationURI($repository->getCallsign().'/'.$path);
}
protected function renderPathLinks(DiffusionRequest $drequest, $action) {
$path = $drequest->getPath();
$path_parts = array_filter(explode('/', trim($path, '/')));
$divider = phutil_tag(
'span',
array(
'class' => 'phui-header-divider'),
'/');
$links = array();
if ($path_parts) {
$links[] = phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => $action,
'path' => '',
)),
),
'r'.$drequest->getRepository()->getCallsign());
$links[] = $divider;
$accum = '';
$last_key = last_key($path_parts);
foreach ($path_parts as $key => $part) {
$accum .= '/'.$part;
if ($key === $last_key) {
$links[] = $part;
} else {
$links[] = phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => $action,
'path' => $accum.'/',
)),
),
$part);
$links[] = $divider;
}
}
} else {
$links[] = 'r'.$drequest->getRepository()->getCallsign();
$links[] = $divider;
}
return $links;
}
+ /**
+ * @phutil-external-symbol class PhabricatorStartup
+ */
+ private function serveGitRequest(PhabricatorRepository $repository) {
+ $request = $this->getRequest();
+
+ $request_path = $this->getRequestDirectoryPath();
+ $repository_root = $repository->getLocalPath();
+
+ // Rebuild the query string to strip `__magic__` parameters and prevent
+ // issues where we might interpret inputs like "service=read&service=write"
+ // differently than the server does and pass it an unsafe command.
+ $query_data = $request->getPassthroughRequestParameters();
+ $query_string = http_build_query($query_data, '', '&');
+
+ // We're about to wipe out PATH with the rest of the environment, so
+ // resolve the binary first.
+ $bin = Filesystem::resolveBinary('git-http-backend');
+ if (!$bin) {
+ throw new Exception("Unable to find `git-http-backend` in PATH!");
+ }
+
+ $env = array(
+ 'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'],
+ 'QUERY_STRING' => $query_string,
+ 'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'],
+ 'REMOTE_USER' => '',
+ 'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
+ 'GIT_PROJECT_ROOT' => $repository_root,
+ 'GIT_HTTP_EXPORT_ALL' => '1',
+ 'PATH_INFO' => $request_path,
+ );
+
+ list($stdout) = id(new ExecFuture('%s', $bin))
+ ->setEnv($env, true)
+ ->write(PhabricatorStartup::getRawInput())
+ ->resolvex();
+
+ return id(new DiffusionGitResponse())->setGitData($stdout);
+ }
+
+ private function getRequestDirectoryPath() {
+ $request = $this->getRequest();
+ $request_path = $request->getRequestURI()->getPath();
+ return preg_replace('@^/diffusion/[A-Z]+@', '', $request_path);
+ }
+
+ protected function renderStatusMessage($title, $body) {
+ return id(new AphrontErrorView())
+ ->setSeverity(AphrontErrorView::SEVERITY_WARNING)
+ ->setTitle($title)
+ ->appendChild($body);
+ }
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php
index 6776a77e3d..8a8779fa99 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php
@@ -1,336 +1,455 @@
<?php
final class DiffusionRepositoryController extends DiffusionController {
public function shouldAllowPublic() {
return true;
}
public function processRequest() {
- $drequest = $this->diffusionRequest;
+ $drequest = $this->getDiffusionRequest();
+ $repository = $drequest->getRepository();
$content = array();
$crumbs = $this->buildCrumbs();
$content[] = $crumbs;
$content[] = $this->buildPropertiesTable($drequest->getRepository());
+ $phids = array();
- $history_results = $this->callConduitWithDiffusionRequest(
- 'diffusion.historyquery',
- array(
- 'commit' => $drequest->getCommit(),
- 'path' => $drequest->getPath(),
- 'offset' => 0,
- 'limit' => 15));
- $history = DiffusionPathChange::newFromConduit(
- $history_results['pathChanges']);
-
- $browse_results = DiffusionBrowseResultSet::newFromConduit(
- $this->callConduitWithDiffusionRequest(
- 'diffusion.browsequery',
+ try {
+ $history_results = $this->callConduitWithDiffusionRequest(
+ 'diffusion.historyquery',
array(
- 'path' => $drequest->getPath(),
'commit' => $drequest->getCommit(),
- )));
- $browse_paths = $browse_results->getPaths();
-
- $phids = array();
- foreach ($history as $item) {
- $data = $item->getCommitData();
- if ($data) {
- if ($data->getCommitDetail('authorPHID')) {
- $phids[$data->getCommitDetail('authorPHID')] = true;
- }
- if ($data->getCommitDetail('committerPHID')) {
- $phids[$data->getCommitDetail('committerPHID')] = true;
+ 'path' => $drequest->getPath(),
+ 'offset' => 0,
+ 'limit' => 15));
+ $history = DiffusionPathChange::newFromConduit(
+ $history_results['pathChanges']);
+
+ foreach ($history as $item) {
+ $data = $item->getCommitData();
+ if ($data) {
+ if ($data->getCommitDetail('authorPHID')) {
+ $phids[$data->getCommitDetail('authorPHID')] = true;
+ }
+ if ($data->getCommitDetail('committerPHID')) {
+ $phids[$data->getCommitDetail('committerPHID')] = true;
+ }
}
}
+ $history_exception = null;
+ } catch (Exception $ex) {
+ $history_results = null;
+ $history = null;
+ $history_exception = $ex;
}
- foreach ($browse_paths as $item) {
- $data = $item->getLastCommitData();
- if ($data) {
- if ($data->getCommitDetail('authorPHID')) {
- $phids[$data->getCommitDetail('authorPHID')] = true;
- }
- if ($data->getCommitDetail('committerPHID')) {
- $phids[$data->getCommitDetail('committerPHID')] = true;
+ try {
+ $browse_results = DiffusionBrowseResultSet::newFromConduit(
+ $this->callConduitWithDiffusionRequest(
+ 'diffusion.browsequery',
+ array(
+ 'path' => $drequest->getPath(),
+ 'commit' => $drequest->getCommit(),
+ )));
+ $browse_paths = $browse_results->getPaths();
+
+ foreach ($browse_paths as $item) {
+ $data = $item->getLastCommitData();
+ if ($data) {
+ if ($data->getCommitDetail('authorPHID')) {
+ $phids[$data->getCommitDetail('authorPHID')] = true;
+ }
+ if ($data->getCommitDetail('committerPHID')) {
+ $phids[$data->getCommitDetail('committerPHID')] = true;
+ }
}
}
+
+ $browse_exception = null;
+ } catch (Exception $ex) {
+ $browse_results = null;
+ $browse_paths = null;
+ $browse_exception = $ex;
}
+
$phids = array_keys($phids);
$handles = $this->loadViewerHandles($phids);
- $readme = $this->callConduitWithDiffusionRequest(
- 'diffusion.readmequery',
- array(
- 'paths' => $browse_results->getPathDicts()
+ if ($browse_results) {
+ $readme = $this->callConduitWithDiffusionRequest(
+ 'diffusion.readmequery',
+ array(
+ 'paths' => $browse_results->getPathDicts()
));
+ } else {
+ $readme = null;
+ }
- $history_table = new DiffusionHistoryTableView();
- $history_table->setUser($this->getRequest()->getUser());
- $history_table->setDiffusionRequest($drequest);
- $history_table->setHandles($handles);
- $history_table->setHistory($history);
- $history_table->loadRevisions();
- $history_table->setParents($history_results['parents']);
- $history_table->setIsHead(true);
-
- $callsign = $drequest->getRepository()->getCallsign();
- $all = phutil_tag(
- 'a',
- array(
- 'href' => $drequest->generateURI(
- array(
- 'action' => 'history',
- )),
- ),
- pht('View Full Commit History'));
-
- $panel = new AphrontPanelView();
- $panel->setHeader(pht("Recent Commits &middot; %s", $all));
- $panel->appendChild($history_table);
- $panel->setNoBackground();
-
- $content[] = $panel;
-
-
- $browse_table = new DiffusionBrowseTableView();
- $browse_table->setDiffusionRequest($drequest);
- $browse_table->setHandles($handles);
- $browse_table->setPaths($browse_paths);
- $browse_table->setUser($this->getRequest()->getUser());
-
- $browse_panel = new AphrontPanelView();
- $browse_panel->setHeader(phutil_tag(
- 'a',
- array('href' => $drequest->generateURI(array('action' => 'browse'))),
- pht('Browse Repository')));
- $browse_panel->appendChild($browse_table);
- $browse_panel->setNoBackground();
+ $content[] = $this->buildHistoryTable(
+ $history_results,
+ $history,
+ $history_exception,
+ $handles);
- $content[] = $browse_panel;
+ $content[] = $this->buildBrowseTable(
+ $browse_results,
+ $browse_paths,
+ $browse_exception,
+ $handles);
- $content[] = $this->buildTagListTable($drequest);
+ try {
+ $content[] = $this->buildTagListTable($drequest);
+ } catch (Exception $ex) {
+ if (!$repository->isImporting()) {
+ $content[] = $this->renderStatusMessage(
+ pht('Unable to Load Tags'),
+ $ex->getMessage());
+ }
+ }
- $content[] = $this->buildBranchListTable($drequest);
+ try {
+ $content[] = $this->buildBranchListTable($drequest);
+ } catch (Exception $ex) {
+ if (!$repository->isImporting()) {
+ $content[] = $this->renderStatusMessage(
+ pht('Unable to Load Branches'),
+ $ex->getMessage());
+ }
+ }
if ($readme) {
$box = new PHUIBoxView();
$box->setShadow(true);
$box->appendChild($readme);
$box->addPadding(PHUI::PADDING_LARGE);
$panel = new AphrontPanelView();
$panel->setHeader(pht('README'));
$panel->setNoBackground();
$panel->appendChild($box);
$content[] = $panel;
}
return $this->buildApplicationPage(
$content,
array(
'title' => $drequest->getRepository()->getName(),
'device' => true,
));
}
private function buildPropertiesTable(PhabricatorRepository $repository) {
$user = $this->getRequest()->getUser();
$header = id(new PHUIHeaderView())
->setHeader($repository->getName())
->setUser($user)
->setPolicyObject($repository);
+ if (!$repository->isTracked()) {
+ $header->setStatus('policy-noone', '', pht('Inactive'));
+ } else if ($repository->isImporting()) {
+ $header->setStatus('time', 'red', pht('Importing...'));
+ } else {
+ $header->setStatus('oh-ok', '', pht('Active'));
+ }
+
+
$actions = $this->buildActionList($repository);
$view = id(new PHUIPropertyListView())
->setUser($user);
$view->addProperty(pht('Callsign'), $repository->getCallsign());
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$view->addProperty(
pht('Clone URI'),
$repository->getPublicRemoteURI());
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$view->addProperty(
pht('Repository Root'),
$repository->getPublicRemoteURI());
break;
}
$description = $repository->getDetail('description');
if (strlen($description)) {
$description = PhabricatorMarkupEngine::renderOneObject(
$repository,
'description',
$user);
$view->addTextContent($description);
}
$view->setActionList($actions);
return id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($view);
}
private function buildBranchListTable(DiffusionRequest $drequest) {
if ($drequest->getBranch() !== null) {
$limit = 15;
$branches = DiffusionBranchInformation::newFromConduit(
$this->callConduitWithDiffusionRequest(
'diffusion.branchquery',
array(
'limit' => $limit
)));
if (!$branches) {
return null;
}
$more_branches = (count($branches) > $limit);
$branches = array_slice($branches, 0, $limit);
$commits = id(new PhabricatorAuditCommitQuery())
->withIdentifiers(
$drequest->getRepository()->getID(),
mpull($branches, 'getHeadCommitIdentifier'))
->needCommitData(true)
->execute();
$table = new DiffusionBranchTableView();
$table->setDiffusionRequest($drequest);
$table->setBranches($branches);
$table->setCommits($commits);
$table->setUser($this->getRequest()->getUser());
$panel = new AphrontPanelView();
$panel->setHeader(pht('Branches'));
$panel->setNoBackground();
if ($more_branches) {
$panel->setCaption(pht('Showing %d branches.', $limit));
}
$panel->addButton(
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'branches',
)),
'class' => 'grey button',
),
pht("Show All Branches \xC2\xBB")));
$panel->appendChild($table);
return $panel;
}
return null;
}
private function buildTagListTable(DiffusionRequest $drequest) {
$tag_limit = 15;
$tags = array();
try {
$tags = DiffusionRepositoryTag::newFromConduit(
$this->callConduitWithDiffusionRequest(
'diffusion.tagsquery',
array(
// On the home page, we want to find tags on any branch.
'commit' => null,
'limit' => $tag_limit + 1,
)));
} catch (ConduitException $e) {
if ($e->getMessage() != 'ERR-UNSUPPORTED-VCS') {
throw $e;
}
}
if (!$tags) {
return null;
}
$more_tags = (count($tags) > $tag_limit);
$tags = array_slice($tags, 0, $tag_limit);
$commits = id(new PhabricatorAuditCommitQuery())
->withIdentifiers(
$drequest->getRepository()->getID(),
mpull($tags, 'getCommitIdentifier'))
->needCommitData(true)
->execute();
$view = new DiffusionTagListView();
$view->setDiffusionRequest($drequest);
$view->setTags($tags);
$view->setUser($this->getRequest()->getUser());
$view->setCommits($commits);
$phids = $view->getRequiredHandlePHIDs();
$handles = $this->loadViewerHandles($phids);
$view->setHandles($handles);
$panel = new AphrontPanelView();
$panel->setHeader(pht('Tags'));
$panel->setNoBackground(true);
if ($more_tags) {
$panel->setCaption(pht('Showing the %d most recent tags.', $tag_limit));
}
$panel->addButton(
phutil_tag(
'a',
array(
'href' => $drequest->generateURI(
array(
'action' => 'tags',
)),
'class' => 'grey button',
),
pht("Show All Tags \xC2\xBB")));
$panel->appendChild($view);
return $panel;
}
private function buildActionList(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view_uri = $this->getApplicationURI($repository->getCallsign().'/');
$edit_uri = $this->getApplicationURI($repository->getCallsign().'/edit/');
$view = id(new PhabricatorActionListView())
->setUser($viewer)
->setObject($repository)
->setObjectURI($view_uri);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Repository'))
->setIcon('edit')
->setHref($edit_uri)
->setWorkflow(!$can_edit)
->setDisabled(!$can_edit));
return $view;
}
+ private function buildHistoryTable(
+ $history_results,
+ $history,
+ $history_exception,
+ array $handles) {
+
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+ $drequest = $this->getDiffusionRequest();
+ $repository = $drequest->getRepository();
+
+ if ($history_exception) {
+ if ($repository->isImporting()) {
+ return $this->renderStatusMessage(
+ pht('Still Importing...'),
+ pht(
+ 'This repository is still importing. History is not yet '.
+ 'available.'));
+ } else {
+ return $this->renderStatusMessage(
+ pht('Unable to Retrieve History'),
+ $history_exception->getMessage());
+ }
+ }
+
+ $history_table = id(new DiffusionHistoryTableView())
+ ->setUser($viewer)
+ ->setDiffusionRequest($drequest)
+ ->setHandles($handles)
+ ->setHistory($history);
+
+ // TODO: Super sketchy.
+ $history_table->loadRevisions();
+
+ if ($history_results) {
+ $history_table->setParents($history_results['parents']);
+ }
+
+ $history_table->setIsHead(true);
+
+ $callsign = $drequest->getRepository()->getCallsign();
+ $all = phutil_tag(
+ 'a',
+ array(
+ 'href' => $drequest->generateURI(
+ array(
+ 'action' => 'history',
+ )),
+ ),
+ pht('View Full Commit History'));
+
+ $panel = new AphrontPanelView();
+ $panel->setHeader(pht("Recent Commits &middot; %s", $all));
+ $panel->appendChild($history_table);
+ $panel->setNoBackground();
+
+ return $panel;
+ }
+
+ private function buildBrowseTable(
+ $browse_results,
+ $browse_paths,
+ $browse_exception,
+ array $handles) {
+
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+ $drequest = $this->getDiffusionRequest();
+ $repository = $drequest->getRepository();
+
+ if ($browse_exception) {
+ if ($repository->isImporting()) {
+ // The history table renders a useful message.
+ return null;
+ } else {
+ return $this->renderStatusMessage(
+ pht('Unable to Retrieve Paths'),
+ $browse_exception->getMessage());
+ }
+ }
+
+ $browse_table = id(new DiffusionBrowseTableView())
+ ->setUser($viewer)
+ ->setDiffusionRequest($drequest)
+ ->setHandles($handles);
+ if ($browse_paths) {
+ $browse_table->setPaths($browse_paths);
+ } else {
+ $browse_table->setPaths(array());
+ }
+
+ $browse_uri = $drequest->generateURI(array('action' => 'browse'));
+
+ $browse_panel = new AphrontPanelView();
+ $browse_panel->setHeader(
+ phutil_tag(
+ 'a',
+ array('href' => $browse_uri),
+ pht('Browse Repository')));
+ $browse_panel->appendChild($browse_table);
+ $browse_panel->setNoBackground();
+
+ return $browse_panel;
+ }
+
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
index c32d08f128..154a7f17c4 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryCreateController.php
@@ -1,689 +1,753 @@
<?php
final class DiffusionRepositoryCreateController
extends DiffusionRepositoryEditController {
private $edit;
private $repository;
public function willProcessRequest(array $data) {
parent::willProcessRequest($data);
$this->edit = idx($data, 'edit');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
// NOTE: We can end up here via either "Create Repository" or via
// "Edit Remote". In the latter case, we show only a few of the pages.
$repository = null;
if ($this->edit) {
$repository = $this->getDiffusionRequest()->getRepository();
// Make sure we have CAN_EDIT.
PhabricatorPolicyFilter::requireCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$this->setRepository($repository);
$cancel_uri = $this->getRepositoryControllerURI($repository, 'edit/');
} else {
+ $this->requireApplicationCapability(
+ DiffusionCapabilityCreateRepositories::CAPABILITY);
+
$cancel_uri = $this->getApplicationURI();
}
$form = id(new PHUIPagedFormView())
->setUser($viewer)
->setCancelURI($cancel_uri);
switch ($this->edit) {
case 'remote':
$title = pht('Edit Remote');
$form
->addPage('remote-uri', $this->buildRemoteURIPage())
->addPage('auth', $this->buildAuthPage());
break;
default:
$title = pht('Import Repository');
$form
->addPage('vcs', $this->buildVCSPage())
->addPage('name', $this->buildNamePage())
->addPage('remote-uri', $this->buildRemoteURIPage())
->addPage('auth', $this->buildAuthPage())
->addPage('done', $this->buildDonePage());
break;
}
if ($request->isFormPost()) {
$form->readFromRequest($request);
if ($form->isComplete()) {
+ $is_create = ($this->edit === null);
- if ($this->edit != 'remote') {
- // TODO: This exception is heartwarming but should probably take more
- // substantive actions.
- throw new Exception("GOOD JOB AT FORM");
+ if ($is_create) {
+ $repository = PhabricatorRepository::initializeNewRepository(
+ $viewer);
}
$template = id(new PhabricatorRepositoryTransaction());
+ $type_name = PhabricatorRepositoryTransaction::TYPE_NAME;
+ $type_vcs = PhabricatorRepositoryTransaction::TYPE_VCS;
+ $type_activate = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
+ $type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH;
$type_remote_uri = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
$type_ssh_login = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN;
$type_ssh_key = PhabricatorRepositoryTransaction::TYPE_SSH_KEY;
$type_ssh_keyfile = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE;
$type_http_login = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN;
$type_http_pass = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS;
$xactions = array();
+ // If we're creating a new repository, set all this core stuff.
+ if ($is_create) {
+ $callsign = $form->getPage('name')
+ ->getControl('callsign')->getValue();
+
+ // We must set this to a unique value to save the repository
+ // initially, and it's immutable, so we don't bother using
+ // transactions to apply this change.
+ $repository->setCallsign($callsign);
+
+ // Put the repository in "Importing" mode until we finish
+ // parsing it.
+ $repository->setDetail('importing', true);
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_name)
+ ->setNewValue(
+ $form->getPage('name')->getControl('name')->getValue());
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_vcs)
+ ->setNewValue(
+ $form->getPage('vcs')->getControl('vcs')->getValue());
+
+ $activate = $form->getPage('done')
+ ->getControl('activate')->getValue();
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_activate)
+ ->setNewValue(
+ ($activate == 'start'));
+
+ $default_local_path = PhabricatorEnv::getEnvConfig(
+ 'repository.default-local-path');
+
+ $default_local_path = rtrim($default_local_path, '/');
+ $default_local_path = $default_local_path.'/'.$callsign.'/';
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_local_path)
+ ->setNewValue($default_local_path);
+ }
+
$xactions[] = id(clone $template)
->setTransactionType($type_remote_uri)
->setNewValue(
$form->getPage('remote-uri')->getControl('remoteURI')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_login)
->setNewValue(
$form->getPage('auth')->getControl('ssh-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_key)
->setNewValue(
$form->getPage('auth')->getControl('ssh-key')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_keyfile)
->setNewValue(
$form->getPage('auth')->getControl('ssh-keyfile')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_login)
->setNewValue(
$form->getPage('auth')->getControl('http-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_pass)
->setNewValue(
$form->getPage('auth')->getControl('http-pass')->getValue());
id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($repository, $xactions);
$repo_uri = $this->getRepositoryControllerURI($repository, 'edit/');
return id(new AphrontRedirectResponse())->setURI($repo_uri);
}
} else {
$dict = array();
if ($repository) {
$dict = array(
'remoteURI' => $repository->getRemoteURI(),
'ssh-login' => $repository->getDetail('ssh-login'),
'ssh-key' => $repository->getDetail('ssh-key'),
'ssh-keyfile' => $repository->getDetail('ssh-keyfile'),
'http-login' => $repository->getDetail('http-login'),
'http-pass' => $repository->getDetail('http-pass'),
);
}
$form->readFromObject($dict);
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($title));
return $this->buildApplicationPage(
array(
$crumbs,
$form,
),
array(
'title' => $title,
'device' => true,
));
}
/* -( Page: VCS Type )----------------------------------------------------- */
private function buildVCSPage() {
return id(new PHUIFormPageView())
->setPageName(pht('Repository Type'))
->setUser($this->getRequest()->getUser())
->setValidateFormPageCallback(array($this, 'validateVCSPage'))
->addControl(
id(new AphrontFormRadioButtonControl())
->setName('vcs')
->setLabel(pht('Type'))
->addButton(
PhabricatorRepositoryType::REPOSITORY_TYPE_GIT,
pht('Git'),
pht(
'Import a Git repository (for example, a repository hosted '.
'on GitHub).'))
->addButton(
PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL,
pht('Mercurial'),
pht(
'Import a Mercurial repository (for example, a repository '.
'hosted on Bitbucket).'))
->addButton(
PhabricatorRepositoryType::REPOSITORY_TYPE_SVN,
pht('Subversion'),
pht('Import a Subversion repository.'))
->addButton(
PhabricatorRepositoryType::REPOSITORY_TYPE_PERFORCE,
pht('Perforce'),
pht(
'Perforce is not directly supported, but you can import '.
'a Perforce repository as a Git repository using %s.',
phutil_tag(
'a',
array(
'href' =>
'http://www.perforce.com/product/components/git-fusion',
'target' => '_blank',
),
pht('Perforce Git Fusion'))),
'disabled',
$disabled = true));
}
public function validateVCSPage(PHUIFormPageView $page) {
$valid = array(
PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => true,
PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => true,
PhabricatorRepositoryType::REPOSITORY_TYPE_SVN => true,
);
$c_vcs = $page->getControl('vcs');
$v_vcs = $c_vcs->getValue();
if (!$v_vcs) {
$c_vcs->setError(pht('Required'));
$page->addPageError(
pht('You must select a version control system.'));
} else if (empty($valid[$v_vcs])) {
$c_vcs->setError(pht('Invalid'));
$page->addPageError(
pht('You must select a valid version control system.'));
}
return $c_vcs->isValid();
}
/* -( Page: Name and Callsign )-------------------------------------------- */
private function buildNamePage() {
return id(new PHUIFormPageView())
->setUser($this->getRequest()->getUser())
->setPageName(pht('Repository Name and Location'))
->setValidateFormPageCallback(array($this, 'validateNamePage'))
->addRemarkupInstructions(
pht(
'**Choose a human-readable name for this repository**, like '.
'"CompanyName Mobile App" or "CompanyName Backend Server". You '.
'can change this later.'))
->addControl(
id(new AphrontFormTextControl())
->setName('name')
->setLabel(pht('Name'))
->setCaption(pht('Human-readable repository name.')))
->addRemarkupInstructions(
pht(
'**Choose a "Callsign" for the repository.** This is a short, '.
'unique string which identifies commits elsewhere in Phabricator. '.
'For example, you might use `M` for your mobile app repository '.
'and `B` for your backend repository.'.
"\n\n".
'**Callsigns must be UPPERCASE**, and can not be edited after the '.
'repository is created. Generally, you should choose short '.
'callsigns.'))
->addControl(
id(new AphrontFormTextControl())
->setName('callsign')
->setLabel(pht('Callsign'))
->setCaption(pht('Short UPPERCASE identifier.')));
}
public function validateNamePage(PHUIFormPageView $page) {
$c_name = $page->getControl('name');
$v_name = $c_name->getValue();
if (!strlen($v_name)) {
$c_name->setError(pht('Required'));
$page->addPageError(
pht('You must choose a name for this repository.'));
}
$c_call = $page->getControl('callsign');
$v_call = $c_call->getValue();
if (!strlen($v_call)) {
$c_call->setError(pht('Required'));
$page->addPageError(
pht('You must choose a callsign for this repository.'));
} else if (!preg_match('/^[A-Z]+$/', $v_call)) {
$c_call->setError(pht('Invalid'));
$page->addPageError(
pht('The callsign must contain only UPPERCASE letters.'));
} else {
$exists = false;
try {
$repo = id(new PhabricatorRepositoryQuery())
->setViewer($this->getRequest()->getUser())
->withCallsigns(array($v_call))
->executeOne();
$exists = (bool)$repo;
} catch (PhabricatorPolicyException $ex) {
$exists = true;
}
if ($exists) {
$c_call->setError(pht('Not Unique'));
$page->addPageError(
pht(
'Another repository already uses that callsign. You must choose '.
'a unique callsign.'));
}
}
return $c_name->isValid() &&
$c_call->isValid();
}
/* -( Page: Remote URI )--------------------------------------------------- */
private function buildRemoteURIPage() {
return id(new PHUIFormPageView())
->setUser($this->getRequest()->getUser())
->setPageName(pht('Repository Remote URI'))
->setValidateFormPageCallback(array($this, 'validateRemoteURIPage'))
->setAdjustFormPageCallback(array($this, 'adjustRemoteURIPage'))
->addControl(
id(new AphrontFormTextControl())
->setName('remoteURI'));
}
public function adjustRemoteURIPage(PHUIFormPageView $page) {
$form = $page->getForm();
$is_git = false;
$is_svn = false;
$is_mercurial = false;
if ($this->getRepository()) {
$vcs = $this->getRepository()->getVersionControlSystem();
} else {
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
}
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$is_git = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$is_svn = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$is_mercurial = true;
break;
default:
throw new Exception("Unsupported VCS!");
}
$has_local = ($is_git || $is_mercurial);
if ($is_git) {
$uri_label = pht('Remote URI');
$instructions = pht(
'Enter the URI to clone this Git repository from. It should usually '.
'look like one of these examples:'.
"\n\n".
"| Example Git Remote URIs |\n".
"| ----------------------- |\n".
"| `git@github.com:example/example.git` |\n".
"| `ssh://user@host.com/git/example.git` |\n".
"| `file:///local/path/to/repo` |\n".
"| `https://example.com/repository.git` |\n");
} else if ($is_mercurial) {
$uri_label = pht('Remote URI');
$instructions = pht(
'Enter the URI to clone this Mercurial repository from. It should '.
'usually look like one of these examples:'.
"\n\n".
"| Example Mercurial Remote URIs |\n".
"| ----------------------- |\n".
"| `ssh://hg@bitbucket.org/example/repository` |\n".
"| `file:///local/path/to/repo` |\n");
} else if ($is_svn) {
$uri_label = pht('Repository Root');
$instructions = pht(
'Enter the **Repository Root** for this Subversion repository. '.
'You can figure this out by running `svn info` in a working copy '.
'and looking at the value in the `Repository Root` field. It '.
'should be a URI and will usually look like these:'.
"\n\n".
"| Example Subversion Repository Root URIs |\n".
"| ------------------------------ |\n".
"| `http://svn.example.org/svnroot/` |\n".
"| `svn+ssh://svn.example.com/svnroot/` |\n".
"| `svn://svn.example.net/svnroot/` |\n".
"| `file:///local/path/to/svnroot/` |\n".
"\n\n".
"Make sure you specify the root of the repository, not a ".
"subdirectory.");
} else {
throw new Exception("Unsupported VCS!");
}
$page->addRemarkupInstructions($instructions, 'remoteURI');
$page->getControl('remoteURI')->setLabel($uri_label);
}
public function validateRemoteURIPage(PHUIFormPageView $page) {
$c_remote = $page->getControl('remoteURI');
$v_remote = $c_remote->getValue();
if (!strlen($v_remote)) {
$c_remote->setError(pht('Required'));
$page->addPageError(
pht("You must specify a URI."));
} else {
$proto = $this->getRemoteURIProtocol($v_remote);
if ($proto === 'file') {
if (!preg_match('@^file:///@', $v_remote)) {
$c_remote->setError(pht('Invalid'));
$page->addPageError(
pht(
"URIs using the 'file://' protocol should have three slashes ".
"(e.g., 'file:///absolute/path/to/file'). You only have two. ".
"Add another one."));
}
}
+ // Catch confusion between Git/SCP-style URIs and normal URIs. See T3619
+ // for discussion. This is usually a user adding "ssh://" to an implicit
+ // SSH Git URI.
+ if ($proto == 'ssh') {
+ if (preg_match('(^[^:@]+://[^/:]+:[^\d])', $v_remote)) {
+ $c_remote->setError(pht('Invalid'));
+ $page->addPageError(
+ pht(
+ "The Remote URI is not formatted correctly. Remote URIs ".
+ "with an explicit protocol should be in the form ".
+ "'proto://domain/path', not 'proto://domain:/path'. ".
+ "The ':/path' syntax is only valid in SCP-style URIs."));
+ }
+ }
+
switch ($proto) {
case 'ssh':
case 'http':
case 'https':
case 'file':
case 'git':
case 'svn':
case 'svn+ssh':
break;
default:
$c_remote->setError(pht('Invalid'));
$page->addPageError(
pht(
"The URI protocol is unrecognized. It should begin ".
"'ssh://', 'http://', 'https://', 'file://', 'git://', ".
"'svn://', 'svn+ssh://', or be in the form ".
"'git@domain.com:path'."));
break;
}
}
return $c_remote->isValid();
}
/* -( Page: Authentication )----------------------------------------------- */
public function buildAuthPage() {
return id(new PHUIFormPageView())
->setPageName(pht('Authentication'))
->setUser($this->getRequest()->getUser())
->setAdjustFormPageCallback(array($this, 'adjustAuthPage'))
->addControl(
id(new AphrontFormTextControl())
->setName('ssh-login')
->setLabel('SSH User'))
->addControl(
id(new AphrontFormTextAreaControl())
->setName('ssh-key')
->setLabel('SSH Private Key')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setCaption(
hsprintf('Specify the entire private key, <em>or</em>...')))
->addControl(
id(new AphrontFormTextControl())
->setName('ssh-keyfile')
->setLabel('SSH Private Key Path')
->setCaption(
'...specify a path on disk where the daemon should '.
'look for a private key.'))
->addControl(
id(new AphrontFormTextControl())
->setName('http-login')
->setLabel('Username'))
->addControl(
id(new AphrontFormPasswordControl())
->setName('http-pass')
->setLabel('Password'));
}
public function adjustAuthPage($page) {
$form = $page->getForm();
$remote_uri = $form->getPage('remote-uri')
->getControl('remoteURI')
->getValue();
if ($this->getRepository()) {
$vcs = $this->getRepository()->getVersionControlSystem();
} else {
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
}
$proto = $this->getRemoteURIProtocol($remote_uri);
$remote_user = $this->getRemoteURIUser($remote_uri);
$page->getControl('ssh-login')->setHidden(true);
$page->getControl('ssh-key')->setHidden(true);
$page->getControl('ssh-keyfile')->setHidden(true);
$page->getControl('http-login')->setHidden(true);
$page->getControl('http-pass')->setHidden(true);
if ($this->isSSHProtocol($proto)) {
$page->getControl('ssh-login')->setHidden(false);
$page->getControl('ssh-key')->setHidden(false);
$page->getControl('ssh-keyfile')->setHidden(false);
$c_login = $page->getControl('ssh-login');
if (!strlen($c_login->getValue())) {
$c_login->setValue($remote_user);
}
$page->addRemarkupInstructions(
pht(
'Enter the username and private key to use to connect to the '.
'the repository hosted at:'.
"\n\n".
" lang=text\n".
" %s".
"\n\n".
'You can either copy/paste the entire private key, or put it '.
'somewhere on disk and provide the path to it.',
$remote_uri),
'ssh-login');
} else if ($this->isUsernamePasswordProtocol($proto)) {
$page->getControl('http-login')->setHidden(false);
$page->getControl('http-pass')->setHidden(false);
$page->addRemarkupInstructions(
pht(
'Enter the a username and pasword used to connect to the '.
'repository hosted at:'.
"\n\n".
" lang=text\n".
" %s".
"\n\n".
"If this repository does not require a username or password, ".
"you can leave these fields blank.",
$remote_uri),
'http-login');
} else if ($proto == 'file') {
$page->addRemarkupInstructions(
pht(
'You do not need to configure any authentication options for '.
'repositories accessed over the `file://` protocol. Continue '.
'to the next step.'),
'ssh-login');
} else {
throw new Exception("Unknown URI protocol!");
}
}
public function validateAuthPage(PHUIFormPageView $page) {
$form = $page->getForm();
$remote_uri = $form->getPage('remote')->getControl('remoteURI')->getValue();
$proto = $this->getRemoteURIProtocol($remote_uri);
if ($this->isSSHProtocol($proto)) {
$c_user = $page->getControl('ssh-login');
$c_key = $page->getControl('ssh-key');
$c_file = $page->getControl('ssh-keyfile');
$v_user = $c_user->getValue();
$v_key = $c_key->getValue();
$v_file = $c_file->getValue();
if (!strlen($v_user)) {
$c_user->setError(pht('Required'));
$page->addPageError(
pht('You must provide an SSH login username to connect over SSH.'));
}
if (!strlen($v_key) && !strlen($v_file)) {
$c_key->setError(pht('No Key'));
$c_file->setError(pht('No Key'));
$page->addPageError(
pht(
'You must provide either a private key or the path to a private '.
'key to connect over SSH.'));
} else if (strlen($v_key) && strlen($v_file)) {
$c_key->setError(pht('Ambiguous'));
$c_file->setError(pht('Ambiguous'));
$page->addPageError(
pht(
'Provide either a private key or the path to a private key, not '.
'both.'));
} else if (!preg_match('/PRIVATE KEY/', $v_key)) {
$c_key->setError(pht('Invalid'));
$page->addPageError(
pht(
'The private key you provided is missing the PRIVATE KEY header. '.
'You should include the header and footer. (Did you provide a '.
'public key by mistake?)'));
}
return $c_user->isValid() &&
$c_key->isValid() &&
$c_file->isValid();
} else if ($this->isUsernamePasswordProtocol($proto)) {
return true;
} else {
return true;
}
}
/* -( Page: Done )--------------------------------------------------------- */
private function buildDonePage() {
return id(new PHUIFormPageView())
->setPageName(pht('Repository Ready!'))
->setValidateFormPageCallback(array($this, 'validateDonePage'))
->setUser($this->getRequest()->getUser())
->addControl(
id(new AphrontFormRadioButtonControl())
->setName('activate')
->setLabel(pht('Start Now'))
->addButton(
'start',
pht('Start Import Now'),
pht(
'Start importing the repository right away. This will import '.
'the entire repository using default settings.'))
->addButton(
'wait',
pht('Configure More Options First'),
pht(
'Configure more options before beginning the repository '.
- 'import. This will let you fine-tune settings.. You can '.
+ 'import. This will let you fine-tune settings. You can '.
'start the import whenever you are ready.')));
}
public function validateDonePage(PHUIFormPageView $page) {
$c_activate = $page->getControl('activate');
$v_activate = $c_activate->getValue();
if ($v_activate != 'start' && $v_activate != 'wait') {
$c_activate->setError(pht('Required'));
$page->addPageError(
pht('Make a choice about repository activation.'));
}
return $c_activate->isValid();
}
/* -( Internal )----------------------------------------------------------- */
private function getRemoteURIProtocol($raw_uri) {
$uri = new PhutilURI($raw_uri);
if ($uri->getProtocol()) {
return strtolower($uri->getProtocol());
}
$git_uri = new PhutilGitURI($raw_uri);
if (strlen($git_uri->getDomain()) && strlen($git_uri->getPath())) {
return 'ssh';
}
return null;
}
private function getRemoteURIUser($raw_uri) {
$uri = new PhutilURI($raw_uri);
if ($uri->getUser()) {
return $uri->getUser();
}
$git_uri = new PhutilGitURI($raw_uri);
if (strlen($git_uri->getDomain()) && strlen($git_uri->getPath())) {
return $git_uri->getUser();
}
return null;
}
private function isSSHProtocol($proto) {
return ($proto == 'git' || $proto == 'ssh' || $proto == 'svn+ssh');
}
private function isUsernamePasswordProtocol($proto) {
return ($proto == 'http' || $proto == 'https' || $proto == 'svn');
}
private function setRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
private function getRepository() {
return $this->repository;
}
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryDefaultController.php b/src/applications/diffusion/controller/DiffusionRepositoryDefaultController.php
new file mode 100644
index 0000000000..e939d0e54b
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionRepositoryDefaultController.php
@@ -0,0 +1,11 @@
+<?php
+
+final class DiffusionRepositoryDefaultController extends DiffusionController {
+
+ public function processRequest() {
+ // NOTE: This controller is just here to make sure we call
+ // willBeginExecution() on any /diffusion/X/ URI, so we can intercept
+ // `git`, `hg` and `svn` HTTP protocol requests.
+ return new Aphront404Response();
+ }
+}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php
index 0734d52088..9cd546c92a 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditBranchesController.php
@@ -1,146 +1,150 @@
<?php
final class DiffusionRepositoryEditBranchesController
extends DiffusionRepositoryEditController {
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$drequest = $this->diffusionRequest;
$repository = $drequest->getRepository();
$repository = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($repository->getID()))
->executeOne();
if (!$repository) {
return new Aphront404Response();
}
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
throw new Exception(
pht('Subversion does not support branches!'));
default:
throw new Exception(
pht('Repository has unknown version control system!'));
}
$edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
$v_default = $repository->getHumanReadableDetail('default-branch');
- $v_track = $repository->getHumanReadableDetail('branch-filter');
- $v_autoclose = $repository->getHumanReadableDetail('close-commits-filter');
+ $v_track = $repository->getHumanReadableDetail(
+ 'branch-filter',
+ array());
+ $v_autoclose = $repository->getHumanReadableDetail(
+ 'close-commits-filter',
+ array());
if ($request->isFormPost()) {
$v_default = $request->getStr('default');
$v_track = $request->getStrList('track');
$v_autoclose = $request->getStrList('autoclose');
$xactions = array();
$template = id(new PhabricatorRepositoryTransaction());
$type_default = PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH;
$type_track = PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY;
$type_autoclose = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY;
$xactions[] = id(clone $template)
->setTransactionType($type_default)
->setNewValue($v_default);
$xactions[] = id(clone $template)
->setTransactionType($type_track)
->setNewValue($v_track);
$xactions[] = id(clone $template)
->setTransactionType($type_autoclose)
->setNewValue($v_autoclose);
id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($repository, $xactions);
return id(new AphrontRedirectResponse())->setURI($edit_uri);
}
$content = array();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Edit Branches')));
$title = pht('Edit Branches (%s)', $repository->getName());
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($repository)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->appendRemarkupInstructions(
pht(
'You can choose a **Default Branch** for viewing this repository.'.
"\n\n".
'If you want to import only some branches into Diffusion, you can '.
'list them in **Track Only**. Other branches will be ignored. If '.
'you do not specify any branches, all branches are tracked.'.
"\n\n".
'If you have **Autoclose** enabled, Phabricator can close tasks and '.
'revisions when corresponding commits are pushed to the repository. '.
'If you want to autoclose objects only when commits appear on '.
'specific branches, you can list those branches in **Autoclose '.
'Only**. By default, all branches autoclose objects.'))
->appendChild(
id(new AphrontFormTextControl())
->setName('default')
->setLabel(pht('Default Branch'))
->setValue($v_default)
->setCaption(
pht('Example: %s', phutil_tag('tt', array(), 'develop'))))
->appendChild(
id(new AphrontFormTextControl())
->setName('track')
->setLabel(pht('Track Only'))
->setValue($v_track)
->setCaption(
pht('Example: %s', phutil_tag('tt', array(), 'master, develop'))))
->appendChild(
id(new AphrontFormTextControl())
->setName('autoclose')
->setLabel(pht('Autoclose Only'))
->setValue($v_autoclose)
->setCaption(
pht('Example: %s', phutil_tag('tt', array(), 'master, release'))))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save Branches'))
->addCancelButton($edit_uri));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setForm($form);
return $this->buildApplicationPage(
array(
$crumbs,
$form_box,
),
array(
'title' => $title,
'device' => true,
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php
new file mode 100644
index 0000000000..5a47b08d1e
--- /dev/null
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditHostingController.php
@@ -0,0 +1,253 @@
+<?php
+
+final class DiffusionRepositoryEditHostingController
+ extends DiffusionRepositoryEditController {
+
+ private $serve;
+
+ public function willProcessRequest(array $data) {
+ parent::willProcessRequest($data);
+ $this->serve = idx($data, 'serve');
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+ $drequest = $this->diffusionRequest;
+ $repository = $drequest->getRepository();
+
+ $repository = id(new PhabricatorRepositoryQuery())
+ ->setViewer($user)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->withIDs(array($repository->getID()))
+ ->executeOne();
+ if (!$repository) {
+ return new Aphront404Response();
+ }
+
+ if (!$this->serve) {
+ return $this->handleHosting($repository);
+ } else {
+ return $this->handleProtocols($repository);
+ }
+ }
+
+ public function handleHosting(PhabricatorRepository $repository) {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $v_hosting = $repository->isHosted();
+
+ $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
+ $next_uri = $this->getRepositoryControllerURI($repository, 'edit/serve/');
+
+ if ($request->isFormPost()) {
+ $v_hosting = $request->getBool('hosting');
+
+ $xactions = array();
+ $template = id(new PhabricatorRepositoryTransaction());
+
+ $type_hosting = PhabricatorRepositoryTransaction::TYPE_HOSTING;
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_hosting)
+ ->setNewValue($v_hosting);
+
+ id(new PhabricatorRepositoryEditor())
+ ->setContinueOnNoEffect(true)
+ ->setContentSourceFromRequest($request)
+ ->setActor($user)
+ ->applyTransactions($repository, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($next_uri);
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Edit Hosting')));
+
+ $title = pht('Edit Hosting (%s)', $repository->getName());
+
+ $hosted_control = id(new AphrontFormRadioButtonControl())
+ ->setName('hosting')
+ ->setLabel(pht('Hosting'))
+ ->addButton(
+ true,
+ pht('Host Repository on Phabricator'),
+ pht(
+ 'Phabricator will host this repository. Users will be able to '.
+ 'push commits to Phabricator. Phabricator will not pull '.
+ 'changes from elsewhere.'))
+ ->addButton(
+ false,
+ pht('Host Repository Elsewhere'),
+ pht(
+ 'Phabricator will pull updates to this repository from a master '.
+ 'repository elsewhere (for example, on GitHub or Bitbucket). '.
+ 'Users will not be able to push commits to this repository.'))
+ ->setValue($v_hosting);
+
+ $form = id(new AphrontFormView())
+ ->setUser($user)
+ ->appendRemarkupInstructions(
+ pht(
+ 'NOTE: Hosting is extremely new and barely works! Use it at '.
+ 'your own risk.'.
+ "\n\n".
+ 'Phabricator can host repositories, or it can track repositories '.
+ 'hosted elsewhere (like on GitHub or Bitbucket).'))
+ ->appendChild($hosted_control)
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Save and Continue'))
+ ->addCancelButton($edit_uri));
+
+ $object_box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->setForm($form);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $object_box,
+ ),
+ array(
+ 'title' => $title,
+ 'device' => true,
+ ));
+ }
+
+ public function handleProtocols(PhabricatorRepository $repository) {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $v_http_mode = $repository->getServeOverHTTP();
+ $v_ssh_mode = $repository->getServeOverSSH();
+
+ $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
+ $prev_uri = $this->getRepositoryControllerURI($repository, 'edit/hosting/');
+
+ if ($request->isFormPost()) {
+ $v_http_mode = $request->getStr('http');
+ $v_ssh_mode = $request->getStr('ssh');
+
+ $xactions = array();
+ $template = id(new PhabricatorRepositoryTransaction());
+
+ $type_http = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
+ $type_ssh = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_http)
+ ->setNewValue($v_http_mode);
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_ssh)
+ ->setNewValue($v_ssh_mode);
+
+ id(new PhabricatorRepositoryEditor())
+ ->setContinueOnNoEffect(true)
+ ->setContentSourceFromRequest($request)
+ ->setActor($user)
+ ->applyTransactions($repository, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($edit_uri);
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addCrumb(
+ id(new PhabricatorCrumbView())
+ ->setName(pht('Edit Protocols')));
+
+ $title = pht('Edit Protocols (%s)', $repository->getName());
+
+
+ if ($repository->isHosted()) {
+ $rw_message = pht(
+ 'Phabricator will serve a read-write copy of this repository');
+ } else {
+ $rw_message = pht(
+ 'This repository is hosted elsewhere, so Phabricator can not perform '.
+ 'writes.');
+ }
+
+ $ssh_control =
+ id(new AphrontFormRadioButtonControl())
+ ->setName('ssh')
+ ->setLabel(pht('SSH'))
+ ->setValue($v_ssh_mode)
+ ->addButton(
+ PhabricatorRepository::SERVE_OFF,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_OFF),
+ pht('Phabricator will not serve this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READONLY,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READONLY),
+ pht('Phabricator will serve a read-only copy of this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READWRITE,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READWRITE),
+ $rw_message,
+ $repository->isHosted() ? null : 'disabled',
+ $repository->isHosted() ? null : true);
+
+ $http_control =
+ id(new AphrontFormRadioButtonControl())
+ ->setName('http')
+ ->setLabel(pht('HTTP'))
+ ->setValue($v_http_mode)
+ ->addButton(
+ PhabricatorRepository::SERVE_OFF,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_OFF),
+ pht('Phabricator will not serve this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READONLY,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READONLY),
+ pht('Phabricator will serve a read-only copy of this repository.'))
+ ->addButton(
+ PhabricatorRepository::SERVE_READWRITE,
+ PhabricatorRepository::getProtocolAvailabilityName(
+ PhabricatorRepository::SERVE_READWRITE),
+ $rw_message,
+ $repository->isHosted() ? null : 'disabled',
+ $repository->isHosted() ? null : true);
+
+ $form = id(new AphrontFormView())
+ ->setUser($user)
+ ->appendRemarkupInstructions(
+ pht(
+ 'Phabricator can serve repositories over various protocols. You can '.
+ 'configure server protocols here.'))
+ ->appendChild($ssh_control)
+ ->appendChild($http_control)
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Save Changes'))
+ ->addCancelButton($prev_uri, pht('Back')));
+
+ $object_box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->setForm($form);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $object_box,
+ ),
+ array(
+ 'title' => $title,
+ 'device' => true,
+ ));
+ }
+
+}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
index 32e5c0db30..f0140ebdc7 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
@@ -1,504 +1,565 @@
<?php
final class DiffusionRepositoryEditMainController
extends DiffusionRepositoryEditController {
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$drequest = $this->diffusionRequest;
$repository = $drequest->getRepository();
PhabricatorPolicyFilter::requireCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$is_svn = false;
$is_git = false;
$is_hg = false;
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$has_local = true;
$is_git = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- // TOOD: This will be true for hosted SVN repositories.
- $has_local = false;
+ $has_local = $repository->isHosted();
$is_svn = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$has_local = true;
$is_hg = true;
break;
}
$has_branches = ($is_git || $is_hg);
$crumbs = $this->buildApplicationCrumbs();
$title = pht('Edit %s', $repository->getName());
$header = id(new PHUIHeaderView())
->setHeader($title);
if ($repository->isTracked()) {
$header->setStatus('oh-ok', '', pht('Active'));
} else {
$header->setStatus('policy-noone', '', pht('Inactive'));
}
$basic_actions = $this->buildBasicActions($repository);
$basic_properties =
$this->buildBasicProperties($repository, $basic_actions);
$policy_actions = $this->buildPolicyActions($repository);
$policy_properties =
$this->buildPolicyProperties($repository, $policy_actions);
$remote_properties = $this->buildRemoteProperties(
$repository,
$this->buildRemoteActions($repository));
$encoding_actions = $this->buildEncodingActions($repository);
$encoding_properties =
$this->buildEncodingProperties($repository, $encoding_actions);
+ $hosting_properties = $this->buildHostingProperties(
+ $repository,
+ $this->buildHostingActions($repository));
+
$branches_properties = null;
if ($has_branches) {
$branches_properties = $this->buildBranchesProperties(
$repository,
$this->buildBranchesActions($repository));
}
$subversion_properties = null;
if ($is_svn) {
$subversion_properties = $this->buildSubversionProperties(
$repository,
$this->buildSubversionActions($repository));
}
$local_properties = null;
if ($has_local) {
$local_properties = $this->buildLocalProperties(
$repository,
$this->buildLocalActions($repository));
}
$actions_properties = $this->buildActionsProperties(
$repository,
$this->buildActionsActions($repository));
$xactions = id(new PhabricatorRepositoryTransactionQuery())
->setViewer($viewer)
->withObjectPHIDs(array($repository->getPHID()))
->execute();
$engine = id(new PhabricatorMarkupEngine())
->setViewer($viewer);
foreach ($xactions as $xaction) {
if ($xaction->getComment()) {
$engine->addObject(
$xaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
$xaction_view = id(new PhabricatorApplicationTransactionView())
->setUser($viewer)
->setObjectPHID($repository->getPHID())
->setTransactions($xactions)
->setMarkupEngine($engine);
$obj_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($basic_properties)
->addPropertyList($policy_properties)
+ ->addPropertyList($hosting_properties)
->addPropertyList($remote_properties);
if ($local_properties) {
$obj_box->addPropertyList($local_properties);
}
$obj_box->addPropertyList($encoding_properties);
if ($branches_properties) {
$obj_box->addPropertyList($branches_properties);
}
if ($subversion_properties) {
$obj_box->addPropertyList($subversion_properties);
}
$obj_box->addPropertyList($actions_properties);
return $this->buildApplicationPage(
array(
$crumbs,
$obj_box,
$xaction_view,
),
array(
'title' => $title,
'device' => true,
));
}
private function buildBasicActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Basic Information'))
->setHref($this->getRepositoryControllerURI($repository, 'edit/basic/'));
$view->addAction($edit);
$activate = id(new PhabricatorActionView())
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/activate/'))
->setWorkflow(true);
if ($repository->isTracked()) {
$activate
->setIcon('disable')
->setName(pht('Deactivate Repository'));
} else {
$activate
->setIcon('enable')
->setName(pht('Activate Repository'));
}
$view->addAction($activate);
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Delete Repository'))
->setIcon('delete')
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/delete/'))
->setWorkflow(true));
return $view;
}
private function buildBasicProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions);
$view->addProperty(pht('Name'), $repository->getName());
$view->addProperty(pht('ID'), $repository->getID());
$view->addProperty(pht('PHID'), $repository->getPHID());
$type = PhabricatorRepositoryType::getNameForRepositoryType(
$repository->getVersionControlSystem());
$view->addProperty(pht('Type'), $type);
$view->addProperty(pht('Callsign'), $repository->getCallsign());
$description = $repository->getDetail('description');
$view->addSectionHeader(pht('Description'));
if (!strlen($description)) {
$description = phutil_tag('em', array(), pht('No description provided.'));
} else {
$description = PhabricatorMarkupEngine::renderOneObject(
$repository,
'description',
$viewer);
}
$view->addTextContent($description);
return $view;
}
private function buildEncodingActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Text Encoding'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/encoding/'));
$view->addAction($edit);
return $view;
}
private function buildEncodingProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Text Encoding'));
$encoding = $repository->getDetail('encoding');
if (!$encoding) {
$encoding = phutil_tag('em', array(), pht('Use Default (UTF-8)'));
}
$view->addProperty(pht('Encoding'), $encoding);
return $view;
}
private function buildPolicyActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Policies'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/policy/'));
$view->addAction($edit);
return $view;
}
private function buildPolicyProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Policies'));
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
$viewer,
$repository);
$view->addProperty(
pht('Visible To'),
$descriptions[PhabricatorPolicyCapability::CAN_VIEW]);
$view->addProperty(
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
+ $pushable = $repository->isHosted()
+ ? $descriptions[DiffusionCapabilityPush::CAPABILITY]
+ : phutil_tag('em', array(), pht('Not a Hosted Repository'));
+ $view->addProperty(pht('Pushable By'), $pushable);
return $view;
}
private function buildBranchesActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Branches'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/branches/'));
$view->addAction($edit);
return $view;
}
private function buildBranchesProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Branches'));
$default_branch = nonempty(
$repository->getHumanReadableDetail('default-branch'),
phutil_tag('em', array(), $repository->getDefaultBranch()));
$view->addProperty(pht('Default Branch'), $default_branch);
$track_only = nonempty(
- $repository->getHumanReadableDetail('branch-filter'),
+ $repository->getHumanReadableDetail('branch-filter', array()),
phutil_tag('em', array(), pht('Track All Branches')));
$view->addProperty(pht('Track Only'), $track_only);
$autoclose_only = nonempty(
- $repository->getHumanReadableDetail('close-commits-filter'),
+ $repository->getHumanReadableDetail('close-commits-filter', array()),
phutil_tag('em', array(), pht('Autoclose On All Branches')));
$view->addProperty(pht('Autoclose Only'), $autoclose_only);
return $view;
}
private function buildSubversionActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Subversion Info'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/subversion/'));
$view->addAction($edit);
return $view;
}
private function buildSubversionProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Subversion'));
$svn_uuid = nonempty(
$repository->getUUID(),
phutil_tag('em', array(), pht('Not Configured')));
$view->addProperty(pht('Subversion UUID'), $svn_uuid);
$svn_subpath = nonempty(
$repository->getHumanReadableDetail('svn-subpath'),
phutil_tag('em', array(), pht('Import Entire Repository')));
$view->addProperty(pht('Import Only'), $svn_subpath);
return $view;
}
private function buildActionsActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Actions'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/actions/'));
$view->addAction($edit);
return $view;
}
private function buildActionsProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Actions'));
$notify = $repository->getDetail('herald-disabled')
? pht('Off')
: pht('On');
$notify = phutil_tag('em', array(), $notify);
$view->addProperty(pht('Publish/Notify'), $notify);
$autoclose = $repository->getDetail('disable-autoclose')
? pht('Off')
: pht('On');
$autoclose = phutil_tag('em', array(), $autoclose);
$view->addProperty(pht('Autoclose'), $autoclose);
return $view;
}
private function buildRemoteActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Remote'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/remote/'));
$view->addAction($edit);
return $view;
}
private function buildRemoteProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Remote'));
$view->addProperty(
pht('Remote URI'),
$repository->getHumanReadableDetail('remote-uri'));
return $view;
}
private function buildLocalActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Local'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/local/'));
$view->addAction($edit);
return $view;
}
private function buildLocalProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Local'));
$view->addProperty(
pht('Local Path'),
$repository->getHumanReadableDetail('local-path'));
return $view;
}
+
+ private function buildHostingActions(PhabricatorRepository $repository) {
+ $user = $this->getRequest()->getUser();
+
+ $view = id(new PhabricatorActionListView())
+ ->setObjectURI($this->getRequest()->getRequestURI())
+ ->setUser($user);
+
+ $edit = id(new PhabricatorActionView())
+ ->setIcon('edit')
+ ->setName(pht('Edit Hosting'))
+ ->setHref(
+ $this->getRepositoryControllerURI($repository, 'edit/hosting/'));
+ $view->addAction($edit);
+
+ return $view;
+ }
+
+ private function buildHostingProperties(
+ PhabricatorRepository $repository,
+ PhabricatorActionListView $actions) {
+
+ $user = $this->getRequest()->getUser();
+
+ $view = id(new PHUIPropertyListView())
+ ->setUser($user)
+ ->setActionList($actions)
+ ->addSectionHeader(pht('Hosting'));
+
+ $hosting = $repository->isHosted()
+ ? pht('Hosted on Phabricator')
+ : pht('Hosted Elsewhere');
+ $view->addProperty(pht('Hosting'), phutil_tag('em', array(), $hosting));
+
+ $view->addProperty(
+ pht('Serve over HTTP'),
+ phutil_tag(
+ 'em',
+ array(),
+ PhabricatorRepository::getProtocolAvailabilityName(
+ $repository->getServeOverHTTP())));
+
+ $view->addProperty(
+ pht('Serve over SSH'),
+ phutil_tag(
+ 'em',
+ array(),
+ PhabricatorRepository::getProtocolAvailabilityName(
+ $repository->getServeOverSSH())));
+
+ return $view;
+ }
+
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php
index b68057adb3..1a6f7dff2e 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php
@@ -1,108 +1,135 @@
<?php
final class DiffusionRepositoryEditPolicyController
extends DiffusionRepositoryEditController {
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$drequest = $this->diffusionRequest;
$repository = $drequest->getRepository();
$repository = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->withIDs(array($repository->getID()))
->executeOne();
if (!$repository) {
return new Aphront404Response();
}
$edit_uri = $this->getRepositoryControllerURI($repository, 'edit/');
$v_view = $repository->getViewPolicy();
$v_edit = $repository->getEditPolicy();
+ $v_push = $repository->getPushPolicy();
if ($request->isFormPost()) {
$v_view = $request->getStr('viewPolicy');
$v_edit = $request->getStr('editPolicy');
+ $v_push = $request->getStr('pushPolicy');
$xactions = array();
$template = id(new PhabricatorRepositoryTransaction());
$type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
$type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
+ $type_push = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
$xactions[] = id(clone $template)
->setTransactionType($type_view)
->setNewValue($v_view);
$xactions[] = id(clone $template)
->setTransactionType($type_edit)
->setNewValue($v_edit);
+ if ($repository->isHosted()) {
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_push)
+ ->setNewValue($v_push);
+ }
+
id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($repository, $xactions);
return id(new AphrontRedirectResponse())->setURI($edit_uri);
}
$content = array();
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Edit Policies')));
- $title = pht('Edit %s', $repository->getName());
+ $title = pht('Edit Policies (%s)', $repository->getName());
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($repository)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($repository)
->setPolicies($policies)
->setName('viewPolicy'))
->appendChild(
id(new AphrontFormPolicyControl())
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($repository)
->setPolicies($policies)
- ->setName('editPolicy'))
+ ->setName('editPolicy'));
+
+ if ($repository->isHosted()) {
+ $form->appendChild(
+ id(new AphrontFormPolicyControl())
+ ->setUser($viewer)
+ ->setCapability(DiffusionCapabilityPush::CAPABILITY)
+ ->setPolicyObject($repository)
+ ->setPolicies($policies)
+ ->setName('pushPolicy'));
+ } else {
+ $form->appendChild(
+ id(new AphrontFormMarkupControl())
+ ->setLabel(pht('Can Push'))
+ ->setValue(
+ phutil_tag('em', array(), pht('Not a Hosted Repository'))));
+ }
+
+ $form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Save Policies'))
->addCancelButton($edit_uri));
$form_box = id(new PHUIObjectBoxView())
->setHeaderText($title)
->setForm($form);
return $this->buildApplicationPage(
array(
$crumbs,
$form_box,
),
array(
'title' => $title,
'device' => true,
));
}
}
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryListController.php b/src/applications/diffusion/controller/DiffusionRepositoryListController.php
index dc548dc5c5..cc85aa1009 100644
--- a/src/applications/diffusion/controller/DiffusionRepositoryListController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryListController.php
@@ -1,132 +1,147 @@
<?php
final class DiffusionRepositoryListController extends DiffusionController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $queryKey;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() {
$request = $this->getRequest();
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setPreface($this->buildShortcuts())
->setSearchEngine(new PhabricatorRepositorySearchEngine())
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
public function renderResultsList(
array $repositories,
PhabricatorSavedQuery $query) {
assert_instances_of($repositories, 'PhabricatorRepository');
$viewer = $this->getRequest()->getUser();
$list = new PHUIObjectItemListView();
foreach ($repositories as $repository) {
$id = $repository->getID();
$item = id(new PHUIObjectItemView())
->setUser($viewer)
->setHeader($repository->getName())
->setHref($this->getApplicationURI($repository->getCallsign().'/'));
$commit = $repository->getMostRecentCommit();
if ($commit) {
$commit_link = DiffusionView::linkCommit(
$repository,
$commit->getCommitIdentifier(),
$commit->getSummary());
$item->setSubhead($commit_link);
$item->setEpoch($commit->getEpoch());
}
$item->addAttribute(
PhabricatorRepositoryType::getNameForRepositoryType(
$repository->getVersionControlSystem()));
$size = $repository->getCommitCount();
if ($size) {
$history_uri = DiffusionRequest::generateDiffusionURI(
array(
'callsign' => $repository->getCallsign(),
'action' => 'history',
));
$item->addAttribute(
phutil_tag(
'a',
array(
'href' => $history_uri,
),
pht('%s Commit(s)', new PhutilNumber($size))));
} else {
$item->addAttribute(pht('No Commits'));
}
if (!$repository->isTracked()) {
$item->setDisabled(true);
$item->addIcon('disable-grey', pht('Inactive'));
}
$list->addItem($item);
}
return $list;
}
public function buildSideNavView($for_app = false) {
$viewer = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-
id(new PhabricatorRepositorySearchEngine())
->setViewer($viewer)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav;
}
+ public function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $can_create = $this->hasApplicationCapability(
+ DiffusionCapabilityCreateRepositories::CAPABILITY);
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('Import Repository'))
+ ->setHref($this->getApplicationURI('/create/'))
+ ->setDisabled(!$can_create)
+ ->setIcon('create'));
+
+ return $crumbs;
+ }
+
private function buildShortcuts() {
$shortcuts = id(new PhabricatorRepositoryShortcut())->loadAll();
if ($shortcuts) {
$shortcuts = msort($shortcuts, 'getSequence');
$rows = array();
foreach ($shortcuts as $shortcut) {
$rows[] = array(
$shortcut->getName(),
$shortcut->getHref(),
$shortcut->getDescription(),
);
}
$list = new PHUIObjectItemListView();
foreach ($rows as $row) {
$item = id(new PHUIObjectItemView())
->setHeader($row[0])
->setHref($row[1])
->setSubhead(($row[2] ? $row[2] : pht('No Description')));
$list->addItem($item);
}
$shortcut_panel = array($list, phutil_tag('hr'));
} else {
$shortcut_panel = null;
}
return $shortcut_panel;
}
}
diff --git a/src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php b/src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php
index 5bbf05b684..8c03ad96e7 100644
--- a/src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php
+++ b/src/applications/diffusion/query/stablecommitname/DiffusionGitStableCommitNameQuery.php
@@ -1,17 +1,16 @@
<?php
final class DiffusionGitStableCommitNameQuery
extends DiffusionStableCommitNameQuery {
protected function executeQuery() {
$repository = $this->getRepository();
$branch = $this->getBranch();
list($stdout) = $repository->execxLocalCommand(
- 'rev-parse --verify %s/%s',
- DiffusionBranchInformation::DEFAULT_GIT_REMOTE,
+ 'rev-parse --verify %s',
$branch);
$commit = trim($stdout);
return substr($commit, 0, 16);
}
}
diff --git a/src/applications/diffusion/request/DiffusionGitRequest.php b/src/applications/diffusion/request/DiffusionGitRequest.php
index ab34ce1af1..975051d898 100644
--- a/src/applications/diffusion/request/DiffusionGitRequest.php
+++ b/src/applications/diffusion/request/DiffusionGitRequest.php
@@ -1,38 +1,37 @@
<?php
/**
* @group diffusion
*/
final class DiffusionGitRequest extends DiffusionRequest {
protected function getSupportsBranches() {
return true;
}
protected function didInitialize() {
if (!$this->commit) {
return;
}
$this->expandCommitName();
}
public function getBranch() {
if ($this->branch) {
return $this->branch;
}
if ($this->repository) {
return $this->repository->getDefaultBranch();
}
throw new Exception("Unable to determine branch!");
}
public function getCommit() {
if ($this->commit) {
return $this->commit;
}
- $remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE;
- return $remote.'/'.$this->getBranch();
+ return $this->getBranch();
}
}
diff --git a/src/applications/diffusion/response/DiffusionGitResponse.php b/src/applications/diffusion/response/DiffusionGitResponse.php
new file mode 100644
index 0000000000..edf8d4f051
--- /dev/null
+++ b/src/applications/diffusion/response/DiffusionGitResponse.php
@@ -0,0 +1,44 @@
+<?php
+
+final class DiffusionGitResponse extends AphrontResponse {
+
+ private $httpCode;
+ private $headers = array();
+ private $response;
+
+ public function setGitData($data) {
+ list($headers, $body) = explode("\r\n\r\n", $data, 2);
+ $this->response = $body;
+ $headers = explode("\r\n", $headers);
+
+ $matches = null;
+ $this->httpCode = 200;
+ $this->headers = array();
+ foreach ($headers as $header) {
+ if (preg_match('/^Status:\s*(\d+)/i', $header, $matches)) {
+ $this->httpCode = (int)$matches[1];
+ } else {
+ $this->headers[] = explode(': ', $header, 2);
+ }
+ }
+
+ return $this;
+ }
+
+ public function buildResponseString() {
+ return $this->response;
+ }
+
+ public function getHeaders() {
+ return $this->headers;
+ }
+
+ public function getCacheHeaders() {
+ return array();
+ }
+
+ public function getHTTPResponseCode() {
+ return $this->httpCode;
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHGitReceivePackWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHGitReceivePackWorkflow.php
new file mode 100644
index 0000000000..b617f22505
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHGitReceivePackWorkflow.php
@@ -0,0 +1,34 @@
+<?php
+
+final class DiffusionSSHGitReceivePackWorkflow
+ extends DiffusionSSHGitWorkflow {
+
+ public function didConstruct() {
+ $this->setName('git-receive-pack');
+ $this->setArguments(
+ array(
+ array(
+ 'name' => 'dir',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function isReadOnly() {
+ return false;
+ }
+
+ public function getRequestPath() {
+ $args = $this->getArgs();
+ return head($args->getArg('dir'));
+ }
+
+ protected function executeRepositoryOperations(
+ PhabricatorRepository $repository) {
+ $future = new ExecFuture(
+ 'git-receive-pack %s',
+ $repository->getLocalPath());
+ return $this->passthruIO($future);
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php
new file mode 100644
index 0000000000..915ae45970
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHGitUploadPackWorkflow.php
@@ -0,0 +1,34 @@
+<?php
+
+final class DiffusionSSHGitUploadPackWorkflow
+ extends DiffusionSSHGitWorkflow {
+
+ public function didConstruct() {
+ $this->setName('git-upload-pack');
+ $this->setArguments(
+ array(
+ array(
+ 'name' => 'dir',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function isReadOnly() {
+ return true;
+ }
+
+ public function getRequestPath() {
+ $args = $this->getArgs();
+ return head($args->getArg('dir'));
+ }
+
+ protected function executeRepositoryOperations(
+ PhabricatorRepository $repository) {
+
+ $future = new ExecFuture('git-upload-pack %s', $repository->getLocalPath());
+
+ return $this->passthruIO($future);
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php
new file mode 100644
index 0000000000..ceaf7c146e
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHGitWorkflow.php
@@ -0,0 +1,10 @@
+<?php
+
+abstract class DiffusionSSHGitWorkflow extends DiffusionSSHWorkflow {
+
+ protected function writeError($message) {
+ // Git assumes we'll add our own newlines.
+ return parent::writeError($message."\n");
+ }
+
+}
diff --git a/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
new file mode 100644
index 0000000000..5c2c182c9b
--- /dev/null
+++ b/src/applications/diffusion/ssh/DiffusionSSHWorkflow.php
@@ -0,0 +1,89 @@
+<?php
+
+abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
+
+ private $args;
+
+ public function getArgs() {
+ return $this->args;
+ }
+
+ abstract protected function isReadOnly();
+ abstract protected function getRequestPath();
+ abstract protected function executeRepositoryOperations(
+ PhabricatorRepository $repository);
+
+ protected function writeError($message) {
+ $this->getErrorChannel()->write($message);
+ return $this;
+ }
+
+ final public function execute(PhutilArgumentParser $args) {
+ $this->args = $args;
+
+ try {
+ $repository = $this->loadRepository();
+ return $this->executeRepositoryOperations($repository);
+ } catch (Exception $ex) {
+ $this->writeError(get_class($ex).': '.$ex->getMessage());
+ return 1;
+ }
+ }
+
+ private function loadRepository() {
+ $viewer = $this->getUser();
+ $path = $this->getRequestPath();
+
+ $regex = '@^/?diffusion/(?P<callsign>[A-Z]+)(?:/|$)@';
+ $matches = null;
+ if (!preg_match($regex, $path, $matches)) {
+ throw new Exception(
+ pht(
+ 'Unrecognized repository path "%s". Expected a path like '.
+ '"%s".',
+ $path,
+ "/diffusion/X/"));
+ }
+
+ $callsign = $matches[1];
+ $repository = id(new PhabricatorRepositoryQuery())
+ ->setViewer($viewer)
+ ->withCallsigns(array($callsign))
+ ->executeOne();
+
+ if (!$repository) {
+ throw new Exception(
+ pht('No repository "%s" exists!', $callsign));
+ }
+
+ $is_push = !$this->isReadOnly();
+
+ switch ($repository->getServeOverSSH()) {
+ case PhabricatorRepository::SERVE_READONLY:
+ if ($is_push) {
+ throw new Exception(
+ pht('This repository is read-only over SSH.'));
+ }
+ break;
+ case PhabricatorRepository::SERVE_READWRITE:
+ if ($is_push) {
+ $can_push = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $repository,
+ DiffusionCapabilityPush::CAPABILITY);
+ if (!$can_push) {
+ throw new Exception(
+ pht('You do not have permission to push to this repository.'));
+ }
+ }
+ break;
+ case PhabricatorRepository::SERVE_OFF:
+ default:
+ throw new Exception(
+ pht('This repository is not available over SSH.'));
+ }
+
+ return $repository;
+ }
+
+}
diff --git a/src/applications/diffusion/view/DiffusionHistoryTableView.php b/src/applications/diffusion/view/DiffusionHistoryTableView.php
index 0a9ee516fc..6cf855da43 100644
--- a/src/applications/diffusion/view/DiffusionHistoryTableView.php
+++ b/src/applications/diffusion/view/DiffusionHistoryTableView.php
@@ -1,332 +1,334 @@
<?php
final class DiffusionHistoryTableView extends DiffusionView {
private $history;
private $revisions = array();
private $handles = array();
private $isHead;
private $parents;
public function setHistory(array $history) {
assert_instances_of($history, 'DiffusionPathChange');
$this->history = $history;
return $this;
}
public function loadRevisions() {
$commit_phids = array();
foreach ($this->history as $item) {
if ($item->getCommit()) {
$commit_phids[] = $item->getCommit()->getPHID();
}
}
+
+ // TODO: Get rid of this.
$this->revisions = id(new DifferentialRevision())
->loadIDsByCommitPHIDs($commit_phids);
return $this;
}
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function getRequiredHandlePHIDs() {
$phids = array();
foreach ($this->history as $item) {
$data = $item->getCommitData();
if ($data) {
if ($data->getCommitDetail('authorPHID')) {
$phids[$data->getCommitDetail('authorPHID')] = true;
}
if ($data->getCommitDetail('committerPHID')) {
$phids[$data->getCommitDetail('committerPHID')] = true;
}
}
}
return array_keys($phids);
}
public function setParents(array $parents) {
$this->parents = $parents;
return $this;
}
public function setIsHead($is_head) {
$this->isHead = $is_head;
return $this;
}
public function render() {
$drequest = $this->getDiffusionRequest();
$handles = $this->handles;
$graph = null;
if ($this->parents) {
$graph = $this->renderGraph();
}
$rows = array();
$ii = 0;
foreach ($this->history as $history) {
$epoch = $history->getEpoch();
if ($epoch) {
$date = phabricator_date($epoch, $this->user);
$time = phabricator_time($epoch, $this->user);
} else {
$date = null;
$time = null;
}
$data = $history->getCommitData();
$author_phid = $committer = $committer_phid = null;
if ($data) {
$author_phid = $data->getCommitDetail('authorPHID');
$committer_phid = $data->getCommitDetail('committerPHID');
$committer = $data->getCommitDetail('committer');
}
if ($author_phid && isset($handles[$author_phid])) {
$author = $handles[$author_phid]->renderLink();
} else {
$author = self::renderName($history->getAuthorName());
}
$different_committer = false;
if ($committer_phid) {
$different_committer = ($committer_phid != $author_phid);
} else if ($committer != '') {
$different_committer = ($committer != $history->getAuthorName());
}
if ($different_committer) {
if ($committer_phid && isset($handles[$committer_phid])) {
$committer = $handles[$committer_phid]->renderLink();
} else {
$committer = self::renderName($committer);
}
$author = hsprintf('%s/%s', $author, $committer);
}
$commit = $history->getCommit();
if ($commit && !$commit->getIsUnparsed() && $data) {
$change = $this->linkChange(
$history->getChangeType(),
$history->getFileType(),
$path = null,
$history->getCommitIdentifier());
} else {
$change = phutil_tag('em', array(), "Importing\xE2\x80\xA6");
}
$rows[] = array(
$this->linkBrowse(
$drequest->getPath(),
array(
'commit' => $history->getCommitIdentifier(),
)),
$graph ? $graph[$ii++] : null,
self::linkCommit(
$drequest->getRepository(),
$history->getCommitIdentifier()),
($commit ?
self::linkRevision(idx($this->revisions, $commit->getPHID())) :
null),
$change,
$date,
$time,
$author,
AphrontTableView::renderSingleDisplayLine($history->getSummary()),
// TODO: etc etc
);
}
$view = new AphrontTableView($rows);
$view->setHeaders(
array(
pht('Browse'),
'',
pht('Commit'),
pht('Revision'),
pht('Change'),
pht('Date'),
pht('Time'),
pht('Author/Committer'),
pht('Details'),
));
$view->setColumnClasses(
array(
'',
'threads',
'n',
'n',
'',
'',
'right',
'',
'wide',
));
$view->setColumnVisibility(
array(
true,
$graph ? true : false,
));
return $view->render();
}
/**
* Draw a merge/branch graph from the parent revision data. We're basically
* building up a bunch of strings like this:
*
* ^
* |^
* o|
* |o
* o
*
* ...which form an ASCII representation of the graph we eventaully want to
* draw.
*
* NOTE: The actual implementation is black magic.
*/
private function renderGraph() {
// This keeps our accumulated information about each line of the
// merge/branch graph.
$graph = array();
// This holds the next commit we're looking for in each column of the
// graph.
$threads = array();
// This is the largest number of columns any row has, i.e. the width of
// the graph.
$count = 0;
foreach ($this->history as $key => $history) {
$joins = array();
$splits = array();
$parent_list = $this->parents[$history->getCommitIdentifier()];
// Look for some thread which has this commit as the next commit. If
// we find one, this commit goes on that thread. Otherwise, this commit
// goes on a new thread.
$line = '';
$found = false;
$pos = count($threads);
for ($n = 0; $n < $count; $n++) {
if (empty($threads[$n])) {
$line .= ' ';
continue;
}
if ($threads[$n] == $history->getCommitIdentifier()) {
if ($found) {
$line .= ' ';
$joins[] = $n;
unset($threads[$n]);
} else {
$line .= 'o';
$found = true;
$pos = $n;
}
} else {
// We render a "|" for any threads which have a commit that we haven't
// seen yet, this is later drawn as a vertical line.
$line .= '|';
}
}
// If we didn't find the thread this commit goes on, start a new thread.
// We use "o" to mark the commit for the rendering engine, or "^" to
// indicate that there's nothing after it so the line from the commit
// upward should not be drawn.
if (!$found) {
if ($this->isHead) {
$line .= '^';
} else {
$line .= 'o';
foreach ($graph as $k => $meta) {
// Go back across all the lines we've already drawn and add a
// "|" to the end, since this is connected to some future commit
// we don't know about.
for ($jj = strlen($meta['line']); $jj <= $count; $jj++) {
$graph[$k]['line'] .= '|';
}
}
}
}
// Update the next commit on this thread to the commit's first parent.
// This might have the effect of making a new thread.
$threads[$pos] = head($parent_list);
// If we made a new thread, increase the thread count.
$count = max($pos + 1, $count);
// Now, deal with splits (merges). I picked this terms opposite to the
// underlying repository term to confuse you.
foreach (array_slice($parent_list, 1) as $parent) {
$found = false;
// Try to find the other parent(s) in our existing threads. If we find
// them, split to that thread.
foreach ($threads as $idx => $thread_commit) {
if ($thread_commit == $parent) {
$found = true;
$splits[] = $idx;
}
}
// If we didn't find the parent, we don't know about it yet. Find the
// first free thread and add it as the "next" commit in that thread.
// This might create a new thread.
if (!$found) {
for ($n = 0; $n < $count; $n++) {
if (empty($threads[$n])) {
break;
}
}
$threads[$n] = $parent;
$splits[] = $n;
$count = max($n + 1, $count);
}
}
$graph[] = array(
'line' => $line,
'split' => $splits,
'join' => $joins,
);
}
// Render into tags for the behavior.
foreach ($graph as $k => $meta) {
$graph[$k] = javelin_tag(
'div',
array(
'sigil' => 'commit-graph',
'meta' => $meta,
),
'');
}
Javelin::initBehavior(
'diffusion-commit-graph',
array(
'count' => $count,
));
return $graph;
}
}
diff --git a/src/applications/repository/PhabricatorRepositoryConfigOptions.php b/src/applications/repository/PhabricatorRepositoryConfigOptions.php
index 17d52652a8..32fb0bbb33 100644
--- a/src/applications/repository/PhabricatorRepositoryConfigOptions.php
+++ b/src/applications/repository/PhabricatorRepositoryConfigOptions.php
@@ -1,36 +1,36 @@
<?php
/**
* @group repository
*/
final class PhabricatorRepositoryConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Repositories');
}
public function getDescription() {
return pht('Configure repositories.');
}
public function getOptions() {
return array(
- $this->newOption('repository.default-local-path', 'string', null)
+ $this->newOption('repository.default-local-path', 'string', '/var/repo/')
->setSummary(
pht("Default location to store local copies of repositories."))
->setDescription(
pht(
"The default location in which to store local copies of ".
"repositories. Anything stored in this directory will be assumed ".
- "to be under the control of phabricator, which means that ".
+ "to be under the control of Phabricator, which means that ".
"Phabricator will try to do some maintenance on working copies ".
"if there are problems (such as a change to the remote origin ".
"url). This maintenance may include completely removing (and ".
"recloning) anything in this directory.\n\n".
"When set to null, this option is ignored (i.e. Phabricator will ".
"not fully control any working copies).")),
);
}
}
diff --git a/src/applications/repository/application/PhabricatorApplicationRepositories.php b/src/applications/repository/application/PhabricatorApplicationRepositories.php
index 49f692849d..0afce533b4 100644
--- a/src/applications/repository/application/PhabricatorApplicationRepositories.php
+++ b/src/applications/repository/application/PhabricatorApplicationRepositories.php
@@ -1,44 +1,40 @@
<?php
/**
* @group repository
*/
final class PhabricatorApplicationRepositories extends PhabricatorApplication {
public function getBaseURI() {
return '/repository/';
}
public function getIconName() {
return 'repositories';
}
public function getShortDescription() {
return 'Track Repositories';
}
public function getTitleGlyph() {
return "rX";
}
public function getApplicationGroup() {
return self::GROUP_ADMIN;
}
public function getRoutes() {
return array(
'/repository/' => array(
'' => 'PhabricatorRepositoryListController',
- 'create/' => 'PhabricatorRepositoryCreateController',
- 'edit/(?P<id>[1-9]\d*)/(?:(?P<view>\w+)/)?' =>
- 'PhabricatorRepositoryEditController',
- 'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorRepositoryDeleteController',
'project/edit/(?P<id>[1-9]\d*)/' =>
'PhabricatorRepositoryArcanistProjectEditController',
'project/delete/(?P<id>[1-9]\d*)/' =>
'PhabricatorRepositoryArcanistProjectDeleteController',
),
);
}
}
diff --git a/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php b/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
index 1f9a168d65..7fba83c15d 100644
--- a/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
+++ b/src/applications/repository/conduit/ConduitAPI_repository_create_Method.php
@@ -1,130 +1,139 @@
<?php
/**
* @group conduit
*/
final class ConduitAPI_repository_create_Method
extends ConduitAPI_repository_Method {
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
}
public function getMethodStatusDescription() {
return "Repository methods are new and subject to change.";
}
public function getMethodDescription() {
return "Create a new repository (Admin Only).";
}
public function defineParamTypes() {
return array(
'name' => 'required string',
'vcs' => 'required enum<git, hg, svn>',
'callsign' => 'required string',
'description' => 'optional string',
'encoding' => 'optional string',
'tracking' => 'optional bool',
'uri' => 'optional string',
'sshUser' => 'optional string',
'sshKey' => 'optional string',
'sshKeyFile' => 'optional string',
'httpUser' => 'optional string',
'httpPassword' => 'optional string',
'localPath' => 'optional string',
'svnSubpath' => 'optional string',
'branchFilter' => 'optional list<string>',
'closeCommitsFilter' => 'optional list<string>',
'pullFrequency' => 'optional int',
'defaultBranch' => 'optional string',
'heraldEnabled' => 'optional bool, default = true',
'autocloseEnabled' => 'optional bool, default = true',
'svnUUID' => 'optional string',
);
}
public function defineReturnType() {
return 'nonempty dict';
}
public function defineErrorTypes() {
return array(
'ERR-PERMISSIONS' =>
'You do not have the authority to call this method.',
'ERR-DUPLICATE' =>
'Duplicate repository callsign.',
'ERR-BAD-CALLSIGN' =>
'Callsign is required and must be ALL UPPERCASE LETTERS.',
'ERR-UNKNOWN-REPOSITORY-VCS' =>
'Unknown repository VCS type.',
);
}
protected function execute(ConduitAPIRequest $request) {
- if (!$request->getUser()->getIsAdmin()) {
- throw new ConduitException('ERR-PERMISSIONS');
- }
+ $application = id(new PhabricatorApplicationQuery())
+ ->setViewer($request->getUser())
+ ->withClasses(array('PhabricatorApplicationDiffusion'))
+ ->executeOne();
+
+ PhabricatorPolicyFilter::requireCapability(
+ $request->getUser(),
+ $application,
+ DiffusionCapabilityCreateRepositories::CAPABILITY);
// TODO: This has some duplication with (and lacks some of the validation
// of) the web workflow; refactor things so they can share more code as this
- // stabilizes.
+ // stabilizes. Specifically, this should move to transactions since they
+ // work properly now.
+
+ $repository = PhabricatorRepository::initializeNewRepository(
+ $request->getUser());
- $repository = new PhabricatorRepository();
$repository->setName($request->getValue('name'));
$callsign = $request->getValue('callsign');
if (!preg_match('/[A-Z]+$/', $callsign)) {
throw new ConduitException('ERR-BAD-CALLSIGN');
}
$repository->setCallsign($callsign);
$vcs = $request->getValue('vcs');
$map = array(
'git' => PhabricatorRepositoryType::REPOSITORY_TYPE_GIT,
'hg' => PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL,
'svn' => PhabricatorRepositoryType::REPOSITORY_TYPE_SVN,
);
if (empty($map[$vcs])) {
throw new ConduitException('ERR-UNKNOWN-REPOSITORY-VCS');
}
$repository->setVersionControlSystem($map[$vcs]);
$details = array(
'encoding' => $request->getValue('encoding'),
'description' => $request->getValue('description'),
'tracking-enabled' => (bool)$request->getValue('tracking', true),
'remote-uri' => $request->getValue('uri'),
'local-path' => $request->getValue('localPath'),
'branch-filter' => array_fill_keys(
$request->getValue('branchFilter', array()),
true),
'close-commits-filter' => array_fill_keys(
$request->getValue('closeCommitsFilter', array()),
true),
'pull-frequency' => $request->getValue('pullFrequency'),
'default-branch' => $request->getValue('defaultBranch'),
'ssh-login' => $request->getValue('sshUser'),
'ssh-key' => $request->getValue('sshKey'),
'ssh-keyfile' => $request->getValue('sshKeyFile'),
'herald-disabled' => !$request->getValue('heraldEnabled', true),
'svn-subpath' => $request->getValue('svnSubpath'),
'disable-autoclose' => !$request->getValue('autocloseEnabled', true),
);
foreach ($details as $key => $value) {
$repository->setDetail($key, $value);
}
try {
$repository->save();
} catch (AphrontQueryDuplicateKeyException $ex) {
throw new ConduitException('ERR-DUPLICATE');
}
return $repository->toDictionary();
}
}
diff --git a/src/applications/repository/controller/PhabricatorRepositoryCreateController.php b/src/applications/repository/controller/PhabricatorRepositoryCreateController.php
deleted file mode 100644
index 807d2dba34..0000000000
--- a/src/applications/repository/controller/PhabricatorRepositoryCreateController.php
+++ /dev/null
@@ -1,119 +0,0 @@
-<?php
-
-final class PhabricatorRepositoryCreateController
- extends PhabricatorRepositoryController {
-
- public function processRequest() {
-
-
- $request = $this->getRequest();
- $user = $request->getUser();
-
- $e_name = true;
- $e_callsign = true;
-
- $repository = new PhabricatorRepository();
-
- $type_map = PhabricatorRepositoryType::getAllRepositoryTypes();
- $errors = array();
-
- if ($request->isFormPost()) {
-
- $repository->setName($request->getStr('name'));
- $repository->setCallsign($request->getStr('callsign'));
- $repository->setVersionControlSystem($request->getStr('type'));
-
- if (!strlen($repository->getName())) {
- $e_name = 'Required';
- $errors[] = 'Repository name is required.';
- } else {
- $e_name = null;
- }
-
- if (!strlen($repository->getCallsign())) {
- $e_callsign = 'Required';
- $errors[] = 'Callsign is required.';
- } else if (!preg_match('/^[A-Z]+$/', $repository->getCallsign())) {
- $e_callsign = 'Invalid';
- $errors[] = 'Callsign must be ALL UPPERCASE LETTERS.';
- } else {
- $e_callsign = null;
- }
-
- if (empty($type_map[$repository->getVersionControlSystem()])) {
- $errors[] = 'Invalid version control system.';
- }
-
- if (!$errors) {
- try {
- $repository->save();
-
- return id(new AphrontRedirectResponse())
- ->setURI('/repository/edit/'.$repository->getID().'/');
-
- } catch (AphrontQueryDuplicateKeyException $ex) {
- $e_callsign = 'Duplicate';
- $errors[] = 'Callsign must be unique. Another repository already '.
- 'uses that callsign.';
- }
- }
- }
-
- $error_view = null;
- if ($errors) {
- $error_view = new AphrontErrorView();
- $error_view->setErrors($errors);
- $error_view->setTitle('Form Errors');
- }
-
- $form = new AphrontFormView();
- $form
- ->setUser($user)
- ->setAction('/repository/create/')
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setLabel('Name')
- ->setName('name')
- ->setValue($repository->getName())
- ->setError($e_name)
- ->setCaption('Human-readable repository name.'))
- ->appendChild(hsprintf(
- '<p class="aphront-form-instructions">Select a "Callsign" &mdash; a '.
- 'short, uppercase string to identify revisions in this repository. If '.
- 'you choose "EX", revisions in this repository will be identified '.
- 'with the prefix "rEX".</p>'))
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setLabel('Callsign')
- ->setName('callsign')
- ->setValue($repository->getCallsign())
- ->setError($e_callsign)
- ->setCaption(
- 'Short, UPPERCASE identifier. Once set, it can not be changed.'))
- ->appendChild(
- id(new AphrontFormSelectControl())
- ->setLabel('Type')
- ->setName('type')
- ->setOptions($type_map)
- ->setValue($repository->getVersionControlSystem()))
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->setValue('Create Repository')
- ->addCancelButton('/repository/'));
-
- $form_box = id(new PHUIObjectBoxView())
- ->setHeaderText(pht('Create Repository'))
- ->setFormError($error_view)
- ->setForm($form);
-
- return $this->buildApplicationPage(
- array(
- $form_box,
- ),
- array(
- 'title' => pht('Create Repository'),
- 'device' => true,
- ));
- }
-
-}
diff --git a/src/applications/repository/controller/PhabricatorRepositoryEditController.php b/src/applications/repository/controller/PhabricatorRepositoryEditController.php
deleted file mode 100644
index 468dac45e9..0000000000
--- a/src/applications/repository/controller/PhabricatorRepositoryEditController.php
+++ /dev/null
@@ -1,696 +0,0 @@
-<?php
-
-final class PhabricatorRepositoryEditController
- extends PhabricatorRepositoryController {
-
- private $id;
- private $view;
- private $repository;
- private $sideNav;
-
- public function willProcessRequest(array $data) {
- $this->id = $data['id'];
- $this->view = idx($data, 'view');
- }
-
- public function processRequest() {
-
- $request = $this->getRequest();
- $viewer = $request->getUser();
-
- $repository = id(new PhabricatorRepositoryQuery())
- ->setViewer($viewer)
- ->withIDs(array($this->id))
- ->executeOne();
- if (!$repository) {
- return new Aphront404Response();
- }
-
- $views = array(
- 'basic' => 'Basics',
- 'tracking' => 'Tracking',
- );
-
- $this->repository = $repository;
-
- if (!isset($views[$this->view])) {
- $this->view = head_key($views);
- }
-
- $nav = new AphrontSideNavFilterView();
- $base_uri = new PhutilURI('/repository/edit/'.$repository->getID().'/');
- $nav->setBaseURI($base_uri);
- foreach ($views as $view => $name) {
- $nav->addFilter($view, $name);
- }
- $nav->selectFilter($this->view, null);
-
- $nav->appendChild($this->renderDaemonNotice());
-
- $this->sideNav = $nav;
-
- switch ($this->view) {
- case 'basic':
- return $this->processBasicRequest();
- case 'tracking':
- return $this->processTrackingRequest();
- default:
- throw new Exception("Unknown view.");
- }
- }
-
- protected function processBasicRequest() {
- $request = $this->getRequest();
- $user = $request->getUser();
- $repository = $this->repository;
- $repository_id = $repository->getID();
-
- $errors = array();
-
- $e_name = true;
-
- if ($request->isFormPost()) {
- $repository->setName($request->getStr('name'));
-
- if (!strlen($repository->getName())) {
- $e_name = 'Required';
- $errors[] = 'Repository name is required.';
- } else {
- $e_name = null;
- }
-
- $repository->setDetail('description', $request->getStr('description'));
- $repository->setDetail('encoding', $request->getStr('encoding'));
-
- if (!$errors) {
- $repository->save();
- return id(new AphrontRedirectResponse())
- ->setURI('/repository/edit/'.$repository_id.'/basic/?saved=true');
- }
- }
-
- $error_view = null;
- if ($errors) {
- $error_view = new AphrontErrorView();
- $error_view->setErrors($errors);
- $error_view->setTitle('Form Errors');
- } else if ($request->getStr('saved')) {
- $error_view = new AphrontErrorView();
- $error_view->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
- $error_view->setTitle('Changes Saved');
- $error_view->appendChild('Repository changes were saved.');
- }
-
- $encoding_doc_link = PhabricatorEnv::getDoclink(
- 'article/User_Guide_UTF-8_and_Character_Encoding.html');
-
- $form = new AphrontFormView();
- $form
- ->setUser($user)
- ->setAction('/repository/edit/'.$repository->getID().'/')
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setLabel('Name')
- ->setName('name')
- ->setValue($repository->getName())
- ->setError($e_name)
- ->setCaption('Human-readable repository name.'))
- ->appendChild(
- id(new AphrontFormTextAreaControl())
- ->setLabel('Description')
- ->setName('description')
- ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
- ->setValue($repository->getDetail('description')))
- ->appendChild(
- id(new AphrontFormStaticControl())
- ->setLabel('Callsign')
- ->setName('callsign')
- ->setValue($repository->getCallsign()))
- ->appendChild(hsprintf('
- <p class="aphront-form-instructions">'.
- 'If source code in this repository uses a character '.
- 'encoding other than UTF-8 (for example, ISO-8859-1), '.
- 'specify it here. You can usually leave this field blank. '.
- 'See User Guide: '.
- '<a href="%s">UTF-8 and Character Encoding</a> for more information.'.
- '</p>',
- $encoding_doc_link))
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setLabel('Encoding')
- ->setName('encoding')
- ->setValue($repository->getDetail('encoding')))
- ->appendChild(
- id(new AphrontFormStaticControl())
- ->setLabel('Type')
- ->setName('type')
- ->setValue($repository->getVersionControlSystem()))
- ->appendChild(
- id(new AphrontFormStaticControl())
- ->setLabel('ID')
- ->setValue($repository->getID()))
- ->appendChild(
- id(new AphrontFormStaticControl())
- ->setLabel('PHID')
- ->setValue($repository->getPHID()))
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->setValue('Save'));
-
- $nav = $this->sideNav;
-
- $form_box = id(new PHUIObjectBoxView())
- ->setHeaderText(pht('Edit Repository'))
- ->setFormError($error_view)
- ->setForm($form);
-
- $nav->appendChild($form_box);
-
- return $this->buildApplicationPage(
- $nav,
- array(
- 'title' => pht('Edit Repository'),
- 'device' => true,
- ));
- }
-
- private function processTrackingRequest() {
- $request = $this->getRequest();
- $user = $request->getUser();
- $repository = $this->repository;
- $repository_id = $repository->getID();
-
- $errors = array();
-
- $e_uri = null;
- $e_path = null;
-
- $is_git = false;
- $is_svn = false;
- $is_mercurial = false;
-
- $e_ssh_key = null;
- $e_ssh_keyfile = null;
- $e_branch = null;
-
- switch ($repository->getVersionControlSystem()) {
- case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- $is_git = true;
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- $is_svn = true;
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
- $is_mercurial = true;
- break;
- default:
- throw new Exception("Unsupported VCS!");
- }
-
- $has_branches = ($is_git || $is_mercurial);
- $has_local = ($is_git || $is_mercurial);
- $has_branch_filter = ($is_git);
- $has_auth_support = $is_svn;
-
- if ($request->isFormPost()) {
- $tracking = ($request->getStr('tracking') == 'enabled' ? true : false);
- $repository->setDetail('tracking-enabled', $tracking);
- $repository->setDetail('remote-uri', $request->getStr('uri'));
- if ($has_local) {
- $repository->setDetail('local-path', $request->getStr('path'));
- }
-
- if ($has_branch_filter) {
- $branch_filter = $request->getStrList('branch-filter');
- $branch_filter = array_fill_keys($branch_filter, true);
-
- $repository->setDetail('branch-filter', $branch_filter);
-
- $close_commits_filter = $request->getStrList('close-commits-filter');
- $close_commits_filter = array_fill_keys($close_commits_filter, true);
-
- $repository->setDetail('close-commits-filter', $close_commits_filter);
- }
-
- $repository->setDetail(
- 'disable-autoclose',
- $request->getStr('autoclose') == 'disabled' ? true : false);
-
- $repository->setDetail(
- 'pull-frequency',
- max(1, $request->getInt('frequency')));
-
- if ($has_branches) {
- $repository->setDetail(
- 'default-branch',
- $request->getStr('default-branch'));
- if ($is_git) {
- $branch_name = $repository->getDetail('default-branch');
- if (strpos($branch_name, '/') !== false) {
- $e_branch = 'Invalid';
- $errors[] = "Your branch name should not specify an explicit ".
- "remote. For instance, use 'master', not ".
- "'origin/master'.";
- }
- }
- }
-
- $repository->setDetail(
- 'default-owners-path',
- $request->getStr(
- 'default-owners-path',
- '/'));
-
- $repository->setDetail('ssh-login', $request->getStr('ssh-login'));
- $repository->setDetail('ssh-key', $request->getStr('ssh-key'));
- $repository->setDetail('ssh-keyfile', $request->getStr('ssh-keyfile'));
-
- $repository->setDetail('http-login', $request->getStr('http-login'));
- $repository->setDetail('http-pass', $request->getStr('http-pass'));
-
- $repository->setDetail('show-user', $request->getInt('show-user'));
-
- if ($repository->getDetail('ssh-key') &&
- $repository->getDetail('ssh-keyfile')) {
- $errors[] =
- "Specify only one of 'SSH Private Key' and 'SSH Private Key File', ".
- "not both.";
- $e_ssh_key = 'Choose Only One';
- $e_ssh_keyfile = 'Choose Only One';
- }
-
- $repository->setDetail(
- 'herald-disabled',
- $request->getInt('herald-disabled', 0));
-
- if ($is_svn) {
- $repository->setUUID($request->getStr('uuid'));
- $subpath = ltrim($request->getStr('svn-subpath'), '/');
- if ($subpath) {
- $subpath = rtrim($subpath, '/').'/';
- }
- $repository->setDetail('svn-subpath', $subpath);
- }
-
- if ($tracking) {
- if (!$repository->getDetail('remote-uri')) {
- $e_uri = 'Required';
- $errors[] = "Repository URI is required.";
- } else if ($is_svn &&
- !preg_match('@/$@', $repository->getDetail('remote-uri'))) {
-
- $e_uri = 'Invalid';
- $errors[] = 'Subversion Repository Root must end in a slash ("/").';
- } else {
- $e_uri = null;
- }
-
- if ($has_local) {
- if (!$repository->getDetail('local-path')) {
- $e_path = 'Required';
- $errors[] = "Local path is required.";
- } else {
- $e_path = null;
- }
- }
- }
-
- if (!$errors) {
- $repository->save();
- return id(new AphrontRedirectResponse())
- ->setURI('/repository/edit/'.$repository_id.'/tracking/?saved=true');
- }
- }
-
- $error_view = null;
- if ($errors) {
- $error_view = new AphrontErrorView();
- $error_view->setErrors($errors);
- $error_view->setTitle('Form Errors');
- } else if ($request->getStr('saved')) {
- $error_view = new AphrontErrorView();
- $error_view->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
- $error_view->setTitle('Changes Saved');
- $error_view->appendChild('Tracking changes were saved.');
- } else if (!$repository->isTracked()) {
- $error_view = new AphrontErrorView();
- $error_view->setSeverity(AphrontErrorView::SEVERITY_WARNING);
- $error_view->setTitle('Repository Not Tracked');
- $error_view->appendChild(
- 'Tracking is currently "Disabled" for this repository, so it will '.
- 'not be imported into Phabricator. You can enable it below.');
- }
-
- switch ($repository->getVersionControlSystem()) {
- case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- $is_git = true;
- break;
- case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
- $is_svn = true;
- break;
- }
-
- $doc_href = PhabricatorEnv::getDoclink('article/Diffusion_User_Guide.html');
- $user_guide_link = phutil_tag(
- 'a',
- array(
- 'href' => $doc_href,
- ),
- 'Diffusion User Guide');
-
- $form = new AphrontFormView();
- $form
- ->setUser($user)
- ->setAction('/repository/edit/'.$repository->getID().'/tracking/')
- ->appendChild(hsprintf(
- '<p class="aphront-form-instructions">Phabricator can track '.
- 'repositories, importing commits as they happen and notifying '.
- 'Differential, Diffusion, Herald, and other services. To enable '.
- 'tracking for a repository, configure it here and then start (or '.
- 'restart) the daemons. More information is available in the '.
- '<strong>%s</strong>.</p>',
- $user_guide_link));
-
- $form
- ->appendChild(
- id(new AphrontFormInsetView())
- ->setTitle('Basics')
- ->appendChild(id(new AphrontFormStaticControl())
- ->setLabel('Repository Name')
- ->setValue($repository->getName()))
- ->appendChild(id(new AphrontFormSelectControl())
- ->setName('tracking')
- ->setLabel('Tracking')
- ->setOptions(array(
- 'disabled' => 'Disabled',
- 'enabled' => 'Enabled',
- ))
- ->setValue(
- $repository->isTracked()
- ? 'enabled'
- : 'disabled')));
-
- $inset = new AphrontFormInsetView();
- $inset->setTitle('Remote URI');
-
- $clone_command = null;
- $fetch_command = null;
- if ($is_git) {
- $clone_command = 'git clone';
- $fetch_command = 'git fetch';
- } else if ($is_mercurial) {
- $clone_command = 'hg clone';
- $fetch_command = 'hg pull';
- }
-
- $uri_label = 'Repository URI';
- if ($has_local) {
- if ($is_git) {
- $instructions = hsprintf(
- 'Enter the URI to clone this repository from. It should look like '.
- '<tt>git@github.com:example/example.git</tt>, '.
- '<tt>ssh://user@host.com/git/example.git</tt>, or '.
- '<tt>file:///local/path/to/repo</tt>');
- } else if ($is_mercurial) {
- $instructions = hsprintf(
- 'Enter the URI to clone this repository from. It should look '.
- 'something like <tt>ssh://user@host.com/hg/example</tt>');
- }
- $inset->appendChild(hsprintf(
- '<p class="aphront-form-instructions">%s</p>',
- $instructions));
- } else if ($is_svn) {
- $instructions = hsprintf(
- 'Enter the <strong>Repository Root</strong> for this SVN repository. '.
- 'You can figure this out by running <tt>svn info</tt> and looking at '.
- 'the value in the <tt>Repository Root</tt> field. It should be a URI '.
- 'and look like <tt>http://svn.example.org/svn/</tt>, '.
- '<tt>svn+ssh://svn.example.com/svnroot/</tt>, or '.
- '<tt>svn://svn.example.net/svn/</tt>');
- $inset->appendChild(hsprintf(
- '<p class="aphront-form-instructions">%s</p>',
- $instructions));
- $uri_label = 'Repository Root';
- }
-
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('uri')
- ->setLabel($uri_label)
- ->setID('remote-uri')
- ->setValue($repository->getDetail('remote-uri'))
- ->setError($e_uri));
-
- $inset->appendChild(
- id(new AphrontFormCheckboxControl())
- ->addCheckbox(
- 'show-user',
- 1,
- pht('Permit users to view the username of this connection.'),
- $repository->getDetail('show-user') == 1));
-
- $inset->appendChild(hsprintf(
- '<div class="aphront-form-instructions">'.
- 'If you want to connect to this repository over SSH, enter the '.
- 'username and private key to use. You can leave these fields blank if '.
- 'the repository does not use SSH.'.
- '</div>'));
-
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('ssh-login')
- ->setLabel('SSH User')
- ->setValue($repository->getDetail('ssh-login')))
- ->appendChild(
- id(new AphrontFormTextAreaControl())
- ->setName('ssh-key')
- ->setLabel('SSH Private Key')
- ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
- ->setValue($repository->getDetail('ssh-key'))
- ->setError($e_ssh_key)
- ->setCaption(
- hsprintf('Specify the entire private key, <em>or</em>...')))
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('ssh-keyfile')
- ->setLabel('SSH Private Key File')
- ->setValue($repository->getDetail('ssh-keyfile'))
- ->setError($e_ssh_keyfile)
- ->setCaption(
- '...specify a path on disk where the daemon should '.
- 'look for a private key.'));
-
- if ($has_auth_support) {
- $inset
- ->appendChild(hsprintf(
- '<div class="aphront-form-instructions">'.
- 'If you want to connect to this repository with a username and '.
- 'password, such as over HTTP Basic Auth or SVN with SASL, '.
- 'enter the username and password to use. You can leave these '.
- 'fields blank if the repository does not use a username and '.
- 'password for authentication.'.
- '</div>'))
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('http-login')
- ->setLabel('Username')
- ->setValue($repository->getDetail('http-login')))
- ->appendChild(
- id(new AphrontFormPasswordControl())
- ->setName('http-pass')
- ->setLabel('Password')
- ->setValue($repository->getDetail('http-pass')));
- }
-
- $inset
- ->appendChild(hsprintf(
- '<div class="aphront-form-important">'.
- 'To test your authentication configuration, <strong>save this '.
- 'form</strong> and then run this script:'.
- '<code>'.
- 'phabricator/ $ ./scripts/repository/test_connection.php %s'.
- '</code>'.
- 'This will verify that your configuration is correct and the '.
- 'daemons can connect to the remote repository and pull changes '.
- 'from it.'.
- '</div>',
- $repository->getCallsign()));
-
- $form->appendChild($inset);
-
- $inset = new AphrontFormInsetView();
- $inset->setTitle('Repository Information');
-
- if ($has_local) {
- $default_local_path = '';
- $default =
- PhabricatorEnv::getEnvConfig('repository.default-local-path');
- if (!$repository->getDetail('remote-uri') && $default) {
- $default_local_path = $default.strtolower($repository->getCallsign());
- }
- $inset->appendChild(hsprintf(
- '<p class="aphront-form-instructions">Select a path on local disk '.
- 'which the daemons should <tt>%s</tt> the repository into. This must '.
- 'be readable and writable by the daemons, and readable by the '.
- 'webserver. The daemons will <tt>%s</tt> and keep this repository up '.
- 'to date.</p>',
- $clone_command,
- $fetch_command));
- $inset->appendChild(
- id(new AphrontFormTextControl())
- ->setName('path')
- ->setLabel('Local Path')
- ->setValue($repository->getDetail('local-path', $default_local_path))
- ->setError($e_path));
- } else if ($is_svn) {
- $inset->appendChild(hsprintf(
- '<p class="aphront-form-instructions">If you only want to parse one '.
- 'subpath of the repository, specify it here, relative to the '.
- 'repository root (e.g., <tt>trunk/</tt> or <tt>projects/wheel/</tt>). '.
- 'If you want to parse multiple subdirectories, create a separate '.
- 'Phabricator repository for each one.</p>'));
- $inset->appendChild(
- id(new AphrontFormTextControl())
- ->setName('svn-subpath')
- ->setLabel('Subpath')
- ->setValue($repository->getDetail('svn-subpath'))
- ->setError($e_path));
- }
-
- if ($has_branch_filter) {
- $branch_filter_str = implode(
- ', ',
- array_keys($repository->getDetail('branch-filter', array())));
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('branch-filter')
- ->setLabel('Track Only')
- ->setValue($branch_filter_str)
- ->setCaption(hsprintf(
- 'Optional list of branches to track. Other branches will be '.
- 'completely ignored. If left empty, all branches are tracked. '.
- 'Example: <tt>master, release</tt>')));
- }
-
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('frequency')
- ->setLabel('Pull Frequency')
- ->setValue($repository->getDetail('pull-frequency', 15))
- ->setCaption(
- 'Number of seconds daemon should sleep between requests. Larger '.
- 'numbers reduce load but also decrease responsiveness.'));
-
- $form->appendChild($inset);
-
- $inset = new AphrontFormInsetView();
- $inset->setTitle('Application Configuration');
-
- if ($has_branches) {
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('default-branch')
- ->setLabel('Default Branch')
- ->setValue($repository->getDefaultBranch())
- ->setError($e_branch)
- ->setCaption(
- 'Default branch to show in Diffusion.'));
- }
-
- $inset
- ->appendChild(id(new AphrontFormSelectControl())
- ->setName('autoclose')
- ->setLabel('Autoclose')
- ->setOptions(array(
- 'enabled' => 'Enabled: Automatically Close Pushed Revisions',
- 'disabled' => 'Disabled: Ignore Pushed Revisions',
- ))
- ->setCaption(
- "Automatically close Differential revisions when associated commits ".
- "are pushed to this repository.")
- ->setValue(
- $repository->getDetail('disable-autoclose', false)
- ? 'disabled'
- : 'enabled'));
-
- if ($has_branch_filter) {
- $close_commits_filter_str = implode(
- ', ',
- array_keys($repository->getDetail('close-commits-filter', array())));
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('close-commits-filter')
- ->setLabel('Autoclose Branches')
- ->setValue($close_commits_filter_str)
- ->setCaption(
- 'Optional list of branches which can trigger autoclose. '.
- 'If left empty, all branches trigger autoclose.'));
- }
-
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('default-owners-path')
- ->setLabel('Default Owners Path')
- ->setValue(
- $repository->getDetail(
- 'default-owners-path',
- '/'))
- ->setCaption('Default path in Owners tool.'));
-
- $inset
- ->appendChild(
- id(new AphrontFormSelectControl())
- ->setName('herald-disabled')
- ->setLabel('Herald/Feed Enabled')
- ->setValue($repository->getDetail('herald-disabled', 0))
- ->setOptions(
- array(
- 0 => 'Enabled - Send Email and Publish Stories',
- 1 => 'Disabled - Do Not Send Email or Publish Stories',
- ))
- ->setCaption(
- 'You can disable Herald commit notifications and feed stories '.
- 'for this repository. This can be useful when initially importing '.
- 'a repository. Feed stories are never published about commits '.
- 'that are more than 24 hours old.'));
-
- if ($is_svn) {
- $inset
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('uuid')
- ->setLabel('UUID')
- ->setValue($repository->getUUID())
- ->setCaption(hsprintf('Repository UUID from <tt>svn info</tt>.')));
- }
-
- $form->appendChild($inset);
-
- $form
- ->appendChild(
- id(new AphrontFormSubmitControl())
- ->setValue('Save Configuration'));
-
- $form_box = id(new PHUIObjectBoxView())
- ->setHeaderText(pht('Edit Repository Tracking'))
- ->setFormError($error_view)
- ->setForm($form);
-
- $nav = $this->sideNav;
- $nav->appendChild($form_box);
-
- return $this->buildApplicationPage(
- $nav,
- array(
- 'title' => pht('Edit Repository Tracking'),
- ));
- }
-
-}
diff --git a/src/applications/repository/controller/PhabricatorRepositoryListController.php b/src/applications/repository/controller/PhabricatorRepositoryListController.php
index 535cf69cdb..b7c839e427 100644
--- a/src/applications/repository/controller/PhabricatorRepositoryListController.php
+++ b/src/applications/repository/controller/PhabricatorRepositoryListController.php
@@ -1,155 +1,155 @@
<?php
final class PhabricatorRepositoryListController
extends PhabricatorRepositoryController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$is_admin = $user->getIsAdmin();
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($user)
->execute();
$repos = msort($repos, 'getName');
$rows = array();
foreach ($repos as $repo) {
if ($repo->isTracked()) {
$diffusion_link = phutil_tag(
'a',
array(
'href' => '/diffusion/'.$repo->getCallsign().'/',
),
'View in Diffusion');
} else {
$diffusion_link = phutil_tag('em', array(), 'Not Tracked');
}
$rows[] = array(
$repo->getCallsign(),
$repo->getName(),
PhabricatorRepositoryType::getNameForRepositoryType(
$repo->getVersionControlSystem()),
$diffusion_link,
phutil_tag(
'a',
array(
'class' => 'button small grey',
- 'href' => '/repository/edit/'.$repo->getID().'/',
+ 'href' => '/diffusion/'.$repo->getCallsign().'/edit/',
),
'Edit'),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Callsign',
'Repository',
'Type',
'Diffusion',
'',
));
$table->setColumnClasses(
array(
null,
'wide',
null,
null,
'action',
));
$table->setColumnVisibility(
array(
true,
true,
true,
true,
$is_admin,
));
$panel = new AphrontPanelView();
$panel->setHeader('Repositories');
if ($is_admin) {
- $panel->setCreateButton('Create New Repository', '/repository/create/');
+ $panel->setCreateButton('Create New Repository', '/diffusion/create/');
}
$panel->appendChild($table);
$panel->setNoBackground();
$projects = id(new PhabricatorRepositoryArcanistProject())->loadAll();
$rows = array();
foreach ($projects as $project) {
$repo = idx($repos, $project->getRepositoryID());
if ($repo) {
$repo_name = $repo->getName();
} else {
$repo_name = '-';
}
$rows[] = array(
$project->getName(),
$repo_name,
phutil_tag(
'a',
array(
'href' => '/repository/project/edit/'.$project->getID().'/',
'class' => 'button grey small',
),
'Edit'),
javelin_tag(
'a',
array(
'href' => '/repository/project/delete/'.$project->getID().'/',
'class' => 'button grey small',
'sigil' => 'workflow',
),
'Delete'),
);
}
$project_table = new AphrontTableView($rows);
$project_table->setHeaders(
array(
'Project ID',
'Repository',
'',
'',
));
$project_table->setColumnClasses(
array(
'',
'wide',
'action',
'action',
));
$project_table->setColumnVisibility(
array(
true,
true,
$is_admin,
$is_admin,
));
$project_panel = new AphrontPanelView();
$project_panel->setHeader('Arcanist Projects');
$project_panel->appendChild($project_table);
$project_panel->setNoBackground();
return $this->buildStandardPageResponse(
array(
$this->renderDaemonNotice(),
$panel,
$project_panel,
),
array(
'title' => 'Repository List',
));
}
}
diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
index 503b4a7bc0..5feee191ed 100644
--- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
+++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
@@ -1,722 +1,774 @@
<?php
/**
* Run pull commands on local working copies to keep them up to date. This
* daemon handles all repository types.
*
* By default, the daemon pulls **every** repository. If you want it to be
* responsible for only some repositories, you can launch it with a list of
* PHIDs or callsigns:
*
* ./phd launch repositorypulllocal -- X Q Z
*
* You can also launch a daemon which is responsible for all //but// one or
* more repositories:
*
* ./phd launch repositorypulllocal -- --not A --not B
*
* If you have a very large number of repositories and some aren't being pulled
* as frequently as you'd like, you can either change the pull frequency of
* the less-important repositories to a larger number (so the daemon will skip
* them more often) or launch one daemon for all the less-important repositories
* and one for the more important repositories (or one for each more important
* repository).
*
* @task pull Pulling Repositories
* @task git Git Implementation
* @task hg Mercurial Implementation
*/
final class PhabricatorRepositoryPullLocalDaemon
extends PhabricatorDaemon {
private $commitCache = array();
private $repair;
private $discoveryEngines = array();
public function setRepair($repair) {
$this->repair = $repair;
return $this;
}
/* -( Pulling Repositories )----------------------------------------------- */
/**
* @task pull
*/
public function run() {
$argv = $this->getArgv();
array_unshift($argv, __CLASS__);
$args = new PhutilArgumentParser($argv);
$args->parse(
array(
array(
'name' => 'no-discovery',
'help' => 'Pull only, without discovering commits.',
),
array(
'name' => 'not',
'param' => 'repository',
'repeat' => true,
'help' => 'Do not pull __repository__.',
),
array(
'name' => 'repositories',
'wildcard' => true,
'help' => 'Pull specific __repositories__ instead of all.',
),
));
$no_discovery = $args->getArg('no-discovery');
$repo_names = $args->getArg('repositories');
$exclude_names = $args->getArg('not');
// Each repository has an individual pull frequency; after we pull it,
// wait that long to pull it again. When we start up, try to pull everything
// serially.
$retry_after = array();
$min_sleep = 15;
while (true) {
$repositories = $this->loadRepositories($repo_names);
if ($exclude_names) {
$exclude = $this->loadRepositories($exclude_names);
$repositories = array_diff_key($repositories, $exclude);
}
// Shuffle the repositories, then re-key the array since shuffle()
// discards keys. This is mostly for startup, we'll use soft priorities
// later.
shuffle($repositories);
$repositories = mpull($repositories, null, 'getID');
// If any repositories were deleted, remove them from the retry timer map
// so we don't end up with a retry timer that never gets updated and
// causes us to sleep for the minimum amount of time.
$retry_after = array_select_keys(
$retry_after,
array_keys($repositories));
// Assign soft priorities to repositories based on how frequently they
// should pull again.
asort($retry_after);
$repositories = array_select_keys(
$repositories,
array_keys($retry_after)) + $repositories;
foreach ($repositories as $id => $repository) {
$after = idx($retry_after, $id, 0);
if ($after > time()) {
continue;
}
$tracked = $repository->isTracked();
if (!$tracked) {
continue;
}
$callsign = $repository->getCallsign();
try {
$this->log("Updating repository '{$callsign}'.");
id(new PhabricatorRepositoryPullEngine())
->setRepository($repository)
->pullRepository();
if (!$no_discovery) {
// TODO: It would be nice to discover only if we pulled something,
- // but this isn't totally trivial.
+ // but this isn't totally trivial. It's slightly more complicated
+ // with hosted repositories, too.
$lock_name = get_class($this).':'.$callsign;
$lock = PhabricatorGlobalLock::newLock($lock_name);
$lock->lock();
try {
$this->discoverRepository($repository);
} catch (Exception $ex) {
$lock->unlock();
throw $ex;
}
$lock->unlock();
}
$sleep_for = $repository->getDetail('pull-frequency', $min_sleep);
$retry_after[$id] = time() + $sleep_for;
} catch (PhutilLockException $ex) {
$retry_after[$id] = time() + $min_sleep;
$this->log("Failed to acquire lock.");
} catch (Exception $ex) {
$retry_after[$id] = time() + $min_sleep;
$proxy = new PhutilProxyException(
"Error while fetching changes to the '{$callsign}' repository.",
$ex);
phlog($proxy);
}
$this->stillWorking();
}
if ($retry_after) {
$sleep_until = max(min($retry_after), time() + $min_sleep);
} else {
$sleep_until = time() + $min_sleep;
}
$this->sleep($sleep_until - time());
}
}
/**
* @task pull
*/
protected function loadRepositories(array $names) {
$query = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer());
if ($names) {
$query->withCallsigns($names);
}
$repos = $query->execute();
if ($names) {
$by_callsign = mpull($repos, null, 'getCallsign');
foreach ($names as $name) {
if (empty($by_callsign[$name])) {
throw new Exception(
"No repository exists with callsign '{$name}'!");
}
}
}
return $repos;
}
public function discoverRepository(PhabricatorRepository $repository) {
$vcs = $repository->getVersionControlSystem();
+
+ $result = null;
+ $refs = null;
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- return $this->executeGitDiscover($repository);
+ $result = $this->executeGitDiscover($repository);
+ break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$refs = $this->getDiscoveryEngine($repository)
->discoverCommits();
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
- return $this->executeHgDiscover($repository);
+ $result = $this->executeHgDiscover($repository);
+ break;
default:
throw new Exception("Unknown VCS '{$vcs}'!");
}
- foreach ($refs as $ref) {
- $this->recordCommit(
- $repository,
- $ref->getIdentifier(),
- $ref->getEpoch(),
- $ref->getBranch());
+ if ($refs !== null) {
+ foreach ($refs as $ref) {
+ $this->recordCommit(
+ $repository,
+ $ref->getIdentifier(),
+ $ref->getEpoch(),
+ $ref->getBranch());
+ }
}
- return (bool)count($refs);
+ $this->checkIfRepositoryIsFullyImported($repository);
+
+ if ($refs !== null) {
+ return (bool)count($refs);
+ } else {
+ return $result;
+ }
}
private function getDiscoveryEngine(PhabricatorRepository $repository) {
$id = $repository->getID();
if (empty($this->discoveryEngines[$id])) {
$engine = id(new PhabricatorRepositoryDiscoveryEngine())
->setRepository($repository)
->setVerbose($this->getVerbose())
->setRepairMode($this->repair);
$this->discoveryEngines[$id] = $engine;
}
return $this->discoveryEngines[$id];
}
private function isKnownCommit(
PhabricatorRepository $repository,
$target) {
if ($this->getCache($repository, $target)) {
return true;
}
if ($this->repair) {
// In repair mode, rediscover the entire repository, ignoring the
// database state. We can hit the local cache above, but if we miss it
// stop the script from going to the database cache.
return false;
}
$commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repository->getID(),
$target);
if (!$commit) {
return false;
}
$this->setCache($repository, $target);
while (count($this->commitCache) > 2048) {
array_shift($this->commitCache);
}
return true;
}
private function isKnownCommitOnAnyAutocloseBranch(
PhabricatorRepository $repository,
$target) {
$commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repository->getID(),
$target);
if (!$commit) {
$callsign = $repository->getCallsign();
$console = PhutilConsole::getConsole();
$console->writeErr(
"WARNING: Repository '%s' is missing commits ('%s' is missing from ".
"history). Run '%s' to repair the repository.\n",
$callsign,
$target,
"bin/repository discover --repair {$callsign}");
return false;
}
$data = $commit->loadCommitData();
if (!$data) {
return false;
}
if ($repository->shouldAutocloseCommit($commit, $data)) {
return true;
}
return false;
}
private function recordCommit(
PhabricatorRepository $repository,
$commit_identifier,
$epoch,
$branch = null) {
$commit = new PhabricatorRepositoryCommit();
$commit->setRepositoryID($repository->getID());
$commit->setCommitIdentifier($commit_identifier);
$commit->setEpoch($epoch);
$data = new PhabricatorRepositoryCommitData();
if ($branch) {
$data->setCommitDetail('seenOnBranches', array($branch));
}
try {
$commit->openTransaction();
$commit->save();
$data->setCommitID($commit->getID());
$data->save();
$commit->saveTransaction();
$this->insertTask($repository, $commit);
queryfx(
$repository->establishConnection('w'),
'INSERT INTO %T (repositoryID, size, lastCommitID, epoch)
VALUES (%d, 1, %d, %d)
ON DUPLICATE KEY UPDATE
size = size + 1,
lastCommitID =
IF(VALUES(epoch) > epoch, VALUES(lastCommitID), lastCommitID),
epoch = IF(VALUES(epoch) > epoch, VALUES(epoch), epoch)',
PhabricatorRepository::TABLE_SUMMARY,
$repository->getID(),
$commit->getID(),
$epoch);
if ($this->repair) {
// Normally, the query should throw a duplicate key exception. If we
// reach this in repair mode, we've actually performed a repair.
$this->log("Repaired commit '{$commit_identifier}'.");
}
$this->setCache($repository, $commit_identifier);
PhutilEventEngine::dispatchEvent(
new PhabricatorEvent(
PhabricatorEventType::TYPE_DIFFUSION_DIDDISCOVERCOMMIT,
array(
'repository' => $repository,
'commit' => $commit,
)));
} catch (AphrontQueryDuplicateKeyException $ex) {
$commit->killTransaction();
// Ignore. This can happen because we discover the same new commit
// more than once when looking at history, or because of races or
// data inconsistency or cosmic radiation; in any case, we're still
// in a good state if we ignore the failure.
$this->setCache($repository, $commit_identifier);
}
}
private function updateCommit(
PhabricatorRepository $repository,
$commit_identifier,
$branch) {
$commit = id(new PhabricatorRepositoryCommit())->loadOneWhere(
'repositoryID = %d AND commitIdentifier = %s',
$repository->getID(),
$commit_identifier);
if (!$commit) {
// This can happen if the phabricator DB doesn't have the commit info,
// or the commit is so big that phabricator couldn't parse it. In this
// case we just ignore it.
return;
}
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
if (!$data) {
$data = new PhabricatorRepositoryCommitData();
$data->setCommitID($commit->getID());
}
$branches = $data->getCommitDetail('seenOnBranches', array());
$branches[] = $branch;
$data->setCommitDetail('seenOnBranches', $branches);
$data->save();
$this->insertTask(
$repository,
$commit,
array(
'only' => true
));
}
private function insertTask(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit,
$data = array()) {
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$class = 'PhabricatorRepositoryGitCommitMessageParserWorker';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$class = 'PhabricatorRepositorySvnCommitMessageParserWorker';
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$class = 'PhabricatorRepositoryMercurialCommitMessageParserWorker';
break;
default:
throw new Exception("Unknown repository type '{$vcs}'!");
}
$data['commitID'] = $commit->getID();
PhabricatorWorker::scheduleTask($class, $data);
}
private function setCache(
PhabricatorRepository $repository,
$commit_identifier) {
$key = $this->getCacheKey($repository, $commit_identifier);
$this->commitCache[$key] = true;
}
private function getCache(
PhabricatorRepository $repository,
$commit_identifier) {
$key = $this->getCacheKey($repository, $commit_identifier);
return idx($this->commitCache, $key, false);
}
private function getCacheKey(
PhabricatorRepository $repository,
$commit_identifier) {
return $repository->getID().':'.$commit_identifier;
}
+ private function checkIfRepositoryIsFullyImported(
+ PhabricatorRepository $repository) {
+ // Check if the repository has the "Importing" flag set. We want to clear
+ // the flag if we can.
+ $importing = $repository->getDetail('importing');
+ if (!$importing) {
+ // This repository isn't marked as "Importing", so we're done.
+ return;
+ }
+
+ // Look for any commit which hasn't imported.
+ $unparsed_commit = queryfx_one(
+ $repository->establishConnection('r'),
+ 'SELECT * FROM %T WHERE repositoryID = %d AND importStatus != %d',
+ id(new PhabricatorRepositoryCommit())->getTableName(),
+ $repository->getID(),
+ PhabricatorRepositoryCommit::IMPORTED_ALL);
+ if ($unparsed_commit) {
+ // We found a commit which still needs to import, so we can't clear the
+ // flag.
+ return;
+ }
+
+ // Clear the "importing" flag.
+ $repository->openTransaction();
+ $repository->beginReadLocking();
+ $repository = $repository->reload();
+ $repository->setDetail('importing', false);
+ $repository->save();
+ $repository->endReadLocking();
+ $repository->saveTransaction();
+ }
/* -( Git Implementation )------------------------------------------------- */
/**
* @task git
*/
private function executeGitDiscover(
PhabricatorRepository $repository) {
list($remotes) = $repository->execxLocalCommand(
'remote show -n origin');
$matches = null;
if (!preg_match('/^\s*Fetch URL:\s*(.*?)\s*$/m', $remotes, $matches)) {
throw new Exception(
"Expected 'Fetch URL' in 'git remote show -n origin'.");
}
self::executeGitVerifySameOrigin(
$matches[1],
$repository->getRemoteURI(),
$repository->getLocalPath());
list($stdout) = $repository->execxLocalCommand(
'branch -r --verbose --no-abbrev');
$branches = DiffusionGitBranch::parseRemoteBranchOutput(
$stdout,
$only_this_remote = DiffusionBranchInformation::DEFAULT_GIT_REMOTE);
+ if (!$branches) {
+ // This repository has no branches at all, so we don't need to do
+ // anything. Generally, this means the repository is empty.
+ return;
+ }
+
$callsign = $repository->getCallsign();
$tracked_something = false;
$this->log("Discovering commits in repository '{$callsign}'...");
foreach ($branches as $name => $commit) {
$this->log("Examining branch '{$name}', at {$commit}.");
if (!$repository->shouldTrackBranch($name)) {
$this->log("Skipping, branch is untracked.");
continue;
}
$tracked_something = true;
if ($this->isKnownCommit($repository, $commit)) {
$this->log("Skipping, HEAD is known.");
continue;
}
$this->log("Looking for new commits.");
$this->executeGitDiscoverCommit($repository, $commit, $name, false);
}
if (!$tracked_something) {
$repo_name = $repository->getName();
$repo_callsign = $repository->getCallsign();
throw new Exception(
"Repository r{$repo_callsign} '{$repo_name}' has no tracked branches! ".
"Verify that your branch filtering settings are correct.");
}
$this->log("Discovering commits on autoclose branches...");
foreach ($branches as $name => $commit) {
$this->log("Examining branch '{$name}', at {$commit}'.");
if (!$repository->shouldTrackBranch($name)) {
$this->log("Skipping, branch is untracked.");
continue;
}
if (!$repository->shouldAutocloseBranch($name)) {
$this->log("Skipping, branch is not autoclose.");
continue;
}
if ($this->isKnownCommitOnAnyAutocloseBranch($repository, $commit)) {
$this->log("Skipping, commit is known on an autoclose branch.");
continue;
}
$this->log("Looking for new autoclose commits.");
$this->executeGitDiscoverCommit($repository, $commit, $name, true);
}
}
/**
* @task git
*/
private function executeGitDiscoverCommit(
PhabricatorRepository $repository,
$commit,
$branch,
$autoclose) {
$discover = array($commit);
$insert = array($commit);
$seen_parent = array();
$stream = new PhabricatorGitGraphStream($repository, $commit);
while (true) {
$target = array_pop($discover);
$parents = $stream->getParents($target);
foreach ($parents as $parent) {
if (isset($seen_parent[$parent])) {
// We end up in a loop here somehow when we parse Arcanist if we
// don't do this. TODO: Figure out why and draw a pretty diagram
// since it's not evident how parsing a DAG with this causes the
// loop to stop terminating.
continue;
}
$seen_parent[$parent] = true;
if ($autoclose) {
$known = $this->isKnownCommitOnAnyAutocloseBranch(
$repository,
$parent);
} else {
$known = $this->isKnownCommit($repository, $parent);
}
if (!$known) {
$this->log("Discovered commit '{$parent}'.");
$discover[] = $parent;
$insert[] = $parent;
}
}
if (empty($discover)) {
break;
}
}
$n = count($insert);
if ($autoclose) {
$this->log("Found {$n} new autoclose commits on branch '{$branch}'.");
} else {
$this->log("Found {$n} new commits on branch '{$branch}'.");
}
while (true) {
$target = array_pop($insert);
$epoch = $stream->getCommitDate($target);
$epoch = trim($epoch);
if ($autoclose) {
$this->updateCommit($repository, $target, $branch);
} else {
$this->recordCommit($repository, $target, $epoch, $branch);
}
if (empty($insert)) {
break;
}
}
}
/**
* @task git
*/
public static function executeGitVerifySameOrigin($remote, $expect, $where) {
$remote_path = self::getPathFromGitURI($remote);
$expect_path = self::getPathFromGitURI($expect);
$remote_match = self::executeGitNormalizePath($remote_path);
$expect_match = self::executeGitNormalizePath($expect_path);
if ($remote_match != $expect_match) {
throw new Exception(
"Working copy at '{$where}' has a mismatched origin URL. It has ".
"origin URL '{$remote}' (with remote path '{$remote_path}'), but the ".
"configured URL '{$expect}' (with remote path '{$expect_path}') is ".
"expected. Refusing to proceed because this may indicate that the ".
"working copy is actually some other repository.");
}
}
private static function getPathFromGitURI($raw_uri) {
$uri = new PhutilURI($raw_uri);
if ($uri->getProtocol()) {
return $uri->getPath();
}
$uri = new PhutilGitURI($raw_uri);
if ($uri->getDomain()) {
return $uri->getPath();
}
return $raw_uri;
}
/**
* @task git
*/
private static function executeGitNormalizePath($path) {
// Strip away "/" and ".git", so similar paths correctly match.
$path = trim($path, '/');
$path = preg_replace('/\.git$/', '', $path);
return $path;
}
/* -( Mercurial Implementation )------------------------------------------- */
private function executeHgDiscover(PhabricatorRepository $repository) {
// NOTE: "--debug" gives us 40-character hashes.
list($stdout) = $repository->execxLocalCommand('--debug branches');
$branches = ArcanistMercurialParser::parseMercurialBranches($stdout);
$got_something = false;
foreach ($branches as $name => $branch) {
$commit = $branch['rev'];
if ($this->isKnownCommit($repository, $commit)) {
continue;
} else {
$this->executeHgDiscoverCommit($repository, $commit);
$got_something = true;
}
}
return $got_something;
}
private function executeHgDiscoverCommit(
PhabricatorRepository $repository,
$commit) {
$discover = array($commit);
$insert = array($commit);
$seen_parent = array();
$stream = new PhabricatorMercurialGraphStream($repository);
// For all the new commits at the branch heads, walk backward until we
// find only commits we've aleady seen.
while ($discover) {
$target = array_pop($discover);
$parents = $stream->getParents($target);
foreach ($parents as $parent) {
if (isset($seen_parent[$parent])) {
continue;
}
$seen_parent[$parent] = true;
if (!$this->isKnownCommit($repository, $parent)) {
$discover[] = $parent;
$insert[] = $parent;
}
}
}
foreach ($insert as $target) {
$epoch = $stream->getCommitDate($target);
$this->recordCommit($repository, $target, $epoch);
}
}
}
diff --git a/src/applications/repository/editor/PhabricatorRepositoryEditor.php b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
index dca02acd8d..cf28febdf0 100644
--- a/src/applications/repository/editor/PhabricatorRepositoryEditor.php
+++ b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
@@ -1,222 +1,289 @@
<?php
final class PhabricatorRepositoryEditor
extends PhabricatorApplicationTransactionEditor {
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
+ $types[] = PhabricatorRepositoryTransaction::TYPE_VCS;
$types[] = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
$types[] = PhabricatorRepositoryTransaction::TYPE_NAME;
$types[] = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION;
$types[] = PhabricatorRepositoryTransaction::TYPE_ENCODING;
$types[] = PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH;
$types[] = PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY;
$types[] = PhabricatorRepositoryTransaction::TYPE_UUID;
$types[] = PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH;
$types[] = PhabricatorRepositoryTransaction::TYPE_NOTIFY;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE;
$types[] = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEY;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE;
$types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN;
$types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS;
$types[] = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH;
+ $types[] = PhabricatorRepositoryTransaction::TYPE_HOSTING;
+ $types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
+ $types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
+ $types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
+ case PhabricatorRepositoryTransaction::TYPE_VCS:
+ return $object->getVersionControlSystem();
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
return $object->isTracked();
case PhabricatorRepositoryTransaction::TYPE_NAME:
return $object->getName();
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
return $object->getDetail('description');
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
return $object->getDetail('encoding');
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
return $object->getDetail('default-branch');
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
return array_keys($object->getDetail('branch-filter', array()));
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
return array_keys($object->getDetail('close-commits-filter', array()));
case PhabricatorRepositoryTransaction::TYPE_UUID:
return $object->getUUID();
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
return $object->getDetail('svn-subpath');
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
return (int)!$object->getDetail('herald-disabled');
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
return (int)!$object->getDetail('disable-autoclose');
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
return $object->getDetail('remote-uri');
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
return $object->getDetail('ssh-login');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
return $object->getDetail('ssh-key');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
return $object->getDetail('ssh-keyfile');
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
return $object->getDetail('http-login');
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
return $object->getDetail('http-pass');
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
return $object->getDetail('local-path');
+ case PhabricatorRepositoryTransaction::TYPE_HOSTING:
+ return $object->isHosted();
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
+ return $object->getServeOverHTTP();
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
+ return $object->getServeOverSSH();
+ case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
+ return $object->getPushPolicy();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
case PhabricatorRepositoryTransaction::TYPE_NAME:
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
case PhabricatorRepositoryTransaction::TYPE_UUID:
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
+ case PhabricatorRepositoryTransaction::TYPE_VCS:
+ case PhabricatorRepositoryTransaction::TYPE_HOSTING:
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
+ case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
return $xaction->getNewValue();
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
return (int)$xaction->getNewValue();
}
}
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
+ case PhabricatorRepositoryTransaction::TYPE_VCS:
+ $object->setVersionControlSystem($xaction->getNewValue());
+ break;
case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
$object->setDetail('tracking-enabled', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
$object->setDetail('description', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
$object->setDetail('default-branch', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
$object->setDetail(
'branch-filter',
array_fill_keys($xaction->getNewValue(), true));
break;
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
$object->setDetail(
'close-commits-filter',
array_fill_keys($xaction->getNewValue(), true));
break;
case PhabricatorRepositoryTransaction::TYPE_UUID:
$object->setUUID($xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
$object->setDetail('svn-subpath', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
$object->setDetail('herald-disabled', (int)!$xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
$object->setDetail('disable-autoclose', (int)!$xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
$object->setDetail('remote-uri', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
$object->setDetail('ssh-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
$object->setDetail('ssh-key', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
$object->setDetail('ssh-keyfile', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
$object->setDetail('http-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
$object->setDetail('http-pass', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
$object->setDetail('local-path', $xaction->getNewValue());
break;
+ case PhabricatorRepositoryTransaction::TYPE_HOSTING:
+ return $object->setHosted($xaction->getNewValue());
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
+ return $object->setServeOverHTTP($xaction->getNewValue());
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
+ return $object->setServeOverSSH($xaction->getNewValue());
+ case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
+ return $object->setPushPolicy($xaction->getNewValue());
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't type
// a garbage encoding name. Note that we're converting from UTF-8 to
// the target encoding, because mbstring is fine with converting from
// a nonsense encoding.
$encoding = $xaction->getNewValue();
if (strlen($encoding)) {
try {
phutil_utf8_convert('.', $encoding, 'UTF-8');
} catch (Exception $ex) {
throw new PhutilProxyException(
pht(
"Error setting repository encoding '%s': %s'",
$encoding,
$ex->getMessage()),
$ex);
}
}
$object->setDetail('encoding', $encoding);
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$type = $u->getTransactionType();
switch ($type) {
}
return parent::mergeTransactions($u, $v);
}
protected function transactionHasEffect(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$type = $xaction->getTransactionType();
switch ($type) {
}
return parent::transactionHasEffect($object, $xaction);
}
+ protected function requireCapabilities(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorRepositoryTransaction::TYPE_ACTIVATE:
+ case PhabricatorRepositoryTransaction::TYPE_NAME:
+ case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION:
+ case PhabricatorRepositoryTransaction::TYPE_ENCODING:
+ case PhabricatorRepositoryTransaction::TYPE_DEFAULT_BRANCH:
+ case PhabricatorRepositoryTransaction::TYPE_TRACK_ONLY:
+ case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
+ case PhabricatorRepositoryTransaction::TYPE_UUID:
+ case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
+ case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
+ case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
+ case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
+ case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
+ case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
+ case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
+ case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
+ case PhabricatorRepositoryTransaction::TYPE_VCS:
+ case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
+ case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
+ case PhabricatorRepositoryTransaction::TYPE_HOSTING:
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
+ case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
+ case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
+ PhabricatorPolicyFilter::requireCapability(
+ $this->requireActor(),
+ $object,
+ PhabricatorPolicyCapability::CAN_EDIT);
+ break;
+ }
+ }
+
}
diff --git a/src/applications/repository/engine/PhabricatorRepositoryEngine.php b/src/applications/repository/engine/PhabricatorRepositoryEngine.php
index 60b8a9584c..7685a91ee5 100644
--- a/src/applications/repository/engine/PhabricatorRepositoryEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryEngine.php
@@ -1,62 +1,63 @@
<?php
/**
* @task config Configuring Repository Engines
* @task internal Internals
*/
abstract class PhabricatorRepositoryEngine {
private $repository;
private $verbose;
/**
* @task config
*/
public function setRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
/**
* @task config
*/
protected function getRepository() {
if ($this->repository === null) {
throw new Exception("Call setRepository() to provide a repository!");
}
return $this->repository;
}
/**
* @task config
*/
public function setVerbose($verbose) {
$this->verbose = $verbose;
return $this;
}
/**
* @task config
*/
public function getVerbose() {
return $this->verbose;
}
/**
* @task internal
*/
protected function log($pattern /* ... */) {
if ($this->getVerbose()) {
$console = PhutilConsole::getConsole();
$argv = func_get_args();
- call_user_func_array(array($console, 'writeLog'), $argv);
+ $argv[0] = $argv[0]."\n";
+ call_user_func_array(array($console, 'writeOut'), $argv);
}
return $this;
}
}
diff --git a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
index 777e1e0a11..7e5349e01f 100644
--- a/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
+++ b/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
@@ -1,264 +1,273 @@
<?php
/**
* Manages execution of `git pull` and `hg pull` commands for
* @{class:PhabricatorRepository} objects. Used by
* @{class:PhabricatorRepositoryPullLocalDaemon}.
*
* @task pull Pulling Working Copies
* @task git Pulling Git Working Copies
* @task hg Pulling Mercurial Working Copies
* @task internal Internals
*/
final class PhabricatorRepositoryPullEngine
extends PhabricatorRepositoryEngine {
/* -( Pulling Working Copies )--------------------------------------------- */
public function pullRepository() {
$repository = $this->getRepository();
$is_hg = false;
$is_git = false;
$vcs = $repository->getVersionControlSystem();
$callsign = $repository->getCallsign();
+
+ if ($repository->isHosted()) {
+ $this->log(
+ pht(
+ 'Repository "%s" is hosted, so Phabricator does not pull updates '.
+ 'for it.',
+ $callsign));
+ return;
+ }
+
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
// We never pull a local copy of Subversion repositories.
$this->log(
"Repository '%s' is a Subversion repository, which does not require ".
"a local working copy to be pulled.",
$callsign);
return;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$is_git = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$is_hg = true;
break;
default:
throw new Exception("Unsupported VCS '{$vcs}'!");
}
$callsign = $repository->getCallsign();
$local_path = $repository->getLocalPath();
if ($local_path === null) {
throw new Exception(
"No local path is configured for repository '{$callsign}'.");
}
$dirname = dirname($local_path);
if (!Filesystem::pathExists($dirname)) {
Filesystem::createDirectory($dirname, 0755, $recursive = true);
}
if (!Filesystem::pathExists($local_path)) {
$this->log(
"Creating a new working copy for repository '%s'.",
$callsign);
if ($is_git) {
$this->executeGitCreate();
} else {
$this->executeMercurialCreate();
}
} else {
$this->log(
"Updating the working copy for repository '%s'.",
$callsign);
if ($is_git) {
$this->executeGitUpdate();
} else {
$this->executeMercurialUpdate();
}
}
return $this;
}
/* -( Pulling Git Working Copies )----------------------------------------- */
/**
* @task git
*/
private function executeGitCreate() {
$repository = $this->getRepository();
$repository->execxRemoteCommand(
- 'clone --origin origin %s %s',
+ 'clone --bare %s %s',
$repository->getRemoteURI(),
rtrim($repository->getLocalPath(), '/'));
}
/**
* @task git
*/
private function executeGitUpdate() {
$repository = $this->getRepository();
list($err, $stdout) = $repository->execLocalCommand(
'rev-parse --show-toplevel');
$message = null;
$path = $repository->getLocalPath();
if ($err) {
// Try to raise a more tailored error message in the more common case
// of the user creating an empty directory. (We could try to remove it,
// but might not be able to, and it's much simpler to raise a good
// message than try to navigate those waters.)
if (is_dir($path)) {
$files = Filesystem::listDirectory($path, $include_hidden = true);
if (!$files) {
$message =
"Expected to find a git repository at '{$path}', but there ".
"is an empty directory there. Remove the directory: the daemon ".
"will run 'git clone' for you.";
} else {
$message =
"Expected to find a git repository at '{$path}', but there is ".
"a non-repository directory (with other stuff in it) there. Move ".
"or remove this directory (or reconfigure the repository to use a ".
"different directory), and then either clone a repository ".
"yourself or let the daemon do it.";
}
} else if (is_file($path)) {
$message =
"Expected to find a git repository at '{$path}', but there is a ".
"file there instead. Remove it and let the daemon clone a ".
"repository for you.";
} else {
$message =
"Expected to find a git repository at '{$path}', but did not.";
}
} else {
$repo_path = rtrim($stdout, "\n");
if (empty($repo_path)) {
- $err = true;
- $message =
- "Expected to find a git repository at '{$path}', but ".
- "there was no result from `git rev-parse --show-toplevel`. ".
- "Something is misconfigured or broken. The git repository ".
- "may be inside a '.git/' directory.";
+ // This can mean one of two things: we're in a bare repository, or
+ // we're inside a git repository inside another git repository. Since
+ // the first is dramatically more likely now that we perform bare
+ // clones and I don't have a great way to test for the latter, assume
+ // we're OK.
} else if (!Filesystem::pathsAreEquivalent($repo_path, $path)) {
$err = true;
$message =
"Expected to find repo at '{$path}', but the actual ".
"git repository root for this directory is '{$repo_path}'. ".
"Something is misconfigured. The repository's 'Local Path' should ".
"be set to some place where the daemon can check out a working ".
"copy, and should not be inside another git repository.";
}
}
if ($err && $this->canDestroyWorkingCopy($path)) {
phlog("Repository working copy at '{$path}' failed sanity check; ".
"destroying and re-cloning. {$message}");
Filesystem::remove($path);
$this->executeGitCreate();
} else if ($err) {
throw new Exception($message);
}
$retry = false;
do {
// This is a local command, but needs credentials.
$future = $repository->getRemoteCommandFuture('fetch --all --prune');
$future->setCWD($path);
list($err, $stdout, $stderr) = $future->resolve();
if ($err && !$retry && $this->canDestroyWorkingCopy($path)) {
$retry = true;
// Fix remote origin url if it doesn't match our configuration
$origin_url = $repository->execLocalCommand(
'config --get remote.origin.url');
$remote_uri = $repository->getDetail('remote-uri');
if ($origin_url != $remote_uri) {
$repository->execLocalCommand(
'remote set-url origin %s',
$remote_uri);
}
} else if ($err) {
throw new Exception(
"git fetch failed with error #{$err}:\n".
"stdout:{$stdout}\n\n".
"stderr:{$stderr}\n");
} else {
$retry = false;
}
} while ($retry);
}
/* -( Pulling Mercurial Working Copies )----------------------------------- */
/**
* @task hg
*/
private function executeMercurialCreate() {
$repository = $this->getRepository();
$repository->execxRemoteCommand(
'clone %s %s',
$repository->getRemoteURI(),
rtrim($repository->getLocalPath(), '/'));
}
/**
* @task hg
*/
private function executeMercurialUpdate() {
$repository = $this->getRepository();
$path = $repository->getLocalPath();
// This is a local command, but needs credentials.
$future = $repository->getRemoteCommandFuture('pull -u');
$future->setCWD($path);
try {
$future->resolvex();
} catch (CommandException $ex) {
$err = $ex->getError();
$stdout = $ex->getStdOut();
// NOTE: Between versions 2.1 and 2.1.1, Mercurial changed the behavior
// of "hg pull" to return 1 in case of a successful pull with no changes.
// This behavior has been reverted, but users who updated between Feb 1,
// 2012 and Mar 1, 2012 will have the erroring version. Do a dumb test
// against stdout to check for this possibility.
// See: https://github.com/facebook/phabricator/issues/101/
// NOTE: Mercurial has translated versions, which translate this error
// string. In a translated version, the string will be something else,
// like "aucun changement trouve". There didn't seem to be an easy way
// to handle this (there are hard ways but this is not a common problem
// and only creates log spam, not application failures). Assume English.
// TODO: Remove this once we're far enough in the future that deployment
// of 2.1 is exceedingly rare?
if ($err == 1 && preg_match('/no changes found/', $stdout)) {
return;
} else {
throw $ex;
}
}
}
/* -( Internals )---------------------------------------------------------- */
private function canDestroyWorkingCopy($path) {
$default_path = PhabricatorEnv::getEnvConfig(
'repository.default-local-path');
return Filesystem::isDescendant($path, $default_path);
}
}
diff --git a/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php b/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php
index 0ab91d2b48..ac3ce297a3 100644
--- a/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php
+++ b/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php
@@ -1,32 +1,32 @@
<?php
final class PhabricatorWorkingCopyPullTestCase
extends PhabricatorWorkingCopyTestCase {
public function testGitPullBasic() {
$repo = $this->buildPulledRepository('GT');
$this->assertEqual(
true,
- Filesystem::pathExists($repo->getLocalPath().'/.git'));
+ Filesystem::pathExists($repo->getLocalPath().'/HEAD'));
}
public function testHgPullBasic() {
$repo = $this->buildPulledRepository('HT');
$this->assertEqual(
true,
Filesystem::pathExists($repo->getLocalPath().'/.hg'));
}
public function testSVNPullBasic() {
$repo = $this->buildPulledRepository('ST');
// We don't pull local clones for SVN, so we don't expect there to be
// a working copy.
$this->assertEqual(
false,
Filesystem::pathExists($repo->getLocalPath()));
}
}
diff --git a/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php b/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php
index a8f160cd94..336a8fe89d 100644
--- a/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php
+++ b/src/applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php
@@ -1,83 +1,84 @@
<?php
abstract class PhabricatorWorkingCopyTestCase extends PhabricatorTestCase {
private $dirs = array();
protected function getPhabricatorTestCaseConfiguration() {
return array(
self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
);
}
protected function buildBareRepository($callsign) {
$data_dir = dirname(__FILE__).'/data/';
$types = array(
'svn' => PhabricatorRepositoryType::REPOSITORY_TYPE_SVN,
'hg' => PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL,
'git' => PhabricatorRepositoryType::REPOSITORY_TYPE_GIT,
);
$hits = array();
foreach ($types as $type => $const) {
$path = $data_dir.$callsign.'.'.$type.'.tgz';
if (Filesystem::pathExists($path)) {
$hits[$const] = $path;
}
}
if (!$hits) {
throw new Exception(
"No test data for callsign '{$callsign}'. Expected an archive ".
"like '{$callsign}.git.tgz' in '{$data_dir}'.");
}
if (count($hits) > 1) {
throw new Exception(
"Expected exactly one archive matching callsign '{$callsign}', ".
"found too many: ".implode(', ', $hits));
}
$path = head($hits);
$vcs_type = head_key($hits);
$dir = PhutilDirectoryFixture::newFromArchive($path);
$local = new TempFile('.ignore');
- $repo = id(new PhabricatorRepository())
+ $user = $this->generateNewTestUser();
+ $repo = PhabricatorRepository::initializeNewRepository($user)
->setCallsign($callsign)
->setName(pht('Test Repo "%s"', $callsign))
->setVersionControlSystem($vcs_type)
->setDetail('local-path', dirname($local).'/'.$callsign)
->setDetail('remote-uri', 'file://'.$dir->getPath().'/');
$this->didConstructRepository($repo);
$repo->save();
$repo->makeEphemeral();
// Keep the disk resources around until we exit.
$this->dirs[] = $dir;
$this->dirs[] = $local;
return $repo;
}
protected function didConstructRepository(PhabricatorRepository $repository) {
return;
}
protected function buildPulledRepository($callsign) {
$repository = $this->buildBareRepository($callsign);
id(new PhabricatorRepositoryPullEngine())
->setRepository($repository)
->pullRepository();
$this->pulled[$callsign] = true;
return $repository;
}
}
diff --git a/src/applications/repository/response/PhabricatorVCSResponse.php b/src/applications/repository/response/PhabricatorVCSResponse.php
new file mode 100644
index 0000000000..aa0a3dff1d
--- /dev/null
+++ b/src/applications/repository/response/PhabricatorVCSResponse.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * In Git, there appears to be no way to send a message which will be output
+ * by `git clone http://...`, although the response code is visible.
+ *
+ * In Mercurial, the HTTP status response message is printed to the console, so
+ * we send human-readable text there.
+ *
+ * In Subversion, we can get it to print a custom message if we send an
+ * invalid/unknown response code, although the output is ugly and difficult
+ * to read. For known codes like 404, it prints a canned message.
+ *
+ * All VCS binaries ignore the response body; we include it only for
+ * completeness.
+ */
+final class PhabricatorVCSResponse extends AphrontResponse {
+
+ private $code;
+ private $message;
+
+ public function __construct($code, $message) {
+ $this->code = $code;
+
+ $message = head(phutil_split_lines($message));
+ $this->message = $message;
+ }
+
+ public function getMessage() {
+ return $this->message;
+ }
+
+ public function buildResponseString() {
+ return $this->code.' '.$this->message;
+ }
+
+ public function getHeaders() {
+ $headers = array();
+
+ if ($this->getHTTPResponseCode() == 401) {
+ $headers[] = array(
+ 'WWW-Authenticate',
+ 'Basic realm="Phabricator Repositories"',
+ );
+ }
+
+ return $headers;
+ }
+
+ public function getCacheHeaders() {
+ return array();
+ }
+
+ public function getHTTPResponseCode() {
+ return $this->code;
+ }
+
+ public function getHTTPResponseMessage() {
+ return $this->message;
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php
index c395c0f1a7..0471665f4e 100644
--- a/src/applications/repository/storage/PhabricatorRepository.php
+++ b/src/applications/repository/storage/PhabricatorRepository.php
@@ -1,757 +1,855 @@
<?php
/**
* @task uri Repository URI Management
*/
final class PhabricatorRepository extends PhabricatorRepositoryDAO
implements
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
PhabricatorMarkupInterface {
/**
* Shortest hash we'll recognize in raw "a829f32" form.
*/
const MINIMUM_UNQUALIFIED_HASH = 7;
/**
* Shortest hash we'll recognize in qualified "rXab7ef2f8" form.
*/
const MINIMUM_QUALIFIED_HASH = 5;
const TABLE_PATH = 'repository_path';
const TABLE_PATHCHANGE = 'repository_pathchange';
const TABLE_FILESYSTEM = 'repository_filesystem';
const TABLE_SUMMARY = 'repository_summary';
const TABLE_BADCOMMIT = 'repository_badcommit';
const TABLE_LINTMESSAGE = 'repository_lintmessage';
+ const SERVE_OFF = 'off';
+ const SERVE_READONLY = 'readonly';
+ const SERVE_READWRITE = 'readwrite';
+
protected $name;
protected $callsign;
protected $uuid;
- protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
- protected $editPolicy = PhabricatorPolicies::POLICY_ADMIN;
+ protected $viewPolicy;
+ protected $editPolicy;
+ protected $pushPolicy;
protected $versionControlSystem;
protected $details = array();
private $sshKeyfile;
private $commitCount = self::ATTACHABLE;
private $mostRecentCommit = self::ATTACHABLE;
+ public static function initializeNewRepository(PhabricatorUser $actor) {
+ $app = id(new PhabricatorApplicationQuery())
+ ->setViewer($actor)
+ ->withClasses(array('PhabricatorApplicationDiffusion'))
+ ->executeOne();
+
+ $view_policy = $app->getPolicy(DiffusionCapabilityDefaultView::CAPABILITY);
+ $edit_policy = $app->getPolicy(DiffusionCapabilityDefaultEdit::CAPABILITY);
+ $push_policy = $app->getPolicy(DiffusionCapabilityDefaultPush::CAPABILITY);
+
+ return id(new PhabricatorRepository())
+ ->setViewPolicy($view_policy)
+ ->setEditPolicy($edit_policy)
+ ->setPushPolicy($push_policy);
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorRepositoryPHIDTypeRepository::TYPECONST);
}
public function toDictionary() {
return array(
'name' => $this->getName(),
'phid' => $this->getPHID(),
'callsign' => $this->getCallsign(),
'vcs' => $this->getVersionControlSystem(),
'uri' => PhabricatorEnv::getProductionURI($this->getURI()),
'remoteURI' => (string)$this->getPublicRemoteURI(),
'tracking' => $this->getDetail('tracking-enabled'),
'description' => $this->getDetail('description'),
);
}
public function getDetail($key, $default = null) {
return idx($this->details, $key, $default);
}
public function getHumanReadableDetail($key, $default = null) {
$value = $this->getDetail($key, $default);
switch ($key) {
case 'branch-filter':
case 'close-commits-filter':
$value = array_keys($value);
$value = implode(', ', $value);
break;
}
return $value;
}
public function setDetail($key, $value) {
$this->details[$key] = $value;
return $this;
}
public function attachCommitCount($count) {
$this->commitCount = $count;
return $this;
}
public function getCommitCount() {
return $this->assertAttached($this->commitCount);
}
public function attachMostRecentCommit(
PhabricatorRepositoryCommit $commit = null) {
$this->mostRecentCommit = $commit;
return $this;
}
public function getMostRecentCommit() {
return $this->assertAttached($this->mostRecentCommit);
}
public function getDiffusionBrowseURIForPath(
PhabricatorUser $user,
$path,
$line = null,
$branch = null) {
$drequest = DiffusionRequest::newFromDictionary(
array(
'user' => $user,
'repository' => $this,
'path' => $path,
'branch' => $branch,
));
return $drequest->generateURI(
array(
'action' => 'browse',
'line' => $line,
));
}
public function getLocalPath() {
return $this->getDetail('local-path');
}
public function getSubversionBaseURI() {
$vcs = $this->getVersionControlSystem();
if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
throw new Exception("Not a subversion repository!");
}
$uri = $this->getDetail('remote-uri');
$subpath = $this->getDetail('svn-subpath');
return $uri.$subpath;
}
public function execRemoteCommand($pattern /* , $arg, ... */) {
$args = func_get_args();
$args = $this->formatRemoteCommand($args);
return call_user_func_array('exec_manual', $args);
}
public function execxRemoteCommand($pattern /* , $arg, ... */) {
$args = func_get_args();
$args = $this->formatRemoteCommand($args);
return call_user_func_array('execx', $args);
}
public function getRemoteCommandFuture($pattern /* , $arg, ... */) {
$args = func_get_args();
$args = $this->formatRemoteCommand($args);
return newv('ExecFuture', $args);
}
public function passthruRemoteCommand($pattern /* , $arg, ... */) {
$args = func_get_args();
$args = $this->formatRemoteCommand($args);
return call_user_func_array('phutil_passthru', $args);
}
public function execLocalCommand($pattern /* , $arg, ... */) {
+ $this->assertLocalExists();
+
$args = func_get_args();
$args = $this->formatLocalCommand($args);
return call_user_func_array('exec_manual', $args);
}
public function execxLocalCommand($pattern /* , $arg, ... */) {
+ $this->assertLocalExists();
+
$args = func_get_args();
$args = $this->formatLocalCommand($args);
return call_user_func_array('execx', $args);
}
public function getLocalCommandFuture($pattern /* , $arg, ... */) {
+ $this->assertLocalExists();
+
$args = func_get_args();
$args = $this->formatLocalCommand($args);
return newv('ExecFuture', $args);
}
public function passthruLocalCommand($pattern /* , $arg, ... */) {
+ $this->assertLocalExists();
+
$args = func_get_args();
$args = $this->formatLocalCommand($args);
return call_user_func_array('phutil_passthru', $args);
}
private function formatRemoteCommand(array $args) {
$pattern = $args[0];
$args = array_slice($args, 1);
$empty = $this->getEmptyReadableDirectoryPath();
if ($this->shouldUseSSH()) {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "SVN_SSH=%s svn --non-interactive {$pattern}";
array_unshift(
$args,
csprintf(
'ssh -l %P -i %P',
new PhutilOpaqueEnvelope($this->getSSHLogin()),
new PhutilOpaqueEnvelope($this->getSSHKeyfile())));
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$command = call_user_func_array(
'csprintf',
array_merge(
array(
"(ssh-add %P && HOME=%s git {$pattern})",
new PhutilOpaqueEnvelope($this->getSSHKeyfile()),
$empty,
),
$args));
$pattern = "ssh-agent sh -c %s";
$args = array($command);
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$pattern = "hg --config ui.ssh=%s {$pattern}";
array_unshift(
$args,
csprintf(
'ssh -l %P -i %P',
new PhutilOpaqueEnvelope($this->getSSHLogin()),
new PhutilOpaqueEnvelope($this->getSSHKeyfile())));
break;
default:
throw new Exception("Unrecognized version control system.");
}
} else if ($this->shouldUseHTTP()) {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern =
"svn ".
"--non-interactive ".
"--no-auth-cache ".
"--trust-server-cert ".
"--username %P ".
"--password %P ".
$pattern;
array_unshift(
$args,
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
break;
default:
throw new Exception(
"No support for HTTP Basic Auth in this version control system.");
}
} else if ($this->shouldUseSVNProtocol()) {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern =
"svn ".
"--non-interactive ".
"--no-auth-cache ".
"--username %P ".
"--password %P ".
$pattern;
array_unshift(
$args,
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
break;
default:
throw new Exception(
"SVN protocol is SVN only.");
}
} else {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "svn --non-interactive {$pattern}";
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$pattern = "HOME=%s git {$pattern}";
array_unshift($args, $empty);
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$pattern = "hg {$pattern}";
break;
default:
throw new Exception("Unrecognized version control system.");
}
}
array_unshift($args, $pattern);
return $args;
}
private function formatLocalCommand(array $args) {
$pattern = $args[0];
$args = array_slice($args, 1);
$empty = $this->getEmptyReadableDirectoryPath();
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "(cd %s && svn --non-interactive {$pattern})";
array_unshift($args, $this->getLocalPath());
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$pattern = "(cd %s && HOME=%s git {$pattern})";
array_unshift($args, $this->getLocalPath(), $empty);
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
$hgplain = (phutil_is_windows() ? "set HGPLAIN=1 &&" : "HGPLAIN=1");
$pattern = "(cd %s && {$hgplain} hg {$pattern})";
array_unshift($args, $this->getLocalPath());
break;
default:
throw new Exception("Unrecognized version control system.");
}
array_unshift($args, $pattern);
return $args;
}
private function getEmptyReadableDirectoryPath() {
// See T2965. Some time after Git 1.7.5.4, Git started fataling if it can
// not read $HOME. For many users, $HOME points at /root (this seems to be
// a default result of Apache setup). Instead, explicitly point $HOME at a
// readable, empty directory so that Git looks for the config file it's
// after, fails to locate it, and moves on. This is really silly, but seems
// like the least damaging approach to mitigating the issue.
$root = dirname(phutil_get_library_root('phabricator'));
return $root.'/support/empty/';
}
private function getSSHLogin() {
return $this->getDetail('ssh-login');
}
private function getSSHKeyfile() {
if ($this->sshKeyfile === null) {
$key = $this->getDetail('ssh-key');
$keyfile = $this->getDetail('ssh-keyfile');
if ($keyfile) {
// Make sure we can read the file, that it exists, etc.
Filesystem::readFile($keyfile);
$this->sshKeyfile = $keyfile;
} else if ($key) {
$keyfile = new TempFile('phabricator-repository-ssh-key');
chmod($keyfile, 0600);
Filesystem::writeFile($keyfile, $key);
$this->sshKeyfile = $keyfile;
} else {
$this->sshKeyfile = '';
}
}
return (string)$this->sshKeyfile;
}
public function getURI() {
return '/diffusion/'.$this->getCallsign().'/';
}
public function isTracked() {
return $this->getDetail('tracking-enabled', false);
}
public function getDefaultBranch() {
$default = $this->getDetail('default-branch');
if (strlen($default)) {
return $default;
}
$default_branches = array(
PhabricatorRepositoryType::REPOSITORY_TYPE_GIT => 'master',
PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL => 'default',
);
return idx($default_branches, $this->getVersionControlSystem());
}
public function getDefaultArcanistBranch() {
return coalesce($this->getDefaultBranch(), 'svn');
}
private function isBranchInFilter($branch, $filter_key) {
$vcs = $this->getVersionControlSystem();
$is_git = ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT);
$use_filter = ($is_git);
if ($use_filter) {
$filter = $this->getDetail($filter_key, array());
if ($filter && empty($filter[$branch])) {
return false;
}
}
// By default, all branches pass.
return true;
}
public function shouldTrackBranch($branch) {
return $this->isBranchInFilter($branch, 'branch-filter');
}
public function shouldAutocloseBranch($branch) {
+ if ($this->isImporting()) {
+ return false;
+ }
+
if ($this->getDetail('disable-autoclose', false)) {
return false;
}
return $this->isBranchInFilter($branch, 'close-commits-filter');
}
public function shouldAutocloseCommit(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
if ($this->getDetail('disable-autoclose', false)) {
return false;
}
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
return true;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
return true;
default:
throw new Exception("Unrecognized version control system.");
}
$branches = $data->getCommitDetail('seenOnBranches', array());
foreach ($branches as $branch) {
if ($this->shouldAutocloseBranch($branch)) {
return true;
}
}
return false;
}
public function formatCommitName($commit_identifier) {
$vcs = $this->getVersionControlSystem();
$type_git = PhabricatorRepositoryType::REPOSITORY_TYPE_GIT;
$type_hg = PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL;
$is_git = ($vcs == $type_git);
$is_hg = ($vcs == $type_hg);
if ($is_git || $is_hg) {
$short_identifier = substr($commit_identifier, 0, 12);
} else {
$short_identifier = $commit_identifier;
}
return 'r'.$this->getCallsign().$short_identifier;
}
+ public function isImporting() {
+ return (bool)$this->getDetail('importing', false);
+ }
+
/* -( Repository URI Management )------------------------------------------ */
/**
* Get the remote URI for this repository.
*
* @return string
* @task uri
*/
public function getRemoteURI() {
return (string)$this->getRemoteURIObject();
}
/**
* Get the remote URI for this repository, without authentication information.
*
* @return string Repository URI.
* @task uri
*/
public function getPublicRemoteURI() {
$uri = $this->getRemoteURIObject();
// Make sure we don't leak anything if this repo is using HTTP Basic Auth
// with the credentials in the URI or something zany like that.
if ($uri instanceof PhutilGitURI) {
if (!$this->getDetail('show-user', false)) {
$uri->setUser(null);
}
} else {
if (!$this->getDetail('show-user', false)) {
$uri->setUser(null);
}
$uri->setPass(null);
}
return (string)$uri;
}
/**
* Get the protocol for the repository's remote.
*
* @return string Protocol, like "ssh" or "git".
* @task uri
*/
public function getRemoteProtocol() {
$uri = $this->getRemoteURIObject();
if ($uri instanceof PhutilGitURI) {
return 'ssh';
} else {
return $uri->getProtocol();
}
}
/**
* Get a parsed object representation of the repository's remote URI. This
* may be a normal URI (returned as a @{class@libphutil:PhutilURI}) or a git
* URI (returned as a @{class@libphutil:PhutilGitURI}).
*
* @return wild A @{class@libphutil:PhutilURI} or
* @{class@libphutil:PhutilGitURI}.
* @task uri
*/
private function getRemoteURIObject() {
$raw_uri = $this->getDetail('remote-uri');
if (!$raw_uri) {
return new PhutilURI('');
}
if (!strncmp($raw_uri, '/', 1)) {
return new PhutilURI('file://'.$raw_uri);
}
$uri = new PhutilURI($raw_uri);
if ($uri->getProtocol()) {
if ($this->isSSHProtocol($uri->getProtocol())) {
if ($this->getSSHLogin()) {
$uri->setUser($this->getSSHLogin());
}
}
return $uri;
}
$uri = new PhutilGitURI($raw_uri);
if ($uri->getDomain()) {
if ($this->getSSHLogin()) {
$uri->setUser($this->getSSHLogin());
}
return $uri;
}
throw new Exception("Remote URI '{$raw_uri}' could not be parsed!");
}
/**
* Determine if we should connect to the remote using SSH flags and
* credentials.
*
* @return bool True to use the SSH protocol.
* @task uri
*/
private function shouldUseSSH() {
$protocol = $this->getRemoteProtocol();
if ($this->isSSHProtocol($protocol)) {
return (bool)$this->getSSHKeyfile();
} else {
return false;
}
}
/**
* Determine if we should connect to the remote using HTTP flags and
* credentials.
*
* @return bool True to use the HTTP protocol.
* @task uri
*/
private function shouldUseHTTP() {
$protocol = $this->getRemoteProtocol();
if ($protocol == 'http' || $protocol == 'https') {
return (bool)$this->getDetail('http-login');
} else {
return false;
}
}
/**
* Determine if we should connect to the remote using SVN flags and
* credentials.
*
* @return bool True to use the SVN protocol.
* @task uri
*/
private function shouldUseSVNProtocol() {
$protocol = $this->getRemoteProtocol();
if ($protocol == 'svn') {
return (bool)$this->getDetail('http-login');
} else {
return false;
}
}
/**
* Determine if a protocol is SSH or SSH-like.
*
* @param string A protocol string, like "http" or "ssh".
* @return bool True if the protocol is SSH-like.
* @task uri
*/
private function isSSHProtocol($protocol) {
return ($protocol == 'ssh' || $protocol == 'svn+ssh');
}
public function delete() {
$this->openTransaction();
$paths = id(new PhabricatorOwnersPath())
->loadAllWhere('repositoryPHID = %s', $this->getPHID());
foreach ($paths as $path) {
$path->delete();
}
$projects = id(new PhabricatorRepositoryArcanistProject())
->loadAllWhere('repositoryID = %d', $this->getID());
foreach ($projects as $project) {
// note each project deletes its PhabricatorRepositorySymbols
$project->delete();
}
$commits = id(new PhabricatorRepositoryCommit())
->loadAllWhere('repositoryID = %d', $this->getID());
foreach ($commits as $commit) {
// note PhabricatorRepositoryAuditRequests and
// PhabricatorRepositoryCommitData are deleted here too.
$commit->delete();
}
$conn_w = $this->establishConnection('w');
queryfx(
$conn_w,
'DELETE FROM %T WHERE repositoryID = %d',
self::TABLE_FILESYSTEM,
$this->getID());
queryfx(
$conn_w,
'DELETE FROM %T WHERE repositoryID = %d',
self::TABLE_PATHCHANGE,
$this->getID());
queryfx(
$conn_w,
'DELETE FROM %T WHERE repositoryID = %d',
self::TABLE_SUMMARY,
$this->getID());
$result = parent::delete();
$this->saveTransaction();
return $result;
}
public function isGit() {
$vcs = $this->getVersionControlSystem();
return ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT);
}
public function isSVN() {
$vcs = $this->getVersionControlSystem();
return ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN);
}
public function isHg() {
$vcs = $this->getVersionControlSystem();
return ($vcs == PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL);
}
+ public function isHosted() {
+ return (bool)$this->getDetail('hosting-enabled', false);
+ }
+
+ public function setHosted($enabled) {
+ return $this->setDetail('hosting-enabled', $enabled);
+ }
+
+ public function getServeOverHTTP() {
+ return $this->getDetail('serve-over-http', self::SERVE_OFF);
+ }
+
+ public function setServeOverHTTP($mode) {
+ return $this->setDetail('serve-over-http', $mode);
+ }
+
+ public function getServeOverSSH() {
+ return $this->getDetail('serve-over-ssh', self::SERVE_OFF);
+ }
+
+ public function setServeOverSSH($mode) {
+ return $this->setDetail('serve-over-ssh', $mode);
+ }
+
+ public static function getProtocolAvailabilityName($constant) {
+ switch ($constant) {
+ case self::SERVE_OFF:
+ return pht('Off');
+ case self::SERVE_READONLY:
+ return pht('Read Only');
+ case self::SERVE_READWRITE:
+ return pht('Read/Write');
+ default:
+ return pht('Unknown');
+ }
+ }
+
+
+ /**
+ * Raise more useful errors when there are basic filesystem problems.
+ */
+ private function assertLocalExists() {
+ switch ($this->getVersionControlSystem()) {
+ case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
+ if (!$this->isHosted()) {
+ // For non-hosted SVN repositories, we don't expect a local directory
+ // to exist.
+ return;
+ }
+ break;
+ }
+
+ $local = $this->getLocalPath();
+ Filesystem::assertExists($local);
+ Filesystem::assertIsDirectory($local);
+ Filesystem::assertReadable($local);
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
+ DiffusionCapabilityPush::CAPABILITY,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
+ case DiffusionCapabilityPush::CAPABILITY:
+ return $this->getPushPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
return false;
}
public function describeAutomaticCapability($capability) {
return null;
}
/* -( PhabricatorMarkupInterface )----------------------------------------- */
public function getMarkupFieldKey($field) {
$hash = PhabricatorHash::digestForIndex($this->getMarkupText($field));
return "repo:{$hash}";
}
public function newMarkupEngine($field) {
return PhabricatorMarkupEngine::newMarkupEngine(array());
}
public function getMarkupText($field) {
return $this->getDetail('description');
}
public function didMarkupText(
$field,
$output,
PhutilMarkupEngine $engine) {
require_celerity_resource('phabricator-remarkup-css');
return phutil_tag(
'div',
array(
'class' => 'phabricator-remarkup',
),
$output);
}
public function shouldUseMarkupCache($field) {
return true;
}
}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
index 66f0fd1026..a999726162 100644
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -1,216 +1,237 @@
<?php
final class PhabricatorRepositoryCommit
extends PhabricatorRepositoryDAO
implements
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
PhabricatorTokenReceiverInterface {
protected $repositoryID;
protected $phid;
protected $commitIdentifier;
protected $epoch;
protected $mailKey;
protected $authorPHID;
protected $auditStatus = PhabricatorAuditCommitStatusConstants::NONE;
protected $summary = '';
+ protected $importStatus = 0;
+
+ const IMPORTED_MESSAGE = 1;
+ const IMPORTED_CHANGE = 2;
+ const IMPORTED_OWNERS = 4;
+ const IMPORTED_HERALD = 8;
+ const IMPORTED_ALL = 15;
private $commitData = self::ATTACHABLE;
private $audits;
private $isUnparsed;
private $repository = self::ATTACHABLE;
public function attachRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
public function getRepository() {
return $this->assertAttached($this->repository);
}
public function setIsUnparsed($is_unparsed) {
$this->isUnparsed = $is_unparsed;
return $this;
}
public function getIsUnparsed() {
return $this->isUnparsed;
}
+ public function isImported() {
+ return ($this->getImportStatus() == self::IMPORTED_ALL);
+ }
+
+ public function writeImportStatusFlag($flag) {
+ queryfx(
+ $this->establishConnection('w'),
+ 'UPDATE %T SET importStatus = (importStatus | %d) WHERE id = %d',
+ $this->getTableName(),
+ $flag,
+ $this->getID());
+ return $this;
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_TIMESTAMPS => false,
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorRepositoryPHIDTypeCommit::TYPECONST);
}
public function loadCommitData() {
if (!$this->getID()) {
return null;
}
return id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$this->getID());
}
public function attachCommitData(PhabricatorRepositoryCommitData $data) {
$this->commitData = $data;
return $this;
}
public function getCommitData() {
return $this->assertAttached($this->commitData);
}
public function attachAudits(array $audits) {
assert_instances_of($audits, 'PhabricatorAuditComment');
$this->audits = $audits;
return $this;
}
public function getAudits() {
return $this->audits;
}
public function save() {
if (!$this->mailKey) {
$this->mailKey = Filesystem::readRandomCharacters(20);
}
return parent::save();
}
public function delete() {
$data = $this->loadCommitData();
$audits = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere('commitPHID = %s', $this->getPHID());
$this->openTransaction();
if ($data) {
$data->delete();
}
foreach ($audits as $audit) {
$audit->delete();
}
$result = parent::delete();
$this->saveTransaction();
return $result;
}
public function getDateCreated() {
// This is primarily to make analysis of commits with the Fact engine work.
return $this->getEpoch();
}
/**
* Synchronize a commit's overall audit status with the individual audit
* triggers.
*/
public function updateAuditStatus(array $requests) {
assert_instances_of($requests, 'PhabricatorRepositoryAuditRequest');
$any_concern = false;
$any_accept = false;
$any_need = false;
foreach ($requests as $request) {
switch ($request->getAuditStatus()) {
case PhabricatorAuditStatusConstants::AUDIT_REQUIRED:
$any_need = true;
break;
case PhabricatorAuditStatusConstants::ACCEPTED:
$any_accept = true;
break;
case PhabricatorAuditStatusConstants::CONCERNED:
$any_concern = true;
break;
}
}
if ($any_concern) {
$status = PhabricatorAuditCommitStatusConstants::CONCERN_RAISED;
} else if ($any_accept) {
if ($any_need) {
$status = PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED;
} else {
$status = PhabricatorAuditCommitStatusConstants::FULLY_AUDITED;
}
} else if ($any_need) {
$status = PhabricatorAuditCommitStatusConstants::NEEDS_AUDIT;
} else {
$status = PhabricatorAuditCommitStatusConstants::NONE;
}
return $this->setAuditStatus($status);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getRepository()->getPolicy($capability);
case PhabricatorPolicyCapability::CAN_EDIT:
// TODO: (T603) Who should be able to edit a commit? For now, retain
// the existing policy.
return PhabricatorPolicies::POLICY_USER;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
}
public function describeAutomaticCapability($capability) {
return pht(
'Commits inherit the policies of the repository they belong to.');
}
/* -( PhabricatorTokenReceiverInterface )---------------------------------- */
public function getUsersToNotifyOfTokenGiven() {
return array(
$this->getAuthorPHID(),
);
}
/* -( Stuff for serialization )---------------------------------------------- */
/**
* NOTE: this is not a complete serialization; only the 'protected' fields are
* involved. This is due to ease of (ab)using the Lisk abstraction to get this
* done, as well as complexity of the other fields.
*/
public function toDictionary() {
return array(
'repositoryID' => $this->getRepositoryID(),
'phid' => $this->getPHID(),
'commitIdentifier' => $this->getCommitIdentifier(),
'epoch' => $this->getEpoch(),
'mailKey' => $this->getMailKey(),
'authorPHID' => $this->getAuthorPHID(),
'auditStatus' => $this->getAuditStatus(),
'summary' => $this->getSummary());
}
public static function newFromDictionary(array $dict) {
return id(new PhabricatorRepositoryCommit())
->loadFromArray($dict);
}
}
diff --git a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
index 888a17b88c..e40c139cf4 100644
--- a/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryTransaction.php
@@ -1,268 +1,364 @@
<?php
final class PhabricatorRepositoryTransaction
extends PhabricatorApplicationTransaction {
+ const TYPE_VCS = 'repo:vcs';
const TYPE_ACTIVATE = 'repo:activate';
const TYPE_NAME = 'repo:name';
const TYPE_DESCRIPTION = 'repo:description';
const TYPE_ENCODING = 'repo:encoding';
const TYPE_DEFAULT_BRANCH = 'repo:default-branch';
const TYPE_TRACK_ONLY = 'repo:track-only';
const TYPE_AUTOCLOSE_ONLY = 'repo:autoclose-only';
const TYPE_SVN_SUBPATH = 'repo:svn-subpath';
const TYPE_UUID = 'repo:uuid';
const TYPE_NOTIFY = 'repo:notify';
const TYPE_AUTOCLOSE = 'repo:autoclose';
const TYPE_REMOTE_URI = 'repo:remote-uri';
const TYPE_SSH_LOGIN = 'repo:ssh-login';
const TYPE_SSH_KEY = 'repo:ssh-key';
const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile';
const TYPE_HTTP_LOGIN = 'repo:http-login';
const TYPE_HTTP_PASS = 'repo:http-pass';
const TYPE_LOCAL_PATH = 'repo:local-path';
+ const TYPE_HOSTING = 'repo:hosting';
+ const TYPE_PROTOCOL_HTTP = 'repo:serve-http';
+ const TYPE_PROTOCOL_SSH = 'repo:serve-ssh';
+ const TYPE_PUSH_POLICY = 'repo:push-policy';
public function getApplicationName() {
return 'repository';
}
public function getApplicationTransactionType() {
return PhabricatorRepositoryPHIDTypeRepository::TYPECONST;
}
public function getApplicationTransactionCommentObject() {
return null;
}
+ public function getRequiredHandlePHIDs() {
+ $phids = parent::getRequiredHandlePHIDs();
+
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ switch ($this->getTransactionType()) {
+ case self::TYPE_PUSH_POLICY:
+ $phids[] = $old;
+ $phids[] = $new;
+ break;
+ }
+
+ return $phids;
+ }
+
+ public function shouldHide() {
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ switch ($this->getTransactionType()) {
+ case self::TYPE_REMOTE_URI:
+ case self::TYPE_SSH_LOGIN:
+ case self::TYPE_SSH_KEY:
+ case self::TYPE_SSH_KEYFILE:
+ case self::TYPE_HTTP_LOGIN:
+ case self::TYPE_HTTP_PASS:
+ // Hide null vs empty string changes.
+ return (!strlen($old) && !strlen($new));
+ case self::TYPE_LOCAL_PATH:
+ case self::TYPE_NAME:
+ // Hide these on create, they aren't interesting and we have an
+ // explicit "create" transaction.
+ if (!strlen($old)) {
+ return true;
+ }
+ break;
+ }
+
+ return parent::shouldHide();
+ }
+
+ public function getIcon() {
+ switch ($this->getTransactionType()) {
+ case self::TYPE_VCS:
+ return 'create';
+ }
+ return parent::getIcon();
+ }
+
+ public function getColor() {
+ switch ($this->getTransactionType()) {
+ case self::TYPE_VCS:
+ return 'green';
+ }
+ return parent::getIcon();
+ }
+
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
+ case self::TYPE_VCS:
+ return pht(
+ '%s created this repository.',
+ $this->renderHandleLink($author_phid));
case self::TYPE_ACTIVATE:
if ($new) {
return pht(
'%s activated this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s deactivated this repository.',
$this->renderHandleLink($author_phid));
}
case self::TYPE_NAME:
return pht(
'%s renamed this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
case self::TYPE_DESCRIPTION:
return pht(
'%s updated the description of this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_ENCODING:
if (strlen($old) && !strlen($new)) {
return pht(
'%s removed the "%s" encoding configured for this repository.',
$this->renderHandleLink($author_phid),
$old);
} else if (strlen($new) && !strlen($old)) {
return pht(
'%s set the encoding for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the repository encoding from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
case self::TYPE_DEFAULT_BRANCH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the default branch.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the default branch to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the default branch from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_TRACK_ONLY:
if (!$new) {
return pht(
'%s set this repository to track all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to track branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed track branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_AUTOCLOSE_ONLY:
if (!$new) {
return pht(
'%s set this repository to autoclose on all branches.',
$this->renderHandleLink($author_phid));
} else if (!$old) {
return pht(
'%s set this repository to autoclose on branches: %s.',
$this->renderHandleLink($author_phid),
implode(', ', $new));
} else {
return pht(
'%s changed autoclose branches from "%s" to "%s".',
$this->renderHandleLink($author_phid),
implode(', ', $old),
implode(', ', $new));
}
break;
case self::TYPE_UUID:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the repository UUID.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the repository UUID to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the repository UUID from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_SVN_SUBPATH:
if (!strlen($new)) {
return pht(
'%s removed "%s" as the Import Only path.',
$this->renderHandleLink($author_phid),
$old);
} else if (!strlen($old)) {
return pht(
'%s set the repository to import only "%s".',
$this->renderHandleLink($author_phid),
$new);
} else {
return pht(
'%s changed the import path from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_NOTIFY:
if ($new) {
return pht(
'%s enabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled notifications and publishing for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_AUTOCLOSE:
if ($new) {
return pht(
'%s enabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s disabled autoclose for this repository.',
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_REMOTE_URI:
if (!strlen($old)) {
return pht(
'%s set the remote URI for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else if (!strlen($new)) {
return pht(
'%s removed the remote URI for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s changed the remote URI for this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_SSH_LOGIN:
return pht(
'%s updated the SSH login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEY:
return pht(
'%s updated the SSH key for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEYFILE:
return pht(
'%s updated the SSH keyfile for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_LOGIN:
return pht(
'%s updated the HTTP login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_PASS:
return pht(
'%s updated the HTTP password for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_LOCAL_PATH:
return pht(
'%s changed the local path from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
+ case self::TYPE_HOSTING:
+ if ($new) {
+ return pht(
+ '%s changed this repository to be hosted on Phabricator.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s changed this repository to track a remote elsewhere.',
+ $this->renderHandleLink($author_phid));
+ }
+ case self::TYPE_PROTOCOL_HTTP:
+ return pht(
+ '%s changed the availability of this repository over HTTP from '.
+ '"%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ PhabricatorRepository::getProtocolAvailabilityName($old),
+ PhabricatorRepository::getProtocolAvailabilityName($new));
+ case self::TYPE_PROTOCOL_SSH:
+ return pht(
+ '%s changed the availability of this repository over SSH from '.
+ '"%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ PhabricatorRepository::getProtocolAvailabilityName($old),
+ PhabricatorRepository::getProtocolAvailabilityName($new));
+ case self::TYPE_PUSH_POLICY:
+ return pht(
+ '%s changed the push policy of this repository from "%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ $this->renderPolicyName($old),
+ $this->renderPolicyName($new));
}
return parent::getTitle();
}
public function hasChangeDetails() {
switch ($this->getTransactionType()) {
case self::TYPE_DESCRIPTION:
return true;
}
return parent::hasChangeDetails();
}
public function renderChangeDetails(PhabricatorUser $viewer) {
$old = $this->getOldValue();
$new = $this->getNewValue();
$view = id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setUser($viewer)
->setOldText($old)
->setNewText($new);
return $view->render();
}
-
}
diff --git a/src/applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php b/src/applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php
index e896536ef4..eaa9f682e8 100644
--- a/src/applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php
+++ b/src/applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php
@@ -1,425 +1,444 @@
<?php
final class PhabricatorRepositoryCommitHeraldWorker
extends PhabricatorRepositoryCommitParserWorker {
public function getRequiredLeaseTime() {
// Herald rules may take a long time to process.
return 4 * 60 * 60;
}
public function parseCommit(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit) {
+ $result = $this->applyHeraldRules($repository, $commit);
+
+ $commit->writeImportStatusFlag(
+ PhabricatorRepositoryCommit::IMPORTED_HERALD);
+
+ return $result;
+ }
+
+ private function applyHeraldRules(
+ PhabricatorRepository $repository,
+ PhabricatorRepositoryCommit $commit) {
+
+ // Don't take any actions on an importing repository. Principally, this
+ // avoids generating thousands of audits or emails when you import an
+ // established repository on an existing install.
+ if ($repository->isImporting()) {
+ return;
+ }
+
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
if (!$data) {
// TODO: Permanent failure.
return;
}
$adapter = HeraldCommitAdapter::newLegacyAdapter(
$repository,
$commit,
$data);
$rules = id(new HeraldRuleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withContentTypes(array($adapter->getAdapterContentType()))
->withDisabled(false)
->needConditionsAndActions(true)
->needAppliedToPHIDs(array($adapter->getPHID()))
->needValidateAuthors(true)
->execute();
$engine = new HeraldEngine();
$effects = $engine->applyRules($rules, $adapter);
$engine->applyEffects($effects, $adapter, $rules);
$xscript = $engine->getTranscript();
$audit_phids = $adapter->getAuditMap();
$cc_phids = $adapter->getAddCCMap();
if ($audit_phids || $cc_phids) {
$this->createAudits($commit, $audit_phids, $cc_phids, $rules);
}
$explicit_auditors = $this->createAuditsFromCommitMessage($commit, $data);
if ($repository->getDetail('herald-disabled')) {
// This just means "disable email"; audits are (mostly) idempotent.
return;
}
$this->publishFeedStory($repository, $commit, $data);
$herald_targets = $adapter->getEmailPHIDs();
$email_phids = array_unique(
array_merge(
$explicit_auditors,
array_keys($cc_phids),
$herald_targets));
if (!$email_phids) {
return;
}
$revision = $adapter->loadDifferentialRevision();
if ($revision) {
$name = $revision->getTitle();
} else {
$name = $data->getSummary();
}
$author_phid = $data->getCommitDetail('authorPHID');
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
$phids = array_filter(
array(
$author_phid,
$reviewer_phid,
$commit->getPHID(),
));
$handles = id(new PhabricatorHandleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($phids)
->execute();
$commit_handle = $handles[$commit->getPHID()];
$commit_name = $commit_handle->getName();
if ($author_phid) {
$author_name = $handles[$author_phid]->getName();
} else {
$author_name = $data->getAuthorName();
}
if ($reviewer_phid) {
$reviewer_name = $handles[$reviewer_phid]->getName();
} else {
$reviewer_name = null;
}
$who = implode(', ', array_filter(array($author_name, $reviewer_name)));
$description = $data->getCommitMessage();
$commit_uri = PhabricatorEnv::getProductionURI($commit_handle->getURI());
$differential = $revision
? PhabricatorEnv::getProductionURI('/D'.$revision->getID())
: 'No revision.';
$files = $adapter->loadAffectedPaths();
sort($files);
$files = implode("\n", $files);
$xscript_id = $xscript->getID();
$why_uri = '/herald/transcript/'.$xscript_id.'/';
$reply_handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit(
$commit);
$template = new PhabricatorMetaMTAMail();
$inline_patch_text = $this->buildPatch($template, $repository, $commit);
$body = new PhabricatorMetaMTAMailBody();
$body->addRawSection($description);
$body->addTextSection(pht('DETAILS'), $commit_uri);
$body->addTextSection(pht('DIFFERENTIAL REVISION'), $differential);
$body->addTextSection(pht('AFFECTED FILES'), $files);
$body->addReplySection($reply_handler->getReplyHandlerInstructions());
$body->addHeraldSection($why_uri);
$body->addRawSection($inline_patch_text);
$body = $body->render();
$prefix = PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix');
$threading = PhabricatorAuditCommentEditor::getMailThreading(
$repository,
$commit);
list($thread_id, $thread_topic) = $threading;
$template->setRelatedPHID($commit->getPHID());
$template->setSubject("{$commit_name}: {$name}");
$template->setSubjectPrefix($prefix);
$template->setVarySubjectPrefix("[Commit]");
$template->setBody($body);
$template->setThreadID($thread_id, $is_new = true);
$template->addHeader('Thread-Topic', $thread_topic);
$template->setIsBulk(true);
$template->addHeader('X-Herald-Rules', $xscript->getXHeraldRulesHeader());
if ($author_phid) {
$template->setFrom($author_phid);
}
// TODO: We should verify that each recipient can actually see the
// commit before sending them email (T603).
$mails = $reply_handler->multiplexMail(
$template,
id(new PhabricatorHandleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($email_phids)
->execute(),
array());
foreach ($mails as $mail) {
$mail->saveAndSend();
}
}
private function createAudits(
PhabricatorRepositoryCommit $commit,
array $map,
array $ccmap,
array $rules) {
assert_instances_of($rules, 'HeraldRule');
$requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'commitPHID = %s',
$commit->getPHID());
$requests = mpull($requests, null, 'getAuditorPHID');
$rules = mpull($rules, null, 'getID');
$maps = array(
PhabricatorAuditStatusConstants::AUDIT_REQUIRED => $map,
PhabricatorAuditStatusConstants::CC => $ccmap,
);
foreach ($maps as $status => $map) {
foreach ($map as $phid => $rule_ids) {
$request = idx($requests, $phid);
if ($request) {
continue;
}
$reasons = array();
foreach ($rule_ids as $id) {
$rule_name = '?';
if ($rules[$id]) {
$rule_name = $rules[$id]->getName();
}
if ($status == PhabricatorAuditStatusConstants::AUDIT_REQUIRED) {
$reasons[] = pht(
'Herald Rule #%d "%s" Triggered Audit',
$id,
$rule_name);
} else {
$reasons[] = pht(
'Herald Rule #%d "%s" Triggered CC',
$id,
$rule_name);
}
}
$request = new PhabricatorRepositoryAuditRequest();
$request->setCommitPHID($commit->getPHID());
$request->setAuditorPHID($phid);
$request->setAuditStatus($status);
$request->setAuditReasons($reasons);
$request->save();
}
}
$commit->updateAuditStatus($requests);
$commit->save();
}
/**
* Find audit requests in the "Auditors" field if it is present and trigger
* explicit audit requests.
*/
private function createAuditsFromCommitMessage(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
$message = $data->getCommitMessage();
$matches = null;
if (!preg_match('/^Auditors:\s*(.*)$/im', $message, $matches)) {
return array();
}
$phids = DifferentialFieldSpecification::parseCommitMessageObjectList(
$matches[1],
$include_mailables = false,
$allow_partial = true);
if (!$phids) {
return array();
}
$requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'commitPHID = %s',
$commit->getPHID());
$requests = mpull($requests, null, 'getAuditorPHID');
foreach ($phids as $phid) {
if (isset($requests[$phid])) {
continue;
}
$request = new PhabricatorRepositoryAuditRequest();
$request->setCommitPHID($commit->getPHID());
$request->setAuditorPHID($phid);
$request->setAuditStatus(
PhabricatorAuditStatusConstants::AUDIT_REQUESTED);
$request->setAuditReasons(
array(
'Requested by Author',
));
$request->save();
$requests[$phid] = $request;
}
$commit->updateAuditStatus($requests);
$commit->save();
return $phids;
}
private function publishFeedStory(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
if (time() > $commit->getEpoch() + (24 * 60 * 60)) {
// Don't publish stories that are more than 24 hours old, to avoid
// ridiculous levels of feed spam if a repository is imported without
// disabling feed publishing.
return;
}
$author_phid = $commit->getAuthorPHID();
$committer_phid = $data->getCommitDetail('committerPHID');
$publisher = new PhabricatorFeedStoryPublisher();
$publisher->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_COMMIT);
$publisher->setStoryData(
array(
'commitPHID' => $commit->getPHID(),
'summary' => $data->getSummary(),
'authorName' => $data->getAuthorName(),
'authorPHID' => $author_phid,
'committerName' => $data->getCommitDetail('committer'),
'committerPHID' => $committer_phid,
));
$publisher->setStoryTime($commit->getEpoch());
$publisher->setRelatedPHIDs(
array_filter(
array(
$author_phid,
$committer_phid,
)));
if ($author_phid) {
$publisher->setStoryAuthorPHID($author_phid);
}
$publisher->publish();
}
private function buildPatch(
PhabricatorMetaMTAMail $template,
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit) {
$attach_key = 'metamta.diffusion.attach-patches';
$inline_key = 'metamta.diffusion.inline-patches';
$attach_patches = PhabricatorEnv::getEnvConfig($attach_key);
$inline_patches = PhabricatorEnv::getEnvConfig($inline_key);
if (!$attach_patches && !$inline_patches) {
return;
}
$encoding = $repository->getDetail('encoding', 'UTF-8');
$result = null;
$patch_error = null;
try {
$raw_patch = $this->loadRawPatchText($repository, $commit);
if ($attach_patches) {
$commit_name = $repository->formatCommitName(
$commit->getCommitIdentifier());
$template->addAttachment(
new PhabricatorMetaMTAAttachment(
$raw_patch,
$commit_name.'.patch',
'text/x-patch; charset='.$encoding));
}
} catch (Exception $ex) {
phlog($ex);
$patch_error = 'Unable to generate: '.$ex->getMessage();
}
if ($patch_error) {
$result = $patch_error;
} else if ($inline_patches) {
$len = substr_count($raw_patch, "\n");
if ($len <= $inline_patches) {
// We send email as utf8, so we need to convert the text to utf8 if
// we can.
if ($encoding) {
$raw_patch = phutil_utf8_convert($raw_patch, 'UTF-8', $encoding);
}
$result = phutil_utf8ize($raw_patch);
}
}
if ($result) {
$result = "PATCH\n\n{$result}\n";
}
return $result;
}
private function loadRawPatchText(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit) {
$drequest = DiffusionRequest::newFromDictionary(
array(
'user' => PhabricatorUser::getOmnipotentUser(),
'initFromConduit' => false,
'repository' => $repository,
'commit' => $commit->getCommitIdentifier(),
));
$raw_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest);
$raw_query->setLinesOfContext(3);
$time_key = 'metamta.diffusion.time-limit';
$byte_key = 'metamta.diffusion.byte-limit';
$time_limit = PhabricatorEnv::getEnvConfig($time_key);
$byte_limit = PhabricatorEnv::getEnvConfig($byte_key);
if ($time_limit) {
$raw_query->setTimeout($time_limit);
}
$raw_diff = $raw_query->loadRawDiff();
$size = strlen($raw_diff);
if ($byte_limit && $size > $byte_limit) {
$pretty_size = phabricator_format_bytes($size);
$pretty_limit = phabricator_format_bytes($byte_limit);
throw new Exception(
"Patch size of {$pretty_size} exceeds configured byte size limit of ".
"{$pretty_limit}.");
}
return $raw_diff;
}
}
diff --git a/src/applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php b/src/applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php
index 78d062d223..e02632ad9f 100644
--- a/src/applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php
+++ b/src/applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php
@@ -1,129 +1,132 @@
<?php
final class PhabricatorRepositoryCommitOwnersWorker
extends PhabricatorRepositoryCommitParserWorker {
protected function parseCommit(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit) {
$affected_paths = PhabricatorOwnerPathQuery::loadAffectedPaths(
$repository,
$commit,
PhabricatorUser::getOmnipotentUser());
$affected_packages = PhabricatorOwnersPackage::loadAffectedPackages(
$repository,
$affected_paths);
if ($affected_packages) {
$requests = id(new PhabricatorRepositoryAuditRequest())
->loadAllWhere(
'commitPHID = %s',
$commit->getPHID());
$requests = mpull($requests, null, 'getAuditorPHID');
foreach ($affected_packages as $package) {
$request = idx($requests, $package->getPHID());
if ($request) {
// Don't update request if it exists already.
continue;
}
if ($package->getAuditingEnabled()) {
$reasons = $this->checkAuditReasons($commit, $package);
if ($reasons) {
$audit_status =
PhabricatorAuditStatusConstants::AUDIT_REQUIRED;
} else {
$audit_status =
PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED;
}
} else {
$reasons = array();
$audit_status = PhabricatorAuditStatusConstants::NONE;
}
$relationship = new PhabricatorRepositoryAuditRequest();
$relationship->setAuditorPHID($package->getPHID());
$relationship->setCommitPHID($commit->getPHID());
$relationship->setAuditReasons($reasons);
$relationship->setAuditStatus($audit_status);
$relationship->save();
$requests[$package->getPHID()] = $relationship;
}
$commit->updateAuditStatus($requests);
$commit->save();
}
+ $commit->writeImportStatusFlag(
+ PhabricatorRepositoryCommit::IMPORTED_OWNERS);
+
if ($this->shouldQueueFollowupTasks()) {
PhabricatorWorker::scheduleTask(
'PhabricatorRepositoryCommitHeraldWorker',
array(
'commitID' => $commit->getID(),
));
}
}
private function checkAuditReasons(
PhabricatorRepositoryCommit $commit,
PhabricatorOwnersPackage $package) {
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
$reasons = array();
if ($data->getCommitDetail('vsDiff')) {
$reasons[] = "Changed After Revision Was Accepted";
}
$commit_author_phid = $data->getCommitDetail('authorPHID');
if (!$commit_author_phid) {
$reasons[] = "Commit Author Not Recognized";
}
$revision_id = $data->getCommitDetail('differential.revisionID');
$revision_author_phid = null;
$commit_reviewedby_phid = null;
if ($revision_id) {
// TODO: (T603) This is probably safe to use an omnipotent user on,
// but check things more closely.
$revision = id(new DifferentialRevision())->load($revision_id);
if ($revision) {
$revision_author_phid = $revision->getAuthorPHID();
$revision_reviewedby_phid = $revision->loadReviewedBy();
$commit_reviewedby_phid = $data->getCommitDetail('reviewerPHID');
if ($revision_author_phid !== $commit_author_phid) {
$reasons[] = "Author Not Matching with Revision";
}
if ($revision_reviewedby_phid !== $commit_reviewedby_phid) {
$reasons[] = "ReviewedBy Not Matching with Revision";
}
} else {
$reasons[] = "Revision Not Found";
}
} else {
$reasons[] = "No Revision Specified";
}
$owners_phids = PhabricatorOwnersOwner::loadAffiliatedUserPHIDs(
array($package->getID()));
if (!($commit_author_phid && in_array($commit_author_phid, $owners_phids) ||
$commit_reviewedby_phid && in_array($commit_reviewedby_phid,
$owners_phids))) {
$reasons[] = "Owners Not Involved";
}
return $reasons;
}
}
diff --git a/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php b/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php
index 10b99993cc..9ff7f89234 100644
--- a/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php
+++ b/src/applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php
@@ -1,74 +1,77 @@
<?php
abstract class PhabricatorRepositoryCommitChangeParserWorker
extends PhabricatorRepositoryCommitParserWorker {
public function getRequiredLeaseTime() {
// It can take a very long time to parse commits; some commits in the
// Facebook repository affect many millions of paths. Acquire 24h leases.
return 60 * 60 * 24;
}
public static function lookupOrCreatePaths(array $paths) {
$repository = new PhabricatorRepository();
$conn_w = $repository->establishConnection('w');
$result_map = self::lookupPaths($paths);
$missing_paths = array_fill_keys($paths, true);
$missing_paths = array_diff_key($missing_paths, $result_map);
$missing_paths = array_keys($missing_paths);
if ($missing_paths) {
foreach (array_chunk($missing_paths, 128) as $path_chunk) {
$sql = array();
foreach ($path_chunk as $path) {
$sql[] = qsprintf($conn_w, '(%s, %s)', $path, md5($path));
}
queryfx(
$conn_w,
'INSERT IGNORE INTO %T (path, pathHash) VALUES %Q',
PhabricatorRepository::TABLE_PATH,
implode(', ', $sql));
}
$result_map += self::lookupPaths($missing_paths);
}
return $result_map;
}
private static function lookupPaths(array $paths) {
$repository = new PhabricatorRepository();
$conn_w = $repository->establishConnection('w');
$result_map = array();
foreach (array_chunk($paths, 128) as $path_chunk) {
$chunk_map = queryfx_all(
$conn_w,
'SELECT path, id FROM %T WHERE pathHash IN (%Ls)',
PhabricatorRepository::TABLE_PATH,
array_map('md5', $path_chunk));
foreach ($chunk_map as $row) {
$result_map[$row['path']] = $row['id'];
}
}
return $result_map;
}
protected function finishParse() {
$commit = $this->commit;
+ $commit->writeImportStatusFlag(
+ PhabricatorRepositoryCommit::IMPORTED_CHANGE);
+
id(new PhabricatorSearchIndexer())
->indexDocumentByPHID($commit->getPHID());
PhabricatorOwnersPackagePathValidator::updateOwnersPackagePaths($commit);
if ($this->shouldQueueFollowupTasks()) {
PhabricatorWorker::scheduleTask(
'PhabricatorRepositoryCommitOwnersWorker',
array(
'commitID' => $commit->getID(),
));
}
}
}
diff --git a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
index 71f88f1a1e..cced97b33d 100644
--- a/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
+++ b/src/applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php
@@ -1,541 +1,554 @@
<?php
abstract class PhabricatorRepositoryCommitMessageParserWorker
extends PhabricatorRepositoryCommitParserWorker {
abstract protected function getCommitHashes(
PhabricatorRepository $repository,
PhabricatorRepositoryCommit $commit);
final protected function updateCommitData($author, $message,
$committer = null) {
$commit = $this->commit;
$data = id(new PhabricatorRepositoryCommitData())->loadOneWhere(
'commitID = %d',
$commit->getID());
if (!$data) {
$data = new PhabricatorRepositoryCommitData();
}
$data->setCommitID($commit->getID());
$data->setAuthorName($author);
$data->setCommitDetail(
'authorPHID',
$this->resolveUserPHID($author));
$data->setCommitMessage($message);
if ($committer) {
$data->setCommitDetail('committer', $committer);
$data->setCommitDetail(
'committerPHID',
$this->resolveUserPHID($committer));
}
$repository = $this->repository;
$author_phid = $this->lookupUser(
$commit,
$data->getAuthorName(),
$data->getCommitDetail('authorPHID'));
$data->setCommitDetail('authorPHID', $author_phid);
$user = new PhabricatorUser();
if ($author_phid) {
$user = $user->loadOneWhere(
'phid = %s',
$author_phid);
}
$call = new ConduitCall(
'differential.parsecommitmessage',
array(
'corpus' => $message,
'partial' => true,
));
$call->setUser(PhabricatorUser::getOmnipotentUser());
$result = $call->execute();
$field_values = $result['fields'];
if (!empty($field_values['reviewedByPHIDs'])) {
$data->setCommitDetail(
'reviewerPHID',
reset($field_values['reviewedByPHIDs']));
}
$revision_id = idx($field_values, 'revisionID');
if (!$revision_id) {
$hashes = $this->getCommitHashes(
$repository,
$commit);
if ($hashes) {
$revisions = id(new DifferentialRevisionQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withCommitHashes($hashes)
->execute();
if (!empty($revisions)) {
$revision = $this->identifyBestRevision($revisions);
$revision_id = $revision->getID();
}
}
}
$data->setCommitDetail(
'differential.revisionID',
$revision_id);
$committer_phid = $this->lookupUser(
$commit,
$data->getCommitDetail('committer'),
$data->getCommitDetail('committerPHID'));
$data->setCommitDetail('committerPHID', $committer_phid);
if ($author_phid != $commit->getAuthorPHID()) {
$commit->setAuthorPHID($author_phid);
}
$commit->setSummary($data->getSummary());
$commit->save();
$conn_w = id(new DifferentialRevision())->establishConnection('w');
// NOTE: The `differential_commit` table has a unique ID on `commitPHID`,
// preventing more than one revision from being associated with a commit.
// Generally this is good and desirable, but with the advent of hash
// tracking we may end up in a situation where we match several different
// revisions. We just kind of ignore this and pick one, we might want to
// revisit this and do something differently. (If we match several revisions
// someone probably did something very silly, though.)
$revision = null;
$should_autoclose = $repository->shouldAutocloseCommit($commit, $data);
if ($revision_id) {
$lock = PhabricatorGlobalLock::newLock(get_class($this).':'.$revision_id);
$lock->lock(5 * 60);
// TODO: Check if a more restrictive viewer could be set here
$revision = id(new DifferentialRevisionQuery())
->withIDs(array($revision_id))
->setViewer(PhabricatorUser::getOmnipotentUser())
->needRelationships(true)
->needReviewerStatus(true)
->executeOne();
if ($revision) {
$commit_drev = PhabricatorEdgeConfig::TYPE_COMMIT_HAS_DREV;
id(new PhabricatorEdgeEditor())
->setActor($user)
->addEdge($commit->getPHID(), $commit_drev, $revision->getPHID())
->save();
queryfx(
$conn_w,
'INSERT IGNORE INTO %T (revisionID, commitPHID) VALUES (%d, %s)',
DifferentialRevision::TABLE_COMMIT,
$revision->getID(),
$commit->getPHID());
$status_closed = ArcanistDifferentialRevisionStatus::CLOSED;
$should_close = ($revision->getStatus() != $status_closed) &&
$should_autoclose;
if ($should_close) {
$actor_phid = nonempty(
$committer_phid,
$author_phid,
$revision->getAuthorPHID());
$actor = id(new PhabricatorUser())
->loadOneWhere('phid = %s', $actor_phid);
$diff = $this->attachToRevision($revision, $actor_phid);
$revision->setDateCommitted($commit->getEpoch());
$editor = new DifferentialCommentEditor(
$revision,
DifferentialAction::ACTION_CLOSE);
$editor->setActor($actor);
$editor->setIsDaemonWorkflow(true);
$vs_diff = $this->loadChangedByCommit($diff);
if ($vs_diff) {
$data->setCommitDetail('vsDiff', $vs_diff->getID());
$changed_by_commit = PhabricatorEnv::getProductionURI(
'/D'.$revision->getID().
'?vs='.$vs_diff->getID().
'&id='.$diff->getID().
'#toc');
$editor->setChangedByCommit($changed_by_commit);
}
$commit_name = $repository->formatCommitName(
$commit->getCommitIdentifier());
$committer_name = $this->loadUserName(
$committer_phid,
$data->getCommitDetail('committer'),
$actor);
$author_name = $this->loadUserName(
$author_phid,
$data->getAuthorName(),
$actor);
$info = array();
$info[] = "authored by {$author_name}";
if ($committer_name && ($committer_name != $author_name)) {
$info[] = "committed by {$committer_name}";
}
$info = implode(', ', $info);
$editor
->setMessage("Closed by commit {$commit_name} ({$info}).")
->save();
}
}
$lock->unlock();
}
if ($should_autoclose) {
$fields = DifferentialFieldSelector::newSelector()
->getFieldSpecifications();
foreach ($fields as $key => $field) {
if (!$field->shouldAppearOnCommitMessage()) {
continue;
}
$field->setUser($user);
$value = idx($field_values, $field->getCommitMessageKey());
$field->setValueFromParsedCommitMessage($value);
if ($revision) {
$field->setRevision($revision);
}
$field->didParseCommit($repository, $commit, $data);
}
}
$data->save();
+
+ $commit->writeImportStatusFlag(
+ PhabricatorRepositoryCommit::IMPORTED_MESSAGE);
}
private function loadUserName($user_phid, $default, PhabricatorUser $actor) {
if (!$user_phid) {
return $default;
}
$handle = id(new PhabricatorHandleQuery())
->setViewer($actor)
->withPHIDs(array($user_phid))
->executeOne();
return '@'.$handle->getName();
}
private function attachToRevision(
DifferentialRevision $revision,
$actor_phid) {
$drequest = DiffusionRequest::newFromDictionary(array(
'user' => PhabricatorUser::getOmnipotentUser(),
'initFromConduit' => false,
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
));
$raw_diff = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest)
->loadRawDiff();
// TODO: Support adds, deletes and moves under SVN.
- $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff);
+ if (strlen($raw_diff)) {
+ $changes = id(new ArcanistDiffParser())->parseDiff($raw_diff);
+ } else {
+ // This is an empty diff, maybe made with `git commit --allow-empty`.
+ // NOTE: These diffs have the same tree hash as their ancestors, so
+ // they may attach to revisions in an unexpected way. Just let this
+ // happen for now, although it might make sense to special case it
+ // eventually.
+ $changes = array();
+ }
+
$diff = DifferentialDiff::newFromRawChanges($changes)
->setRevisionID($revision->getID())
->setAuthorPHID($actor_phid)
->setCreationMethod('commit')
->setSourceControlSystem($this->repository->getVersionControlSystem())
->setLintStatus(DifferentialLintStatus::LINT_SKIP)
->setUnitStatus(DifferentialUnitStatus::UNIT_SKIP)
->setDateCreated($this->commit->getEpoch())
->setDescription(
'Commit r'.
$this->repository->getCallsign().
$this->commit->getCommitIdentifier());
// TODO: This is not correct in SVN where one repository can have multiple
// Arcanist projects.
$arcanist_project = id(new PhabricatorRepositoryArcanistProject())
->loadOneWhere('repositoryID = %d LIMIT 1', $this->repository->getID());
if ($arcanist_project) {
$diff->setArcanistProjectPHID($arcanist_project->getPHID());
}
$parents = DiffusionCommitParentsQuery::newFromDiffusionRequest($drequest)
->loadParents();
if ($parents) {
$diff->setSourceControlBaseRevision(head_key($parents));
}
// TODO: Attach binary files.
$revision->setLineCount($diff->getLineCount());
return $diff->save();
}
private function loadChangedByCommit(DifferentialDiff $diff) {
$repository = $this->repository;
$vs_changesets = array();
$vs_diff = id(new DifferentialDiff())->loadOneWhere(
'revisionID = %d AND creationMethod != %s ORDER BY id DESC LIMIT 1',
$diff->getRevisionID(),
'commit');
foreach ($vs_diff->loadChangesets() as $changeset) {
$path = $changeset->getAbsoluteRepositoryPath($repository, $vs_diff);
$path = ltrim($path, '/');
$vs_changesets[$path] = $changeset;
}
$changesets = array();
foreach ($diff->getChangesets() as $changeset) {
$path = $changeset->getAbsoluteRepositoryPath($repository, $diff);
$path = ltrim($path, '/');
$changesets[$path] = $changeset;
}
if (array_fill_keys(array_keys($changesets), true) !=
array_fill_keys(array_keys($vs_changesets), true)) {
return $vs_diff;
}
$hunks = id(new DifferentialHunk())->loadAllWhere(
'changesetID IN (%Ld)',
mpull($vs_changesets, 'getID'));
$hunks = mgroup($hunks, 'getChangesetID');
foreach ($vs_changesets as $changeset) {
$changeset->attachHunks(idx($hunks, $changeset->getID(), array()));
}
$file_phids = array();
foreach ($vs_changesets as $changeset) {
$metadata = $changeset->getMetadata();
$file_phid = idx($metadata, 'new:binary-phid');
if ($file_phid) {
$file_phids[$file_phid] = $file_phid;
}
}
$files = array();
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
}
foreach ($changesets as $path => $changeset) {
$vs_changeset = $vs_changesets[$path];
$file_phid = idx($vs_changeset->getMetadata(), 'new:binary-phid');
if ($file_phid) {
if (!isset($files[$file_phid])) {
return $vs_diff;
}
$drequest = DiffusionRequest::newFromDictionary(array(
'user' => PhabricatorUser::getOmnipotentUser(),
'initFromConduit' => false,
'repository' => $this->repository,
'commit' => $this->commit->getCommitIdentifier(),
'path' => $path,
));
$corpus = DiffusionFileContentQuery::newFromDiffusionRequest($drequest)
->setViewer(PhabricatorUser::getOmnipotentUser())
->loadFileContent()
->getCorpus();
if ($files[$file_phid]->loadFileData() != $corpus) {
return $vs_diff;
}
} else {
$context = implode("\n", $changeset->makeChangesWithContext());
$vs_context = implode("\n", $vs_changeset->makeChangesWithContext());
// We couldn't just compare $context and $vs_context because following
// diffs will be considered different:
//
// -(empty line)
// -echo 'test';
// (empty line)
//
// (empty line)
// -echo "test";
// -(empty line)
$hunk = id(new DifferentialHunk())->setChanges($context);
$vs_hunk = id(new DifferentialHunk())->setChanges($vs_context);
if ($hunk->makeOldFile() != $vs_hunk->makeOldFile() ||
$hunk->makeNewFile() != $vs_hunk->makeNewFile()) {
return $vs_diff;
}
}
}
return null;
}
/**
* When querying for revisions by hash, more than one revision may be found.
* This function identifies the "best" revision from such a set. Typically,
* there is only one revision found. Otherwise, we try to pick an accepted
* revision first, followed by an open revision, and otherwise we go with a
* closed or abandoned revision as a last resort.
*/
private function identifyBestRevision(array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
// get the simplest, common case out of the way
if (count($revisions) == 1) {
return reset($revisions);
}
$first_choice = array();
$second_choice = array();
$third_choice = array();
foreach ($revisions as $revision) {
switch ($revision->getStatus()) {
// "Accepted" revisions -- ostensibly what we're looking for!
case ArcanistDifferentialRevisionStatus::ACCEPTED:
$first_choice[] = $revision;
break;
// "Open" revisions
case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW:
case ArcanistDifferentialRevisionStatus::NEEDS_REVISION:
$second_choice[] = $revision;
break;
// default is a wtf? here
default:
case ArcanistDifferentialRevisionStatus::ABANDONED:
case ArcanistDifferentialRevisionStatus::CLOSED:
$third_choice[] = $revision;
break;
}
}
// go down the ladder like a bro at last call
if (!empty($first_choice)) {
return $this->identifyMostRecentRevision($first_choice);
}
if (!empty($second_choice)) {
return $this->identifyMostRecentRevision($second_choice);
}
if (!empty($third_choice)) {
return $this->identifyMostRecentRevision($third_choice);
}
}
/**
* Given a set of revisions, returns the revision with the latest
* updated time. This is ostensibly the most recent revision.
*/
private function identifyMostRecentRevision(array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$revisions = msort($revisions, 'getDateModified');
return end($revisions);
}
/**
* Emit an event so installs can do custom lookup of commit authors who may
* not be naturally resolvable.
*/
private function lookupUser(
PhabricatorRepositoryCommit $commit,
$query,
$guess) {
$type = PhabricatorEventType::TYPE_DIFFUSION_LOOKUPUSER;
$data = array(
'commit' => $commit,
'query' => $query,
'result' => $guess,
);
$event = new PhabricatorEvent($type, $data);
PhutilEventEngine::dispatchEvent($event);
return $event->getValue('result');
}
private function resolveUserPHID($user_name) {
if (!strlen($user_name)) {
return null;
}
$phid = $this->findUserByUserName($user_name);
if ($phid) {
return $phid;
}
$phid = $this->findUserByEmailAddress($user_name);
if ($phid) {
return $phid;
}
$phid = $this->findUserByRealName($user_name);
if ($phid) {
return $phid;
}
// No hits yet, try to parse it as an email address.
$email = new PhutilEmailAddress($user_name);
$phid = $this->findUserByEmailAddress($email->getAddress());
if ($phid) {
return $phid;
}
$display_name = $email->getDisplayName();
if ($display_name) {
$phid = $this->findUserByUserName($display_name);
if ($phid) {
return $phid;
}
$phid = $this->findUserByRealName($display_name);
if ($phid) {
return $phid;
}
}
return null;
}
private function findUserByUserName($user_name) {
$by_username = id(new PhabricatorUser())->loadOneWhere(
'userName = %s',
$user_name);
if ($by_username) {
return $by_username->getPHID();
}
return null;
}
private function findUserByRealName($real_name) {
// Note, real names are not guaranteed unique, which is why we do it this
// way.
$by_realname = id(new PhabricatorUser())->loadAllWhere(
'realName = %s',
$real_name);
if (count($by_realname) == 1) {
return reset($by_realname)->getPHID();
}
return null;
}
private function findUserByEmailAddress($email_address) {
$by_email = PhabricatorUser::loadOneWithEmailAddress($email_address);
if ($by_email) {
return $by_email->getPHID();
}
return null;
}
}
diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php b/src/applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php
index d9fd4742d0..908671669e 100644
--- a/src/applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php
+++ b/src/applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php
@@ -1,265 +1,265 @@
<?php
final class PhabricatorSettingsPanelSSHKeys
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'ssh';
}
public function getPanelName() {
return pht('SSH Public Keys');
}
public function getPanelGroup() {
return pht('Authentication');
}
public function isEnabled() {
- return PhabricatorEnv::getEnvConfig('auth.sshkeys.enabled');
+ return true;
}
public function processRequest(AphrontRequest $request) {
$user = $request->getUser();
$edit = $request->getStr('edit');
$delete = $request->getStr('delete');
if (!$edit && !$delete) {
return $this->renderKeyListView($request);
}
$id = nonempty($edit, $delete);
if ($id && is_numeric($id)) {
// NOTE: Prevent editing/deleting of keys you don't own.
$key = id(new PhabricatorUserSSHKey())->loadOneWhere(
'userPHID = %s AND id = %d',
$user->getPHID(),
(int)$id);
if (!$key) {
return new Aphront404Response();
}
} else {
$key = new PhabricatorUserSSHKey();
$key->setUserPHID($user->getPHID());
}
if ($delete) {
return $this->processDelete($request, $key);
}
$e_name = true;
$e_key = true;
$errors = array();
$entire_key = $key->getEntireKey();
if ($request->isFormPost()) {
$key->setName($request->getStr('name'));
$entire_key = $request->getStr('key');
if (!strlen($entire_key)) {
$errors[] = pht('You must provide an SSH Public Key.');
$e_key = pht('Required');
} else {
$parts = str_replace("\n", '', trim($entire_key));
$parts = preg_split('/\s+/', $parts);
if (count($parts) == 2) {
$parts[] = ''; // Add an empty comment part.
} else if (count($parts) == 3) {
// This is the expected case.
} else {
if (preg_match('/private\s*key/i', $entire_key)) {
// Try to give the user a better error message if it looks like
// they uploaded a private key.
$e_key = pht('Invalid');
$errors[] = pht('Provide your public key, not your private key!');
} else {
$e_key = pht('Invalid');
$errors[] = pht('Provided public key is not properly formatted.');
}
}
if (!$errors) {
list($type, $body, $comment) = $parts;
if (!preg_match('/^ssh-dsa|ssh-rsa$/', $type)) {
$e_key = pht('Invalid');
$errors[] = pht('Public key should be "ssh-dsa" or "ssh-rsa".');
} else {
$key->setKeyType($type);
$key->setKeyBody($body);
$key->setKeyHash(md5($body));
$key->setKeyComment($comment);
$e_key = null;
}
}
}
if (!strlen($key->getName())) {
$errors[] = pht('You must name this public key.');
$e_name = pht('Required');
} else {
$e_name = null;
}
if (!$errors) {
try {
$key->save();
return id(new AphrontRedirectResponse())
->setURI($this->getPanelURI());
} catch (AphrontQueryDuplicateKeyException $ex) {
$e_key = pht('Duplicate');
$errors[] = pht('This public key is already associated with a user '.
'account.');
}
}
}
$error_view = null;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setTitle(pht('Form Errors'));
$error_view->setErrors($errors);
}
$is_new = !$key->getID();
if ($is_new) {
$header = pht('Add New SSH Public Key');
$save = pht('Add Key');
} else {
$header = pht('Edit SSH Public Key');
$save = pht('Save Changes');
}
$form = id(new AphrontFormView())
->setUser($user)
->addHiddenInput('edit', $is_new ? 'true' : $key->getID())
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Name'))
->setName('name')
->setValue($key->getName())
->setError($e_name))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel(pht('Public Key'))
->setName('key')
->setValue($entire_key)
->setError($e_key))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton($this->getPanelURI())
->setValue($save));
$header_title = new PHUIHeaderView();
$header_title->setHeader($header);
return id(new AphrontNullView())
->appendChild(
array(
$error_view,
$header_title,
$form,
));
}
private function renderKeyListView(AphrontRequest $request) {
$user = $request->getUser();
$keys = id(new PhabricatorUserSSHKey())->loadAllWhere(
'userPHID = %s',
$user->getPHID());
$rows = array();
foreach ($keys as $key) {
$rows[] = array(
phutil_tag(
'a',
array(
'href' => $this->getPanelURI('?edit='.$key->getID()),
),
$key->getName()),
$key->getKeyComment(),
$key->getKeyType(),
phabricator_date($key->getDateCreated(), $user),
phabricator_time($key->getDateCreated(), $user),
javelin_tag(
'a',
array(
'href' => $this->getPanelURI('?delete='.$key->getID()),
'class' => 'small grey button',
'sigil' => 'workflow',
),
pht('Delete')),
);
}
$table = new AphrontTableView($rows);
$table->setNoDataString(pht("You haven't added any SSH Public Keys."));
$table->setHeaders(
array(
pht('Name'),
pht('Comment'),
pht('Type'),
pht('Created'),
pht('Time'),
'',
));
$table->setColumnClasses(
array(
'wide pri',
'',
'',
'',
'right',
'action',
));
$panel = new AphrontPanelView();
$panel->addButton(
phutil_tag(
'a',
array(
'href' => $this->getPanelURI('?edit=true'),
'class' => 'green button',
),
pht('Add New Public Key')));
$panel->setHeader(pht('SSH Public Keys'));
$panel->appendChild($table);
$panel->setNoBackground();
return $panel;
}
private function processDelete(
AphrontRequest $request,
PhabricatorUserSSHKey $key) {
$user = $request->getUser();
$name = phutil_tag('strong', array(), $key->getName());
if ($request->isDialogFormPost()) {
$key->delete();
return id(new AphrontReloadResponse())
->setURI($this->getPanelURI());
}
$dialog = id(new AphrontDialogView())
->setUser($user)
->addHiddenInput('delete', $key->getID())
->setTitle(pht('Really delete SSH Public Key?'))
->appendChild(phutil_tag('p', array(), pht(
'The key "%s" will be permanently deleted, and you will not longer be '.
'able to use the corresponding private key to authenticate.',
$name)))
->addSubmitButton(pht('Delete Public Key'))
->addCancelButton($this->getPanelURI());
return id(new AphrontDialogResponse())
->setDialog($dialog);
}
}
diff --git a/src/infrastructure/ssh/PhabricatorSSHWorkflow.php b/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
index 7ad956c636..60a9f03fcd 100644
--- a/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
+++ b/src/infrastructure/ssh/PhabricatorSSHWorkflow.php
@@ -1,41 +1,109 @@
<?php
abstract class PhabricatorSSHWorkflow extends PhutilArgumentWorkflow {
private $user;
private $iochannel;
+ private $errorChannel;
+
+ public function setErrorChannel(PhutilChannel $error_channel) {
+ $this->errorChannel = $error_channel;
+ return $this;
+ }
+
+ public function getErrorChannel() {
+ return $this->errorChannel;
+ }
public function setUser(PhabricatorUser $user) {
$this->user = $user;
return $this;
}
public function getUser() {
return $this->user;
}
final public function isExecutable() {
return false;
}
public function setIOChannel(PhutilChannel $channel) {
$this->iochannel = $channel;
return $this;
}
public function getIOChannel() {
return $this->iochannel;
}
+ public function passthruIO(ExecFuture $future) {
+ $exec_channel = new PhutilExecChannel($future);
+ $exec_channel->setStderrHandler(array($this, 'writeErrorIOCallback'));
+
+ $io_channel = $this->getIOChannel();
+ $error_channel = $this->getErrorChannel();
+
+ $channels = array($exec_channel, $io_channel, $error_channel);
+
+ while (true) {
+ PhutilChannel::waitForAny($channels);
+
+ $io_channel->update();
+ $exec_channel->update();
+ $error_channel->update();
+
+ $done = !$exec_channel->isOpen();
+
+ $data = $io_channel->read();
+ if (strlen($data)) {
+ $exec_channel->write($data);
+ }
+
+ $data = $exec_channel->read();
+ if (strlen($data)) {
+ $io_channel->write($data);
+ }
+
+ // If we have nothing left on stdin, close stdin on the subprocess.
+ if (!$io_channel->isOpenForReading()) {
+ // TODO: This should probably be part of PhutilExecChannel?
+ $future->write('');
+ }
+
+ if ($done) {
+ break;
+ }
+ }
+
+ list($err) = $future->resolve();
+
+ return $err;
+ }
+
public function readAllInput() {
$channel = $this->getIOChannel();
while ($channel->update()) {
PhutilChannel::waitForAny(array($channel));
if (!$channel->isOpenForReading()) {
break;
}
}
return $channel->read();
}
+ public function writeIO($data) {
+ $this->getIOChannel()->write($data);
+ return $this;
+ }
+
+ public function writeErrorIO($data) {
+ $this->getErrorChannel()->write($data);
+ return $this;
+ }
+
+ public function writeErrorIOCallback(PhutilChannel $channel, $data) {
+ $this->writeErrorIO($data);
+ }
+
}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
index 88ded8d29f..5b21dcfab8 100644
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1,1709 +1,1717 @@
<?php
final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
public function getNamespace() {
return 'phabricator';
}
private function getPatchPath($file) {
$root = dirname(phutil_get_library_root('phabricator'));
$path = $root.'/resources/sql/patches/'.$file;
// Make sure it exists.
Filesystem::readFile($path);
return $path;
}
public function getPatches() {
return array(
'db.audit' => array(
'type' => 'db',
'name' => 'audit',
'after' => array( /* First Patch */ ),
),
'db.calendar' => array(
'type' => 'db',
'name' => 'calendar',
),
'db.chatlog' => array(
'type' => 'db',
'name' => 'chatlog',
),
'db.conduit' => array(
'type' => 'db',
'name' => 'conduit',
),
'db.countdown' => array(
'type' => 'db',
'name' => 'countdown',
),
'db.daemon' => array(
'type' => 'db',
'name' => 'daemon',
),
'db.differential' => array(
'type' => 'db',
'name' => 'differential',
),
'db.draft' => array(
'type' => 'db',
'name' => 'draft',
),
'db.drydock' => array(
'type' => 'db',
'name' => 'drydock',
),
'db.feed' => array(
'type' => 'db',
'name' => 'feed',
),
'db.file' => array(
'type' => 'db',
'name' => 'file',
),
'db.flag' => array(
'type' => 'db',
'name' => 'flag',
),
'db.harbormaster' => array(
'type' => 'db',
'name' => 'harbormaster',
),
'db.herald' => array(
'type' => 'db',
'name' => 'herald',
),
'db.maniphest' => array(
'type' => 'db',
'name' => 'maniphest',
),
'db.meta_data' => array(
'type' => 'db',
'name' => 'meta_data',
),
'db.metamta' => array(
'type' => 'db',
'name' => 'metamta',
),
'db.oauth_server' => array(
'type' => 'db',
'name' => 'oauth_server',
),
'db.owners' => array(
'type' => 'db',
'name' => 'owners',
),
'db.pastebin' => array(
'type' => 'db',
'name' => 'pastebin',
),
'db.phame' => array(
'type' => 'db',
'name' => 'phame',
),
'db.phriction' => array(
'type' => 'db',
'name' => 'phriction',
),
'db.project' => array(
'type' => 'db',
'name' => 'project',
),
'db.repository' => array(
'type' => 'db',
'name' => 'repository',
),
'db.search' => array(
'type' => 'db',
'name' => 'search',
),
'db.slowvote' => array(
'type' => 'db',
'name' => 'slowvote',
),
'db.timeline' => array(
'type' => 'db',
'name' => 'timeline',
'dead' => true,
),
'db.user' => array(
'type' => 'db',
'name' => 'user',
),
'db.worker' => array(
'type' => 'db',
'name' => 'worker',
),
'db.xhpastview' => array(
'type' => 'db',
'name' => 'xhpastview',
),
'db.cache' => array(
'type' => 'db',
'name' => 'cache',
),
'db.fact' => array(
'type' => 'db',
'name' => 'fact',
),
'db.ponder' => array(
'type' => 'db',
'name' => 'ponder',
),
'db.xhprof' => array(
'type' => 'db',
'name' => 'xhprof',
),
'db.pholio' => array(
'type' => 'db',
'name' => 'pholio',
),
'db.conpherence' => array(
'type' => 'db',
'name' => 'conpherence',
),
'db.config' => array(
'type' => 'db',
'name' => 'config',
),
'db.token' => array(
'type' => 'db',
'name' => 'token',
),
'db.releeph' => array(
'type' => 'db',
'name' => 'releeph',
),
'db.phlux' => array(
'type' => 'db',
'name' => 'phlux',
),
'db.phortune' => array(
'type' => 'db',
'name' => 'phortune',
),
'db.phrequent' => array(
'type' => 'db',
'name' => 'phrequent',
),
'db.diviner' => array(
'type' => 'db',
'name' => 'diviner',
),
'db.auth' => array(
'type' => 'db',
'name' => 'auth',
),
'db.doorkeeper' => array(
'type' => 'db',
'name' => 'doorkeeper',
),
'db.legalpad' => array(
'type' => 'db',
'name' => 'legalpad',
),
'db.policy' => array(
'type' => 'db',
'name' => 'policy',
),
'0000.legacy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('0000.legacy.sql'),
'legacy' => 0,
),
'000.project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('000.project.sql'),
'legacy' => 0,
),
'001.maniphest_projects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('001.maniphest_projects.sql'),
'legacy' => 1,
),
'002.oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('002.oauth.sql'),
'legacy' => 2,
),
'003.more_oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('003.more_oauth.sql'),
'legacy' => 3,
),
'004.daemonrepos.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('004.daemonrepos.sql'),
'legacy' => 4,
),
'005.workers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('005.workers.sql'),
'legacy' => 5,
),
'006.repository.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('006.repository.sql'),
'legacy' => 6,
),
'007.daemonlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('007.daemonlog.sql'),
'legacy' => 7,
),
'008.repoopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('008.repoopt.sql'),
'legacy' => 8,
),
'009.repo_summary.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('009.repo_summary.sql'),
'legacy' => 9,
),
'010.herald.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('010.herald.sql'),
'legacy' => 10,
),
'011.badcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('011.badcommit.sql'),
'legacy' => 11,
),
'012.dropphidtype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('012.dropphidtype.sql'),
'legacy' => 12,
),
'013.commitdetail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('013.commitdetail.sql'),
'legacy' => 13,
),
'014.shortcuts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('014.shortcuts.sql'),
'legacy' => 14,
),
'015.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('015.preferences.sql'),
'legacy' => 15,
),
'016.userrealnameindex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('016.userrealnameindex.sql'),
'legacy' => 16,
),
'017.sessionkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('017.sessionkeys.sql'),
'legacy' => 17,
),
'018.owners.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('018.owners.sql'),
'legacy' => 18,
),
'019.arcprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('019.arcprojects.sql'),
'legacy' => 19,
),
'020.pathcapital.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('020.pathcapital.sql'),
'legacy' => 20,
),
'021.xhpastview.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('021.xhpastview.sql'),
'legacy' => 21,
),
'022.differentialcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('022.differentialcommit.sql'),
'legacy' => 22,
),
'023.dxkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('023.dxkeys.sql'),
'legacy' => 23,
),
'024.mlistkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('024.mlistkeys.sql'),
'legacy' => 24,
),
'025.commentopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('025.commentopt.sql'),
'legacy' => 25,
),
'026.diffpropkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('026.diffpropkey.sql'),
'legacy' => 26,
),
'027.metamtakeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('027.metamtakeys.sql'),
'legacy' => 27,
),
'028.systemagent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('028.systemagent.sql'),
'legacy' => 28,
),
'029.cursors.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('029.cursors.sql'),
'legacy' => 29,
),
'030.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('030.imagemacro.sql'),
'legacy' => 30,
),
'031.workerrace.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('031.workerrace.sql'),
'legacy' => 31,
),
'032.viewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('032.viewtime.sql'),
'legacy' => 32,
),
'033.privtest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('033.privtest.sql'),
'legacy' => 33,
),
'034.savedheader.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('034.savedheader.sql'),
'legacy' => 34,
),
'035.proxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('035.proxyimage.sql'),
'legacy' => 35,
),
'036.mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('036.mailkey.sql'),
'legacy' => 36,
),
'037.setuptest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('037.setuptest.sql'),
'legacy' => 37,
),
'038.admin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('038.admin.sql'),
'legacy' => 38,
),
'039.userlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('039.userlog.sql'),
'legacy' => 39,
),
'040.transform.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('040.transform.sql'),
'legacy' => 40,
),
'041.heraldrepetition.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('041.heraldrepetition.sql'),
'legacy' => 41,
),
'042.commentmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('042.commentmetadata.sql'),
'legacy' => 42,
),
'043.pastebin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('043.pastebin.sql'),
'legacy' => 43,
),
'044.countdown.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('044.countdown.sql'),
'legacy' => 44,
),
'045.timezone.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('045.timezone.sql'),
'legacy' => 45,
),
'046.conduittoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('046.conduittoken.sql'),
'legacy' => 46,
),
'047.projectstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('047.projectstatus.sql'),
'legacy' => 47,
),
'048.relationshipkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('048.relationshipkeys.sql'),
'legacy' => 48,
),
'049.projectowner.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('049.projectowner.sql'),
'legacy' => 49,
),
'050.taskdenormal.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('050.taskdenormal.sql'),
'legacy' => 50,
),
'051.projectfilter.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('051.projectfilter.sql'),
'legacy' => 51,
),
'052.pastelanguage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('052.pastelanguage.sql'),
'legacy' => 52,
),
'053.feed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('053.feed.sql'),
'legacy' => 53,
),
'054.subscribers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('054.subscribers.sql'),
'legacy' => 54,
),
'055.add_author_to_files.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('055.add_author_to_files.sql'),
'legacy' => 55,
),
'056.slowvote.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('056.slowvote.sql'),
'legacy' => 56,
),
'057.parsecache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('057.parsecache.sql'),
'legacy' => 57,
),
'058.missingkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('058.missingkeys.sql'),
'legacy' => 58,
),
'059.engines.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('059.engines.php'),
'legacy' => 59,
),
'060.phriction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('060.phriction.sql'),
'legacy' => 60,
),
'061.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('061.phrictioncontent.sql'),
'legacy' => 61,
),
'062.phrictionmenu.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('062.phrictionmenu.sql'),
'legacy' => 62,
),
'063.pasteforks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('063.pasteforks.sql'),
'legacy' => 63,
),
'064.subprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('064.subprojects.sql'),
'legacy' => 64,
),
'065.sshkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('065.sshkeys.sql'),
'legacy' => 65,
),
'066.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('066.phrictioncontent.sql'),
'legacy' => 66,
),
'067.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('067.preferences.sql'),
'legacy' => 67,
),
'068.maniphestauxiliarystorage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('068.maniphestauxiliarystorage.sql'),
'legacy' => 68,
),
'069.heraldxscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('069.heraldxscript.sql'),
'legacy' => 69,
),
'070.differentialaux.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('070.differentialaux.sql'),
'legacy' => 70,
),
'071.contentsource.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('071.contentsource.sql'),
'legacy' => 71,
),
'072.blamerevert.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('072.blamerevert.sql'),
'legacy' => 72,
),
'073.reposymbols.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('073.reposymbols.sql'),
'legacy' => 73,
),
'074.affectedpath.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('074.affectedpath.sql'),
'legacy' => 74,
),
'075.revisionhash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('075.revisionhash.sql'),
'legacy' => 75,
),
'076.indexedlanguages.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('076.indexedlanguages.sql'),
'legacy' => 76,
),
'077.originalemail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('077.originalemail.sql'),
'legacy' => 77,
),
'078.nametoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('078.nametoken.sql'),
'legacy' => 78,
),
'079.nametokenindex.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('079.nametokenindex.php'),
'legacy' => 79,
),
'080.filekeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('080.filekeys.sql'),
'legacy' => 80,
),
'081.filekeys.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('081.filekeys.php'),
'legacy' => 81,
),
'082.xactionkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('082.xactionkey.sql'),
'legacy' => 82,
),
'083.dxviewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('083.dxviewtime.sql'),
'legacy' => 83,
),
'084.pasteauthorkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('084.pasteauthorkey.sql'),
'legacy' => 84,
),
'085.packagecommitrelationship.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('085.packagecommitrelationship.sql'),
'legacy' => 85,
),
'086.formeraffil.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('086.formeraffil.sql'),
'legacy' => 86,
),
'087.phrictiondelete.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('087.phrictiondelete.sql'),
'legacy' => 87,
),
'088.audit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('088.audit.sql'),
'legacy' => 88,
),
'089.projectwiki.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('089.projectwiki.sql'),
'legacy' => 89,
),
'090.forceuniqueprojectnames.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('090.forceuniqueprojectnames.php'),
'legacy' => 90,
),
'091.uniqueslugkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('091.uniqueslugkey.sql'),
'legacy' => 91,
),
'092.dropgithubnotification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('092.dropgithubnotification.sql'),
'legacy' => 92,
),
'093.gitremotes.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('093.gitremotes.php'),
'legacy' => 93,
),
'094.phrictioncolumn.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('094.phrictioncolumn.sql'),
'legacy' => 94,
),
'095.directory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('095.directory.sql'),
'legacy' => 95,
),
'096.filename.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('096.filename.sql'),
'legacy' => 96,
),
'097.heraldruletypes.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('097.heraldruletypes.sql'),
'legacy' => 97,
),
'098.heraldruletypemigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('098.heraldruletypemigration.php'),
'legacy' => 98,
),
'099.drydock.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('099.drydock.sql'),
'legacy' => 99,
),
'100.projectxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('100.projectxaction.sql'),
'legacy' => 100,
),
'101.heraldruleapplied.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('101.heraldruleapplied.sql'),
'legacy' => 101,
),
'102.heraldcleanup.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('102.heraldcleanup.php'),
'legacy' => 102,
),
'103.heraldedithistory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('103.heraldedithistory.sql'),
'legacy' => 103,
),
'104.searchkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('104.searchkey.sql'),
'legacy' => 104,
),
'105.mimetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('105.mimetype.sql'),
'legacy' => 105,
),
'106.chatlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('106.chatlog.sql'),
'legacy' => 106,
),
'107.oauthserver.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('107.oauthserver.sql'),
'legacy' => 107,
),
'108.oauthscope.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('108.oauthscope.sql'),
'legacy' => 108,
),
'109.oauthclientphidkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('109.oauthclientphidkey.sql'),
'legacy' => 109,
),
'110.commitaudit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('110.commitaudit.sql'),
'legacy' => 110,
),
'111.commitauditmigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('111.commitauditmigration.php'),
'legacy' => 111,
),
'112.oauthaccesscoderedirecturi.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('112.oauthaccesscoderedirecturi.sql'),
'legacy' => 112,
),
'113.lastreviewer.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('113.lastreviewer.sql'),
'legacy' => 113,
),
'114.auditrequest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('114.auditrequest.sql'),
'legacy' => 114,
),
'115.prepareutf8.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('115.prepareutf8.sql'),
'legacy' => 115,
),
'116.utf8-backup-first-expect-wait.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('116.utf8-backup-first-expect-wait.sql'),
'legacy' => 116,
),
'117.repositorydescription.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('117.repositorydescription.php'),
'legacy' => 117,
),
'118.auditinline.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('118.auditinline.sql'),
'legacy' => 118,
),
'119.filehash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('119.filehash.sql'),
'legacy' => 119,
),
'120.noop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('120.noop.sql'),
'legacy' => 120,
),
'121.drydocklog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('121.drydocklog.sql'),
'legacy' => 121,
),
'122.flag.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('122.flag.sql'),
'legacy' => 122,
),
'123.heraldrulelog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('123.heraldrulelog.sql'),
'legacy' => 123,
),
'124.subpriority.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('124.subpriority.sql'),
'legacy' => 124,
),
'125.ipv6.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('125.ipv6.sql'),
'legacy' => 125,
),
'126.edges.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('126.edges.sql'),
'legacy' => 126,
),
'127.userkeybody.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('127.userkeybody.sql'),
'legacy' => 127,
),
'128.phabricatorcom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('128.phabricatorcom.sql'),
'legacy' => 128,
),
'129.savedquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('129.savedquery.sql'),
'legacy' => 129,
),
'130.denormalrevisionquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('130.denormalrevisionquery.sql'),
'legacy' => 130,
),
'131.migraterevisionquery.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('131.migraterevisionquery.php'),
'legacy' => 131,
),
'132.phame.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('132.phame.sql'),
'legacy' => 132,
),
'133.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('133.imagemacro.sql'),
'legacy' => 133,
),
'134.emptysearch.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('134.emptysearch.sql'),
'legacy' => 134,
),
'135.datecommitted.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('135.datecommitted.sql'),
'legacy' => 135,
),
'136.sex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('136.sex.sql'),
'legacy' => 136,
),
'137.auditmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('137.auditmetadata.sql'),
'legacy' => 137,
),
'138.notification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('138.notification.sql'),
),
'holidays.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('holidays.sql'),
),
'userstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('userstatus.sql'),
),
'emailtable.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtable.sql'),
),
'emailtableport.sql' => array(
'type' => 'php',
'name' => $this->getPatchPath('emailtableport.php'),
),
'emailtableremove.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtableremove.sql'),
),
'phiddrop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phiddrop.sql'),
),
'testdatabase.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('testdatabase.sql'),
),
'ldapinfo.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ldapinfo.sql'),
),
'threadtopic.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('threadtopic.sql'),
),
'usertranslation.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('usertranslation.sql'),
),
'differentialbookmarks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('differentialbookmarks.sql'),
),
'harbormasterobject.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('harbormasterobject.sql'),
),
'markupcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('markupcache.sql'),
),
'maniphestxcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('maniphestxcache.sql'),
),
'migrate-maniphest-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-dependencies.php'),
),
'migrate-differential-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath(
'migrate-differential-dependencies.php'),
),
'phameblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameblog.sql'),
),
'migrate-maniphest-revisions.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-revisions.php'),
),
'daemonstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatus.sql'),
),
'symbolcontexts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('symbolcontexts.sql'),
),
'migrate-project-edges.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-project-edges.php'),
),
'fact-raw.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('fact-raw.sql'),
),
'ponder.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder.sql')
),
'policy-project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('policy-project.sql'),
),
'daemonstatuskey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatuskey.sql'),
),
'edgetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('edgetype.sql'),
),
'ponder-comments.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-comments.sql'),
),
'pastepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pastepolicy.sql'),
),
'xhprof.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('xhprof.sql'),
),
'draft-metadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('draft-metadata.sql'),
),
'phamedomain.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamedomain.sql'),
),
'ponder-mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-mailkey.sql'),
),
'ponder-mailkey-populate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('ponder-mailkey-populate.php'),
),
'phamepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamepolicy.sql'),
),
'phameoneblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameoneblog.sql'),
),
'statustxt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('statustxt.sql'),
),
'daemontaskarchive.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemontaskarchive.sql'),
),
'drydocktaskid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydocktaskid.sql'),
),
'drydockresoucetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydockresourcetype.sql'),
),
'liskcounters.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters.sql'),
),
'liskcounters.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('liskcounters.php'),
),
'dropfileproxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('dropfileproxyimage.sql'),
),
'repository-lint.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('repository-lint.sql'),
),
'liskcounters-task.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters-task.sql'),
),
'pholio.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pholio.sql'),
),
'owners-exclude.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('owners-exclude.sql'),
),
'20121209.pholioxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.pholioxactions.sql'),
),
'20121209.xmacroadd.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacroadd.sql'),
),
'20121209.xmacromigrate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20121209.xmacromigrate.php'),
),
'20121209.xmacromigratekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacromigratekey.sql'),
),
'20121220.generalcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121220.generalcache.sql'),
),
'20121226.config.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121226.config.sql'),
),
'20130101.confxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130101.confxaction.sql'),
),
'20130102.metamtareceivedmailmessageidhash.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('20130102.metamtareceivedmailmessageidhash.sql'),
),
'20130103.filemetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130103.filemetadata.sql'),
),
'20130111.conpherence.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130111.conpherence.sql'),
),
'20130127.altheraldtranscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130127.altheraldtranscript.sql'),
),
'20130201.revisionunsubscribed.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.php'),
),
'20130201.revisionunsubscribed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.sql'),
),
'20130131.conpherencepics.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130131.conpherencepics.sql'),
),
'20130214.chatlogchannel.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.chatlogchannel.sql'),
),
'20130214.chatlogchannelid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.chatlogchannelid.sql'),
),
'20130214.token.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130214.token.sql'),
),
'20130215.phabricatorfileaddttl.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130215.phabricatorfileaddttl.sql'),
),
'20130217.cachettl.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130217.cachettl.sql'),
),
'20130218.updatechannelid.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130218.updatechannelid.php'),
),
'20130218.longdaemon.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130218.longdaemon.sql'),
),
'20130219.commitsummary.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130219.commitsummary.sql'),
),
'20130219.commitsummarymig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130219.commitsummarymig.php'),
),
'20130222.dropchannel.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130222.dropchannel.sql'),
),
'20130226.commitkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130226.commitkey.sql'),
),
'20131302.maniphestvalue.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131302.maniphestvalue.sql'),
),
'20130304.lintauthor.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130304.lintauthor.sql'),
),
'releeph.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('releeph.sql'),
),
'20130319.phabricatorfileexplicitupload.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath(
'20130319.phabricatorfileexplicitupload.sql')
),
'20130319.conpherence.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130319.conpherence.sql'),
),
'20130320.phlux.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130320.phlux.sql'),
),
'20130317.phrictionedge.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130317.phrictionedge.sql'),
),
'20130321.token.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130321.token.sql'),
),
'20130310.xactionmeta.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130310.xactionmeta.sql'),
),
'20130322.phortune.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130322.phortune.sql'),
),
'20130323.phortunepayment.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130323.phortunepayment.sql'),
),
'20130324.phortuneproduct.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130324.phortuneproduct.sql'),
),
'20130330.phrequent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130330.phrequent.sql'),
),
'20130403.conpherencecache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130403.conpherencecache.sql'),
),
'20130403.conpherencecachemig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130403.conpherencecachemig.php'),
),
'20130409.commitdrev.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130409.commitdrev.php'),
),
'20130417.externalaccount.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130417.externalaccount.sql'),
),
'20130423.updateexternalaccount.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130423.updateexternalaccount.sql'),
),
'20130423.phortunepaymentrevised.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130423.phortunepaymentrevised.sql'),
),
'20130423.conpherenceindices.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130423.conpherenceindices.sql'),
),
'20130426.search_savedquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130426.search_savedquery.sql'),
),
'20130502.countdownrevamp1.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130502.countdownrevamp1.sql'),
),
'20130502.countdownrevamp2.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130502.countdownrevamp2.php'),
),
'20130502.countdownrevamp3.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130502.countdownrevamp3.sql'),
),
'20130507.releephrqsimplifycols.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130507.releephrqsimplifycols.sql'),
),
'20130507.releephrqmailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130507.releephrqmailkey.sql'),
),
'20130507.releephrqmailkeypop.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130507.releephrqmailkeypop.php'),
),
'20130508.search_namedquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130508.search_namedquery.sql'),
),
'20130508.releephtransactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130508.releephtransactions.sql'),
),
'20130508.releephtransactionsmig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130508.releephtransactionsmig.php'),
),
'20130513.receviedmailstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130513.receviedmailstatus.sql'),
),
'20130519.diviner.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130519.diviner.sql'),
),
'20130521.dropconphimages.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130521.dropconphimages.sql'),
),
'20130523.maniphest_owners.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130523.maniphest_owners.sql'),
),
'20130524.repoxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130524.repoxactions.sql'),
),
'20130529.macroauthor.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130529.macroauthor.sql'),
),
'20130529.macroauthormig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130529.macroauthormig.php'),
),
'20130530.sessionhash.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130530.sessionhash.php'),
),
'20130530.macrodatekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130530.macrodatekey.sql'),
),
'20130530.pastekeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130530.pastekeys.sql'),
),
'20130531.filekeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130531.filekeys.sql'),
),
'20130602.morediviner.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130602.morediviner.sql'),
),
'20130602.namedqueries.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130602.namedqueries.sql'),
),
'20130606.userxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130606.userxactions.sql'),
),
'20130607.xaccount.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130607.xaccount.sql'),
),
'20130611.migrateoauth.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130611.migrateoauth.php'),
),
'20130611.nukeldap.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130611.nukeldap.php'),
),
'20130613.authdb.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130613.authdb.sql'),
),
'20130619.authconf.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130619.authconf.php'),
),
'20130620.diffxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130620.diffxactions.sql'),
),
'20130621.diffcommentphid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130621.diffcommentphid.sql'),
),
'20130621.diffcommentphidmig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130621.diffcommentphidmig.php'),
),
'20130621.diffcommentunphid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130621.diffcommentunphid.sql'),
),
'20130622.doorkeeper.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130622.doorkeeper.sql'),
),
'20130628.legalpadv0.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130628.legalpadv0.sql'),
),
'20130701.conduitlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130701.conduitlog.sql'),
),
'legalpad-mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('legalpad-mailkey.sql'),
),
'legalpad-mailkey-populate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('legalpad-mailkey-populate.php'),
),
'20130703.legalpaddocdenorm.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130703.legalpaddocdenorm.sql'),
),
'20130703.legalpaddocdenorm.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130703.legalpaddocdenorm.php'),
),
'20130709.legalpadsignature.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130709.legalpadsignature.sql'),
),
'20130709.droptimeline.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130709.droptimeline.sql'),
),
'20130711.trimrealnames.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130711.trimrealnames.php'),
),
'20130714.votexactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130714.votexactions.sql'),
),
'20130715.votecomments.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130715.votecomments.php'),
),
'20130715.voteedges.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130715.voteedges.sql'),
),
'20130711.pholioimageobsolete.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130711.pholioimageobsolete.sql'),
),
'20130711.pholioimageobsolete.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130711.pholioimageobsolete.php'),
),
'20130711.pholioimageobsolete2.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130711.pholioimageobsolete2.sql'),
),
'20130716.archivememberlessprojects.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130716.archivememberlessprojects.php'),
),
'20130722.pholioreplace.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130722.pholioreplace.sql'),
),
'20130723.taskstarttime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130723.taskstarttime.sql'),
),
'20130727.ponderquestionstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130727.ponderquestionstatus.sql'),
),
'20130726.ponderxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130726.ponderxactions.sql'),
),
'20130728.ponderunique.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130728.ponderunique.php'),
),
'20130728.ponderuniquekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130728.ponderuniquekey.sql'),
),
'20130728.ponderxcomment.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130728.ponderxcomment.php'),
),
'20130801.pastexactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130801.pastexactions.sql'),
),
'20130801.pastexactions.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130801.pastexactions.php'),
),
'20130805.pastemailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130805.pastemailkey.sql'),
),
'20130805.pasteedges.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130805.pasteedges.sql'),
),
'20130805.pastemailkeypop.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130805.pastemailkeypop.php'),
),
'20130802.heraldphid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130802.heraldphid.sql'),
),
'20130802.heraldphids.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130802.heraldphids.php'),
),
'20130802.heraldphidukey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130802.heraldphidukey.sql'),
),
'20130802.heraldxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130802.heraldxactions.sql'),
),
'20130731.releephrepoid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130731.releephrepoid.sql'),
),
'20130731.releephproject.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130731.releephproject.sql'),
),
'20130731.releephcutpointidentifier.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130731.releephcutpointidentifier.sql'),
),
'20130814.usercustom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130814.usercustom.sql'),
),
'20130820.releephxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130820.releephxactions.sql'),
),
'20130826.divinernode.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130826.divinernode.sql'),
),
'20130820.filexactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130820.filexactions.sql'),
),
'20130820.filemailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130820.filemailkey.sql'),
),
'20130820.file-mailkey-populate.php' => array(
'type' => 'php',
'name' =>
$this->getPatchPath('20130820.file-mailkey-populate.php'),
),
'20130912.maniphest.1.touch.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130912.maniphest.1.touch.sql'),
),
'20130912.maniphest.2.created.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130912.maniphest.2.created.sql'),
),
'20130912.maniphest.3.nameindex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130912.maniphest.3.nameindex.sql'),
),
'20130912.maniphest.4.fillindex.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130912.maniphest.4.fillindex.php'),
),
'20130913.maniphest.1.migratesearch.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130913.maniphest.1.migratesearch.php'),
),
'20130914.usercustom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130914.usercustom.sql'),
),
'20130915.maniphestcustom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130915.maniphestcustom.sql'),
),
'20130915.maniphestmigrate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130915.maniphestmigrate.php'),
),
'20130919.mfieldconf.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130919.mfieldconf.php'),
),
'20130920.repokeyspolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130920.repokeyspolicy.sql'),
),
'20130921.mtransactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130921.mtransactions.sql'),
),
'20130921.xmigratemaniphest.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130921.xmigratemaniphest.php'),
),
'20130923.mrename.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130923.mrename.sql'),
),
'20130924.mdraftkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130924.mdraftkey.sql'),
),
'20130925.mpolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130925.mpolicy.sql'),
),
'20130925.xpolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130925.xpolicy.sql'),
),
'20130926.dcustom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130926.dcustom.sql'),
),
'20130926.dinkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130926.dinkeys.sql'),
),
'20130927.audiomacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130927.audiomacro.sql'),
),
'20130929.filepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130929.filepolicy.sql'),
),
'20131004.dxedgekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131004.dxedgekey.sql'),
),
'20131004.dxreviewers.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20131004.dxreviewers.php'),
),
'20131006.hdisable.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131006.hdisable.sql'),
),
'20131010.pstorage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131010.pstorage.sql'),
),
'20131015.cpolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131015.cpolicy.sql'),
),
'20130915.maniphestqdrop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130915.maniphestqdrop.sql'),
),
'20130926.dinline.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130926.dinline.php'),
),
'20131020.pcustom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131020.pcustom.sql'),
),
'20131020.col1.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131020.col1.sql'),
),
'20131020.pxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131020.pxaction.sql'),
),
'20131020.pxactionmig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20131020.pxactionmig.php'),
),
'20131020.harbormaster.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131020.harbormaster.sql'),
),
+ '20131025.repopush.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20131025.repopush.sql'),
+ ),
+ '20131026.commitstatus.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20131026.commitstatus.sql'),
+ ),
);
}
}
diff --git a/src/view/form/control/AphrontFormPolicyControl.php b/src/view/form/control/AphrontFormPolicyControl.php
index 473c1b3cb8..8f9a7b7441 100644
--- a/src/view/form/control/AphrontFormPolicyControl.php
+++ b/src/view/form/control/AphrontFormPolicyControl.php
@@ -1,215 +1,226 @@
<?php
final class AphrontFormPolicyControl extends AphrontFormControl {
private $object;
private $capability;
private $policies;
public function setPolicyObject(PhabricatorPolicyInterface $object) {
$this->object = $object;
return $this;
}
public function setPolicies(array $policies) {
assert_instances_of($policies, 'PhabricatorPolicy');
$this->policies = $policies;
return $this;
}
public function setCapability($capability) {
$this->capability = $capability;
$labels = array(
PhabricatorPolicyCapability::CAN_VIEW => pht('Visible To'),
PhabricatorPolicyCapability::CAN_EDIT => pht('Editable By'),
PhabricatorPolicyCapability::CAN_JOIN => pht('Joinable By'),
);
- $this->setLabel(idx($labels, $this->capability, pht('Unknown Policy')));
+ if (isset($labels[$capability])) {
+ $label = $labels[$capability];
+ } else {
+ $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability);
+ if ($capobj) {
+ $label = $capobj->getCapabilityName();
+ } else {
+ $label = pht('Capability "%s"', $capability);
+ }
+ }
+
+ $this->setLabel($label);
return $this;
}
protected function getCustomControlClass() {
return 'aphront-form-control-policy';
}
protected function getOptions() {
$capability = $this->capability;
$options = array();
foreach ($this->policies as $policy) {
if ($policy->getPHID() == PhabricatorPolicies::POLICY_PUBLIC) {
// Never expose "Public" for capabilities which don't support it.
$capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability);
if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) {
continue;
}
}
$options[$policy->getType()][$policy->getPHID()] = array(
'name' => phutil_utf8_shorten($policy->getName(), 28),
'full' => $policy->getName(),
'icon' => $policy->getIcon(),
);
}
// If we were passed several custom policy options, throw away the ones
// which aren't the value for this capability. For example, an object might
// have a custom view pollicy and a custom edit policy. When we render
// the selector for "Can View", we don't want to show the "Can Edit"
// custom policy -- if we did, the menu would look like this:
//
// Custom
// Custom Policy
// Custom Policy
//
// ...where one is the "view" custom policy, and one is the "edit" custom
// policy.
$type_custom = PhabricatorPolicyType::TYPE_CUSTOM;
if (!empty($options[$type_custom])) {
$options[$type_custom] = array_select_keys(
$options[$type_custom],
array($this->getValue()));
}
// If there aren't any custom policies, add a placeholder policy so we
// render a menu item. This allows the user to switch to a custom policy.
if (empty($options[$type_custom])) {
$placeholder = new PhabricatorPolicy();
$placeholder->setName(pht('Custom Policy...'));
$options[$type_custom][$this->getCustomPolicyPlaceholder()] = array(
'name' => $placeholder->getName(),
'full' => $placeholder->getName(),
'icon' => $placeholder->getIcon(),
);
}
$options = array_select_keys(
$options,
array(
PhabricatorPolicyType::TYPE_GLOBAL,
PhabricatorPolicyType::TYPE_CUSTOM,
PhabricatorPolicyType::TYPE_PROJECT,
));
return $options;
}
protected function renderInput() {
if (!$this->object) {
throw new Exception(pht("Call setPolicyObject() before rendering!"));
}
if (!$this->capability) {
throw new Exception(pht("Call setCapability() before rendering!"));
}
$policy = $this->object->getPolicy($this->capability);
if (!$policy) {
// TODO: Make this configurable.
$policy = PhabricatorPolicies::POLICY_USER;
}
$this->setValue($policy);
$control_id = celerity_generate_unique_node_id();
$input_id = celerity_generate_unique_node_id();
$caret = phutil_tag(
'span',
array(
'class' => 'caret',
));
$input = phutil_tag(
'input',
array(
'type' => 'hidden',
'id' => $input_id,
'name' => $this->getName(),
'value' => $this->getValue(),
));
$options = $this->getOptions();
$order = array();
$labels = array();
foreach ($options as $key => $values) {
$order[$key] = array_keys($values);
$labels[$key] = PhabricatorPolicyType::getPolicyTypeName($key);
}
$flat_options = array_mergev($options);
$icons = array();
foreach (igroup($flat_options, 'icon') as $icon => $ignored) {
$icons[$icon] = id(new PHUIIconView())
->setSpriteSheet(PHUIIconView::SPRITE_STATUS)
->setSpriteIcon($icon);
}
Javelin::initBehavior(
'policy-control',
array(
'controlID' => $control_id,
'inputID' => $input_id,
'options' => $flat_options,
'groups' => array_keys($options),
'order' => $order,
'icons' => $icons,
'labels' => $labels,
'value' => $this->getValue(),
'customPlaceholder' => $this->getCustomPolicyPlaceholder(),
));
$selected = $flat_options[$this->getValue()];
return phutil_tag(
'div',
array(
),
array(
javelin_tag(
'a',
array(
'class' => 'grey button dropdown has-icon policy-control',
'href' => '#',
'mustcapture' => true,
'sigil' => 'policy-control',
'id' => $control_id,
),
array(
$caret,
javelin_tag(
'span',
array(
'sigil' => 'policy-label',
'class' => 'phui-button-text',
),
array(
$icons[$selected['icon']],
$selected['name'],
)),
)),
$input,
));
return AphrontFormSelectControl::renderSelectTag(
$this->getValue(),
$this->getOptions(),
array(
'name' => $this->getName(),
'disabled' => $this->getDisabled() ? 'disabled' : null,
'id' => $this->getID(),
));
}
private function getCustomPolicyPlaceholder() {
return 'custom:placeholder';
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Nov 24, 2:00 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
388566
Default Alt Text
(881 KB)

Event Timeline