Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 33 additions & 54 deletions lib/MountManager/CircleMountProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use OCA\Circles\Exceptions\MountPointConstructionException;
use OCA\Circles\Exceptions\RequestBuilderException;
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
use OCA\Circles\IFederatedUser;
use OCA\Circles\Model\Member;
use OCA\Circles\Model\Mount;
use OCA\Circles\Model\Mountpoint;
Expand All @@ -29,10 +28,8 @@
use OCP\DB\Exception;
use OCP\Federation\ICloudIdManager;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorageFactory;
use OCP\Http\Client\IClientService;
use OCP\IUser;
Expand All @@ -42,6 +39,7 @@ class CircleMountProvider implements IMountProvider {
use TArrayTools;

public const EXTERNAL_STORAGE = ExternalStorage::class;
public array $mountedPoint = [];

public function __construct(
private IClientService $clientService,
Expand Down Expand Up @@ -188,63 +186,44 @@ private function fixDuplicateFile(string $userId, Mount $mount): void {
return;
}

$fs = $this->rootFolder->getUserFolder($userId);

try {
$fs->get($mount->getMountPoint());
} catch (NotFoundException) {
// in case no alternate mountpoint, we generate one in database (easier to catch duplicate mountpoint)
if ($mount->getAlternateMountPoint() !== null) {
return;
}

$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
$mountPoint = new Mountpoint($mount->getMountId(), $federatedUser->getSingleId(), $mount->getOriginalMountPoint());
try {
$this->mountPointRequest->insert($mountPoint);
return;
} catch (Exception $e) {
// meaning a duplicate mountpoint already exists, we need to set a new filename
if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
throw $e;
}
}
// we will be using cache version of the filesystem, to not cycle while operating it
$mountId = $mount->getId();
$baseFile = $mountPoint = '/files' . $mount->getMountPoint();
$parentMount = $this->rootFolder->getUserFolder($userId)->getMountPoint();
$parentCache = $parentMount->getStorage()->getCache();

// splitting extension to have a nice /file (1).ext
$ext = pathinfo($mountPoint, PATHINFO_EXTENSION);
if ($ext !== '') {
$baseFile = substr($mountPoint, 0, -(strlen($ext) + 1));
$ext = '.' . $ext;
}

$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
$this->generateIncrementedMountpoint($fs, $mount, $federatedUser);
}
// based on cached content, improving naming
$n = 1;
while ($parentCache->inCache($mountPoint)
|| ($this->mountedPoint[$mountPoint] ?? $mountId) !== $mountId) {
$mountPoint = $baseFile . ' (' . $n++ . ')' . $ext;
}

private function generateIncrementedMountpoint(Folder $fs, Mount $mount, IFederatedUser $federatedUser): void {
$info = pathinfo($mount->getMountPoint());
$filename = rtrim($this->get('dirname', $info), '/') . '/' . $this->get('filename', $info);
$extension = $this->get('extension', $info);
$extension = ($extension === '') ? '' : '.' . $extension;
// we keep trace as this won't be available in cache
$this->mountedPoint[$mountPoint] = $mount->getId();

$n = 2;
while (true) {
$path = $filename . " ($n)" . $extension;
$federatedUser = $this->federatedUserService->getLocalFederatedUser($userId);
$mountPoint = new Mountpoint($mount->getMountId(), $federatedUser->getSingleId(), substr($mountPoint, 6));
try {
try {
$fs->get($path);
} catch (NotFoundException) {
$mountPoint = new Mountpoint($mount->getMountId(), $federatedUser->getSingleId(), $path);
$mount->setAlternateMountPoint($mountPoint);
try {
try {
$this->mountPointRequest->update($mountPoint);
} catch (MountNotFoundException) {
$this->mountPointRequest->insert($mountPoint);
}
return;
} catch (Exception $e) {
// meaning path is already used by another share for this user, we keep incrementing
if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
throw $e;
}
}
$this->mountPointRequest->update($mountPoint);
} catch (MountNotFoundException) {
$this->mountPointRequest->insert($mountPoint);
}
return;
} catch (Exception $e) {
$this->logger->error('issue while creating alternate mount point', ['exception' => $e]);
// while there should be no reason for a unique constraint violation, we just log and ignore it
if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
throw $e;
}

$n++;
}
}
}
Loading