Skip to content

Commit

Permalink
fix test & psalm
Browse files Browse the repository at this point in the history
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
  • Loading branch information
ArtificialOwl committed Oct 27, 2023
1 parent 1a7bfd5 commit 76faa13
Show file tree
Hide file tree
Showing 26 changed files with 225 additions and 160 deletions.
5 changes: 5 additions & 0 deletions apps/files_trashbin/lib/Trash/TrashItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
namespace OCA\Files_Trashbin\Trash;

use OCP\Files\FileInfo;
use OCP\FilesMetadata\Model\IFilesMetadata;
use OCP\IUser;

class TrashItem implements ITrashItem {
Expand Down Expand Up @@ -191,6 +192,10 @@ public function getParentId(): int {
return $this->fileInfo->getParentId();
}

/**
* @inheritDoc
* @return IFilesMetadata[]
*/
public function getMetadata(): array {
return $this->fileInfo->getMetadata();
}
Expand Down
66 changes: 40 additions & 26 deletions core/Command/FilesMetadata/Get.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@

namespace OC\Core\Command\FilesMetadata;

use OC\User\NoUserException;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\FilesMetadata\Exceptions\FilesMetadataNotFoundException;
use OCP\FilesMetadata\IFilesMetadataManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -43,52 +46,63 @@ public function __construct(
parent::__construct();
}

protected function configure() {
protected function configure(): void {
$this->setName('metadata:get')
->setDescription('get stored metadata about a file, by its id')
->addArgument(
'fileId',
InputArgument::REQUIRED,
'id of the file document'
'fileId',
InputArgument::REQUIRED,
'id of the file document'
)
->addArgument(
'userId',
InputArgument::OPTIONAL,
'file owner'
'userId',
InputArgument::OPTIONAL,
'file owner'
)
->addOption(
'as-array',
'',
InputOption::VALUE_NONE,
'display metadata as a simple key=>value array'
'as-array',
'',
InputOption::VALUE_NONE,
'display metadata as a simple key=>value array'
)
->addOption(
'refresh',
'',
InputOption::VALUE_NONE,
'refresh metadata'
)
'refresh',
'',
InputOption::VALUE_NONE,
'refresh metadata'
)
->addOption(
'reset',
'',
InputOption::VALUE_NONE,
'refresh metadata from scratch'
'reset',
'',
InputOption::VALUE_NONE,
'refresh metadata from scratch'
);
}

/**
* @throws NotPermittedException
* @throws FilesMetadataNotFoundException
* @throws NoUserException
* @throws NotFoundException
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$fileId = (int)$input->getArgument('fileId');

if ($input->getOption('reset')) {
$this->filesMetadataManager->deleteMetadata($fileId);
if (!$input->getOption('refresh')) {
return 0;
}
}

if ($input->getOption('refresh')) {
$node = $this->rootFolder->getUserFolder($input->getArgument('userId'))->getById($fileId);
$file = $node[0];
if (null === $file) {
if (count($node) === 0) {
throw new NotFoundException();
}

$metadata = $this->filesMetadataManager->refreshMetadata(
$file,
IFilesMetadataManager::PROCESS_LIVE | IFilesMetadataManager::PROCESS_BACKGROUND,
$input->getOption('reset')
$node[0],
IFilesMetadataManager::PROCESS_LIVE | IFilesMetadataManager::PROCESS_BACKGROUND
);
} else {
$metadata = $this->filesMetadataManager->getMetadata($fileId);
Expand Down
17 changes: 10 additions & 7 deletions core/Migrations/Version28000Date20231004103301.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<?php

declare(strict_types=1);

/**
* @copyright Copyright (c) 2023 Maxence Lange <maxence@artificial-owl.com>
* @copyright 2023 Maxence Lange <maxence@artificial-owl.com>
*
* @author Maxence Lange <maxence@artificial-owl.com>
*
Expand Down Expand Up @@ -33,10 +32,10 @@
use OCP\Migration\SimpleMigrationStep;

class Version28000Date20231004103301 extends SimpleMigrationStep {

public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
$updated = false;

if (!$schema->hasTable('files_metadata')) {
$table = $schema->createTable('files_metadata');
Expand All @@ -53,6 +52,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt

$table->setPrimaryKey(['id']);
$table->addUniqueIndex(['file_id'], 'files_meta_fileid');
$updated = true;
}

if (!$schema->hasTable('files_metadata_index')) {
Expand All @@ -65,14 +65,17 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
]);
$table->addColumn('file_id', Types::BIGINT, ['notnull' => false, 'length' => 15]);
$table->addColumn('meta_key', Types::STRING, ['notnull' => false, 'length' => 31]);
$table->addColumn('meta_value', Types::STRING, ['notnull' => false, 'length' => 63]);
$table->addColumn('meta_value_string', Types::STRING, ['notnull' => false, 'length' => 63]);
$table->addColumn('meta_value_int', Types::BIGINT, ['notnull' => false, 'length' => 11]);
// $table->addColumn('meta_value_float', Types::FLOAT, ['notnull' => false, 'length' => 11,5]);

$table->setPrimaryKey(['id']);
$table->addIndex(['file_id', 'meta_key', 'meta_value'], 'f_meta_index');
$table->addIndex(['file_id', 'meta_key', 'meta_value_string'], 'f_meta_index');
$table->addIndex(['file_id', 'meta_key', 'meta_value_int'], 'f_meta_index_i');
// $table->addIndex(['file_id', 'meta_key', 'meta_value_float'], 'f_meta_index_f');
$updated = true;
}

if (!$updated) {
return null;
}

return $schema;
Expand Down
22 changes: 22 additions & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,17 @@
'OCP\\Federation\\ICloudId' => $baseDir . '/lib/public/Federation/ICloudId.php',
'OCP\\Federation\\ICloudIdManager' => $baseDir . '/lib/public/Federation/ICloudIdManager.php',
'OCP\\Files' => $baseDir . '/lib/public/Files.php',
'OCP\\FilesMetadata\\AMetadataEvent' => $baseDir . '/lib/public/FilesMetadata/AMetadataEvent.php',
'OCP\\FilesMetadata\\Event\\MetadataBackgroundEvent' => $baseDir . '/lib/public/FilesMetadata/Event/MetadataBackgroundEvent.php',
'OCP\\FilesMetadata\\Event\\MetadataLiveEvent' => $baseDir . '/lib/public/FilesMetadata/Event/MetadataLiveEvent.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataException' => $baseDir . '/lib/public/FilesMetadata/Exceptions/FilesMetadataException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataKeyFormatException' => $baseDir . '/lib/public/FilesMetadata/Exceptions/FilesMetadataKeyFormatException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataNotFoundException' => $baseDir . '/lib/public/FilesMetadata/Exceptions/FilesMetadataNotFoundException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataTypeException' => $baseDir . '/lib/public/FilesMetadata/Exceptions/FilesMetadataTypeException.php',
'OCP\\FilesMetadata\\IFilesMetadataManager' => $baseDir . '/lib/public/FilesMetadata/IFilesMetadataManager.php',
'OCP\\FilesMetadata\\Model\\IFilesMetadata' => $baseDir . '/lib/public/FilesMetadata/Model/IFilesMetadata.php',
'OCP\\FilesMetadata\\Model\\IMetadataQuery' => $baseDir . '/lib/public/FilesMetadata/Model/IMetadataQuery.php',
'OCP\\FilesMetadata\\Model\\IMetadataValueWrapper' => $baseDir . '/lib/public/FilesMetadata/Model/IMetadataValueWrapper.php',
'OCP\\Files\\AlreadyExistsException' => $baseDir . '/lib/public/Files/AlreadyExistsException.php',
'OCP\\Files\\AppData\\IAppDataFactory' => $baseDir . '/lib/public/Files/AppData/IAppDataFactory.php',
'OCP\\Files\\Cache\\AbstractCacheEvent' => $baseDir . '/lib/public/Files/Cache/AbstractCacheEvent.php',
Expand Down Expand Up @@ -1022,6 +1033,7 @@
'OC\\Core\\Command\\Encryption\\SetDefaultModule' => $baseDir . '/core/Command/Encryption/SetDefaultModule.php',
'OC\\Core\\Command\\Encryption\\ShowKeyStorageRoot' => $baseDir . '/core/Command/Encryption/ShowKeyStorageRoot.php',
'OC\\Core\\Command\\Encryption\\Status' => $baseDir . '/core/Command/Encryption/Status.php',
'OC\\Core\\Command\\FilesMetadata\\Get' => $baseDir . '/core/Command/FilesMetadata/Get.php',
'OC\\Core\\Command\\Group\\Add' => $baseDir . '/core/Command/Group/Add.php',
'OC\\Core\\Command\\Group\\AddUser' => $baseDir . '/core/Command/Group/AddUser.php',
'OC\\Core\\Command\\Group\\Delete' => $baseDir . '/core/Command/Group/Delete.php',
Expand Down Expand Up @@ -1194,6 +1206,7 @@
'OC\\Core\\Migrations\\Version28000Date20230728104802' => $baseDir . '/core/Migrations/Version28000Date20230728104802.php',
'OC\\Core\\Migrations\\Version28000Date20230803221055' => $baseDir . '/core/Migrations/Version28000Date20230803221055.php',
'OC\\Core\\Migrations\\Version28000Date20230906104802' => $baseDir . '/core/Migrations/Version28000Date20230906104802.php',
'OC\\Core\\Migrations\\Version28000Date20231004103301' => $baseDir . '/core/Migrations/Version28000Date20231004103301.php',
'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php',
'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php',
'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php',
Expand Down Expand Up @@ -1278,6 +1291,15 @@
'OC\\Federation\\CloudFederationShare' => $baseDir . '/lib/private/Federation/CloudFederationShare.php',
'OC\\Federation\\CloudId' => $baseDir . '/lib/private/Federation/CloudId.php',
'OC\\Federation\\CloudIdManager' => $baseDir . '/lib/private/Federation/CloudIdManager.php',
'OC\\FilesMetadata\\FilesMetadataManager' => $baseDir . '/lib/private/FilesMetadata/FilesMetadataManager.php',
'OC\\FilesMetadata\\Job\\UpdateSingleMetadata' => $baseDir . '/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php',
'OC\\FilesMetadata\\Listener\\MetadataDelete' => $baseDir . '/lib/private/FilesMetadata/Listener/MetadataDelete.php',
'OC\\FilesMetadata\\Listener\\MetadataUpdate' => $baseDir . '/lib/private/FilesMetadata/Listener/MetadataUpdate.php',
'OC\\FilesMetadata\\Model\\FilesMetadata' => $baseDir . '/lib/private/FilesMetadata/Model/FilesMetadata.php',
'OC\\FilesMetadata\\Model\\MetadataQuery' => $baseDir . '/lib/private/FilesMetadata/Model/MetadataQuery.php',
'OC\\FilesMetadata\\Model\\MetadataValueWrapper' => $baseDir . '/lib/private/FilesMetadata/Model/MetadataValueWrapper.php',
'OC\\FilesMetadata\\Service\\IndexRequestService' => $baseDir . '/lib/private/FilesMetadata/Service/IndexRequestService.php',
'OC\\FilesMetadata\\Service\\MetadataRequestService' => $baseDir . '/lib/private/FilesMetadata/Service/MetadataRequestService.php',
'OC\\Files\\AppData\\AppData' => $baseDir . '/lib/private/Files/AppData/AppData.php',
'OC\\Files\\AppData\\Factory' => $baseDir . '/lib/private/Files/AppData/Factory.php',
'OC\\Files\\Cache\\Cache' => $baseDir . '/lib/private/Files/Cache/Cache.php',
Expand Down
22 changes: 22 additions & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,17 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Federation\\ICloudId' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudId.php',
'OCP\\Federation\\ICloudIdManager' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudIdManager.php',
'OCP\\Files' => __DIR__ . '/../../..' . '/lib/public/Files.php',
'OCP\\FilesMetadata\\AMetadataEvent' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/AMetadataEvent.php',
'OCP\\FilesMetadata\\Event\\MetadataBackgroundEvent' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Event/MetadataBackgroundEvent.php',
'OCP\\FilesMetadata\\Event\\MetadataLiveEvent' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Event/MetadataLiveEvent.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataException' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Exceptions/FilesMetadataException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataKeyFormatException' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Exceptions/FilesMetadataKeyFormatException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataNotFoundException' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Exceptions/FilesMetadataNotFoundException.php',
'OCP\\FilesMetadata\\Exceptions\\FilesMetadataTypeException' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Exceptions/FilesMetadataTypeException.php',
'OCP\\FilesMetadata\\IFilesMetadataManager' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/IFilesMetadataManager.php',
'OCP\\FilesMetadata\\Model\\IFilesMetadata' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Model/IFilesMetadata.php',
'OCP\\FilesMetadata\\Model\\IMetadataQuery' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Model/IMetadataQuery.php',
'OCP\\FilesMetadata\\Model\\IMetadataValueWrapper' => __DIR__ . '/../../..' . '/lib/public/FilesMetadata/Model/IMetadataValueWrapper.php',
'OCP\\Files\\AlreadyExistsException' => __DIR__ . '/../../..' . '/lib/public/Files/AlreadyExistsException.php',
'OCP\\Files\\AppData\\IAppDataFactory' => __DIR__ . '/../../..' . '/lib/public/Files/AppData/IAppDataFactory.php',
'OCP\\Files\\Cache\\AbstractCacheEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Cache/AbstractCacheEvent.php',
Expand Down Expand Up @@ -1055,6 +1066,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Command\\Encryption\\SetDefaultModule' => __DIR__ . '/../../..' . '/core/Command/Encryption/SetDefaultModule.php',
'OC\\Core\\Command\\Encryption\\ShowKeyStorageRoot' => __DIR__ . '/../../..' . '/core/Command/Encryption/ShowKeyStorageRoot.php',
'OC\\Core\\Command\\Encryption\\Status' => __DIR__ . '/../../..' . '/core/Command/Encryption/Status.php',
'OC\\Core\\Command\\FilesMetadata\\Get' => __DIR__ . '/../../..' . '/core/Command/FilesMetadata/Get.php',
'OC\\Core\\Command\\Group\\Add' => __DIR__ . '/../../..' . '/core/Command/Group/Add.php',
'OC\\Core\\Command\\Group\\AddUser' => __DIR__ . '/../../..' . '/core/Command/Group/AddUser.php',
'OC\\Core\\Command\\Group\\Delete' => __DIR__ . '/../../..' . '/core/Command/Group/Delete.php',
Expand Down Expand Up @@ -1227,6 +1239,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Core\\Migrations\\Version28000Date20230728104802' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230728104802.php',
'OC\\Core\\Migrations\\Version28000Date20230803221055' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230803221055.php',
'OC\\Core\\Migrations\\Version28000Date20230906104802' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20230906104802.php',
'OC\\Core\\Migrations\\Version28000Date20231004103301' => __DIR__ . '/../../..' . '/core/Migrations/Version28000Date20231004103301.php',
'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php',
'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php',
'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php',
Expand Down Expand Up @@ -1311,6 +1324,15 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Federation\\CloudFederationShare' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudFederationShare.php',
'OC\\Federation\\CloudId' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudId.php',
'OC\\Federation\\CloudIdManager' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudIdManager.php',
'OC\\FilesMetadata\\FilesMetadataManager' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/FilesMetadataManager.php',
'OC\\FilesMetadata\\Job\\UpdateSingleMetadata' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Job/UpdateSingleMetadata.php',
'OC\\FilesMetadata\\Listener\\MetadataDelete' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Listener/MetadataDelete.php',
'OC\\FilesMetadata\\Listener\\MetadataUpdate' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Listener/MetadataUpdate.php',
'OC\\FilesMetadata\\Model\\FilesMetadata' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Model/FilesMetadata.php',
'OC\\FilesMetadata\\Model\\MetadataQuery' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Model/MetadataQuery.php',
'OC\\FilesMetadata\\Model\\MetadataValueWrapper' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Model/MetadataValueWrapper.php',
'OC\\FilesMetadata\\Service\\IndexRequestService' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Service/IndexRequestService.php',
'OC\\FilesMetadata\\Service\\MetadataRequestService' => __DIR__ . '/../../..' . '/lib/private/FilesMetadata/Service/MetadataRequestService.php',
'OC\\Files\\AppData\\AppData' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/AppData.php',
'OC\\Files\\AppData\\Factory' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/Factory.php',
'OC\\Files\\Cache\\Cache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Cache.php',
Expand Down
3 changes: 0 additions & 3 deletions lib/private/Files/Cache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,6 @@ public function get($file) {
$data = $result->fetch();
$result->closeCursor();

// @Louis: use asArray()
// $data['metadata'] = $metadataQuery?->extractMetadata($data)?->asArray() ?? [];

//merge partial data
if (!$data && is_string($file) && isset($this->partial[$file])) {
return $this->partial[$file];
Expand Down
6 changes: 5 additions & 1 deletion lib/private/Files/Cache/QuerySearchHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ protected function equipQueryForMetadata(CacheQueryBuilder $query, ISearchQuery
$order = $searchQuery->getOrder();
if ($order) {
foreach ($order as $orderField) {
$metadataQuery->joinIndex($orderField->getField());
$field = $orderField->getField();
if (!str_starts_with($field, 'metakey_')) {
continue;
}
$metadataQuery->joinIndex(substr($field, 8));
$query->orderBy($metadataQuery->getMetadataValueIntField(), $orderField->getDirection());
}
}
Expand Down
6 changes: 5 additions & 1 deletion lib/private/Files/FileInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
*/
namespace OC\Files;

use OC\FilesMetadata\Model\FilesMetadata;
use OCA\Files_Sharing\ISharedStorage;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\IHomeStorage;
use OCP\Files\Mount\IMountPoint;
use OCP\FilesMetadata\Model\IFilesMetadata;
use OCP\IUser;

class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
Expand Down Expand Up @@ -418,6 +418,10 @@ public function getParentId(): int {
return $this->data['parent'] ?? -1;
}

/**
* @inheritDoc
* @return IFilesMetadata[]
*/
public function getMetadata(): array {
return $this->data['metadata'] ?? [];
}
Expand Down
5 changes: 5 additions & 0 deletions lib/private/Files/Node/LazyFolder.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotPermittedException;
use OCP\FilesMetadata\Model\IFilesMetadata;

/**
* Class LazyFolder
Expand Down Expand Up @@ -575,6 +576,10 @@ public function getParentId(): int {
return $this->__call(__FUNCTION__, func_get_args());
}

/**
* @inheritDoc
* @return IFilesMetadata[]
*/
public function getMetadata(): array {
return $this->data['metadata'] ?? $this->__call(__FUNCTION__, func_get_args());
}
Expand Down
5 changes: 5 additions & 0 deletions lib/private/Files/Node/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use OCP\Files\Node as INode;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\FilesMetadata\Model\IFilesMetadata;
use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;

Expand Down Expand Up @@ -491,6 +492,10 @@ public function getParentId(): int {
return $this->fileInfo->getParentId();
}

/**
* @inheritDoc
* @return IFilesMetadata[]
*/
public function getMetadata(): array {
return $this->fileInfo->getMetadata();
}
Expand Down
Loading

0 comments on commit 76faa13

Please sign in to comment.