Aaron Schulz has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/61745


Change subject: Made ProfileSection support multiple section names.
......................................................................

Made ProfileSection support multiple section names.

* Switched FileBackendStore to use ProfileSection when possible.

Change-Id: I44e775fbd4d3e41c0a4070582d1806dc35c60188
---
M includes/filebackend/FileBackendStore.php
M includes/profiler/Profiler.php
2 files changed, 40 insertions(+), 136 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/45/61745/1

diff --git a/includes/filebackend/FileBackendStore.php 
b/includes/filebackend/FileBackendStore.php
index ea379bc..a8b2f97 100644
--- a/includes/filebackend/FileBackendStore.php
+++ b/includes/filebackend/FileBackendStore.php
@@ -103,8 +103,7 @@
         * @return Status
         */
        final public function createInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                if ( strlen( $params['content'] ) > 
$this->maxFileSizeInternal() ) {
                        $status = Status::newFatal( 'backend-fail-maxsize',
                                $params['dst'], $this->maxFileSizeInternal() );
@@ -115,8 +114,6 @@
                                $this->deleteFileCache( $params['dst'] ); // 
persistent cache
                        }
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -145,8 +142,7 @@
         * @return Status
         */
        final public function storeInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                if ( filesize( $params['src'] ) > $this->maxFileSizeInternal() 
) {
                        $status = Status::newFatal( 'backend-fail-maxsize',
                                $params['dst'], $this->maxFileSizeInternal() );
@@ -157,8 +153,6 @@
                                $this->deleteFileCache( $params['dst'] ); // 
persistent cache
                        }
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -188,15 +182,12 @@
         * @return Status
         */
        final public function copyInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = $this->doCopyInternal( $params );
                $this->clearCache( array( $params['dst'] ) );
                if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) {
                        $this->deleteFileCache( $params['dst'] ); // persistent 
cache
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -221,13 +212,10 @@
         * @return Status
         */
        final public function deleteInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = $this->doDeleteInternal( $params );
                $this->clearCache( array( $params['src'] ) );
                $this->deleteFileCache( $params['src'] ); // persistent cache
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -257,16 +245,13 @@
         * @return Status
         */
        final public function moveInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = $this->doMoveInternal( $params );
                $this->clearCache( array( $params['src'], $params['dst'] ) );
                $this->deleteFileCache( $params['src'] ); // persistent cache
                if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) {
                        $this->deleteFileCache( $params['dst'] ); // persistent 
cache
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -303,8 +288,7 @@
         * @return Status
         */
        final public function describeInternal( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                if ( count( $params['headers'] ) ) {
                        $status = $this->doDescribeInternal( $params );
                        $this->clearCache( array( $params['src'] ) );
@@ -312,8 +296,6 @@
                } else {
                        $status = Status::newGood(); // nothing to do
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -341,8 +323,7 @@
         * @return Status
         */
        final public function concatenate( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                // Try to lock the source files for the scope of this function
@@ -358,8 +339,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -434,15 +413,12 @@
         * @return Status
         */
        final protected function doPrepare( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
-
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
+
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( 
$params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', 
$params['dir'] );
-                       wfProfileOut( __METHOD__ . '-' . $this->name );
-                       wfProfileOut( __METHOD__ );
                        return $status; // invalid storage path
                }
 
@@ -456,8 +432,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -474,15 +448,12 @@
         * @return Status
         */
        final protected function doSecure( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( 
$params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', 
$params['dir'] );
-                       wfProfileOut( __METHOD__ . '-' . $this->name );
-                       wfProfileOut( __METHOD__ );
                        return $status; // invalid storage path
                }
 
@@ -496,8 +467,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -514,15 +483,12 @@
         * @return Status
         */
        final protected function doPublish( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( 
$params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', 
$params['dir'] );
-                       wfProfileOut( __METHOD__ . '-' . $this->name );
-                       wfProfileOut( __METHOD__ );
                        return $status; // invalid storage path
                }
 
@@ -536,8 +502,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -554,8 +518,7 @@
         * @return Status
         */
        final protected function doClean( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                // Recursive: first delete all empty subdirs recursively
@@ -573,8 +536,6 @@
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( 
$params['dir'] );
                if ( $dir === null ) {
                        $status->fatal( 'backend-fail-invalidpath', 
$params['dir'] );
-                       wfProfileOut( __METHOD__ . '-' . $this->name );
-                       wfProfileOut( __METHOD__ );
                        return $status; // invalid storage path
                }
 
@@ -582,8 +543,6 @@
                $filesLockEx = array( $params['dir'] );
                $scopedLockE = $this->getScopedFileLocks( $filesLockEx, 
LockManager::LOCK_EX, $status );
                if ( !$status->isOK() ) {
-                       wfProfileOut( __METHOD__ . '-' . $this->name );
-                       wfProfileOut( __METHOD__ );
                        return $status; // abort
                }
 
@@ -599,8 +558,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -617,11 +574,8 @@
         * @return bool|null
         */
        final public function fileExists( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $stat = $this->getFileStat( $params );
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return ( $stat === null ) ? null : (bool)$stat; // null => 
failure
        }
 
@@ -630,11 +584,8 @@
         * @return bool
         */
        final public function getFileTimestamp( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $stat = $this->getFileStat( $params );
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $stat ? $stat['mtime'] : false;
        }
 
@@ -643,11 +594,8 @@
         * @return bool
         */
        final public function getFileSize( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $stat = $this->getFileStat( $params );
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $stat ? $stat['size'] : false;
        }
 
@@ -660,8 +608,7 @@
                if ( $path === null ) {
                        return false; // invalid storage path
                }
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $latest = !empty( $params['latest'] ); // use latest data?
                if ( !$this->cheapCache->has( $path, 'stat', self::CACHE_TTL ) 
) {
                        $this->primeFileCache( array( $path ) ); // check 
persistent cache
@@ -672,14 +619,10 @@
                        // value was in fact fetched with the latest available 
data.
                        if ( is_array( $stat ) ) {
                                if ( !$latest || $stat['latest'] ) {
-                                       wfProfileOut( __METHOD__ . '-' . 
$this->name );
-                                       wfProfileOut( __METHOD__ );
                                        return $stat;
                                }
                        } elseif ( in_array( $stat, array( 'NOT_EXIST', 
'NOT_EXIST_LATEST' ) ) ) {
                                if ( !$latest || $stat === 'NOT_EXIST_LATEST' ) 
{
-                                       wfProfileOut( __METHOD__ . '-' . 
$this->name );
-                                       wfProfileOut( __METHOD__ );
                                        return false;
                                }
                        }
@@ -703,8 +646,6 @@
                } else { // an error occurred
                        wfDebug( __METHOD__ . ": Could not stat file $path.\n" 
);
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $stat;
        }
 
@@ -718,14 +659,11 @@
         * @return Array
         */
        public function getFileContentsMulti( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
 
                $params = $this->setConcurrencyFlags( $params );
                $contents = $this->doGetFileContentsMulti( $params );
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $contents;
        }
 
@@ -752,16 +690,13 @@
                if ( $path === null ) {
                        return false; // invalid storage path
                }
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $latest = !empty( $params['latest'] ); // use latest data?
                if ( $this->cheapCache->has( $path, 'sha1', self::CACHE_TTL ) ) 
{
                        $stat = $this->cheapCache->get( $path, 'sha1' );
                        // If we want the latest data, check that this cached
                        // value was in fact fetched with the latest available 
data.
                        if ( !$latest || $stat['latest'] ) {
-                               wfProfileOut( __METHOD__ . '-' . $this->name );
-                               wfProfileOut( __METHOD__ );
                                return $stat['hash'];
                        }
                }
@@ -771,8 +706,6 @@
                wfProfileOut( __METHOD__ . '-miss-' . $this->name );
                wfProfileOut( __METHOD__ . '-miss' );
                $this->cheapCache->set( $path, 'sha1', array( 'hash' => $hash, 
'latest' => $latest ) );
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $hash;
        }
 
@@ -794,12 +727,9 @@
         * @return Array
         */
        final public function getFileProps( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $fsFile = $this->getLocalReference( $params );
                $props = $fsFile ? $fsFile->getProps() : 
FSFile::placeholderProps();
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $props;
        }
 
@@ -808,8 +738,7 @@
         * @return Array
         */
        final public function getLocalReferenceMulti( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
 
                $params = $this->setConcurrencyFlags( $params );
 
@@ -839,8 +768,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $fsFiles;
        }
 
@@ -857,14 +784,11 @@
         * @return Array
         */
        final public function getLocalCopyMulti( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
 
                $params = $this->setConcurrencyFlags( $params );
                $tmpFiles = $this->doGetLocalCopyMulti( $params );
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $tmpFiles;
        }
 
@@ -887,8 +811,7 @@
         * @return Status
         */
        final public function streamFile( array $params ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                $info = $this->getFileStat( $params );
@@ -919,8 +842,6 @@
                        $status->fatal( 'backend-fail-stream', $params['src'] );
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -1126,8 +1047,7 @@
         * @return Status
         */
        final protected function doOperationsInternal( array $ops, array $opts 
) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                // Fix up custom header name/value pairs...
@@ -1144,8 +1064,6 @@
                        $scopeLockS = $this->getScopedFileLocks( $paths['sh'], 
LockManager::LOCK_UW, $status );
                        $scopeLockE = $this->getScopedFileLocks( $paths['ex'], 
LockManager::LOCK_EX, $status );
                        if ( !$status->isOK() ) {
-                               wfProfileOut( __METHOD__ . '-' . $this->name );
-                               wfProfileOut( __METHOD__ );
                                return $status; // abort
                        }
                }
@@ -1167,8 +1085,6 @@
                $status->merge( $subStatus );
                $status->success = $subStatus->success; // not done in merge()
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -1178,8 +1094,7 @@
         * @throws MWException
         */
        final protected function doQuickOperationsInternal( array $ops ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                $status = Status::newGood();
 
                // Fix up custom header name/value pairs...
@@ -1198,8 +1113,6 @@
                // Perform the sync-only ops and build up op handles for the 
async ops...
                foreach ( $ops as $index => $params ) {
                        if ( !in_array( $params['op'], $supportedOps ) ) {
-                               wfProfileOut( __METHOD__ . '-' . $this->name );
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Operation 
'{$params['op']}' is not supported." );
                        }
                        $method = $params['op'] . 'Internal'; // e.g. 
"storeInternal"
@@ -1233,8 +1146,6 @@
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -1248,16 +1159,11 @@
         * @throws MWException
         */
        final public function executeOpHandlesInternal( array $fileOpHandles ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
                foreach ( $fileOpHandles as $fileOpHandle ) {
                        if ( !( $fileOpHandle instanceof 
FileBackendStoreOpHandle ) ) {
-                               wfProfileOut( __METHOD__ . '-' . $this->name );
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Given a 
non-FileBackendStoreOpHandle object." );
                        } elseif ( $fileOpHandle->backend->getName() !== 
$this->getName() ) {
-                               wfProfileOut( __METHOD__ . '-' . $this->name );
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Given a 
FileBackendStoreOpHandle for the wrong backend." );
                        }
                }
@@ -1265,8 +1171,6 @@
                foreach ( $fileOpHandles as $fileOpHandle ) {
                        $fileOpHandle->closeResources();
                }
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
                return $res;
        }
 
@@ -1610,8 +1514,7 @@
         * @return void
         */
        final protected function primeContainerCache( array $items ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
 
                $paths = array(); // list of storage paths
                $contNames = array(); // (cache key => resolved container name)
@@ -1643,9 +1546,6 @@
 
                // Populate the container process cache for the backend...
                $this->doPrimeContainerCache( array_filter( $contInfo, 
'is_array' ) );
-
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1715,8 +1615,7 @@
         * @return void
         */
        final protected function primeFileCache( array $items ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $this->name );
+               $_ = new ProfileSection( __METHOD__, array( "-{$this->name}" ) 
);
 
                $paths = array(); // list of storage paths
                $pathNames = array(); // (cache key => storage path)
@@ -1750,9 +1649,6 @@
                                }
                        }
                }
-
-               wfProfileOut( __METHOD__ . '-' . $this->name );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
diff --git a/includes/profiler/Profiler.php b/includes/profiler/Profiler.php
index c77fef5..e2d3512 100644
--- a/includes/profiler/Profiler.php
+++ b/includes/profiler/Profiler.php
@@ -55,7 +55,8 @@
  */
 class ProfileSection {
        protected $name; // string; method name
-       protected $enabled = false; // boolean; whether profiling is enabled
+       /** @var Array List of suffixes to record under this section */
+       protected $suffixes = array();
 
        /**
         * Begin profiling of a function and return an object that ends 
profiling of
@@ -67,20 +68,27 @@
         * <code>$section = new ProfileSection( __METHOD__ );</code>
         *
         * @param string $name Name of the function to profile
+        * @param array $suffixes Suffixes to record identical sections under 
"<name><suffix>"
         */
-       public function __construct( $name ) {
-               $this->name = $name;
+       public function __construct( $name, $suffixes = array() ) {
                if ( Profiler::$__instance === null ) { // use this directly to 
reduce overhead
                        Profiler::instance();
                }
                if ( Profiler::$__instance && !( Profiler::$__instance 
instanceof ProfilerStub ) ) {
-                       $this->enabled = true;
+                       $this->name = $name;
+                       $this->suffixes = $suffixes;
                        Profiler::$__instance->profileIn( $this->name );
+                       foreach ( $this->suffixes as $suffix ) {
+                               Profiler::$__instance->profileIn( $this->name . 
$suffix );
+                       }
                }
        }
 
        function __destruct() {
-               if ( $this->enabled ) {
+               if ( $this->name !== null ) {
+                       foreach ( array_reverse( $this->suffixes ) as $suffix ) 
{
+                               Profiler::$__instance->profileOut( $this->name 
. $suffix );
+                       }
                        Profiler::$__instance->profileOut( $this->name );
                }
        }

-- 
To view, visit https://gerrit.wikimedia.org/r/61745
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I44e775fbd4d3e41c0a4070582d1806dc35c60188
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to