Soeren.oldag has uploaded a new change for review. https://gerrit.wikimedia.org/r/214009
Change subject: Fixed test and did few refactorings on special page. ...................................................................... Fixed test and did few refactorings on special page. Fixed CheckResultTestToViolationTranslatorTest. Constraint Violations are now saved in database (again). Removed unnecessary stuff from special page. Changes access modifiers for methods of special page. Change-Id: I5dccc1a283d4ad1e60db6e104aba2e68e391b35e --- M includes/ConstraintReportFactory.php M modules/SpecialConstraintReportPage.css M specials/SpecialConstraintReport.php M tests/phpunit/DelegatingConstraintCheckerTest.php M tests/phpunit/Specials/SpecialConstraintReportTest.php M tests/phpunit/Violations/CheckResultToViolationTranslatorTest.php 6 files changed, 166 insertions(+), 169 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikidataQualityConstraints refs/changes/09/214009/1 diff --git a/includes/ConstraintReportFactory.php b/includes/ConstraintReportFactory.php index 93dc0a2..5e19dd0 100755 --- a/includes/ConstraintReportFactory.php +++ b/includes/ConstraintReportFactory.php @@ -2,6 +2,7 @@ namespace WikibaseQuality\ConstraintReport; +use Wikibase\Lib\Store\EntityRevisionLookup; use Wikibase\Repo\WikibaseRepo; use Wikibase\Lib\Store\EntityLookup; use WikibaseQuality\ConstraintReport\ConstraintCheck\DelegatingConstraintChecker; @@ -27,12 +28,23 @@ use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConnectionCheckerHelper; use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\RangeCheckerHelper; use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\TypeCheckerHelper; +use WikibaseQuality\ConstraintReport\Violations\CheckResultToViolationTranslator; use WikibaseQuality\ConstraintReport\Violations\ConstraintViolationContext; class ConstraintReportFactory { - /** + /** + * @var EntityLookup + */ + private $entityLookup; + + /** + * @var EntityRevisionLookup + */ + private $entityRevisionLookup; + + /** * @var constraintRepository */ private $constraintRepository; @@ -48,14 +60,14 @@ private $delegatingConstraintChecker; /** - * @var EntityLookup - */ - private $lookup; - - /** * @var array */ private $constraintParameterMap; + + /** + * @var CheckResultToViolationTranslator + */ + private $checkResultToViolationTranslator; /** * Returns the default instance. @@ -67,17 +79,22 @@ static $instance = null; if ( $instance === null ) { - $instance = new self( WikibaseRepo::getDefaultInstance()->getEntityLookup() ); + $instance = new self( + WikibaseRepo::getDefaultInstance()->getEntityLookup(), + WikibaseRepo::getDefaultInstance()->getEntityRevisionLookup() + ); } return $instance; } - /** - * @param EntityLookup $lookup - */ - public function __construct( EntityLookup $lookup ) { - $this->lookup = $lookup; + /** + * @param EntityLookup $entityLookup + * @param EntityRevisionLookup $entityRevisionLookup + */ + public function __construct( EntityLookup $entityLookup, EntityRevisionLookup $entityRevisionLookup ) { + $this->entityLookup = $entityLookup; + $this->entityRevisionLookup = $entityRevisionLookup; } /** @@ -85,7 +102,7 @@ */ public function getConstraintChecker() { if ( $this->delegatingConstraintChecker === null ) { - $this->delegatingConstraintChecker = new DelegatingConstraintChecker( $this->lookup, $this->getConstraintCheckerMap( $this->lookup ) ); + $this->delegatingConstraintChecker = new DelegatingConstraintChecker( $this->entityLookup, $this->getConstraintCheckerMap( $this->entityLookup ) ); } return $this->delegatingConstraintChecker; @@ -99,21 +116,21 @@ $constraintReportHelper = new ConstraintReportHelper(); $connectionCheckerHelper = new ConnectionCheckerHelper(); $rangeCheckerHelper = new RangeCheckerHelper(); - $typeCheckerHelper = new TypeCheckerHelper( $this->lookup ); + $typeCheckerHelper = new TypeCheckerHelper( $this->entityLookup ); $this->constraintCheckerMap = array( - 'Conflicts with' => new ConflictsWithChecker( $this->lookup, $constraintReportHelper, $connectionCheckerHelper ), - 'Item' => new ItemChecker( $this->lookup, $constraintReportHelper, $connectionCheckerHelper ), - 'Target required claim' => new TargetRequiredClaimChecker( $this->lookup, $constraintReportHelper, $connectionCheckerHelper ), - 'Symmetric' => new SymmetricChecker( $this->lookup, $constraintReportHelper, $connectionCheckerHelper ), - 'Inverse' => new InverseChecker( $this->lookup, $constraintReportHelper, $connectionCheckerHelper ), + 'Conflicts with' => new ConflictsWithChecker( $this->entityLookup, $constraintReportHelper, $connectionCheckerHelper ), + 'Item' => new ItemChecker( $this->entityLookup, $constraintReportHelper, $connectionCheckerHelper ), + 'Target required claim' => new TargetRequiredClaimChecker( $this->entityLookup, $constraintReportHelper, $connectionCheckerHelper ), + 'Symmetric' => new SymmetricChecker( $this->entityLookup, $constraintReportHelper, $connectionCheckerHelper ), + 'Inverse' => new InverseChecker( $this->entityLookup, $constraintReportHelper, $connectionCheckerHelper ), 'Qualifier' => new QualifierChecker( $constraintReportHelper ), 'Qualifiers' => new QualifiersChecker( $constraintReportHelper ), 'Mandatory qualifiers' => new MandatoryQualifiersChecker( $constraintReportHelper ), 'Range' => new RangeChecker( $constraintReportHelper, $rangeCheckerHelper ), 'Diff within range' => new DiffWithinRangeChecker( $constraintReportHelper, $rangeCheckerHelper ), - 'Type' => new TypeChecker( $this->lookup, $constraintReportHelper, $typeCheckerHelper ), - 'Value type' => new ValueTypeChecker( $this->lookup, $constraintReportHelper, $typeCheckerHelper ), + 'Type' => new TypeChecker( $this->entityLookup, $constraintReportHelper, $typeCheckerHelper ), + 'Value type' => new ValueTypeChecker( $this->entityLookup, $constraintReportHelper, $typeCheckerHelper ), 'Single value' => new SingleValueChecker(), 'Multi value' => new MultiValueChecker(), 'Unique value' => new UniqueValueChecker(), @@ -126,6 +143,9 @@ return $this->constraintCheckerMap; } + /** + * @return array + */ public function getConstraintParameterMap() { if ( $this->constraintParameterMap === null ) { $this->constraintParameterMap = array( @@ -153,6 +173,9 @@ return $this->constraintParameterMap; } + /** + * @return ConstraintRepository + */ public function getConstraintRepository() { if ( $this->constraintRepository === null ) { $this->constraintRepository = new ConstraintRepository( CONSTRAINT_TABLE ); @@ -161,9 +184,23 @@ return $this->constraintRepository; } + /** + * @return ConstraintViolationContext + */ public function getViolationContext() { return new ConstraintViolationContext( array_keys( $this->getConstraintCheckerMap() ) ); } + + /** + * @return CheckResultToViolationTranslator + */ + public function getCheckResultToViolationTranslator() { + if ( $this->checkResultToViolationTranslator === null ) { + $this->checkResultToViolationTranslator = new CheckResultToViolationTranslator( $this->entityRevisionLookup ); + } + + return $this->checkResultToViolationTranslator; + } } \ No newline at end of file diff --git a/modules/SpecialConstraintReportPage.css b/modules/SpecialConstraintReportPage.css index de89095..2bb3ddb 100755 --- a/modules/SpecialConstraintReportPage.css +++ b/modules/SpecialConstraintReportPage.css @@ -32,23 +32,19 @@ font-weight: bold; } -.wbqc-status-success { +.wbqc-status-compliance { color: #008000; } -.wbqc-status-partial-success { - color: #6CB500; -} - -.wbqc-status-warning { +.wbqc-status-exception { color: #E6B800; } -.wbqc-status-error { +.wbqc-status-violation { color: #BA0000; } -.wbqc-status-unknown { +.wbqc-status-todo { color: #404040; } diff --git a/specials/SpecialConstraintReport.php b/specials/SpecialConstraintReport.php index ad33af0..01daf65 100755 --- a/specials/SpecialConstraintReport.php +++ b/specials/SpecialConstraintReport.php @@ -4,12 +4,14 @@ use SpecialPage; use ValueFormatters\FormatterOptions; +use ValueFormatters\ValueFormatter; use Wikibase\Lib\EntityIdHtmlLinkFormatter; use Wikibase\Lib\EntityIdLabelFormatter; use Wikibase\Lib\EntityIdLinkFormatter; -use Wikibase\Lib\HtmlUrlFormatter; +use Wikibase\DataModel\Entity\EntityIdParser; use Wikibase\Lib\LanguageNameLookup; use Wikibase\Lib\SnakFormatter; +use Wikibase\Lib\Store\EntityLookup; use Wikibase\Lib\Store\LanguageLabelDescriptionLookup; use Wikibase\Repo\WikibaseRepo; use DataValues; @@ -28,11 +30,15 @@ use Wikibase\DataModel\Entity\ItemId; use Wikibase\DataModel\Entity\PropertyId; use Wikibase\Lib\Store\EntityTitleLookup; +use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult; use WikibaseQuality\ConstraintReport\ConstraintReportFactory; use WikibaseQuality\ConstraintReport\EvaluateConstraintReportJob; use WikibaseQuality\ConstraintReport\EvaluateConstraintReportJobService; +use WikibaseQuality\ConstraintReport\Violations\CheckResultToViolationTranslator; use WikibaseQuality\Html\HtmlTable; use WikibaseQuality\Html\HtmlTableHeader; +use WikibaseQuality\Violations\ViolationRepo; +use WikibaseQuality\WikibaseQualityFactory; /** @@ -67,39 +73,39 @@ private $entityTitleLookup; /** - * @var \Wikibase\DataModel\Entity\EntityIdParser + * @var EntityIdParser */ - protected $entityIdParser; + private $entityIdParser; /** - * @var \Wikibase\Lib\Store\EntityLookup + * @var EntityLookup */ - protected $entityLookup; + private $entityLookup; /** - * @var \ValueFormatters\ValueFormatter + * @var ValueFormatter */ - protected $dataValueFormatter; + private $dataValueFormatter; /** * @var EntityIdLabelFormatter */ - protected $entityIdLabelFormatter; - - /** - * @var EntityIdLinkFormatter - */ - protected $entityIdLinkFormatter; + private $entityIdLabelFormatter; /** * @var EntityIdHtmlLinkFormatter */ - protected $entityIdHtmlLinkFormatter; + private $entityIdHtmlLinkFormatter; - /** - * @var HtmlUrlFormatter - */ - protected $htmlUrlFormatter; + /** + * @var CheckResultToViolationTranslator + */ + private $checkResultToViolationTranslator; + + /** + * @var ViolationRepo + */ + private $violationRepo; /** * @param string $name @@ -112,36 +118,46 @@ public function __construct( $name = 'ConstraintReport', $restriction = '', $listed = true, $function = false, $file = '', $includable = false ) { parent::__construct( $name, $restriction, $listed, $function, $file, $includable ); - $repo = WikibaseRepo::getDefaultInstance(); + $repo = WikibaseRepo::getDefaultInstance(); - // Get entity lookup - $this->entityLookup = $repo->getEntityLookup(); + $this->entityLookup = $repo->getEntityLookup(); + $this->entityIdParser = $repo->getEntityIdParser(); + $this->entityTitleLookup = WikibaseRepo::getDefaultInstance()->getEntityTitleLookup(); - // Get entity id parser - $this->entityIdParser = $repo->getEntityIdParser(); + $formatterOptions = new FormatterOptions(); + $formatterOptions->setOption( SnakFormatter::OPT_LANG, $this->getLanguage()->getCode() ); + $this->dataValueFormatter = $repo->getValueFormatterFactory()->getValueFormatter( SnakFormatter::FORMAT_HTML, $formatterOptions ); - // Get value formatter - $formatterOptions = new FormatterOptions(); - $formatterOptions->setOption( SnakFormatter::OPT_LANG, $this->getLanguage()->getCode() ); - $this->dataValueFormatter = $repo->getValueFormatterFactory()->getValueFormatter( SnakFormatter::FORMAT_HTML, $formatterOptions ); + $entityTitleLookup = $repo->getEntityTitleLookup(); + $labelLookup = new LanguageLabelDescriptionLookup( $repo->getTermLookup(), $this->getLanguage()->getCode() ); + $this->entityIdLabelFormatter = new EntityIdLabelFormatter( $labelLookup ); + $this->entityIdHtmlLinkFormatter = new EntityIdHtmlLinkFormatter( + $labelLookup, + $entityTitleLookup, + new LanguageNameLookup() + ); - // Get entity id link formatters - $entityTitleLookup = $repo->getEntityTitleLookup(); - $labelLookup = new LanguageLabelDescriptionLookup( $repo->getTermLookup(), $this->getLanguage()->getCode() ); - $this->entityIdLabelFormatter = new EntityIdLabelFormatter( $labelLookup ); - $this->entityIdLinkFormatter = new EntityIdLinkFormatter( $entityTitleLookup ); - $this->entityIdHtmlLinkFormatter = new EntityIdHtmlLinkFormatter( - $labelLookup, - $entityTitleLookup, - new LanguageNameLookup() - ); - - // Get url formatter - $formatterOptions = new FormatterOptions(); - $this->htmlUrlFormatter = new HtmlUrlFormatter( $formatterOptions ); - - $this->entityTitleLookup = WikibaseRepo::getDefaultInstance()->getEntityTitleLookup(); + $this->checkResultToViolationTranslator = ConstraintReportFactory::getDefaultInstance()->getCheckResultToViolationTranslator(); + $this->violationRepo = WikibaseQualityFactory::getDefaultInstance()->getViolationRepo(); } + + /** + * @see SpecialPage::getGroupName + * + * @return string + */ + function getGroupName() { + return 'wikibasequality'; + } + + /** + * @see SpecialPage::getDescription + * + * @return string + */ + public function getDescription() { + return $this->msg( 'wbqc-constraintreport' )->text(); + } /** * @see SpecialPage::execute @@ -161,7 +177,7 @@ return; } - $out->addModules( $this->getModules() ); + $out->addModules( 'SpecialConstraintReportPage' ); $this->setHeaders(); @@ -196,12 +212,7 @@ } $results = $this->executeCheck( $entity ); - - if ( !is_array( $results ) ) { - if ( !( $results instanceof Traversable && $results instanceof Countable ) ) { - throw new UnexpectedValueException( 'SpecialCheckResultPage::executeCheck has to return an array or traversable and countable object.' ); - } - } + $this->saveResultsInViolationsTable( $entity, $results ); if ( $results && count( $results ) > 0 ) { $out->addHTML( @@ -212,7 +223,7 @@ } else { $out->addHTML( $this->buildResultHeader( $entityId ) - . $this->buildNotice( $this->getEmptyResultText() ) + . $this->buildNotice( $this->msg( 'wbqc-constraintreport-empty-result' )->text() ) ); } } @@ -222,7 +233,7 @@ * * @return string */ - protected function buildEntityIdForm() { + private function buildEntityIdForm() { return Html::openElement( 'form', @@ -262,7 +273,7 @@ * * @return string */ - protected function buildNotice( $message, $error = false ) { + private function buildNotice( $message, $error = false ) { if ( !is_string( $message ) ) { throw new InvalidArgumentException( '$message must be string.' ); } @@ -284,34 +295,7 @@ $message ); } - /** - * Returns array of modules that should be added - * - * @return array - */ - protected function getModules() { - return array ( 'SpecialConstraintReportPage' ); - } - - /** - * @see SpecialPage::getGroupName - * - * @return string - */ - function getGroupName() { - return 'wikibasequality'; - } - - /** - * @see SpecialPage::getDescription - * - * @return string - */ - public function getDescription() { - return $this->msg( 'wbqc-constraintreport' )->text(); - } - - protected function getExplanationText() { + private function getExplanationText() { return Html::openElement( 'div', array( 'class' => 'wbqc-explanation') ) . $this->msg( 'wbqc-constraintreport-explanation-part-one' ) @@ -323,23 +307,13 @@ } /** - * @see SpecialCheckResultPage::getEmptyResultText - * - * @return string - */ - protected function getEmptyResultText() { - return - $this->msg( 'wbqc-constraintreport-empty-result' )->text(); - } - - /** * @see SpecialCheckResultPage::executeCheck * * @param Entity $entity * * @return string */ - protected function executeCheck( Entity $entity ) { + private function executeCheck( Entity $entity ) { $constraintChecker = ConstraintReportFactory::getDefaultInstance()->getConstraintChecker(); $results = $constraintChecker->checkAgainstConstraints( $entity ); @@ -347,6 +321,7 @@ if ( !defined( 'MW_PHPUNIT_TEST' ) ){ $this->doEvaluation( $entity, $results ); } + return $results; } @@ -354,11 +329,11 @@ * @see SpecialCheckResultPage::buildResultTable * * @param EntityId $entityId - * @param array|Traversable $results + * @param CheckResult[] $results * * @return string */ - protected function buildResultTable( EntityId $entityId, $results ) { + private function buildResultTable( EntityId $entityId, $results ) { // Set table headers $table = new HtmlTable( array ( @@ -431,7 +406,7 @@ * * @return string */ - protected function buildResultHeader( EntityId $entityId ) { + private function buildResultHeader( EntityId $entityId ) { $entityLink = sprintf( '%s (%s)', $this->entityIdHtmlLinkFormatter->formatEntityId( $entityId ), $entityId->getSerialization() ); @@ -449,7 +424,7 @@ * * @return string */ - protected function buildSummary( $results ) { + private function buildSummary( $results ) { $statuses = array (); foreach ( $results as $result ) { $status = strtolower( $result->getStatus() ); @@ -489,7 +464,7 @@ * * @return string */ - protected function buildTooltipElement( $content, $tooltipContent, $indicator ) { + private function buildTooltipElement( $content, $tooltipContent, $indicator ) { if ( !is_string( $content ) ) { throw new InvalidArgumentException( '$content has to be string.' ); } @@ -532,7 +507,7 @@ * * @return string */ - protected function buildExpandableElement( $content, $expandableContent, $indicator ) { + private function buildExpandableElement( $content, $expandableContent, $indicator ) { if ( !is_string( $content ) ) { throw new InvalidArgumentException( '$content has to be string.' ); } @@ -573,31 +548,21 @@ * * @return string */ - protected function formatStatus( $status ) { - if ( !is_string( $status ) ) { - throw new InvalidArgumentException( '$status has to be string.' ); - } + private function formatStatus( $status ) { + $messageName = "wbqc-constraintreport-status-" . strtolower( $status ); + $message = $this->msg( $messageName )->text(); - $messageName = 'wbqc-constraintreport-status-' . strtolower( $status ); - $message = $this->msg( $messageName )->text(); + $formattedStatus = + Html::element( + 'span', + array ( + 'class' => 'wbqc-status wbqc-status-' . $status + ), + $message + ); - $statusMapping = $this->getStatusMapping(); - $genericStatus = 'unknown'; - if ( array_key_exists( $status, $statusMapping ) ) { - $genericStatus = $statusMapping[ $status ]; - } - - $formattedStatus = - Html::element( - 'span', - array ( - 'class' => 'wbqc-status wbqc-status-' . $genericStatus - ), - $message - ); - - return $formattedStatus; - } + return $formattedStatus; + } /** * Parses data values to human-readable string @@ -609,7 +574,7 @@ * * @return string */ - protected function formatDataValues( $dataValues, $separator = ', ' ) { + private function formatDataValues( $dataValues, $separator = ', ' ) { if ( $dataValues instanceof DataValue ) { $dataValues = array ( $dataValues ); } elseif ( !is_array( $dataValues ) ) { @@ -728,20 +693,19 @@ return $array; } - /** - * @see SpecialCheckResultPage::getStatusMapping - * - * @return array - */ - protected function getStatusMapping() { - return array ( - 'compliance' => 'success', - 'exception' => 'warning', - 'violation' => 'error' - ); - } - protected function doEvaluation( $entity, $results ) { + /** + * @param Entity $entity + * @param array $results + */ + private function saveResultsInViolationsTable( $entity, $results ) { + $violations = $this->checkResultToViolationTranslator->translateToViolation( $entity, $results ); + foreach( $violations as $violation ) { + $this->violationRepo->save( $violation ); + } + } + + private function doEvaluation( $entity, $results ) { $checkTimeStamp = wfTimestamp( TS_UNIX ); $service = new EvaluateConstraintReportJobService(); $results = $service->buildResultSummary( $results ); @@ -751,5 +715,4 @@ //$jobs[] = EvaluateConstraintReportJob::newInsertDeferred( $entity->getId()->getSerialization(), $checkTimeStamp, 60*60 ); JobQueueGroup::singleton()->push( $jobs ); } - } diff --git a/tests/phpunit/DelegatingConstraintCheckerTest.php b/tests/phpunit/DelegatingConstraintCheckerTest.php index e519884..9460dca 100644 --- a/tests/phpunit/DelegatingConstraintCheckerTest.php +++ b/tests/phpunit/DelegatingConstraintCheckerTest.php @@ -45,7 +45,8 @@ protected function setUp() { parent::setUp(); $this->lookup = new JsonFileEntityLookup( __DIR__ ); - $factory = new ConstraintReportFactory( $this->lookup ); + $entityRevisionLookupMock = $this->getMockForAbstractClass( 'Wikibase\Lib\Store\EntityRevisionLookup' ); + $factory = new ConstraintReportFactory( $this->lookup, $entityRevisionLookupMock ); $this->constraintChecker = $factory->getConstraintChecker(); // specify database tables used by this test diff --git a/tests/phpunit/Specials/SpecialConstraintReportTest.php b/tests/phpunit/Specials/SpecialConstraintReportTest.php index b1b7ef6..5873c70 100755 --- a/tests/phpunit/Specials/SpecialConstraintReportTest.php +++ b/tests/phpunit/Specials/SpecialConstraintReportTest.php @@ -258,7 +258,7 @@ $matchers[ 'value status - violation' ] = array ( 'tag' => 'span', 'attributes' => array ( - 'class' => 'wbqc-status wbqc-status-error' + 'class' => 'wbqc-status wbqc-status-violation' ), 'content' => '(wbqc-constraintreport-status-violation)' ); @@ -266,7 +266,7 @@ $matchers[ 'value status - compliance' ] = array ( 'tag' => 'span', 'attributes' => array ( - 'class' => 'wbqc-status wbqc-status-success' + 'class' => 'wbqc-status wbqc-status-compliance' ), 'content' => '(wbqc-constraintreport-status-compliance)' ); diff --git a/tests/phpunit/Violations/CheckResultToViolationTranslatorTest.php b/tests/phpunit/Violations/CheckResultToViolationTranslatorTest.php index 245df74..6bafe94 100644 --- a/tests/phpunit/Violations/CheckResultToViolationTranslatorTest.php +++ b/tests/phpunit/Violations/CheckResultToViolationTranslatorTest.php @@ -115,7 +115,7 @@ $this->assertEquals( self::$idMap[ 'Q1' ], $violation->getEntityId() ); $this->assertEquals( 'P1', $violation->getPropertyId()->getSerialization() ); $this->assertEquals( $this->statement->getGuid(), $violation->getClaimGuid() ); - $this->assertEquals( md5( $this->statement->getGuid() . $checkResult->getConstraintName() ), $violation->getConstraintId() ); + $this->assertEquals( 'wbqc|P1$aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeeeRange', $violation->getConstraintId() ); $this->assertEquals( $checkResult->getConstraintName(), $violation->getConstraintTypeEntityId() ); $this->assertEquals( 42, $violation->getRevisionId() ); -- To view, visit https://gerrit.wikimedia.org/r/214009 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5dccc1a283d4ad1e60db6e104aba2e68e391b35e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikidataQualityConstraints Gerrit-Branch: master Gerrit-Owner: Soeren.oldag <soeren_ol...@freenet.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits