Merge "objectcache: change "miss" to "renew" in metric name for preemptive refreshes"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 20 Jun 2018 15:42:39 +0000 (15:42 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 20 Jun 2018 15:42:39 +0000 (15:42 +0000)
includes/EditPage.php
includes/api/ApiQueryFileRepoInfo.php
includes/api/i18n/en.json
includes/api/i18n/qqq.json
maintenance/Maintenance.php
tests/selenium/wdio.conf.js

index 9209761..3c97fe6 100644 (file)
@@ -235,7 +235,10 @@ class EditPage {
        /** @var string */
        public $action = 'submit';
 
-       /** @var bool */
+       /** @var bool Whether an edit conflict needs to be resolved. Detected based on whether
+        * $editRevId is different from the current revision. When a conflict has successfully
+        * been resolved by a 3-way-merge, this field is set to false.
+        */
        public $isConflict = false;
 
        /** @var bool New page or new section */
@@ -301,7 +304,7 @@ class EditPage {
        /** @var bool Has a summary been preset using GET parameter &summary= ? */
        public $hasPresetSummary = false;
 
-       /** @var Revision|bool|null */
+       /** @var Revision|bool|null A revision object corresponding to $this->editRevId. */
        public $mBaseRevision = false;
 
        /** @var bool */
@@ -342,7 +345,16 @@ class EditPage {
        /** @var string */
        public $edittime = '';
 
-       /** @var int */
+       /** @var int ID of the current revision at the time editing was initiated on the client.
+        * This is used to detect and resolve edit conflicts.
+        *
+        * @note 0 if the page did not exist at that time.
+        * @note When starting an edit from an old revision, this still records the current
+        * revision at the time , not the one the edit is based on.
+        *
+        * @see $oldid
+        * @see getBaseRevision()
+        */
        private $editRevId = null;
 
        /** @var string */
@@ -354,10 +366,16 @@ class EditPage {
        /** @var string */
        public $starttime = '';
 
-       /** @var int */
+       /** @var int Revision ID the edit is based on, or 0 if it's the current revision.
+        * @see $editRevId
+        */
        public $oldid = 0;
 
-       /** @var int */
+       /** @var int Revision ID the edit is based on, adjusted when an edit conflict is resolved.
+        * @see $editRevId
+        * @see $oldid
+        * @see getparentRevId()
+        */
        public $parentRevId = 0;
 
        /** @var string */
@@ -2021,7 +2039,10 @@ ERROR;
 
                        wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
 
-                       // Check editRevId if set, which handles same-second timestamp collisions
+                       // An edit conflict is detected if the current revision is different from the
+                       // revision that was current when editing was initiated on the client.
+                       // This is checked based on the timestamp and revision ID.
+                       // TODO: the timestamp based check can probably go away now.
                        if ( $timestamp != $this->edittime
                                || ( $this->editRevId !== null && $this->editRevId != $latest )
                        ) {
@@ -2301,7 +2322,8 @@ ERROR;
        private function mergeChangesIntoContent( &$editContent ) {
                $db = wfGetDB( DB_MASTER );
 
-               // This is the revision the editor started from
+               // This is the revision that was current at the time editing was initiated on the client,
+               // even if the edit was based on an old revision.
                $baseRevision = $this->getBaseRevision();
                $baseContent = $baseRevision ? $baseRevision->getContent() : null;
 
@@ -2332,9 +2354,16 @@ ERROR;
        }
 
        /**
-        * @note: this method is very poorly named. If the user opened the form with ?oldid=X,
-        *        one might think of X as the "base revision", which is NOT what this returns.
-        * @return Revision|null Current version when the edit was started
+        * Returns the revision that was current at the time editing was initiated on the client,
+        * even if the edit was based on an old revision.
+        *
+        * @warning: this method is very poorly named. If the user opened the form with ?oldid=X,
+        *        one might think of X as the "base revision", which is NOT what this returns,
+        *        see oldid for that. One might further assume that this corresponds to the $baseRevId
+        *        parameter of WikiPage::doEditContent, which is not the case either.
+        *        getExpectedParentRevision() would perhaps be a better name.
+        *
+        * @return Revision|null Current version when editing was initiated on the client
         */
        public function getBaseRevision() {
                if ( !$this->mBaseRevision ) {
index 4589991..279bc0a 100644 (file)
@@ -81,6 +81,7 @@ class ApiQueryFileRepoInfo extends ApiQueryBase {
                                ApiBase::PARAM_DFLT => implode( '|', $props ),
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_TYPE => $props,
+                               ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
                        ],
                ];
        }
@@ -100,14 +101,20 @@ class ApiQueryFileRepoInfo extends ApiQueryBase {
 
                $propValues[] = 'canUpload';
 
+               sort( $propValues );
                return $propValues;
        }
 
        protected function getExamplesMessages() {
-               return [
-                       'action=query&meta=filerepoinfo&friprop=apiurl|name|displayname'
-                               => 'apihelp-query+filerepoinfo-example-simple',
-               ];
+               $examples = [];
+
+               $props = array_intersect( [ 'apiurl', 'name', 'displayname' ], $this->getProps() );
+               if ( $props ) {
+                       $examples['action=query&meta=filerepoinfo&friprop=' . implode( '|', $props )] =
+                               'apihelp-query+filerepoinfo-example-simple';
+               }
+
+               return $examples;
        }
 
        public function getHelpUrls() {
index 94e1ac6..74efd82 100644 (file)
        "apihelp-query+filearchive-example-simple": "Show a list of all deleted files.",
 
        "apihelp-query+filerepoinfo-summary": "Return meta information about image repositories configured on the wiki.",
-       "apihelp-query+filerepoinfo-param-prop": "Which repository properties to get (there may be more available on some wikis):\n;apiurl:URL to the repository API - helpful for getting image info from the host.\n;name:The key of the repository - used in e.g. <var>[[mw:Special:MyLanguage/Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> and [[Special:ApiHelp/query+imageinfo|imageinfo]] return values.\n;displayname:The human-readable name of the repository wiki.\n;rooturl:Root URL for image paths.\n;local:Whether that repository is the local one or not.",
+       "apihelp-query+filerepoinfo-param-prop": "Which repository properties to get (properties available may vary on other wikis).",
+       "apihelp-query+filerepoinfo-paramvalue-prop-apiurl": "URL to the repository API - helpful for getting image info from the host.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-articlepath": "Repository wiki's <var>[[mw:Special:MyLanguage/Manual:$wgArticlePath|$wgArticlePath]]</var> or equivalent.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-canUpload": "Whether files can be uploaded to this repository, e.g. via CORS and shared authentication.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-displayname": "The human-readable name of the repository wiki.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-favicon": "Repository wiki's favicon URL, from <var>[[mw:Special:MyLanguage/Manual:$wgFavicon|$wgFavicon]]</var>.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-fetchDescription": "Whether file description pages are fetched from this repository when viewing local file description pages.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-initialCapital": "Whether file names implicitly start with a capital letter.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-local": "Whether that repository is the local one or not.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-name": "The key of the repository - used in e.g. <var>[[mw:Special:MyLanguage/Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> and [[Special:ApiHelp/query+imageinfo|imageinfo]] return values.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-rootUrl": "Root URL path for image paths.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-scriptDirUrl": "Root URL path for the repository wiki's MediaWiki installation.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-server": "Repository wiki's <var>[[mw:Special:MyLanguage/Manual:$wgServer|$wgServer]]</var> or equivalent.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-thumbUrl": "Root URL path for thumbnail paths.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-url": "Public zone URL path.",
        "apihelp-query+filerepoinfo-example-simple": "Get information about file repositories.",
 
        "apihelp-query+fileusage-summary": "Find all pages that use the given files.",
index 1680bb8..2b4a587 100644 (file)
        "apihelp-query+filearchive-example-simple": "{{doc-apihelp-example|query+filearchive}}",
        "apihelp-query+filerepoinfo-summary": "{{doc-apihelp-summary|query+filerepoinfo}}",
        "apihelp-query+filerepoinfo-param-prop": "{{doc-apihelp-param|query+filerepoinfo|prop}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-apiurl": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|apiurl}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-articlepath": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|articlepath}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-canUpload": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|canUpload}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-displayname": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|displayname}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-favicon": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|favicon}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-fetchDescription": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|fetchDescription}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-initialCapital": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|initialCapital}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-local": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|local}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-name": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|name}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-rootUrl": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|rootUrl}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-scriptDirUrl": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|scriptDirUrl}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-server": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|server}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-thumbUrl": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|thumbUrl}}",
+       "apihelp-query+filerepoinfo-paramvalue-prop-url": "{{doc-apihelp-paramvalue|query+filerepoinfo|prop|url}}",
        "apihelp-query+filerepoinfo-example-simple": "{{doc-apihelp-example|query+filerepoinfo}}",
        "apihelp-query+fileusage-summary": "{{doc-apihelp-summary|query+fileusage}}",
        "apihelp-query+fileusage-param-prop": "{{doc-apihelp-param|query+fileusage|prop|paramvalues=1}}",
index 39f8c2a..245bb47 100644 (file)
@@ -1143,6 +1143,8 @@ abstract class Maintenance {
                }
                if ( $this->hasOption( 'dbgroupdefault' ) ) {
                        $wgDBDefaultGroup = $this->getOption( 'dbgroupdefault', null );
+
+                       MediaWikiServices::getInstance()->getDBLoadBalancerFactory()->destroy();
                }
 
                if ( $this->getDbType() == self::DB_ADMIN && isset( $wgDBadminuser ) ) {
index f785d36..8b47dff 100644 (file)
@@ -46,6 +46,7 @@ exports.config = {
                relPath( './tests/selenium/specs/**/*.js' ),
                relPath( './extensions/*/tests/selenium/specs/**/*.js' ),
                relPath( './extensions/VisualEditor/modules/ve-mw/tests/selenium/specs/**/*.js' ),
+               relPath( './extensions/Wikibase/repo/tests/selenium/specs/**/*.js' ),
                relPath( './skins/*/tests/selenium/specs/**/*.js' )
        ],
        // Patterns to exclude