jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/353317 )
Change subject: Use WikibaseServices in Client and Repo instead of
EntityDataRetrievalServiceFactory
......................................................................
Use WikibaseServices in Client and Repo instead of
EntityDataRetrievalServiceFactory
WikibaseServices currently only provide services that
EntityDataRetrievalServiceFactory also used to provide.
Dependency between Repo and Client in case of using
"dispatching" services allowing the access to entity data
from multiple repositories is NOT removed in this change.
This also makes WikibaseServices provide an implementation of
EntityStoreWatcher interface, which can be registered as
a watcher to changes done to the entity.
MultipleRepositoryAwareWikibaseServices returns DispatchingServiceFactory,
that already implements EntityStoreWatcher, as a watcher.
Bug: T165047
Change-Id: Iae1bf00a6b02e8656cf97d27371d9c5ee670ad60
---
M client/includes/Store/Sql/DirectSqlStore.php
M client/includes/WikibaseClient.php
M client/tests/phpunit/includes/Store/Sql/DirectSqlStoreTest.php
M data-access/src/MultipleRepositoryAwareWikibaseServices.php
M data-access/src/WikibaseServices.php
M data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php
M repo/includes/Store/Sql/SqlStore.php
M repo/includes/WikibaseRepo.php
8 files changed, 85 insertions(+), 56 deletions(-)
Approvals:
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/client/includes/Store/Sql/DirectSqlStore.php
b/client/includes/Store/Sql/DirectSqlStore.php
index be8e622..91ba3d0 100644
--- a/client/includes/Store/Sql/DirectSqlStore.php
+++ b/client/includes/Store/Sql/DirectSqlStore.php
@@ -20,7 +20,7 @@
use Wikibase\Client\Usage\UsageLookup;
use Wikibase\Client\Usage\UsageTracker;
use Wikibase\Client\WikibaseClient;
-use Wikibase\DataAccess\EntityDataRetrievalServiceFactory;
+use Wikibase\DataAccess\WikibaseServices;
use Wikibase\DataModel\Entity\EntityIdParser;
use Wikibase\DataModel\Services\Lookup\EntityLookup;
use Wikibase\DataModel\Services\Lookup\RedirectResolvingEntityLookup;
@@ -110,9 +110,9 @@
private $entityRevisionLookup = null;
/**
- * @var EntityDataRetrievalServiceFactory
+ * @var WikibaseServices
*/
- private $entityDataRetrievalServices = null;
+ private $wikibaseServices = null;
/**
* @var PropertyLabelResolver|null
@@ -185,7 +185,7 @@
* @param EntityIdParser $entityIdParser
* @param EntityIdComposer $entityIdComposer
* @param EntityNamespaceLookup $entityNamespaceLookup
- * @param EntityDataRetrievalServiceFactory
$entityDataRetrievalServiceFactory
+ * @param WikibaseServices $wikibaseServices
* @param string|bool $repoWiki The symbolic database name of the repo
wiki or false for the
* local wiki.
* @param string $languageCode
@@ -196,7 +196,7 @@
EntityIdParser $entityIdParser,
EntityIdComposer $entityIdComposer,
EntityNamespaceLookup $entityNamespaceLookup,
- EntityDataRetrievalServiceFactory
$entityDataRetrievalServiceFactory,
+ WikibaseServices $wikibaseServices,
$repoWiki = false,
$languageCode
) {
@@ -205,7 +205,7 @@
$this->entityIdParser = $entityIdParser;
$this->entityIdComposer = $entityIdComposer;
$this->entityNamespaceLookup = $entityNamespaceLookup;
- $this->entityDataRetrievalServices =
$entityDataRetrievalServiceFactory;
+ $this->wikibaseServices = $wikibaseServices;
$this->repoWiki = $repoWiki;
$this->languageCode = $languageCode;
@@ -351,7 +351,7 @@
// NOTE: Keep cache key in sync with
SqlStore::newEntityRevisionLookup in WikibaseRepo
$cacheKeyPrefix = $this->cacheKeyPrefix .
':WikiPageEntityRevisionLookup';
- $dispatchingLookup =
$this->entityDataRetrievalServices->getEntityRevisionLookup();
+ $dispatchingLookup =
$this->wikibaseServices->getEntityRevisionLookup();
// Lower caching layer using persistent cache (e.g. memcached).
$persistentCachingLookup = new CachingEntityRevisionLookup(
@@ -460,7 +460,7 @@
*/
public function getPropertyInfoLookup() {
if ( $this->propertyInfoLookup === null ) {
- $propertyInfoLookup =
$this->entityDataRetrievalServices->getPropertyInfoLookup();
+ $propertyInfoLookup =
$this->wikibaseServices->getPropertyInfoLookup();
$cacheKey = $this->cacheKeyPrefix .
':CacheAwarePropertyInfoStore';
$this->propertyInfoLookup = new
CachingPropertyInfoLookup(
@@ -478,7 +478,7 @@
* @return PrefetchingWikiPageEntityMetaDataAccessor
*/
public function getEntityPrefetcher() {
- return
$this->entityDataRetrievalServices->getEntityPrefetcher();
+ return $this->wikibaseServices->getEntityPrefetcher();
}
/**
diff --git a/client/includes/WikibaseClient.php
b/client/includes/WikibaseClient.php
index b2a9b58..456a088 100644
--- a/client/includes/WikibaseClient.php
+++ b/client/includes/WikibaseClient.php
@@ -47,8 +47,9 @@
use Wikibase\Client\Store\TitleFactory;
use Wikibase\Client\Store\ClientStore;
use Wikibase\DataAccess\DispatchingServiceFactory;
-use Wikibase\DataAccess\EntityDataRetrievalServiceFactory;
+use Wikibase\DataAccess\MultipleRepositoryAwareWikibaseServices;
use Wikibase\DataAccess\RepositoryServiceContainerFactory;
+use Wikibase\DataAccess\WikibaseServices;
use Wikibase\DataModel\DeserializerFactory;
use Wikibase\DataModel\Entity\DispatchingEntityIdParser;
use Wikibase\DataModel\Entity\EntityIdParser;
@@ -119,9 +120,9 @@
private $siteLookup;
/**
- * @var EntityDataRetrievalServiceFactory
+ * @var WikibaseServices
*/
- private $entityDataRetrievalServiceFactory;
+ private $wikibaseServices;
/**
* @var PropertyDataTypeLookup|null
@@ -384,20 +385,20 @@
}
/**
- * @return EntityDataRetrievalServiceFactory
+ * @return WikibaseServices
*/
- public function getEntityDataRetrievalServiceFactory() {
- if ( $this->entityDataRetrievalServiceFactory === null ) {
+ public function getWikibaseServices() {
+ if ( $this->wikibaseServices === null ) {
$factory = new DispatchingServiceFactory(
$this->getRepositoryServiceContainerFactory(),
$this->repositoryDefinitions
);
$factory->loadWiringFiles( $this->settings->getSetting(
'dispatchingServiceWiringFiles' ) );
- $this->entityDataRetrievalServiceFactory = $factory;
+ $this->wikibaseServices = new
MultipleRepositoryAwareWikibaseServices( $factory );
}
- return $this->entityDataRetrievalServiceFactory;
+ return $this->wikibaseServices;
}
private function getRepositoryServiceContainerFactory() {
@@ -457,7 +458,7 @@
private function getPrefetchingTermLookup() {
if ( !$this->prefetchingTermLookup ) {
// TODO: This should not assume the TermBuffer instance
to be a PrefetchingTermLookup
- $this->prefetchingTermLookup =
$this->getEntityDataRetrievalServiceFactory()->getTermBuffer();
+ $this->prefetchingTermLookup =
$this->getWikibaseServices()->getTermBuffer();
}
return $this->prefetchingTermLookup;
@@ -471,7 +472,7 @@
* @return TermSearchInteractor
*/
public function newTermSearchInteractor( $displayLanguageCode ) {
- return
$this->getEntityDataRetrievalServiceFactory()->getTermSearchInteractorFactory()
+ return
$this->getWikibaseServices()->getTermSearchInteractorFactory()
->newInteractor( $displayLanguageCode );
}
@@ -550,7 +551,7 @@
$this->getEntityIdParser(),
$this->getEntityIdComposer(),
$this->getEntityNamespaceLookup(),
- $this->getEntityDataRetrievalServiceFactory(),
+ $this->getWikibaseServices(),
$repoDatabase,
$this->getContentLanguage()->getCode()
);
diff --git a/client/tests/phpunit/includes/Store/Sql/DirectSqlStoreTest.php
b/client/tests/phpunit/includes/Store/Sql/DirectSqlStoreTest.php
index 3e17f23..704132b 100644
--- a/client/tests/phpunit/includes/Store/Sql/DirectSqlStoreTest.php
+++ b/client/tests/phpunit/includes/Store/Sql/DirectSqlStoreTest.php
@@ -8,6 +8,7 @@
use Wikibase\Client\Usage\UsageTracker;
use Wikibase\Client\WikibaseClient;
use Wikibase\DataAccess\DispatchingServiceFactory;
+use Wikibase\DataAccess\MultipleRepositoryAwareWikibaseServices;
use Wikibase\DataAccess\RepositoryServiceContainerFactory;
use Wikibase\DataModel\Entity\ItemIdParser;
use Wikibase\DataModel\Services\Entity\EntityPrefetcher;
@@ -78,7 +79,7 @@
new ItemIdParser(),
new EntityIdComposer( [] ),
new EntityNamespaceLookup( [] ),
- $dispatchingServiceFactory,
+ new MultipleRepositoryAwareWikibaseServices(
$dispatchingServiceFactory ),
wfWikiID(),
'en'
);
diff --git a/data-access/src/MultipleRepositoryAwareWikibaseServices.php
b/data-access/src/MultipleRepositoryAwareWikibaseServices.php
index 5076fcb..3ccd028 100644
--- a/data-access/src/MultipleRepositoryAwareWikibaseServices.php
+++ b/data-access/src/MultipleRepositoryAwareWikibaseServices.php
@@ -9,6 +9,7 @@
use Wikibase\Lib\Interactors\TermSearchInteractorFactory;
use Wikibase\Lib\Store\EntityInfoBuilderFactory;
use Wikibase\Lib\Store\EntityRevisionLookup;
+use Wikibase\Lib\Store\EntityStoreWatcher;
use Wikibase\Lib\Store\PropertyInfoLookup;
/**
@@ -32,6 +33,9 @@
},
'EntityRevisionLookup' => function() use (
$dispatchingServiceContainer ) {
return
$dispatchingServiceContainer->getEntityRevisionLookup();
+ },
+ 'EntityStoreWatcher' => function() use (
$dispatchingServiceContainer ) {
+ return $dispatchingServiceContainer;
},
'PropertyInfoLookup' => function() use (
$dispatchingServiceContainer ) {
return
$dispatchingServiceContainer->getPropertyInfoLookup();
@@ -67,6 +71,13 @@
}
/**
+ * @return EntityStoreWatcher
+ */
+ public function getEntityStoreWatcher() {
+ return $this->getService( 'EntityStoreWatcher' );
+ }
+
+ /**
* @return PropertyInfoLookup
*/
public function getPropertyInfoLookup() {
diff --git a/data-access/src/WikibaseServices.php
b/data-access/src/WikibaseServices.php
index cc6cb8d..76342fd 100644
--- a/data-access/src/WikibaseServices.php
+++ b/data-access/src/WikibaseServices.php
@@ -7,6 +7,7 @@
use Wikibase\Lib\Interactors\TermSearchInteractorFactory;
use Wikibase\Lib\Store\EntityInfoBuilderFactory;
use Wikibase\Lib\Store\EntityRevisionLookup;
+use Wikibase\Lib\Store\EntityStoreWatcher;
use Wikibase\Lib\Store\PropertyInfoLookup;
/**
@@ -35,6 +36,15 @@
public function getEntityRevisionLookup();
/**
+ * Returns a service that can be registered as a watcher to changes to
entity data.
+ * Such watcher gets notified when entity is updated or deleted, or
when the entity
+ * redirect is updated.
+ *
+ * @return EntityStoreWatcher
+ */
+ public function getEntityStoreWatcher();
+
+ /**
* Note: Instance returned is not guaranteed to be a caching decorator.
* Callers should take care of caching themselves.
*
diff --git
a/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php
b/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php
index 3bbb723..ff8e067 100644
--- a/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php
+++ b/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php
@@ -9,6 +9,7 @@
use Wikibase\Lib\Interactors\TermSearchInteractorFactory;
use Wikibase\Lib\Store\EntityInfoBuilderFactory;
use Wikibase\Lib\Store\EntityRevisionLookup;
+use Wikibase\Lib\Store\EntityStoreWatcher;
use Wikibase\Lib\Store\PropertyInfoLookup;
/**
@@ -74,6 +75,12 @@
$this->assertInstanceOf( EntityRevisionLookup::class,
$wikibaseServices->getEntityRevisionLookup() );
}
+ public function testGetEntityStoreWatcher() {
+ $wikibaseServices = new
MultipleRepositoryAwareWikibaseServices(
$this->getDispatchingServiceContainer() );
+
+ $this->assertInstanceOf( EntityStoreWatcher::class,
$wikibaseServices->getEntityStoreWatcher() );
+ }
+
public function testGetPropertyInfoLookup() {
$wikibaseServices = new
MultipleRepositoryAwareWikibaseServices(
$this->getDispatchingServiceContainer() );
@@ -107,6 +114,7 @@
$this->assertContains( 'EntityInfoBuilderFactory',
$serviceNames );
$this->assertContains( 'EntityPrefetcher', $serviceNames );
$this->assertContains( 'EntityRevisionLookup', $serviceNames );
+ $this->assertContains( 'EntityStoreWatcher', $serviceNames );
$this->assertContains( 'PropertyInfoLookup', $serviceNames );
$this->assertContains( 'TermBuffer', $serviceNames );
$this->assertContains( 'TermSearchInteractorFactory',
$serviceNames );
diff --git a/repo/includes/Store/Sql/SqlStore.php
b/repo/includes/Store/Sql/SqlStore.php
index 4cc5508..2089253 100644
--- a/repo/includes/Store/Sql/SqlStore.php
+++ b/repo/includes/Store/Sql/SqlStore.php
@@ -5,7 +5,7 @@
use HashBagOStuff;
use ObjectCache;
use Revision;
-use Wikibase\DataAccess\EntityDataRetrievalServiceFactory;
+use Wikibase\DataAccess\WikibaseServices;
use Wikibase\DataModel\Entity\EntityIdParser;
use Wikibase\DataModel\Entity\Item;
use Wikibase\DataModel\Entity\Property;
@@ -156,9 +156,9 @@
private $entityNamespaceLookup;
/**
- * @var EntityDataRetrievalServiceFactory|null
+ * @var WikibaseServices|null
*/
- private $entityDataRetrievalServiceFactory = null;
+ private $wikibaseServices = null;
/**
* @var string
@@ -198,8 +198,7 @@
* @param EntityIdLookup $entityIdLookup
* @param EntityTitleStoreLookup $entityTitleLookup
* @param EntityNamespaceLookup $entityNamespaceLookup
- * @param EntityDataRetrievalServiceFactory|null
$entityDataRetrievalServiceFactory Optional
- * service factory providing services configured for the
configured repositories
+ * @param WikibaseServices|null $wikibaseServices Optional service
container providing data access services
*/
public function __construct(
EntityChangeFactory $entityChangeFactory,
@@ -209,7 +208,7 @@
EntityIdLookup $entityIdLookup,
EntityTitleStoreLookup $entityTitleLookup,
EntityNamespaceLookup $entityNamespaceLookup,
- EntityDataRetrievalServiceFactory
$entityDataRetrievalServiceFactory = null
+ WikibaseServices $wikibaseServices = null
) {
$this->entityChangeFactory = $entityChangeFactory;
$this->contentCodec = $contentCodec;
@@ -218,7 +217,7 @@
$this->entityIdLookup = $entityIdLookup;
$this->entityTitleLookup = $entityTitleLookup;
$this->entityNamespaceLookup = $entityNamespaceLookup;
- $this->entityDataRetrievalServiceFactory =
$entityDataRetrievalServiceFactory;
+ $this->wikibaseServices = $wikibaseServices;
//TODO: inject settings
$settings = WikibaseRepo::getDefaultInstance()->getSettings();
@@ -474,11 +473,9 @@
/** @var WikiPageEntityStore $dispatcher */
$dispatcher = $this->getEntityStoreWatcher();
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- // Use entityDataRetrievalServiceFactory as a watcher
for entity changes,
- // so that caches of services provided are updated when
necessary.
- $dispatcher->registerWatcher(
$this->entityDataRetrievalServiceFactory );
- $nonCachingLookup =
$this->entityDataRetrievalServiceFactory->getEntityRevisionLookup();
+ if ( $this->wikibaseServices !== null ) {
+ $dispatcher->registerWatcher(
$this->wikibaseServices->getEntityStoreWatcher() );
+ $nonCachingLookup =
$this->wikibaseServices->getEntityRevisionLookup();
} else {
// Watch for entity changes
$metaDataFetcher = $this->getEntityPrefetcher();
@@ -536,8 +533,8 @@
* @return EntityInfoBuilderFactory
*/
private function newEntityInfoBuilderFactory() {
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- return
$this->entityDataRetrievalServiceFactory->getEntityInfoBuilderFactory();
+ if ( $this->wikibaseServices !== null ) {
+ return
$this->wikibaseServices->getEntityInfoBuilderFactory();
}
$factory = new SqlEntityInfoBuilderFactory(
@@ -572,8 +569,8 @@
* @return PropertyInfoLookup
*/
private function newPropertyInfoLookup() {
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- $table =
$this->entityDataRetrievalServiceFactory->getPropertyInfoLookup();
+ if ( $this->wikibaseServices !== null ) {
+ $table =
$this->wikibaseServices->getPropertyInfoLookup();
} else {
$table = $this->getPropertyInfoTable();
}
@@ -662,8 +659,8 @@
* @return EntityPrefetcher
*/
private function newEntityPrefetcher() {
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- return
$this->entityDataRetrievalServiceFactory->getEntityPrefetcher();
+ if ( $this->wikibaseServices !== null ) {
+ return $this->wikibaseServices->getEntityPrefetcher();
}
return new PrefetchingWikiPageEntityMetaDataAccessor(
new WikiPageEntityMetaDataLookup(
$this->entityNamespaceLookup )
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 8fdb534..3605d54 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -32,7 +32,7 @@
use ValueFormatters\ValueFormatter;
use Wikibase\Repo\ChangeOp\ChangeOpFactoryProvider;
use Wikibase\Client\WikibaseClient;
-use Wikibase\DataAccess\EntityDataRetrievalServiceFactory;
+use Wikibase\DataAccess\WikibaseServices;
use Wikibase\DataModel\DeserializerFactory;
use Wikibase\DataModel\Entity\DispatchingEntityIdParser;
use Wikibase\DataModel\Entity\EntityIdParser;
@@ -294,9 +294,9 @@
private $cachingCommonsMediaFileNameLookup = null;
/**
- * @var EntityDataRetrievalServiceFactory|null
+ * @var WikibaseServices|null
*/
- private $entityDataRetrievalServiceFactory = null;
+ private $wikibaseServices = null;
/**
* @var EntityRdfBuilderFactory|null
@@ -331,7 +331,7 @@
// If client functionality is enabled, use it to enable
federation.
if ( WikibaseSettings::isClientEnabled() ) {
- $dataRetrievalServices =
WikibaseClient::getDefaultInstance()->getEntityDataRetrievalServiceFactory();
+ $dataRetrievalServices =
WikibaseClient::getDefaultInstance()->getWikibaseServices();
$repositoryDefinitions =
WikibaseClient::getDefaultInstance()->getRepositoryDefinitions();
}
@@ -500,20 +500,21 @@
}
/**
- * FIXME: Optional $entityDataRetrievalServiceFactory makes it possible
to access
+ * FIXME: Optional $wikibaseServices makes it possible to access
* entities from foreign repositories from Repo component but they also
introduce the optional
* dependency on the Client component. Such dependency is bad and in
the long run it should be removed
- * by making EntityDataRetrievalServiceFactory implementation provided
to WikibaseRepo not be
- * bound to WikibaseClient.
+ * by making WikibaseServices implementation provided to WikibaseRepo
not be bound to WikibaseClient.
+ * WikibaseServices provided by WikibaseClient instance is only used in
the transition period until
+ * WikibaseServices no longer depends on services from Wikibase\Client
namespace.
*
* @param SettingsArray $settings
* @param DataTypeDefinitions $dataTypeDefinitions
* @param EntityTypeDefinitions $entityTypeDefinitions
* @param RepositoryDefinitions $repositoryDefinitions
- * @param EntityDataRetrievalServiceFactory|null
$entityDataRetrievalServiceFactory optional factory
- * of entity data retrieval services that will be used by the
Repo instead of it creating
+ * @param WikibaseServices|null $wikibaseServices optional container of
service providing the
+ * access to the entity data that will be used by the Repo
instead of it creating
* instances of those services itself.
- * This factory could be provided in order to allow Repo make
use of Dispatching services
+ * This container could be provided in order to allow Repo make
use of Dispatching services
* and access data of entities from foreign repositories.
*/
public function __construct(
@@ -521,13 +522,13 @@
DataTypeDefinitions $dataTypeDefinitions,
EntityTypeDefinitions $entityTypeDefinitions,
RepositoryDefinitions $repositoryDefinitions,
- EntityDataRetrievalServiceFactory
$entityDataRetrievalServiceFactory = null
+ WikibaseServices $wikibaseServices = null
) {
$this->settings = $settings;
$this->dataTypeDefinitions = $dataTypeDefinitions;
$this->entityTypeDefinitions = $entityTypeDefinitions;
$this->repositoryDefinitions = $repositoryDefinitions;
- $this->entityDataRetrievalServiceFactory =
$entityDataRetrievalServiceFactory;
+ $this->wikibaseServices = $wikibaseServices;
}
/**
@@ -737,8 +738,8 @@
* @return TermIndexSearchInteractor
*/
public function newTermSearchInteractor( $displayLanguageCode ) {
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- return
$this->entityDataRetrievalServiceFactory->getTermSearchInteractorFactory()->newInteractor(
+ if ( $this->wikibaseServices !== null ) {
+ return
$this->wikibaseServices->getTermSearchInteractorFactory()->newInteractor(
$displayLanguageCode
);
}
@@ -956,7 +957,7 @@
$this->getEntityIdLookup(),
$this->getEntityTitleLookup(),
$this->getEntityNamespaceLookup(),
- $this->entityDataRetrievalServiceFactory
+ $this->wikibaseServices
);
}
@@ -1011,8 +1012,8 @@
* @return PrefetchingTermLookup
*/
private function newPrefetchingTermLookup() {
- if ( $this->entityDataRetrievalServiceFactory !== null ) {
- return
$this->entityDataRetrievalServiceFactory->getTermBuffer();
+ if ( $this->wikibaseServices !== null ) {
+ return $this->wikibaseServices->getTermBuffer();
}
return new BufferingTermLookup(
$this->getStore()->getTermIndex(),
--
To view, visit https://gerrit.wikimedia.org/r/353317
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Iae1bf00a6b02e8656cf97d27371d9c5ee670ad60
Gerrit-PatchSet: 13
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: WMDE-leszek <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits