Skip to content

Commit 2172432

Browse files
authored
Merge pull request #23912 from nextcloud/objectstore-copy
use in objectstore copy
2 parents e165dcb + 9d4848e commit 2172432

File tree

9 files changed

+115
-5
lines changed

9 files changed

+115
-5
lines changed

lib/private/Files/ObjectStore/Azure.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,8 @@ public function objectExists($urn) {
130130
}
131131
}
132132
}
133+
134+
public function copyObject($from, $to) {
135+
$this->getBlobClient()->copyBlob($this->containerName, $to, $this->containerName, $from);
136+
}
133137
}

lib/private/Files/ObjectStore/ObjectStoreStorage.php

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,15 @@
3333
use Icewind\Streams\CountWrapper;
3434
use Icewind\Streams\IteratorDirectory;
3535
use OC\Files\Cache\CacheEntry;
36+
use OC\Files\Storage\PolyFill\CopyDirectory;
37+
use OCP\Files\Cache\ICacheEntry;
38+
use OCP\Files\FileInfo;
3639
use OCP\Files\NotFoundException;
3740
use OCP\Files\ObjectStore\IObjectStore;
3841

3942
class ObjectStoreStorage extends \OC\Files\Storage\Common {
43+
use CopyDirectory;
44+
4045
/**
4146
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore
4247
*/
@@ -319,7 +324,7 @@ public function fopen($path, $mode) {
319324
} else {
320325
return false;
321326
}
322-
// no break
327+
// no break
323328
case 'w':
324329
case 'wb':
325330
case 'w+':
@@ -474,7 +479,7 @@ public function writeStream(string $path, $stream, int $size = null): int {
474479
if ($size === null) {
475480
$countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
476481
$this->getCache()->update($fileId, [
477-
'size' => $writtenSize
482+
'size' => $writtenSize,
478483
]);
479484
$size = $writtenSize;
480485
});
@@ -523,4 +528,59 @@ public function writeStream(string $path, $stream, int $size = null): int {
523528
public function getObjectStore(): IObjectStore {
524529
return $this->objectStore;
525530
}
531+
532+
public function copy($path1, $path2) {
533+
$path1 = $this->normalizePath($path1);
534+
$path2 = $this->normalizePath($path2);
535+
536+
$cache = $this->getCache();
537+
$sourceEntry = $cache->get($path1);
538+
if (!$sourceEntry) {
539+
throw new NotFoundException('Source object not found');
540+
}
541+
542+
$this->copyInner($sourceEntry, $path2);
543+
544+
return true;
545+
}
546+
547+
private function copyInner(ICacheEntry $sourceEntry, string $to) {
548+
$cache = $this->getCache();
549+
550+
if ($sourceEntry->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
551+
if ($cache->inCache($to)) {
552+
$cache->remove($to);
553+
}
554+
$this->mkdir($to);
555+
556+
foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) {
557+
$this->copyInner($child, $to . '/' . $child->getName());
558+
}
559+
} else {
560+
$this->copyFile($sourceEntry, $to);
561+
}
562+
}
563+
564+
private function copyFile(ICacheEntry $sourceEntry, string $to) {
565+
$cache = $this->getCache();
566+
567+
$sourceUrn = $this->getURN($sourceEntry->getId());
568+
569+
$cache->copyFromCache($cache, $sourceEntry, $to);
570+
$targetEntry = $cache->get($to);
571+
572+
if (!$targetEntry) {
573+
throw new \Exception('Target not in cache after copy');
574+
}
575+
576+
$targetUrn = $this->getURN($targetEntry->getId());
577+
578+
try {
579+
$this->objectStore->copyObject($sourceUrn, $targetUrn);
580+
} catch (\Exception $e) {
581+
$cache->remove($to);
582+
583+
throw $e;
584+
}
585+
}
526586
}

lib/private/Files/ObjectStore/S3ObjectTrait.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,8 @@ public function deleteObject($urn) {
124124
public function objectExists($urn) {
125125
return $this->getConnection()->doesObjectExist($this->bucket, $urn);
126126
}
127+
128+
public function copyObject($from, $to) {
129+
$this->getConnection()->copy($this->getBucket(), $from, $this->getBucket(), $to);
130+
}
127131
}

lib/private/Files/ObjectStore/StorageObjectStore.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,8 @@ public function deleteObject($urn) {
9393
public function objectExists($urn) {
9494
return $this->storage->file_exists($urn);
9595
}
96+
97+
public function copyObject($from, $to) {
98+
$this->storage->copy($from, $to);
99+
}
96100
}

lib/private/Files/ObjectStore/Swift.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ public function writeObject($urn, $stream) {
8787
if (filesize($tmpFile) < SWIFT_SEGMENT_SIZE) {
8888
$this->getContainer()->createObject([
8989
'name' => $urn,
90-
'stream' => stream_for($handle)
90+
'stream' => stream_for($handle),
9191
]);
9292
} else {
9393
$this->getContainer()->createLargeObject([
9494
'name' => $urn,
9595
'stream' => stream_for($handle),
96-
'segmentSize' => SWIFT_SEGMENT_SIZE
96+
'segmentSize' => SWIFT_SEGMENT_SIZE,
9797
]);
9898
}
9999
}
@@ -114,7 +114,7 @@ public function readObject($urn) {
114114
'stream' => true,
115115
'headers' => [
116116
'X-Auth-Token' => $tokenId,
117-
'Cache-Control' => 'no-cache'
117+
'Cache-Control' => 'no-cache',
118118
],
119119
]
120120
);
@@ -149,4 +149,10 @@ public function deleteContainer() {
149149
public function objectExists($urn) {
150150
return $this->getContainer()->objectExists($urn);
151151
}
152+
153+
public function copyObject($from, $to) {
154+
$this->getContainer()->getObject($from)->copy([
155+
'destination' => $this->getContainer()->name . '/' . $to
156+
]);
157+
}
152158
}

lib/public/Files/ObjectStore/IObjectStore.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,12 @@ public function deleteObject($urn);
7373
* @since 16.0.0
7474
*/
7575
public function objectExists($urn);
76+
77+
/**
78+
* @param string $from the unified resource name used to identify the source object
79+
* @param string $to the unified resource name used to identify the target object
80+
* @return void
81+
* @since 21.0.0
82+
*/
83+
public function copyObject($from, $to);
7684
}

tests/lib/Files/ObjectStore/FailDeleteObjectStore.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,8 @@ public function deleteObject($urn) {
5151
public function objectExists($urn) {
5252
return $this->objectStore->objectExists($urn);
5353
}
54+
55+
public function copyObject($from, $to) {
56+
$this->objectStore->copyObject($from, $to);
57+
}
5458
}

tests/lib/Files/ObjectStore/FailWriteObjectStore.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,8 @@ public function deleteObject($urn) {
5252
public function objectExists($urn) {
5353
return $this->objectStore->objectExists($urn);
5454
}
55+
56+
public function copyObject($from, $to) {
57+
$this->objectStore->copyObject($from, $to);
58+
}
5559
}

tests/lib/Files/ObjectStore/ObjectStoreTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,20 @@ public function testExists() {
108108

109109
$this->assertFalse($instance->objectExists('2'));
110110
}
111+
112+
public function testCopy() {
113+
$stream = $this->stringToStream('foobar');
114+
115+
$instance = $this->getInstance();
116+
117+
$instance->writeObject('source', $stream);
118+
119+
$this->assertFalse($instance->objectExists('target'));
120+
121+
$instance->copyObject('source', 'target');
122+
123+
$this->assertTrue($instance->objectExists('target'));
124+
125+
$this->assertEquals('foobar', stream_get_contents($instance->readObject('target')));
126+
}
111127
}

0 commit comments

Comments
 (0)