From 41e2d64c86fffc3e507a1ad0788bcb498db2c640 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 19 May 2013 14:15:49 -0400 Subject: [PATCH 1/6] Add support for copying/moving folders between storages, move isIgnoredDir() to Filesystem --- lib/files/cache/scanner.php | 14 +------------- lib/files/filesystem.php | 13 +++++++++++++ lib/files/view.php | 32 ++++++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 661bc48633..0b1947f17c 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -115,7 +115,7 @@ class Scanner { \OC_DB::beginTransaction(); while ($file = readdir($dh)) { $child = ($path) ? $path . '/' . $file : $file; - if (!$this->isIgnoredDir($file)) { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { $data = $this->scanFile($child, $recursive === self::SCAN_SHALLOW); if ($data) { if ($data['size'] === -1) { @@ -149,18 +149,6 @@ class Scanner { return $size; } - /** - * @brief check if the directory should be ignored when scanning - * NOTE: the special directories . and .. would cause never ending recursion - * @param String $dir - * @return boolean - */ - private function isIgnoredDir($dir) { - if ($dir === '.' || $dir === '..') { - return true; - } - return false; - } /** * @brief check if the file should be ignored when scanning * NOTE: files with a '.part' extension are ignored as well! diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d60d430d77..99d87011df 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -453,6 +453,19 @@ class Filesystem { return (in_array($filename, $blacklist)); } + /** + * @brief check if the directory should be ignored when scanning + * NOTE: the special directories . and .. would cause never ending recursion + * @param String $dir + * @return boolean + */ + static public function isIgnoredDir($dir) { + if ($dir === '.' || $dir === '..') { + return true; + } + return false; + } + /** * following functions are equivalent to their php builtin equivalents for arguments/return values. */ diff --git a/lib/files/view.php b/lib/files/view.php index f35e1e3dc1..875a6c1a1f 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -372,11 +372,18 @@ class View { $result = false; } } else { - $source = $this->fopen($path1 . $postFix1, 'r'); - $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); - list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); - $storage1->unlink($internalPath1); + if ($this->is_dir($path1)) { + $result = $this->copy($path1, $path2); + if ($result === true) { + $result = $this->deleteAll($path1); + } + } else { + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); + list($count, $result) = \OC_Helper::streamCopy($source, $target); + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + $storage1->unlink($internalPath1); + } } if ($this->fakeRoot == Filesystem::getRoot() && !Cache\Scanner::isPartialFile($path1)) { \OC_Hook::emit( @@ -459,9 +466,18 @@ class View { $result = false; } } else { - $source = $this->fopen($path1 . $postFix1, 'r'); - $target = $this->fopen($path2 . $postFix2, 'w'); - list($count, $result) = \OC_Helper::streamCopy($source, $target); + if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) { + $this->mkdir($path2); + while ($file = readdir($dh)) { + if (!Filesystem::isIgnoredDir($file)) { + $result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file); + } + } + } else { + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); + list($count, $result) = \OC_Helper::streamCopy($source, $target); + } } if ($this->fakeRoot == Filesystem::getRoot()) { \OC_Hook::emit( From e9b71eed691050e23d78910abdd8bf313f2f83cb Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 19 May 2013 14:20:46 -0400 Subject: [PATCH 2/6] Add tests for copying/moving between storages --- tests/lib/files/view.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index a064e44f3e..554bc7291a 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -228,6 +228,40 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals(3, $cachedData['size']); } + function testCopyBetweenStorages() { + $storage1 = $this->getTestStorage(); + $storage2 = $this->getTestStorage(); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); + + $rootView = new \OC\Files\View(''); + $rootView->copy('substorage', 'anotherfolder'); + $this->assertTrue($rootView->is_dir('/anotherfolder')); + $this->assertTrue($rootView->is_dir('/substorage')); + $this->assertTrue($rootView->file_exists('/anotherfolder/foo.txt')); + $this->assertTrue($rootView->file_exists('/anotherfolder/foo.png')); + $this->assertTrue($rootView->file_exists('/anotherfolder/folder/bar.txt')); + $this->assertTrue($rootView->file_exists('/substorage/foo.txt')); + $this->assertTrue($rootView->file_exists('/substorage/foo.png')); + $this->assertTrue($rootView->file_exists('/substorage/folder/bar.txt')); + } + + function testMoveBetweenStorages() { + $storage1 = $this->getTestStorage(); + $storage2 = $this->getTestStorage(); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); + + $rootView = new \OC\Files\View(''); + $rootView->rename('foo.txt', 'substorage/folder/foo.txt'); + $this->assertFalse($rootView->file_exists('foo.txt')); + $this->assertTrue($rootView->file_exists('substorage/folder/foo.txt')); + $rootView->rename('substorage/folder', 'anotherfolder'); + $this->assertFalse($rootView->is_dir('substorage/folder')); + $this->assertTrue($rootView->file_exists('anotherfolder/foo.txt')); + $this->assertTrue($rootView->file_exists('anotherfolder/bar.txt')); + } + /** * @param bool $scan * @return \OC\Files\Storage\Storage From fc5bce1f76a3a67a4ac9095d15441e363dfd03d1 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 19 May 2013 15:04:41 -0400 Subject: [PATCH 3/6] Fix undefined variable for copying empty folders --- lib/files/view.php | 2 +- tests/lib/files/view.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index 875a6c1a1f..8a37a0bcc6 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -467,7 +467,7 @@ class View { } } else { if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) { - $this->mkdir($path2); + $result = $this->mkdir($path2); while ($file = readdir($dh)) { if (!Filesystem::isIgnoredDir($file)) { $result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file); diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 554bc7291a..a51d99e793 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -235,9 +235,12 @@ class View extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); $rootView = new \OC\Files\View(''); + $rootView->mkdir('substorage/emptyfolder'); $rootView->copy('substorage', 'anotherfolder'); $this->assertTrue($rootView->is_dir('/anotherfolder')); $this->assertTrue($rootView->is_dir('/substorage')); + $this->assertTrue($rootView->is_dir('/anotherfolder/emptyfolder')); + $this->assertTrue($rootView->is_dir('/substorage/emptyfolder')); $this->assertTrue($rootView->file_exists('/anotherfolder/foo.txt')); $this->assertTrue($rootView->file_exists('/anotherfolder/foo.png')); $this->assertTrue($rootView->file_exists('/anotherfolder/folder/bar.txt')); From ec475cbcfa04969a58dd3a17d380106074ddbc8b Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 20 May 2013 10:21:13 -0400 Subject: [PATCH 4/6] Add data-dir attribute to home breadcrumb --- apps/files/templates/part.breadcrumb.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/templates/part.breadcrumb.php b/apps/files/templates/part.breadcrumb.php index 7ea1755d1d..9886b42e42 100644 --- a/apps/files/templates/part.breadcrumb.php +++ b/apps/files/templates/part.breadcrumb.php @@ -1,5 +1,5 @@ -
+
From 09ff46eda2a538d4f7a41b7f71ebf0e7df8944f2 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 20 May 2013 10:21:55 -0400 Subject: [PATCH 5/6] Remove user name addition to paths in deleteAll --- lib/files/storage/common.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index e87fe3b523..3da13ac4df 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -138,27 +138,21 @@ abstract class Common implements \OC\Files\Storage\Storage { */ public function deleteAll($directory, $empty = false) { $directory = trim($directory, '/'); - - if (!$this->file_exists(\OCP\USER::getUser() . '/' . $directory) - || !$this->is_dir(\OCP\USER::getUser() . '/' . $directory) - ) { - return false; - } elseif (!$this->isReadable(\OCP\USER::getUser() . '/' . $directory)) { + if (!$this->is_dir($directory) || !$this->isReadable($directory)) { return false; } else { - $directoryHandle = $this->opendir(\OCP\USER::getUser() . '/' . $directory); + $directoryHandle = $this->opendir($directory); while ($contents = readdir($directoryHandle)) { - if ($contents != '.' && $contents != '..') { - $path = $directory . "/" . $contents; + if (!\OC\Files\Filesystem::isIgnoredDir($contents)) { + $path = $directory . '/' . $contents; if ($this->is_dir($path)) { $this->deleteAll($path); } else { - $this->unlink(\OCP\USER::getUser() . '/' . $path); // TODO: make unlink use same system path as is_dir + $this->unlink($path); } } } - //$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV - if ($empty == false) { + if ($empty === false) { if (!$this->rmdir($directory)) { return false; } From 3b6d850e592bbc6db9d67d25ee700c0730c84376 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 23 May 2013 10:23:16 -0400 Subject: [PATCH 6/6] Switch to calling deleteAll via storage to avoid emitting delete hook --- lib/files/view.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index 8a37a0bcc6..d0d473766c 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -375,7 +375,8 @@ class View { if ($this->is_dir($path1)) { $result = $this->copy($path1, $path2); if ($result === true) { - $result = $this->deleteAll($path1); + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + $result = $storage1->deleteAll($internalPath1); } } else { $source = $this->fopen($path1 . $postFix1, 'r');